UNPKG

3.47 kBJavaScriptView Raw
1import path from 'node:path';
2import { validate } from 'schema-utils';
3
4import optionsSchema from './options-schema.js';
5import pExec from './utils/p-exec.js';
6import { copyAction, moveAction, mkdirAction, archiveAction, deleteAction } from './actions/index.js';
7
8const PLUGIN_NAME = 'FileManagerPlugin';
9
10const defaultOptions = {
11 events: {
12 onStart: [],
13 onEnd: [],
14 },
15 runTasksInSeries: false,
16 context: null,
17 runOnceInWatchMode: false,
18};
19
20const resolvePaths = (action, context) => {
21 return action.map((task) => {
22 if (typeof task === 'string') {
23 const source = task;
24 return {
25 source,
26 absoluteSource: path.isAbsolute(source) ? source : path.join(context, source),
27 };
28 }
29
30 const { source, destination } = task;
31
32 if (!destination) {
33 return {
34 ...task,
35 source,
36 absoluteSource: path.isAbsolute(source) ? source : path.join(context, source),
37 };
38 }
39
40 const toType = /(?:\\|\/)$/.test(destination) ? 'dir' : 'file';
41
42 return {
43 ...task,
44 source,
45 absoluteSource: path.isAbsolute(source) ? source : path.join(context, source),
46 destination,
47 absoluteDestination: path.isAbsolute(destination) ? destination : path.join(context, destination),
48 toType,
49 context,
50 };
51 });
52};
53
54class FileManagerPlugin {
55 constructor(options) {
56 validate(optionsSchema, options, {
57 name: PLUGIN_NAME,
58 baseDataPath: 'actions',
59 });
60
61 this.options = { ...defaultOptions, ...options };
62 }
63
64 async applyAction(action, actionParams) {
65 const opts = {
66 runTasksInSeries: this.options.runTasksInSeries,
67 logger: this.logger,
68 };
69
70 await action(resolvePaths(actionParams, this.context), opts);
71 }
72
73 async run(event) {
74 for (const actionType in event) {
75 const action = event[actionType];
76
77 switch (actionType) {
78 case 'delete':
79 await this.applyAction(deleteAction, action);
80 break;
81
82 case 'mkdir':
83 await this.applyAction(mkdirAction, action);
84 break;
85
86 case 'copy':
87 await this.applyAction(copyAction, action);
88 break;
89
90 case 'move':
91 await this.applyAction(moveAction, action);
92 break;
93
94 case 'archive':
95 await this.applyAction(archiveAction, action);
96 break;
97
98 default:
99 throw Error('Unknown action');
100 }
101 }
102 }
103
104 async execute(eventName) {
105 const { events } = this.options;
106
107 if (Array.isArray(events[eventName])) {
108 const eventsArr = events[eventName];
109
110 await pExec(true, eventsArr, async (event) => await this.run(event));
111 return;
112 }
113
114 const event = events[eventName];
115 await this.run(event);
116 }
117
118 apply(compiler) {
119 this.context = this.options.context || compiler.options.context;
120 this.logger = compiler.getInfrastructureLogger(PLUGIN_NAME);
121
122 const onStart = async () => {
123 await this.execute('onStart');
124 };
125
126 const onEnd = async () => {
127 await this.execute('onEnd');
128 };
129
130 compiler.hooks.beforeRun.tapPromise(PLUGIN_NAME, onStart);
131 compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, onEnd);
132
133 let watchRunCount = 0;
134 compiler.hooks.watchRun.tapPromise(PLUGIN_NAME, async () => {
135 if (this.options.runOnceInWatchMode && watchRunCount > 0) {
136 return;
137 }
138
139 ++watchRunCount;
140 await onStart();
141 });
142 }
143}
144
145export default FileManagerPlugin;