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 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
- - [ ] Rename jobs and paths
12
- - [ ] Better dependency tracking
13
- - [ ] Better query filters
14
- - [x] File deletion handling
7
+ - [ ] Destination query filters
15
8
 
16
- ## Project: Jobs
9
+ ## Helpers
17
10
 
18
- 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.
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} 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
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, targets?: Target[] }}
106
+ * @returns {{ jobs?: Jobs, destinations?: Destination[] }}
133
107
  */
134
108
 
135
109
  /**
136
- * @typedef {object} Target
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 {RouteInfo} path
180
- * @returns {Partial<RouteInfo> | path.ParsedPath | false}
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
- sourceTime()
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
- // Process source file abstracts and map jobs
239
- const { abstractsJobs } = readAbstracts(sources, config, database, processors)
200
+ // Process source file abstracts and map jobs
201
+ const { abstractsJobs } = readAbstracts(sources, config, database, processors)
240
202
 
241
- // Scan folders and map out jobs
242
- const foldersJobs = readFolders(folders, config, database, processors) || []
203
+ // Scan folders and map out jobs
204
+ const foldersJobs = readFolders(folders, config, database, processors) || []
243
205
 
244
- const writeTime = stopwatch("build", "wrote files in", config.verbose)
245
- // Write destination files
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
- // await runJobs([
256
- // ...sourcesJobs,
257
- // ...abstractsJobs,
258
- // ...foldersJobs
259
- // ], config, database)
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