funkophile 0.2.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mocharc.json +3 -0
- package/.vscode/settings.json +6 -0
- package/README.md +72 -40
- package/build.ts +23 -0
- package/coverage/clover.xml +6 -0
- package/coverage/coverage-final.json +1 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +101 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov.info +0 -0
- package/dev.ts +26 -0
- package/dist/esm/funkophileHelpers.js +99 -82
- package/dist/esm/funkophileHelpers.js.map +7 -0
- package/dist/esm/index.js +634 -508
- package/dist/esm/index.js.map +7 -0
- package/funkophileHelpers.ts +22 -3
- package/index.test.ts +210 -0
- package/index.ts +98 -450
- package/mocha.log +59 -0
- package/package.json +26 -7
- package/test-utils.ts +40 -0
- package/tsconfig.json +16 -4
- package/utils.ts +539 -0
- package/dev.js +0 -59
- package/dist/esm/funkophileHelpers.d.ts +0 -108
- package/dist/esm/index.d.ts +0 -13
- package/yarn-error.log +0 -107
package/dist/esm/index.js
CHANGED
|
@@ -1,531 +1,657 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
// index.ts
|
|
2
|
+
import Promise2 from "bluebird";
|
|
3
|
+
import fse2 from "fs-extra";
|
|
4
|
+
|
|
5
|
+
// utils.ts
|
|
4
6
|
import fs from "fs";
|
|
5
7
|
import fse from "fs-extra";
|
|
6
|
-
import { glob } from "glob";
|
|
7
8
|
import http from "http";
|
|
8
9
|
import path from "path";
|
|
9
|
-
import
|
|
10
|
+
import { createStore } from "redux";
|
|
11
|
+
import { createSelector } from "reselect";
|
|
10
12
|
import url from "url";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
import { glob } from "glob";
|
|
14
|
+
import chokidar from "chokidar";
|
|
15
|
+
var INITIALIZE = "INITIALIZE";
|
|
16
|
+
var UPSERT = "UPSERT";
|
|
17
|
+
var REMOVE = "REMOVE";
|
|
18
|
+
var previousState = {};
|
|
19
|
+
var logger = {
|
|
20
|
+
watchError: (p) => console.log("\x1B[7m ! \x1B[0m" + p),
|
|
21
|
+
watchReady: (p) => console.log("\x1B[7m\x1B[36m < \x1B[0m" + p),
|
|
22
|
+
watchAdd: (p) => console.log("\x1B[7m\x1B[34m + \x1B[0m./" + p),
|
|
23
|
+
watchChange: (p) => console.log("\x1B[7m\x1B[35m * \x1B[0m" + p),
|
|
24
|
+
watchUnlink: (p) => console.log("\x1B[7m\x1B[31m - \x1B[0m./" + p),
|
|
25
|
+
stateChange: () => console.log("\x1B[7m\x1B[31m --- Redux state changed --- \x1B[0m"),
|
|
26
|
+
cleaningEmptyfolder: (p) => console.log("\x1B[31m\x1B[7m XXX! \x1B[0m" + p),
|
|
27
|
+
readingFile: (p) => console.log("\x1B[31m <-- \x1B[0m" + p),
|
|
28
|
+
removedFile: (p) => console.log("\x1B[31m\x1B[7m ??? \x1B[0m./" + p),
|
|
29
|
+
writingString: (p) => console.log("\x1B[32m --> \x1B[0m" + p),
|
|
30
|
+
writingFunction: (p) => console.log("\x1B[33m ... \x1B[0m" + p),
|
|
31
|
+
writingPromise: (p) => console.log("\x1B[33m ... \x1B[0m" + p),
|
|
32
|
+
writingError: (p, message) => console.log("\x1B[31m !!! \x1B[0m" + p + " " + message),
|
|
33
|
+
waiting: () => console.log(
|
|
34
|
+
"\x1B[7m Funkophile is done for now but waiting on changes...\x1B[0m "
|
|
35
|
+
),
|
|
36
|
+
done: () => console.log("\x1B[7m Funkophile is done!\x1B[0m ")
|
|
37
|
+
};
|
|
38
|
+
function cleanEmptyFoldersRecursively(folder) {
|
|
39
|
+
var isDir = fs.statSync(folder).isDirectory();
|
|
40
|
+
if (!isDir) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
var files = fs.readdirSync(folder);
|
|
44
|
+
if (files.length > 0) {
|
|
45
|
+
files.forEach(function(file) {
|
|
46
|
+
var fullPath = path.join(folder, file);
|
|
14
47
|
});
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
37
|
-
function cleanEmptyFoldersRecursively(folder) {
|
|
38
|
-
var isDir = fs.statSync(folder).isDirectory();
|
|
39
|
-
if (!isDir) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
var files = fs.readdirSync(folder);
|
|
43
|
-
if (files.length > 0) {
|
|
44
|
-
files.forEach(function (file) {
|
|
45
|
-
var fullPath = path.join(folder, file);
|
|
46
|
-
});
|
|
47
|
-
// re-evaluate files; after deleting subfolder
|
|
48
|
-
// we may have parent folder empty now
|
|
49
|
-
files = fs.readdirSync(folder);
|
|
50
|
-
}
|
|
51
|
-
if (files.length == 0) {
|
|
52
|
-
logger.cleaningEmptyfolder(folder);
|
|
53
|
-
fs.rmdirSync(folder);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const dispatchUpsert = (store, key, file, encodings) => {
|
|
58
|
-
const fileType = path.basename(file).split(".")[1];
|
|
59
|
-
let encoding = Object.keys(encodings).find((e) => {
|
|
60
|
-
return encodings[e].includes(fileType);
|
|
61
|
-
});
|
|
62
|
-
logger.readingFile(file);
|
|
63
|
-
store.dispatch({
|
|
64
|
-
type: UPSERT,
|
|
65
|
-
payload: {
|
|
66
|
-
key: key,
|
|
67
|
-
// key: path.relative(process.cwd(), key),
|
|
68
|
-
src: file,
|
|
69
|
-
contents: fse.readFileSync(file, encoding),
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
function omit(key, obj) {
|
|
74
|
-
const { [key]: omitted, ...rest } = obj;
|
|
75
|
-
return rest;
|
|
48
|
+
files = fs.readdirSync(folder);
|
|
49
|
+
}
|
|
50
|
+
if (files.length == 0) {
|
|
51
|
+
logger.cleaningEmptyfolder(folder);
|
|
52
|
+
fs.rmdirSync(folder);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
var dispatchUpsert = (store, key, file, encodings) => {
|
|
57
|
+
const fileType = path.basename(file).split(".")[1];
|
|
58
|
+
let encoding = Object.keys(encodings).find((e) => {
|
|
59
|
+
return encodings[e].includes(fileType);
|
|
60
|
+
});
|
|
61
|
+
logger.readingFile(file);
|
|
62
|
+
store.dispatch({
|
|
63
|
+
type: UPSERT,
|
|
64
|
+
payload: {
|
|
65
|
+
key,
|
|
66
|
+
// key: path.relative(process.cwd(), key),
|
|
67
|
+
src: file,
|
|
68
|
+
contents: fse.readFileSync(file, encoding)
|
|
76
69
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
function omit(key, obj) {
|
|
73
|
+
const { [key]: omitted, ...rest } = obj;
|
|
74
|
+
return rest;
|
|
75
|
+
}
|
|
76
|
+
function newStore(funkophileConfig) {
|
|
77
|
+
const initialInputState = Object.keys(funkophileConfig.inputs).reduce(
|
|
78
|
+
(state, inputKey) => {
|
|
79
|
+
state[inputKey] = {};
|
|
80
|
+
return state;
|
|
81
|
+
},
|
|
82
|
+
{}
|
|
83
|
+
);
|
|
84
|
+
return createStore(
|
|
85
|
+
(state = {
|
|
86
|
+
initialLoad: true,
|
|
87
|
+
...initialInputState,
|
|
88
|
+
...funkophileConfig.initialState,
|
|
89
|
+
timestamp: Date.now()
|
|
81
90
|
}, action) => {
|
|
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
|
-
|
|
91
|
+
if (state === void 0) {
|
|
92
|
+
throw new Error("Redux state is undefined. This should never happen.");
|
|
93
|
+
}
|
|
94
|
+
console.log(
|
|
95
|
+
`\x1B[35m\x1B[1m[Funkophile]\x1B[0m Redux received action: ${action.type}`
|
|
96
|
+
);
|
|
97
|
+
if (!action.type.includes("@@redux")) {
|
|
98
|
+
if (action.type === INITIALIZE) {
|
|
99
|
+
console.log(
|
|
100
|
+
`\x1B[35m\x1B[1m[Funkophile]\x1B[0m INITIALIZE action - setting initialLoad to false`
|
|
101
|
+
);
|
|
102
|
+
return {
|
|
103
|
+
...state,
|
|
104
|
+
initialLoad: false,
|
|
105
|
+
timestamp: Date.now()
|
|
106
|
+
};
|
|
107
|
+
} else if (action.type === UPSERT) {
|
|
108
|
+
console.log(
|
|
109
|
+
`\x1B[35m\x1B[1m[Funkophile]\x1B[0m UPSERT action for key: ${action["payload"].key}, file: ${action["payload"].src}`
|
|
110
|
+
);
|
|
111
|
+
return {
|
|
112
|
+
...state,
|
|
113
|
+
[action["payload"].key]: {
|
|
114
|
+
// @ts-ignore
|
|
115
|
+
...state[action.payload.key],
|
|
116
|
+
...{
|
|
117
|
+
[action["payload"].src]: action["payload"].contents
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
timestamp: Date.now()
|
|
121
|
+
};
|
|
122
|
+
} else if (action.type === REMOVE) {
|
|
123
|
+
console.log(
|
|
124
|
+
`\x1B[35m\x1B[1m[Funkophile]\x1B[0m REMOVE action for key: ${action["payload"].key}, file: ${action["payload"].file}`
|
|
125
|
+
);
|
|
126
|
+
const currentKeyState = state[action["payload"].key] || {};
|
|
127
|
+
return {
|
|
128
|
+
...state,
|
|
129
|
+
[action["payload"].key]: omit(
|
|
130
|
+
action["payload"].file,
|
|
131
|
+
currentKeyState
|
|
132
|
+
),
|
|
133
|
+
timestamp: Date.now()
|
|
134
|
+
};
|
|
135
|
+
} else {
|
|
136
|
+
console.error(
|
|
137
|
+
"Redux was asked to handle an unknown action type: " + action.type
|
|
138
|
+
);
|
|
139
|
+
process.exit(-1);
|
|
119
140
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
// Serve the file
|
|
183
|
-
fs.readFile(fullPath, (readErr, data) => {
|
|
184
|
-
if (readErr) {
|
|
185
|
-
res.statusCode = 500;
|
|
186
|
-
res.end('Internal Server Error');
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
// Set appropriate content type based on file extension
|
|
190
|
-
const ext = path.extname(fullPath).toLowerCase();
|
|
191
|
-
const contentTypes = {
|
|
192
|
-
'.html': 'text/html',
|
|
193
|
-
'.css': 'text/css',
|
|
194
|
-
'.js': 'application/javascript',
|
|
195
|
-
'.json': 'application/json',
|
|
196
|
-
'.png': 'image/png',
|
|
197
|
-
'.jpg': 'image/jpeg',
|
|
198
|
-
'.jpeg': 'image/jpeg',
|
|
199
|
-
'.gif': 'image/gif',
|
|
200
|
-
'.svg': 'image/svg+xml',
|
|
201
|
-
'.ico': 'image/x-icon'
|
|
202
|
-
};
|
|
203
|
-
res.setHeader('Content-Type', contentTypes[ext] || 'application/octet-stream');
|
|
204
|
-
res.end(data);
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
}
|
|
141
|
+
}
|
|
142
|
+
return state;
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
function makeFinalSelector(funkophileConfig) {
|
|
147
|
+
return funkophileConfig.outputs(
|
|
148
|
+
Object.keys(funkophileConfig.inputs).reduce((mm, inputKey) => {
|
|
149
|
+
return {
|
|
150
|
+
...mm,
|
|
151
|
+
[inputKey]: createSelector([(x) => x], (root) => {
|
|
152
|
+
const result = root[inputKey];
|
|
153
|
+
if (result === void 0) {
|
|
154
|
+
console.warn(
|
|
155
|
+
`\x1B[33m\x1B[1m[Funkophile]\x1B[0m Input key "${inputKey}" is undefined in state, which shouldn't happen. Using empty object.`
|
|
156
|
+
);
|
|
157
|
+
return {};
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
})
|
|
161
|
+
};
|
|
162
|
+
}, {})
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
function startServing(funkophileConfig) {
|
|
166
|
+
const port = funkophileConfig.options.port || 8080;
|
|
167
|
+
const server = http.createServer((req, res) => {
|
|
168
|
+
if (!req.url) {
|
|
169
|
+
res.statusCode = 400;
|
|
170
|
+
res.end("Bad Request");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const parsedUrl = url.parse(req.url);
|
|
174
|
+
let pathname = parsedUrl.pathname;
|
|
175
|
+
if (pathname && pathname.endsWith("/")) {
|
|
176
|
+
pathname += "index.html";
|
|
177
|
+
}
|
|
178
|
+
const filePath = pathname ? pathname.substring(1) : "index.html";
|
|
179
|
+
const fullPath = path.join(
|
|
180
|
+
process.cwd(),
|
|
181
|
+
funkophileConfig.options.outFolder,
|
|
182
|
+
filePath
|
|
183
|
+
);
|
|
184
|
+
fs.access(fullPath, fs.constants.F_OK, (err) => {
|
|
185
|
+
if (err) {
|
|
186
|
+
const htmlPath = fullPath + ".html";
|
|
187
|
+
fs.access(htmlPath, fs.constants.F_OK, (htmlErr) => {
|
|
188
|
+
if (htmlErr) {
|
|
189
|
+
res.statusCode = 404;
|
|
190
|
+
res.end("File not found");
|
|
191
|
+
} else {
|
|
192
|
+
fs.readFile(htmlPath, (readErr, data) => {
|
|
193
|
+
if (readErr) {
|
|
194
|
+
res.statusCode = 500;
|
|
195
|
+
res.end("Internal Server Error");
|
|
196
|
+
} else {
|
|
197
|
+
res.setHeader("Content-Type", "text/html");
|
|
198
|
+
res.end(data);
|
|
199
|
+
}
|
|
208
200
|
});
|
|
201
|
+
}
|
|
209
202
|
});
|
|
210
|
-
|
|
211
|
-
|
|
203
|
+
} else {
|
|
204
|
+
fs.readFile(fullPath, (readErr, data) => {
|
|
205
|
+
if (readErr) {
|
|
206
|
+
res.statusCode = 500;
|
|
207
|
+
res.end("Internal Server Error");
|
|
208
|
+
} else {
|
|
209
|
+
const ext = path.extname(fullPath).toLowerCase();
|
|
210
|
+
const contentTypes = {
|
|
211
|
+
".html": "text/html",
|
|
212
|
+
".css": "text/css",
|
|
213
|
+
".js": "application/javascript",
|
|
214
|
+
".json": "application/json",
|
|
215
|
+
".png": "image/png",
|
|
216
|
+
".jpg": "image/jpeg",
|
|
217
|
+
".jpeg": "image/jpeg",
|
|
218
|
+
".gif": "image/gif",
|
|
219
|
+
".svg": "image/svg+xml",
|
|
220
|
+
".ico": "image/x-icon"
|
|
221
|
+
};
|
|
222
|
+
res.setHeader(
|
|
223
|
+
"Content-Type",
|
|
224
|
+
contentTypes[ext] || "application/octet-stream"
|
|
225
|
+
);
|
|
226
|
+
res.end(data);
|
|
227
|
+
}
|
|
212
228
|
});
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
server.listen(port, () => {
|
|
233
|
+
console.log(
|
|
234
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Server running at http://localhost:${port}/`
|
|
235
|
+
);
|
|
236
|
+
});
|
|
237
|
+
process.on("SIGINT", () => {
|
|
238
|
+
if (server) {
|
|
239
|
+
server.close();
|
|
213
240
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
.on("change", (filePath) => {
|
|
284
|
-
logger.watchChange(filePath);
|
|
285
|
-
const absoluteFilePath = path.resolve(process.cwd(), filePath);
|
|
286
|
-
dispatchUpsert(store, inputRuleKey, absoluteFilePath, funkophileConfig.encodings);
|
|
287
|
-
})
|
|
288
|
-
.on("unlink", (filePath) => {
|
|
289
|
-
logger.watchUnlink(filePath);
|
|
290
|
-
const absoluteFilePath = path.resolve(process.cwd(), filePath);
|
|
291
|
-
store.dispatch({
|
|
292
|
-
type: REMOVE,
|
|
293
|
-
payload: {
|
|
294
|
-
key: inputRuleKey,
|
|
295
|
-
file: absoluteFilePath,
|
|
296
|
-
},
|
|
297
|
-
});
|
|
298
|
-
})
|
|
299
|
-
.on("unlinkDir", (filePath) => {
|
|
300
|
-
logger.watchUnlink(filePath);
|
|
301
|
-
});
|
|
302
|
-
})
|
|
303
|
-
.catch((error) => {
|
|
304
|
-
console.error(`[Funkophile] Error globbing for pattern ${globPattern}:`, error);
|
|
305
|
-
reject(error);
|
|
306
|
-
});
|
|
307
|
-
// .on('raw', (event, p, details) => { // internal
|
|
308
|
-
// log('Raw event info:', event, p, details);
|
|
309
|
-
// })
|
|
310
|
-
}
|
|
311
|
-
else {
|
|
312
|
-
console.error(`mode should be 'watch' or 'build', not "${funkophileConfig.mode}"`);
|
|
313
|
-
process.exit(-1);
|
|
314
|
-
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
function logInputKeys(funkophileConfig, currentState) {
|
|
244
|
+
Object.keys(funkophileConfig.inputs).forEach((inputKey) => {
|
|
245
|
+
if (currentState[inputKey]) {
|
|
246
|
+
console.log(
|
|
247
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Input key "${inputKey}" found in state with ${Object.keys(currentState[inputKey]).length} files`
|
|
248
|
+
);
|
|
249
|
+
if (Object.keys(currentState[inputKey]).length > 0) {
|
|
250
|
+
console.log(
|
|
251
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Files for "${inputKey}":`,
|
|
252
|
+
Object.keys(currentState[inputKey])
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
console.warn(
|
|
257
|
+
`\x1B[33m\x1B[1m[Funkophile]\x1B[0m Input key "${inputKey}" NOT found in state`
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
function logDone(funkophileConfig, currentState) {
|
|
263
|
+
if (funkophileConfig.mode === "build") {
|
|
264
|
+
console.log(
|
|
265
|
+
"\x1B[32m\x1B[1m[Funkophile]\x1B[0m Build completed successfully!"
|
|
266
|
+
);
|
|
267
|
+
logger.done();
|
|
268
|
+
} else if (funkophileConfig.mode === "watch") {
|
|
269
|
+
console.log(
|
|
270
|
+
"\x1B[36m\x1B[1m[Funkophile]\x1B[0m Watching for file changes..."
|
|
271
|
+
);
|
|
272
|
+
const port = funkophileConfig.options.port || 8080;
|
|
273
|
+
console.log(
|
|
274
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Serving at: http://localhost:${port}/`
|
|
275
|
+
);
|
|
276
|
+
logger.waiting();
|
|
277
|
+
} else {
|
|
278
|
+
throw `\x1B[31m\x1B[1m[Funkophile]\x1B[0m The mode should be 'watch' or 'build', not "${funkophileConfig.mode}"`;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function makePromissesArray(funkophileConfig, store) {
|
|
282
|
+
return Object.keys(funkophileConfig.inputs).map((inputRuleKey) => {
|
|
283
|
+
const pattern = funkophileConfig.inputs[inputRuleKey] || "";
|
|
284
|
+
const globPattern = path.posix.join(
|
|
285
|
+
funkophileConfig.options.inFolder,
|
|
286
|
+
pattern
|
|
287
|
+
);
|
|
288
|
+
return new Promise((fulfill, reject) => {
|
|
289
|
+
if (funkophileConfig.mode === "build") {
|
|
290
|
+
glob(globPattern, { cwd: process.cwd() }).then((files) => {
|
|
291
|
+
if (files.length === 0) {
|
|
292
|
+
console.warn(
|
|
293
|
+
`No files found for input key "${inputRuleKey}" with pattern "${globPattern}"`
|
|
294
|
+
);
|
|
295
|
+
} else {
|
|
296
|
+
files.forEach((file) => {
|
|
297
|
+
const absoluteFilePath = path.resolve(process.cwd(), file);
|
|
298
|
+
dispatchUpsert(
|
|
299
|
+
store,
|
|
300
|
+
inputRuleKey,
|
|
301
|
+
absoluteFilePath,
|
|
302
|
+
funkophileConfig.encodings
|
|
303
|
+
);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}).then(() => {
|
|
307
|
+
fulfill();
|
|
308
|
+
}).catch((error) => {
|
|
309
|
+
reject(error);
|
|
315
310
|
});
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
console.log(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
311
|
+
} else if (funkophileConfig.mode === "watch") {
|
|
312
|
+
console.log(
|
|
313
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Setting up watcher for pattern: ${globPattern}`
|
|
314
|
+
);
|
|
315
|
+
console.log(
|
|
316
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Current working directory: ${process.cwd()}`
|
|
317
|
+
);
|
|
318
|
+
glob(globPattern, { cwd: process.cwd() }).then((files) => {
|
|
319
|
+
console.log(
|
|
320
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Found ${files.length} initial files for ${inputRuleKey}`
|
|
321
|
+
);
|
|
322
|
+
files.forEach((file) => {
|
|
323
|
+
const absoluteFilePath = path.resolve(process.cwd(), file);
|
|
324
|
+
console.log(
|
|
325
|
+
`\x1B[32m\x1B[1m[Funkophile]\x1B[0m Adding initial file: ${file}`
|
|
326
|
+
);
|
|
327
|
+
dispatchUpsert(
|
|
328
|
+
store,
|
|
329
|
+
inputRuleKey,
|
|
330
|
+
absoluteFilePath,
|
|
331
|
+
funkophileConfig.encodings
|
|
332
|
+
);
|
|
333
|
+
});
|
|
334
|
+
const watcher = chokidar.watch(globPattern, {
|
|
335
|
+
cwd: process.cwd(),
|
|
336
|
+
ignoreInitial: true,
|
|
337
|
+
// We've already processed initial files
|
|
338
|
+
persistent: true,
|
|
339
|
+
usePolling: false,
|
|
340
|
+
interval: 100,
|
|
341
|
+
binaryInterval: 300,
|
|
342
|
+
alwaysStat: false,
|
|
343
|
+
depth: 99,
|
|
344
|
+
awaitWriteFinish: {
|
|
345
|
+
stabilityThreshold: 50,
|
|
346
|
+
pollInterval: 10
|
|
328
347
|
}
|
|
348
|
+
}).on("error", (error) => {
|
|
349
|
+
console.error(
|
|
350
|
+
`\x1B[31m\x1B[1m[Funkophile]\x1B[0m Watcher error for pattern ${globPattern}:`,
|
|
351
|
+
error
|
|
352
|
+
);
|
|
353
|
+
logger.watchError(globPattern);
|
|
354
|
+
}).on("add", (filePath) => {
|
|
355
|
+
console.log(
|
|
356
|
+
`\x1B[32m\x1B[1m[Funkophile]\x1B[0m File added: ${filePath}`
|
|
357
|
+
);
|
|
358
|
+
logger.watchAdd(filePath);
|
|
359
|
+
const absoluteFilePath = path.resolve(process.cwd(), filePath);
|
|
360
|
+
console.log(
|
|
361
|
+
`\x1B[32m\x1B[1m[Funkophile]\x1B[0m Dispatching UPSERT for key: ${inputRuleKey}, file: ${absoluteFilePath}`
|
|
362
|
+
);
|
|
363
|
+
dispatchUpsert(
|
|
364
|
+
store,
|
|
365
|
+
inputRuleKey,
|
|
366
|
+
absoluteFilePath,
|
|
367
|
+
funkophileConfig.encodings
|
|
368
|
+
);
|
|
369
|
+
}).on("change", (filePath) => {
|
|
370
|
+
console.log(
|
|
371
|
+
`\x1B[33m\x1B[1m[Funkophile]\x1B[0m File changed: ${filePath}`
|
|
372
|
+
);
|
|
373
|
+
logger.watchChange(filePath);
|
|
374
|
+
const absoluteFilePath = path.resolve(process.cwd(), filePath);
|
|
375
|
+
console.log(
|
|
376
|
+
`\x1B[33m\x1B[1m[Funkophile]\x1B[0m Dispatching UPSERT for key: ${inputRuleKey}, file: ${absoluteFilePath}`
|
|
377
|
+
);
|
|
378
|
+
dispatchUpsert(
|
|
379
|
+
store,
|
|
380
|
+
inputRuleKey,
|
|
381
|
+
absoluteFilePath,
|
|
382
|
+
funkophileConfig.encodings
|
|
383
|
+
);
|
|
384
|
+
}).on("unlink", (filePath) => {
|
|
385
|
+
console.log(
|
|
386
|
+
`\x1B[31m\x1B[1m[Funkophile]\x1B[0m File removed: ${filePath}`
|
|
387
|
+
);
|
|
388
|
+
logger.watchUnlink(filePath);
|
|
389
|
+
const absoluteFilePath = path.resolve(process.cwd(), filePath);
|
|
390
|
+
console.log(
|
|
391
|
+
`\x1B[31m\x1B[1m[Funkophile]\x1B[0m Dispatching REMOVE for key: ${inputRuleKey}, file: ${absoluteFilePath}`
|
|
392
|
+
);
|
|
393
|
+
store.dispatch({
|
|
394
|
+
type: REMOVE,
|
|
395
|
+
payload: {
|
|
396
|
+
key: inputRuleKey,
|
|
397
|
+
file: absoluteFilePath
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
}).on("unlinkDir", (filePath) => {
|
|
401
|
+
console.log(
|
|
402
|
+
`\x1B[31m\x1B[1m[Funkophile]\x1B[0m Directory removed: ${filePath}`
|
|
403
|
+
);
|
|
404
|
+
logger.watchUnlink(filePath);
|
|
405
|
+
}).on("raw", (event, path2, details) => {
|
|
406
|
+
console.log(
|
|
407
|
+
`\x1B[90m\x1B[1m[Funkophile]\x1B[0m Raw event: ${event} for path: ${path2}`
|
|
408
|
+
);
|
|
409
|
+
});
|
|
410
|
+
console.log(
|
|
411
|
+
`\x1B[32m\x1B[1m[Funkophile]\x1B[0m Watcher is ready for pattern: ${globPattern}`
|
|
412
|
+
);
|
|
413
|
+
logger.watchReady(globPattern);
|
|
414
|
+
fulfill();
|
|
415
|
+
}).catch((error) => {
|
|
416
|
+
console.error(
|
|
417
|
+
`\x1B[31m\x1B[1m[Funkophile]\x1B[0m Error processing initial files for pattern ${globPattern}:`,
|
|
418
|
+
error
|
|
419
|
+
);
|
|
420
|
+
reject(error);
|
|
329
421
|
});
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
422
|
+
} else {
|
|
423
|
+
console.error(
|
|
424
|
+
`mode should be 'watch' or 'build', not "${funkophileConfig.mode}"`
|
|
425
|
+
);
|
|
426
|
+
process.exit(-1);
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// index.ts
|
|
433
|
+
Promise2.config({
|
|
434
|
+
cancellation: true
|
|
435
|
+
});
|
|
436
|
+
var index_default = (funkophileConfig) => {
|
|
437
|
+
let outputPromise = Promise2.resolve();
|
|
438
|
+
const store = newStore(funkophileConfig);
|
|
439
|
+
const finalSelector = makeFinalSelector(funkophileConfig);
|
|
440
|
+
if (funkophileConfig.mode === "watch") {
|
|
441
|
+
startServing(funkophileConfig);
|
|
442
|
+
}
|
|
443
|
+
Promise2.all(
|
|
444
|
+
makePromissesArray(funkophileConfig, store)
|
|
445
|
+
).then(function() {
|
|
446
|
+
console.log(
|
|
447
|
+
"\x1B[32m\x1B[1m[Funkophile]\x1B[0m All input watchers are ready. Setting up store subscription..."
|
|
448
|
+
);
|
|
449
|
+
store.subscribe(() => {
|
|
450
|
+
const s = store.getState();
|
|
451
|
+
console.log(
|
|
452
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Store updated. initialLoad: ${s.initialLoad}, timestamp: ${s.timestamp}`
|
|
453
|
+
);
|
|
454
|
+
if (s.initialLoad) {
|
|
455
|
+
console.log(
|
|
456
|
+
"\x1B[36m\x1B[1m[Funkophile]\x1B[0m Initial load in progress, skipping processing..."
|
|
457
|
+
);
|
|
458
|
+
console.log(
|
|
459
|
+
"\x1B[36m\x1B[1m[Funkophile]\x1B[0m State keys during initial load:",
|
|
460
|
+
Object.keys(s)
|
|
461
|
+
);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
logger.stateChange();
|
|
465
|
+
console.log(
|
|
466
|
+
"\x1B[36m\x1B[1m[Funkophile]\x1B[0m Processing state changes..."
|
|
467
|
+
);
|
|
468
|
+
console.log(
|
|
469
|
+
"\x1B[36m\x1B[1m[Funkophile]\x1B[0m Current state keys:",
|
|
470
|
+
Object.keys(s)
|
|
471
|
+
);
|
|
472
|
+
let outputs;
|
|
473
|
+
try {
|
|
474
|
+
outputs = finalSelector(s);
|
|
475
|
+
console.log(
|
|
476
|
+
`\x1B[36m\x1B[1m[Funkophile]\x1B[0m Generated ${Object.keys(outputs).length} outputs`
|
|
477
|
+
);
|
|
478
|
+
} catch (error) {
|
|
479
|
+
console.error(
|
|
480
|
+
"\x1B[31m\x1B[1m[Funkophile]\x1B[0m FATAL: Error in output selector chain ? :"
|
|
481
|
+
);
|
|
482
|
+
console.error(" Error:", error.message);
|
|
483
|
+
console.error(" Stack:", error.stack);
|
|
484
|
+
if (funkophileConfig.mode === "build") {
|
|
485
|
+
process.exit(1);
|
|
486
|
+
} else {
|
|
487
|
+
console.log(
|
|
488
|
+
"\x1B[33m\x1B[1m[Funkophile]\x1B[0m Continuing to watch for changes despite error..."
|
|
489
|
+
);
|
|
490
|
+
Object.keys(previousState).forEach((key) => {
|
|
491
|
+
delete previousState[key];
|
|
492
|
+
});
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (outputPromise.isPending()) {
|
|
497
|
+
console.log(
|
|
498
|
+
"\x1B[33m\x1B[1m[Funkophile]\x1B[0m Cancelling previous write operation!"
|
|
499
|
+
);
|
|
500
|
+
outputPromise.cancel();
|
|
501
|
+
}
|
|
502
|
+
outputPromise = Promise2.all(
|
|
503
|
+
Array.from(
|
|
504
|
+
new Set(Object.keys(previousState).concat(Object.keys(outputs)))
|
|
505
|
+
).map((key) => {
|
|
506
|
+
return new Promise2((fulfill, reject) => {
|
|
507
|
+
if (!outputs[key]) {
|
|
508
|
+
const file = funkophileConfig.options.outFolder + "/" + key;
|
|
509
|
+
logger.removedFile(file);
|
|
510
|
+
console.log(
|
|
511
|
+
`\x1B[31m\x1B[1m[Funkophile]\x1B[0m Removing file: ${file}`
|
|
512
|
+
);
|
|
513
|
+
try {
|
|
514
|
+
fse2.unlinkSync("./" + file);
|
|
515
|
+
cleanEmptyFoldersRecursively(
|
|
516
|
+
"./" + file.substring(0, file.lastIndexOf("/"))
|
|
517
|
+
);
|
|
518
|
+
} catch (ex) {
|
|
519
|
+
console.error(
|
|
520
|
+
`\x1B[31m\x1B[1m[Funkophile]\x1B[0m Error removing file ${file}:`,
|
|
521
|
+
ex.message
|
|
522
|
+
);
|
|
523
|
+
} finally {
|
|
524
|
+
delete previousState[key];
|
|
525
|
+
fulfill();
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
if (outputs[key] !== previousState[key]) {
|
|
529
|
+
previousState[key] = outputs[key];
|
|
530
|
+
const relativeFilePath = "./" + funkophileConfig.options.outFolder + "/" + key;
|
|
531
|
+
const contents = outputs[key];
|
|
532
|
+
if (typeof contents === "function") {
|
|
533
|
+
logger.writingFunction(relativeFilePath);
|
|
534
|
+
contents((err, res) => {
|
|
535
|
+
if (err) {
|
|
536
|
+
logger.writingError(relativeFilePath, err.message);
|
|
537
|
+
fulfill();
|
|
538
|
+
} else {
|
|
539
|
+
fse2.outputFile(relativeFilePath, res, (err2) => {
|
|
540
|
+
if (err2) {
|
|
541
|
+
logger.writingError(relativeFilePath, err2.message);
|
|
542
|
+
fulfill();
|
|
543
|
+
} else {
|
|
544
|
+
logger.writingString(relativeFilePath);
|
|
545
|
+
fulfill();
|
|
384
546
|
}
|
|
547
|
+
});
|
|
385
548
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
logger.writingString(relativeFilePath);
|
|
433
|
-
fulfill();
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
else if (Array.isArray(contents)) {
|
|
438
|
-
fse.outputFile(relativeFilePath, JSON.stringify(contents), (err) => {
|
|
439
|
-
if (err) {
|
|
440
|
-
logger.writingError(relativeFilePath, err.message);
|
|
441
|
-
fulfill();
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
logger.writingString(relativeFilePath);
|
|
445
|
-
fulfill();
|
|
446
|
-
}
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
else if (typeof contents.then === "function") {
|
|
450
|
-
logger.writingPromise(relativeFilePath);
|
|
451
|
-
Promise.resolve(contents).then(function (value) {
|
|
452
|
-
if (value instanceof Error) {
|
|
453
|
-
logger.writingError(relativeFilePath, value.message);
|
|
454
|
-
fulfill();
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
fse.outputFile(relativeFilePath, value, (err) => {
|
|
458
|
-
if (err) {
|
|
459
|
-
logger.writingError(relativeFilePath, err.message);
|
|
460
|
-
fulfill();
|
|
461
|
-
}
|
|
462
|
-
else {
|
|
463
|
-
logger.writingString(relativeFilePath);
|
|
464
|
-
fulfill();
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
}, function (error) {
|
|
469
|
-
logger.writingError(relativeFilePath, error.message);
|
|
470
|
-
fulfill();
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
else {
|
|
474
|
-
console.log(`\u001b[33m\u001b[1m[Funkophile]\u001b[0m Unrecognized content type for ${relativeFilePath}, attempting to write:`, typeof contents);
|
|
475
|
-
fse.outputFile(relativeFilePath, contents, (err) => {
|
|
476
|
-
if (err) {
|
|
477
|
-
logger.writingError(relativeFilePath, err.message);
|
|
478
|
-
fulfill();
|
|
479
|
-
}
|
|
480
|
-
else {
|
|
481
|
-
logger.writingString(relativeFilePath);
|
|
482
|
-
fulfill();
|
|
483
|
-
}
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
else {
|
|
488
|
-
// console.log(`\u001b[90m\u001b[1m[Funkophile]\u001b[0m Skipping unchanged file: ${key}`);
|
|
549
|
+
});
|
|
550
|
+
} else if (typeof contents === "string") {
|
|
551
|
+
fse2.outputFile(relativeFilePath, contents, (err) => {
|
|
552
|
+
if (err) {
|
|
553
|
+
logger.writingError(relativeFilePath, err.message);
|
|
554
|
+
fulfill();
|
|
555
|
+
} else {
|
|
556
|
+
logger.writingString(relativeFilePath);
|
|
557
|
+
fulfill();
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
} else if (Buffer.isBuffer(contents)) {
|
|
561
|
+
fse2.outputFile(relativeFilePath, contents, (err) => {
|
|
562
|
+
if (err) {
|
|
563
|
+
logger.writingError(relativeFilePath, err.message);
|
|
564
|
+
fulfill();
|
|
565
|
+
} else {
|
|
566
|
+
logger.writingString(relativeFilePath);
|
|
567
|
+
fulfill();
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
} else if (Array.isArray(contents)) {
|
|
571
|
+
fse2.outputFile(
|
|
572
|
+
relativeFilePath,
|
|
573
|
+
JSON.stringify(contents),
|
|
574
|
+
(err) => {
|
|
575
|
+
if (err) {
|
|
576
|
+
logger.writingError(relativeFilePath, err.message);
|
|
577
|
+
fulfill();
|
|
578
|
+
} else {
|
|
579
|
+
logger.writingString(relativeFilePath);
|
|
580
|
+
fulfill();
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
);
|
|
584
|
+
} else if (typeof contents.then === "function") {
|
|
585
|
+
logger.writingPromise(relativeFilePath);
|
|
586
|
+
Promise2.resolve(contents).then(
|
|
587
|
+
function(value) {
|
|
588
|
+
if (value instanceof Error) {
|
|
589
|
+
logger.writingError(relativeFilePath, value.message);
|
|
590
|
+
fulfill();
|
|
591
|
+
} else {
|
|
592
|
+
fse2.outputFile(relativeFilePath, value, (err) => {
|
|
593
|
+
if (err) {
|
|
594
|
+
logger.writingError(relativeFilePath, err.message);
|
|
489
595
|
fulfill();
|
|
490
|
-
|
|
596
|
+
} else {
|
|
597
|
+
logger.writingString(relativeFilePath);
|
|
598
|
+
fulfill();
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
},
|
|
603
|
+
function(error) {
|
|
604
|
+
logger.writingError(relativeFilePath, error.message);
|
|
605
|
+
fulfill();
|
|
491
606
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
else {
|
|
508
|
-
throw (`\u001b[31m\u001b[1m[Funkophile]\u001b[0m The mode should be 'watch' or 'build', not "${funkophileConfig.mode}"`);
|
|
607
|
+
);
|
|
608
|
+
} else {
|
|
609
|
+
console.log(
|
|
610
|
+
`\x1B[33m\x1B[1m[Funkophile]\x1B[0m Unrecognized content type for ${relativeFilePath}, attempting to write:`,
|
|
611
|
+
typeof contents
|
|
612
|
+
);
|
|
613
|
+
fse2.outputFile(relativeFilePath, contents, (err) => {
|
|
614
|
+
if (err) {
|
|
615
|
+
logger.writingError(relativeFilePath, err.message);
|
|
616
|
+
fulfill();
|
|
617
|
+
} else {
|
|
618
|
+
logger.writingString(relativeFilePath);
|
|
619
|
+
fulfill();
|
|
620
|
+
}
|
|
621
|
+
});
|
|
509
622
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
payload: true,
|
|
521
|
-
});
|
|
522
|
-
// console.log('\u001b[36m\u001b[1m[Funkophile]\u001b[0m Store initialized. Starting processing...');
|
|
523
|
-
});
|
|
524
|
-
// Handle process exit to close the server
|
|
525
|
-
process.on('SIGINT', () => {
|
|
526
|
-
if (server) {
|
|
527
|
-
server.close();
|
|
528
|
-
}
|
|
529
|
-
process.exit(0);
|
|
623
|
+
} else {
|
|
624
|
+
fulfill();
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
})
|
|
629
|
+
).then(() => {
|
|
630
|
+
cleanEmptyFoldersRecursively(funkophileConfig.options.outFolder);
|
|
631
|
+
logDone(funkophileConfig, currentState);
|
|
632
|
+
});
|
|
530
633
|
});
|
|
634
|
+
console.log(
|
|
635
|
+
"\x1B[32m\x1B[1m[Funkophile]\x1B[0m Dispatching INITIALIZE action to enable processing..."
|
|
636
|
+
);
|
|
637
|
+
const currentState = store.getState();
|
|
638
|
+
console.log(
|
|
639
|
+
"\x1B[36m\x1B[1m[Funkophile]\x1B[0m Current state keys:",
|
|
640
|
+
Object.keys(currentState)
|
|
641
|
+
);
|
|
642
|
+
logInputKeys(funkophileConfig, currentState);
|
|
643
|
+
setTimeout(() => {
|
|
644
|
+
store.dispatch({
|
|
645
|
+
type: INITIALIZE,
|
|
646
|
+
payload: true
|
|
647
|
+
});
|
|
648
|
+
console.log(
|
|
649
|
+
"\x1B[32m\x1B[1m[Funkophile]\x1B[0m Store initialized. Ready to process changes!"
|
|
650
|
+
);
|
|
651
|
+
}, 100);
|
|
652
|
+
});
|
|
653
|
+
};
|
|
654
|
+
export {
|
|
655
|
+
index_default as default
|
|
531
656
|
};
|
|
657
|
+
//# sourceMappingURL=index.js.map
|