votive 0.2.1 → 0.3.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/README.md +4 -11
- package/lib/bundle.js +26 -118
- package/lib/cleanDeletions.js +32 -0
- package/lib/createDatabase.js +373 -931
- package/lib/readAbstracts.js +9 -12
- package/lib/readFolders.js +15 -18
- package/lib/readSources.js +41 -168
- package/lib/runJobs.js +8 -26
- package/lib/utils/index.js +5 -13
- package/lib/writeDestinations.js +11 -31
- package/package.json +1 -2
- package/tests/index.js +245 -302
package/README.md
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
# Votive
|
|
2
2
|
|
|
3
|
-
*File processor*
|
|
4
|
-
|
|
5
|
-
- Powers [Voot](https://github.com/samlfair/voot)
|
|
6
|
-
- Bundles [Vowel](https://github.com/samlfair/vowel)
|
|
7
|
-
|
|
8
3
|
## Roadmap
|
|
9
4
|
|
|
5
|
+
- [ ] ReadPaths
|
|
10
6
|
- [ ] Flesh out job runners
|
|
11
|
-
- [ ]
|
|
12
|
-
- [ ] Better dependency tracking
|
|
13
|
-
- [ ] Better query filters
|
|
14
|
-
- [x] File deletion handling
|
|
7
|
+
- [ ] Destination query filters
|
|
15
8
|
|
|
16
|
-
##
|
|
9
|
+
## Helpers
|
|
17
10
|
|
|
18
|
-
|
|
11
|
+
- Read
|
package/lib/bundle.js
CHANGED
|
@@ -5,8 +5,6 @@ import readSources from "./readSources.js"
|
|
|
5
5
|
import runJobs from "./runJobs.js"
|
|
6
6
|
import writeDestinations from "./writeDestinations.js"
|
|
7
7
|
import { default as createDatabase } from "./createDatabase.js"
|
|
8
|
-
import { stopwatch } from "./utils/index.js"
|
|
9
|
-
import { styleText } from "node:util"
|
|
10
8
|
|
|
11
9
|
/** @import {Database} from "./createDatabase.js" */
|
|
12
10
|
|
|
@@ -19,40 +17,17 @@ import { styleText } from "node:util"
|
|
|
19
17
|
*/
|
|
20
18
|
|
|
21
19
|
/**
|
|
22
|
-
* @typedef {object}
|
|
23
|
-
* @property {
|
|
24
|
-
* @property {
|
|
25
|
-
* @property {
|
|
26
|
-
* @property {
|
|
27
|
-
* @property {ReadAbstract} [transformFile]
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @typedef {VotiveProcessorCommon & {
|
|
32
|
-
* format: "buffer",
|
|
33
|
-
* readFile: ReadPath | undefined
|
|
34
|
-
* }} VotiveProcessorBuffer
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @typedef {VotiveProcessorCommon & {
|
|
39
|
-
* format: "text",
|
|
40
|
-
* readFile: ReadText | undefined
|
|
41
|
-
* }} VotiveProcessorText
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @typedef {VotiveProcessorBuffer | VotiveProcessorText} VotiveProcessor
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @typedef {object} ReadResource
|
|
20
|
+
* @typedef {object} VotiveProcessor
|
|
21
|
+
* @property {ProcessorFilter} [filter]
|
|
22
|
+
* @property {ProcessorSyntax} syntax
|
|
23
|
+
* @property {ProcessorRead} [read]
|
|
24
|
+
* @property {ProcessorWrite} [write]
|
|
50
25
|
*/
|
|
51
26
|
|
|
52
27
|
/**
|
|
53
28
|
* Filter for files that the processor will read from.
|
|
54
29
|
* @typedef {object} ProcessorFilter
|
|
55
|
-
* @property {string} extensions
|
|
30
|
+
* @property {string[]} extensions
|
|
56
31
|
*/
|
|
57
32
|
|
|
58
33
|
/**
|
|
@@ -81,7 +56,6 @@ import { styleText } from "node:util"
|
|
|
81
56
|
* @callback ReadText
|
|
82
57
|
* @param {string} text
|
|
83
58
|
* @param {string} filePath
|
|
84
|
-
* @param {string} destinationPath
|
|
85
59
|
* @param {Database} database
|
|
86
60
|
* @param {VotiveConfig} config
|
|
87
61
|
* @returns {ReadTextResult | undefined}
|
|
@@ -129,11 +103,11 @@ import { styleText } from "node:util"
|
|
|
129
103
|
* @param {object} Folder
|
|
130
104
|
* @param {Database} database
|
|
131
105
|
* @param {VotiveConfig} config
|
|
132
|
-
* @returns {{ jobs?: Jobs,
|
|
106
|
+
* @returns {{ jobs?: Jobs, destinations?: Destination[] }}
|
|
133
107
|
*/
|
|
134
108
|
|
|
135
109
|
/**
|
|
136
|
-
* @typedef {object}
|
|
110
|
+
* @typedef {object} Destination
|
|
137
111
|
* @property {string} path
|
|
138
112
|
* @property {object} metadata
|
|
139
113
|
* @property {Abstract} abstract
|
|
@@ -170,14 +144,10 @@ import { styleText } from "node:util"
|
|
|
170
144
|
* @property {string} [plugin]
|
|
171
145
|
*/
|
|
172
146
|
|
|
173
|
-
/**
|
|
174
|
-
* @typedef {(Pick<path.ParsedPath, "root" | "base" | "ext" | "name") & { dir: string[] | string }} RouteInfo
|
|
175
|
-
*/
|
|
176
|
-
|
|
177
147
|
/**
|
|
178
148
|
* @callback Router
|
|
179
|
-
* @param {
|
|
180
|
-
* @returns {
|
|
149
|
+
* @param {string} path
|
|
150
|
+
* @returns {string | false | undefined}
|
|
181
151
|
*/
|
|
182
152
|
|
|
183
153
|
/**
|
|
@@ -185,7 +155,6 @@ import { styleText } from "node:util"
|
|
|
185
155
|
* @property {string} sourceFolder
|
|
186
156
|
* @property {string} destinationFolder
|
|
187
157
|
* @property {VotivePlugin[]} plugins
|
|
188
|
-
* @property {boolean} verbose
|
|
189
158
|
*/
|
|
190
159
|
|
|
191
160
|
/**
|
|
@@ -208,6 +177,7 @@ async function bundle(config, cache) {
|
|
|
208
177
|
const processors = config.plugins
|
|
209
178
|
&& config.plugins.flatMap(plugin => plugin.processors && plugin.processors.map(processor => ({ plugin, processor })))
|
|
210
179
|
|
|
180
|
+
// Create database
|
|
211
181
|
const database = cache || createDatabase(path.join(config.sourceFolder, ".votive.db"))
|
|
212
182
|
|
|
213
183
|
/*
|
|
@@ -221,94 +191,32 @@ async function bundle(config, cache) {
|
|
|
221
191
|
even out.
|
|
222
192
|
*/
|
|
223
193
|
|
|
224
|
-
// database.begin()
|
|
225
|
-
|
|
226
|
-
const sourceTime = stopwatch("build", "read sources in", config.verbose)
|
|
227
194
|
// Read folders and source files
|
|
228
195
|
const { folders, sources } = await readSources(config, database, processors)
|
|
229
196
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if(config.verbose) console.info(`${styleText("dim", "build:")} ${styleText("magenta", `found ${sources.length} stale files`)}`)
|
|
233
|
-
|
|
234
|
-
if (sources.length) {
|
|
235
|
-
// Map out jobs from source files
|
|
236
|
-
const sourcesJobs = sources.flatMap(source => source.jobs) || []
|
|
197
|
+
// Map out jobs from source files
|
|
198
|
+
const sourcesJobs = sources.flatMap(source => source.jobs) || []
|
|
237
199
|
|
|
238
|
-
|
|
239
|
-
|
|
200
|
+
// Process source file abstracts and map jobs
|
|
201
|
+
const { abstractsJobs } = readAbstracts(sources, config, database, processors)
|
|
240
202
|
|
|
241
|
-
|
|
242
|
-
|
|
203
|
+
// Scan folders and map out jobs
|
|
204
|
+
const foldersJobs = readFolders(folders, config, database, processors) || []
|
|
243
205
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
await writeDestinations(config, database)
|
|
206
|
+
// Write destination files
|
|
207
|
+
await writeDestinations(config, database)
|
|
247
208
|
|
|
248
|
-
writeTime()
|
|
249
|
-
|
|
250
|
-
// database.commit()
|
|
251
|
-
|
|
252
|
-
await database.saveDB(sources)
|
|
253
|
-
}
|
|
254
209
|
// Run all jobs
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
210
|
+
await runJobs([
|
|
211
|
+
...sourcesJobs,
|
|
212
|
+
...abstractsJobs,
|
|
213
|
+
...foldersJobs
|
|
214
|
+
], config, database)
|
|
260
215
|
|
|
261
216
|
// Back up database (only if in-memory first run)
|
|
217
|
+
await database.saveDB()
|
|
262
218
|
|
|
263
219
|
return database
|
|
264
220
|
}
|
|
265
221
|
|
|
266
|
-
|
|
267
|
-
* @param {VotiveConfig} config
|
|
268
|
-
*/
|
|
269
|
-
async function bundler(config) {
|
|
270
|
-
let queue = []
|
|
271
|
-
let cache
|
|
272
|
-
|
|
273
|
-
async function step() {
|
|
274
|
-
if (queue.length === 0) {
|
|
275
|
-
if(config.verbose) console.info(`${styleText("dim", "build:")} ${styleText("magenta", "starting build")}`)
|
|
276
|
-
/*
|
|
277
|
-
If queue is empty, bundle.
|
|
278
|
-
*/
|
|
279
|
-
if (!cache) {
|
|
280
|
-
queue.push(bundle(config))
|
|
281
|
-
cache = await queue[0]
|
|
282
|
-
} else {
|
|
283
|
-
"cache"
|
|
284
|
-
queue.push(bundle(config, cache))
|
|
285
|
-
await queue[0]
|
|
286
|
-
}
|
|
287
|
-
queue.shift()
|
|
288
|
-
return cache
|
|
289
|
-
} else if (queue.length === 1) {
|
|
290
|
-
/*
|
|
291
|
-
If currently bundling, prepare another
|
|
292
|
-
bundle as cleanup.
|
|
293
|
-
*/
|
|
294
|
-
if(config.verbose) console.info(`${styleText("dim", "build:")} ${styleText("magenta", "queueing build")}`)
|
|
295
|
-
|
|
296
|
-
let bundling
|
|
297
|
-
queue.push(bundling)
|
|
298
|
-
bundling = await bundle(config, cache)
|
|
299
|
-
queue.shift()
|
|
300
|
-
return cache
|
|
301
|
-
} else {
|
|
302
|
-
/*
|
|
303
|
-
If cleanup is already queued, do nothing.
|
|
304
|
-
*/
|
|
305
|
-
if(config.verbose) console.info(`${styleText("dim", "build:")} ${styleText("magenta", "already queued")}`)
|
|
306
|
-
await Promise.all(queue)
|
|
307
|
-
return cache
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
return step
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
export default bundler
|
|
222
|
+
export default bundle
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readdir, rm } from "node:fs/promises"
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
|
|
4
|
+
/** @import {Abstract, Abstracts, VotiveConfig} from "./bundle.js" */
|
|
5
|
+
/** @import {Database} from "./createDatabase.js" */
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {VotiveConfig} config
|
|
10
|
+
* @param {Database} database
|
|
11
|
+
*/
|
|
12
|
+
async function cleanDeletions(config, database) {
|
|
13
|
+
// Must remove from sources first??
|
|
14
|
+
const dirents = new Set((await readdir(config.destinationFolder, {
|
|
15
|
+
recursive: true,
|
|
16
|
+
withFileTypes: true
|
|
17
|
+
})).map(d => d.isFile() && path.relative(config.destinationFolder, path.join(d.parentPath, d.name)))
|
|
18
|
+
.filter(a => a)
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const targets = new Set(database.target.getAll().map(t => t.path))
|
|
22
|
+
|
|
23
|
+
const deletions = dirents.difference(targets)
|
|
24
|
+
|
|
25
|
+
deletions.forEach(async deletion => {
|
|
26
|
+
const deletionPath = path.join(config.destinationFolder, deletion)
|
|
27
|
+
await rm(deletionPath)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default cleanDeletions
|