UNPKG

5.64 kBJavaScriptView Raw
1import {
2 MATCH,
3 isFontCustomFile,
4 isViewCustomFile,
5 isViewFile,
6 isViewLogicFile,
7} from './match-files.js'
8import { promises as fs, existsSync } from 'fs'
9import { getFontId } from './fonts.js'
10import chalk from 'chalk'
11import chokidar from 'chokidar'
12import getPointsOfUse from './get-points-of-use.js'
13import path from 'path'
14
15export default async function watchFiles({ morpher }) {
16 let watcher = chokidar.watch(MATCH, {
17 cwd: morpher.src,
18 ignored: [
19 path.join('**', 'node_modules', '**'),
20 path.join('**', 'view.js'),
21 path.join('**', 'DesignSystem', 'Fonts', '*.js'),
22 path.join('**', 'Logic', 'ViewsFlow.js'),
23 path.join('**', 'Logic', 'useIsMedia.js'),
24 path.join('**', 'Logic', 'useIsBefore.js'),
25 path.join('**', 'Logic', 'useIsHovered.js'),
26 path.join('**', 'Logic', 'ViewsTools', 'logic.js'),
27 path.join('**', 'Data', 'ViewsData.js'),
28 ],
29 ignoreInitial: true,
30 awaitWriteFinish: true,
31 })
32
33 let skipTimeout = null
34 let processEventsPromise = null
35 let queue = []
36
37 function onEvent({ file, op }) {
38 queue.push({ file: path.join(morpher.src, file), op })
39
40 maybeProcess()
41 }
42
43 function maybeProcess() {
44 // if busy, try again in a bit
45 clearTimeout(skipTimeout)
46 skipTimeout = null
47 if (processEventsPromise) {
48 skipTimeout = setTimeout(maybeProcess, 200)
49 return
50 }
51 processEvents()
52 }
53
54 async function processEvents() {
55 if (queue.length === 0 || processEventsPromise) {
56 return
57 }
58
59 let queueClone = [...queue]
60 queue = []
61 processEventsPromise = new Promise(async resolve => {
62 try {
63 await processQueue({ queue: queueClone, morpher })
64 } catch (error) {
65 console.error(error)
66 } finally {
67 resolve()
68 processEventsPromise = null
69 }
70 })
71 }
72
73 watcher.on('add', file => onEvent({ file, op: 'add' }))
74 watcher.on('change', file => onEvent({ file, op: 'change' }))
75 watcher.on('unlink', file => onEvent({ file, op: 'unlink' }))
76
77 return watcher
78}
79
80async function processQueue({ queue, morpher }) {
81 let filesToProcess = {
82 filesView: new Set(),
83 filesViewLogic: new Set(),
84 filesViewCustom: new Set(),
85 filesFontCustom: new Set(),
86 }
87
88 await processUnlinked({
89 files: queue.filter(item => item.op === 'unlink'),
90 morpher,
91 filesToProcess,
92 })
93
94 await processAddedOrChanged({
95 files: queue.filter(item => item.op !== 'unlink'),
96 morpher,
97 filesToProcess,
98 })
99
100 await morpher.processFiles(filesToProcess)
101
102 if (!morpher.verbose) return // && viewsId.size > 0) {
103
104 // Object.entries(filesToProcess).forEach(([key, value]) => {
105 // console.log(chalk.greenBright(key), [...value])
106 // })
107
108 // console.log(chalk.green('M'), [...viewsId].join(', '))
109 // }
110}
111
112function processUnlinked({ files, morpher, filesToProcess }) {
113 return Promise.all(
114 files.map(async ({ file }) => {
115 morpher.verbose && console.log(chalk.magenta('X'), file) // view.id, chalk.dim(`-> ${file}`))
116
117 if (await isFontCustomFile(file)) {
118 let id = getFontId(file)
119 let font = morpher.customFonts.get(id)
120 font.delete(file)
121
122 if (font.size === 0) {
123 morpher.customFonts.delete(id)
124 }
125 } else {
126 let view = morpher.viewsToFiles.get(path.dirname(file))
127 if (!view) return
128
129 processPointsOfUse({ view, morpher, filesToProcess })
130
131 filesToProcess.filesView.delete(view.file)
132 morpher.viewsById.delete(view.id)
133 morpher.viewsToFiles.delete(view.file)
134
135 try {
136 fs.unlink(view.file)
137 } catch (error) {}
138
139 if (await isViewFile(file)) {
140 filesToProcess.filesView.delete(file)
141 } else if (await isViewLogicFile(file)) {
142 filesToProcess.filesView.add(view.file)
143 filesToProcess.filesViewLogic.delete(file)
144 } else if (await isViewCustomFile(file)) {
145 filesToProcess.filesViewCustom.delete(file)
146 }
147 }
148 })
149 )
150}
151
152function processAddedOrChanged({ files, morpher, filesToProcess }) {
153 return Promise.all(
154 files.map(async ({ file, op }) => {
155 morpher.verbose && console.log(chalk.yellow(op), file)
156
157 if (await isFontCustomFile(file)) {
158 filesToProcess.filesFontCustom.add(file)
159 } else {
160 if (await isViewFile(file)) {
161 filesToProcess.filesView.add(file)
162
163 let logicFile = path.join(path.dirname(file), 'logic.js')
164 if (existsSync(logicFile)) {
165 filesToProcess.filesViewLogic.add(logicFile)
166 }
167 } else if (await isViewLogicFile(file)) {
168 filesToProcess.filesView.add(file.replace('logic.js', 'view.blocks'))
169 filesToProcess.filesViewLogic.add(file)
170 } else if (await isViewCustomFile(file)) {
171 filesToProcess.filesViewCustom.add(file)
172 }
173
174 let view = morpher.viewsToFiles.get(path.dirname(file))
175 if (!view) return
176
177 processPointsOfUse({ view, morpher, filesToProcess })
178 }
179
180 // morpher.verbose &&
181 // console.log(
182 // op === 'add'
183 // ? `${chalk.yellow('A')} ${chalk.green('M')}`
184 // : chalk.green('M'),
185 // getViewIdFromFile(file),
186 // chalk.dim(`-> ${file}`)
187 // )
188 })
189 )
190}
191
192function processPointsOfUse({ view, morpher, filesToProcess }) {
193 let { filesView, filesViewLogic } = getPointsOfUse({
194 view,
195 viewsToFiles: morpher.viewsToFiles,
196 })
197 for (let file of filesView) {
198 filesToProcess.filesView.add(file)
199 }
200 for (let file of filesViewLogic) {
201 filesToProcess.filesViewLogic.add(file)
202 }
203}