|
1 | | -import { FileFinder } from "./util.js"; |
2 | | -import { readFile, stat } from "node:fs/promises"; |
| 1 | +import { buildProcessPipeline } from "./util.js"; |
| 2 | +import { readFile } from "node:fs/promises"; |
3 | 3 | import * as path from "node:path"; |
4 | 4 |
|
5 | 5 | export const key = "static"; |
6 | 6 | export const bucket = "static"; |
7 | 7 |
|
8 | 8 | /** @type FaucetPlugin<Config> */ |
9 | | -export function plugin(config, assetManager, { compact } = {}) { |
10 | | - let copiers = config.map(copyConfig => |
11 | | - makeCopier(copyConfig, assetManager, { compact })); |
| 9 | +export function plugin(config, assetManager, options) { |
| 10 | + let pipeline = config.map(copyConfig => { |
| 11 | + let processFile = buildProcessFile(copyConfig, options); |
| 12 | + let { source, target, filter } = copyConfig; |
| 13 | + return buildProcessPipeline(source, target, processFile, assetManager, filter); |
| 14 | + }); |
12 | 15 |
|
13 | | - return filepaths => Promise.all(copiers.map(copy => copy(filepaths))); |
| 16 | + return filepaths => Promise.all(pipeline.map(copy => copy(filepaths))); |
14 | 17 | } |
15 | 18 |
|
16 | 19 | /** |
17 | | - * Create a copier for a single configuration |
| 20 | + * Returns a function that copies a single file with optional compactor |
18 | 21 | * |
19 | 22 | * @param {Config} copyConfig |
20 | | - * @param {AssetManager} assetManager |
21 | 23 | * @param {FaucetPluginOptions} options |
22 | | - * @returns {FaucetPluginFunc} |
| 24 | + * @returns {ProcessFile} |
23 | 25 | */ |
24 | | -function makeCopier(copyConfig, assetManager, { compact } = {}) { |
25 | | - let source = assetManager.resolvePath(copyConfig.source); |
26 | | - let target = assetManager.resolvePath(copyConfig.target, { |
27 | | - enforceRelative: true |
28 | | - }); |
29 | | - let fileFinder = new FileFinder(source, { |
30 | | - skipDotfiles: true, |
31 | | - filter: copyConfig.filter |
32 | | - }); |
33 | | - let { fingerprint } = copyConfig; |
34 | | - let compactors = (compact && copyConfig.compact) || {}; |
| 26 | +function buildProcessFile(copyConfig, options) { |
| 27 | + let compactors = (options.compact && copyConfig.compact) || {}; |
35 | 28 |
|
36 | | - return async filepaths => { |
37 | | - let [filenames, targetDir] = await Promise.all([ |
38 | | - (filepaths ? fileFinder.match(filepaths) : fileFinder.all()), |
39 | | - determineTargetDir(source, target) |
40 | | - ]); |
| 29 | + return async function(filename, |
| 30 | + { source, target, targetDir, assetManager }) { |
| 31 | + let sourcePath = path.join(source, filename); |
| 32 | + let targetPath = path.join(target, filename); |
| 33 | + let content; |
41 | 34 |
|
42 | | - return Promise.all(filenames.map(filename => processFile(filename, { |
43 | | - assetManager, source, target, targetDir, compactors, fingerprint |
44 | | - }))); |
45 | | - }; |
46 | | -} |
47 | | - |
48 | | -/** |
49 | | - * If `source` is a directory, `target` is used as target directory - |
50 | | - * otherwise, `target`'s parent directory is used |
51 | | - * |
52 | | - * @param {string} source |
53 | | - * @param {string} target |
54 | | - * @returns {Promise<string>} |
55 | | - */ |
56 | | -async function determineTargetDir(source, target) { |
57 | | - let results = await stat(source); |
58 | | - return results.isDirectory() ? target : path.dirname(target); |
59 | | -} |
60 | | - |
61 | | -/** |
62 | | - * @param {string} filename |
63 | | - * @param {ProcessFile} opts |
64 | | - * @returns {Promise<unknown>} |
65 | | - */ |
66 | | -async function processFile(filename, |
67 | | - { source, target, targetDir, fingerprint, assetManager, compactors }) { |
68 | | - let sourcePath = path.join(source, filename); |
69 | | - let targetPath = path.join(target, filename); |
70 | | - |
71 | | - try { |
72 | | - var content = await readFile(sourcePath); // eslint-disable-line no-var |
73 | | - } catch(err) { |
74 | | - // @ts-expect-error TS2345 |
75 | | - if(err.code !== "ENOENT") { |
76 | | - throw err; |
| 35 | + try { |
| 36 | + content = await readFile(sourcePath); |
| 37 | + } catch(err) { |
| 38 | + // @ts-expect-error TS2345 |
| 39 | + if(err.code !== "ENOENT") { |
| 40 | + throw err; |
| 41 | + } |
| 42 | + console.error(`WARNING: \`${sourcePath}\` no longer exists`); |
| 43 | + return; |
77 | 44 | } |
78 | | - console.error(`WARNING: \`${sourcePath}\` no longer exists`); |
79 | | - return; |
80 | | - } |
81 | 45 |
|
82 | | - let fileExtension = path.extname(sourcePath).substr(1).toLowerCase(); |
83 | | - if(fileExtension && compactors[fileExtension]) { |
84 | | - let compactor = compactors[fileExtension]; |
85 | | - content = await compactor(content); |
86 | | - } |
| 46 | + let fileExtension = path.extname(sourcePath).substr(1).toLowerCase(); |
| 47 | + if(fileExtension && compactors[fileExtension]) { |
| 48 | + let compactor = compactors[fileExtension]; |
| 49 | + content = await compactor(content); |
| 50 | + } |
87 | 51 |
|
88 | | - /** @type WriteFileOpts */ |
89 | | - let options = { targetDir }; |
90 | | - if(fingerprint !== undefined) { |
91 | | - options.fingerprint = fingerprint; |
92 | | - } |
93 | | - return assetManager.writeFile(targetPath, content, options); |
| 52 | + /** @type WriteFileOpts */ |
| 53 | + let options = { targetDir }; |
| 54 | + if(copyConfig.fingerprint !== undefined) { |
| 55 | + options.fingerprint = copyConfig.fingerprint; |
| 56 | + } |
| 57 | + return assetManager.writeFile(targetPath, content, options); |
| 58 | + }; |
94 | 59 | } |
95 | 60 |
|
96 | 61 | /** @import { |
97 | 62 | * Config, |
98 | | - * AssetManager, |
99 | 63 | * FaucetPlugin, |
100 | 64 | * FaucetPluginOptions, |
101 | | - * FaucetPluginFunc, |
102 | | - * CompactorMap, |
103 | 65 | * WriteFileOpts, |
104 | 66 | * ProcessFile |
105 | 67 | * } from "./types.ts" |
|
0 commit comments