| 
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 = "files";  | 
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