votive 0.0.8 → 0.1.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 -5
- package/lib/bundle.js +121 -55
- package/lib/createDatabase.js +895 -450
- package/lib/readAbstracts.js +12 -9
- package/lib/readBuffers.js +10 -10
- package/lib/readFilePaths.js +12 -12
- package/lib/readFolders.js +10 -17
- package/lib/readSources.js +107 -55
- package/lib/runJobs.js +1 -3
- package/lib/sqlite.js +12 -14
- package/lib/utils/index.js +8 -4
- package/lib/writeDestinations.js +23 -18
- package/package.json +2 -1
- package/tests/index.js +303 -263
- package/tests/markdown/prunee.md +1 -0
- package/tests/.votive.db +0 -0
package/README.md
CHANGED
|
@@ -7,12 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
## Roadmap
|
|
9
9
|
|
|
10
|
-
- [ ] ReadPaths
|
|
11
10
|
- [ ] Flesh out job runners
|
|
12
|
-
- [x] Destination query filters
|
|
13
|
-
- [x] Setters for metadata
|
|
14
11
|
- [ ] Rename jobs and paths
|
|
12
|
+
- [ ] Better dependency tracking
|
|
13
|
+
- [ ] Better query filters
|
|
15
14
|
|
|
16
|
-
##
|
|
15
|
+
## Project: Jobs
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
Jobs was originally a generic concept, but after working it's clear that there are two main categories of jobs: async writes and data fetching. We can probably handle async writes with inbuilt logic. So, instead of a "job", we should have "read uri"? That way we can cache all the uris.
|
package/lib/bundle.js
CHANGED
|
@@ -5,9 +5,10 @@ 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"
|
|
8
10
|
|
|
9
11
|
/** @import {Database} from "./createDatabase.js" */
|
|
10
|
-
/** @import {ParsedPath} from "node:path" */
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @typedef {object} VotivePlugin
|
|
@@ -18,17 +19,40 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
18
19
|
*/
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
|
-
* @typedef {object}
|
|
22
|
-
* @property {
|
|
23
|
-
* @property {
|
|
24
|
-
* @property {
|
|
25
|
-
* @property {
|
|
22
|
+
* @typedef {object} VotiveProcessorCommon
|
|
23
|
+
* @property {string[]} extensions
|
|
24
|
+
* @property {ReadResource} [readResource]
|
|
25
|
+
* @property {ProcessorWrite} [writeFile]
|
|
26
|
+
* @property {ReadFolder} [readFolder]
|
|
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
|
|
26
50
|
*/
|
|
27
51
|
|
|
28
52
|
/**
|
|
29
53
|
* Filter for files that the processor will read from.
|
|
30
54
|
* @typedef {object} ProcessorFilter
|
|
31
|
-
* @property {string
|
|
55
|
+
* @property {string} extensions
|
|
32
56
|
*/
|
|
33
57
|
|
|
34
58
|
/**
|
|
@@ -39,7 +63,6 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
39
63
|
/**
|
|
40
64
|
* @typedef {object} ProcessorRead
|
|
41
65
|
* @property {ReadPath} [path]
|
|
42
|
-
* @property {ReadURL} [url]
|
|
43
66
|
* @property {ReadText} [text]
|
|
44
67
|
* @property {ReadAbstract} [abstract]
|
|
45
68
|
* @property {ReadFolder} [folder]
|
|
@@ -51,14 +74,7 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
51
74
|
* @param {string} filePath
|
|
52
75
|
* @param {Database} database
|
|
53
76
|
* @param {VotiveConfig} config
|
|
54
|
-
* @returns {
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Reads a the response from a URL and returns arbitrary data.
|
|
59
|
-
* @callback ReadURL
|
|
60
|
-
* @param {Response} response
|
|
61
|
-
* @returns {object}
|
|
77
|
+
* @returns {Job[] | undefined}
|
|
62
78
|
*/
|
|
63
79
|
|
|
64
80
|
/**
|
|
@@ -68,14 +84,14 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
68
84
|
* @param {string} destinationPath
|
|
69
85
|
* @param {Database} database
|
|
70
86
|
* @param {VotiveConfig} config
|
|
71
|
-
* @returns {ReadTextResult}
|
|
87
|
+
* @returns {ReadTextResult | undefined}
|
|
72
88
|
*/
|
|
73
89
|
|
|
74
90
|
/**
|
|
75
91
|
* @typedef {object} ReadTextResult
|
|
76
92
|
* @property {Jobs} [jobs]
|
|
77
|
-
* @property {object} metadata
|
|
78
|
-
* @property {Abstract} abstract
|
|
93
|
+
* @property {object} [metadata]
|
|
94
|
+
* @property {Abstract} [abstract]
|
|
79
95
|
*/
|
|
80
96
|
|
|
81
97
|
/**
|
|
@@ -110,15 +126,14 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
110
126
|
|
|
111
127
|
/**
|
|
112
128
|
* @callback ReadFolder
|
|
113
|
-
* @param {object}
|
|
129
|
+
* @param {object} Folder
|
|
114
130
|
* @param {Database} database
|
|
115
131
|
* @param {VotiveConfig} config
|
|
116
|
-
* @
|
|
117
|
-
* @returns {{ jobs?: Jobs, destinations?: Destination[] }}
|
|
132
|
+
* @returns {{ jobs?: Jobs, targets?: Target[] }}
|
|
118
133
|
*/
|
|
119
134
|
|
|
120
135
|
/**
|
|
121
|
-
* @typedef {object}
|
|
136
|
+
* @typedef {object} Target
|
|
122
137
|
* @property {string} path
|
|
123
138
|
* @property {object} metadata
|
|
124
139
|
* @property {Abstract} abstract
|
|
@@ -136,7 +151,7 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
136
151
|
* @param {object} destination
|
|
137
152
|
* @param {Database} database
|
|
138
153
|
* @param {VotiveConfig} config
|
|
139
|
-
* @returns {{ data: string,
|
|
154
|
+
* @returns {{ data: string, encoding?: BufferEncoding = 'utf-8' }}
|
|
140
155
|
*/
|
|
141
156
|
|
|
142
157
|
/**
|
|
@@ -151,22 +166,18 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
151
166
|
* Run a job.
|
|
152
167
|
* @typedef {object} Job
|
|
153
168
|
* @property {object} data
|
|
154
|
-
* @property {
|
|
155
|
-
* @property {string} [
|
|
169
|
+
* @property {string} runner
|
|
170
|
+
* @property {string} [plugin]
|
|
156
171
|
*/
|
|
157
172
|
|
|
158
173
|
/**
|
|
159
|
-
* @typedef {
|
|
160
|
-
* @property {string[]} dir
|
|
161
|
-
* @property {ParsedPath["name"]} name
|
|
162
|
-
* @property {ParsedPath["ext"]} ext
|
|
163
|
-
* @property {boolean} [inRootDir]
|
|
174
|
+
* @typedef {(Pick<path.ParsedPath, "root" | "base" | "ext" | "name") & { dir: string[] | string }} RouteInfo
|
|
164
175
|
*/
|
|
165
176
|
|
|
166
177
|
/**
|
|
167
178
|
* @callback Router
|
|
168
|
-
* @param {
|
|
169
|
-
* @returns {
|
|
179
|
+
* @param {RouteInfo} path
|
|
180
|
+
* @returns {Partial<RouteInfo> | path.ParsedPath | false}
|
|
170
181
|
*/
|
|
171
182
|
|
|
172
183
|
/**
|
|
@@ -174,6 +185,7 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
174
185
|
* @property {string} sourceFolder
|
|
175
186
|
* @property {string} destinationFolder
|
|
176
187
|
* @property {VotivePlugin[]} plugins
|
|
188
|
+
* @property {boolean} verbose
|
|
177
189
|
*/
|
|
178
190
|
|
|
179
191
|
/**
|
|
@@ -191,13 +203,11 @@ import { default as createDatabase } from "./createDatabase.js"
|
|
|
191
203
|
* @param {Database | undefined} [cache]
|
|
192
204
|
*/
|
|
193
205
|
async function bundle(config, cache) {
|
|
194
|
-
// TODO: Ensure all cached destinations exist as expected
|
|
195
206
|
|
|
196
207
|
// Map out all processors
|
|
197
208
|
const processors = config.plugins
|
|
198
209
|
&& config.plugins.flatMap(plugin => plugin.processors && plugin.processors.map(processor => ({ plugin, processor })))
|
|
199
210
|
|
|
200
|
-
// Create database
|
|
201
211
|
const database = cache || createDatabase(path.join(config.sourceFolder, ".votive.db"))
|
|
202
212
|
|
|
203
213
|
/*
|
|
@@ -211,38 +221,94 @@ async function bundle(config, cache) {
|
|
|
211
221
|
even out.
|
|
212
222
|
*/
|
|
213
223
|
|
|
224
|
+
// database.begin()
|
|
225
|
+
|
|
226
|
+
const sourceTime = stopwatch("build", "read sources in", config.verbose)
|
|
214
227
|
// Read folders and source files
|
|
215
228
|
const { folders, sources } = await readSources(config, database, processors)
|
|
216
229
|
|
|
217
|
-
|
|
218
|
-
const sourcesJobs = sources.flatMap(source => source.jobs) || []
|
|
230
|
+
sourceTime()
|
|
219
231
|
|
|
220
|
-
|
|
221
|
-
const { abstractsJobs } = readAbstracts(sources, config, database, processors)
|
|
232
|
+
if(config.verbose) console.info(`${styleText("dim", "build:")} ${styleText("magenta", `found ${sources.length} stale files`)}`)
|
|
222
233
|
|
|
223
|
-
|
|
224
|
-
|
|
234
|
+
if (sources.length) {
|
|
235
|
+
// Map out jobs from source files
|
|
236
|
+
const sourcesJobs = sources.flatMap(source => source.jobs) || []
|
|
225
237
|
|
|
226
|
-
|
|
227
|
-
|
|
238
|
+
// Process source file abstracts and map jobs
|
|
239
|
+
const { abstractsJobs } = readAbstracts(sources, config, database, processors)
|
|
228
240
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
...sourcesJobs,
|
|
232
|
-
...abstractsJobs,
|
|
233
|
-
...foldersJobs
|
|
234
|
-
], config, database)
|
|
241
|
+
// Scan folders and map out jobs
|
|
242
|
+
const foldersJobs = readFolders(folders, config, database, processors) || []
|
|
235
243
|
|
|
244
|
+
const writeTime = stopwatch("build", "wrote files in", config.verbose)
|
|
245
|
+
// Write destination files
|
|
246
|
+
await writeDestinations(config, database)
|
|
236
247
|
|
|
237
|
-
|
|
248
|
+
writeTime()
|
|
238
249
|
|
|
239
|
-
|
|
240
|
-
await database.saveDB()
|
|
250
|
+
// database.commit()
|
|
241
251
|
|
|
242
|
-
|
|
243
|
-
|
|
252
|
+
await database.saveDB(sources)
|
|
253
|
+
}
|
|
254
|
+
// Run all jobs
|
|
255
|
+
// await runJobs([
|
|
256
|
+
// ...sourcesJobs,
|
|
257
|
+
// ...abstractsJobs,
|
|
258
|
+
// ...foldersJobs
|
|
259
|
+
// ], config, database)
|
|
260
|
+
|
|
261
|
+
// Back up database (only if in-memory first run)
|
|
244
262
|
|
|
245
263
|
return database
|
|
246
264
|
}
|
|
247
265
|
|
|
248
|
-
|
|
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
|