Skip to content

Commit 8d7a0f8

Browse files
committed
Release 1.0.7
1 parent 189f33d commit 8d7a0f8

4 files changed

Lines changed: 309 additions & 79 deletions

File tree

bin/storefront-hot-proxy/change-feedback-watcher.js

Lines changed: 105 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,33 @@ const {
1010

1111
const ANSI = {
1212
reset: '\x1b[0m',
13+
red: '\x1b[31m',
1314
gray: '\x1b[90m',
1415
green: '\x1b[32m',
1516
yellow: '\x1b[33m',
1617
cyan: '\x1b[36m',
17-
magenta: '\x1b[35m',
1818
};
1919

2020
function createChangeFeedbackWatcher(projectRoot) {
2121
const DUPLICATE_LOG_WINDOW_MS = 2000;
22+
const TWIG_DEBOUNCE_MS = 90;
2223
const rootPath = path.resolve(projectRoot);
2324
const storefrontApp = resolveStorefrontApp(rootPath);
2425
const storefrontRequire = createStorefrontRequire(rootPath);
2526
const Watchpack = storefrontRequire('watchpack');
2627
const coreOnlyHotMode = process.env.SHOPWARE_STOREFRONT_HOT_CORE_ONLY === '1';
2728
const disableJsCompilation = process.env.SHOPWARE_STOREFRONT_DISABLE_JS === '1';
29+
const jsCompileFeedbackEnabled = process.env.SHOPWARE_STOREFRONT_JS_COMPILE_FEEDBACK !== '0';
2830
const disableTwigWatch = process.env.SHOPWARE_STOREFRONT_DISABLE_TWIG === '1';
29-
const coreStorefrontJsRoot = path.resolve(storefrontApp, 'src');
3031

3132
let watchpack = null;
3233
const recentlyLogged = new Map();
34+
const twigState = {
35+
timer: null,
36+
waitLogged: false,
37+
pendingEventType: '',
38+
pendingFiles: new Set(),
39+
};
3340

3441
function hasInteractiveTty() {
3542
return Boolean(process.stdout && process.stdout.isTTY);
@@ -44,7 +51,7 @@ function createChangeFeedbackWatcher(projectRoot) {
4451
}
4552

4653
function logFileEvent(fileType, eventType, formattedFile, details = '') {
47-
const typeColor = fileType === 'twig' ? ANSI.magenta : ANSI.cyan;
54+
const typeColor = ANSI.cyan;
4855
const eventColor = eventType === 'remove' ? ANSI.yellow : ANSI.green;
4956
const typeTag = colorize(`[${fileType.toUpperCase()}]`, typeColor);
5057
const eventTag = colorize(`[${eventType.toUpperCase()}]`, eventColor);
@@ -53,6 +60,24 @@ function createChangeFeedbackWatcher(projectRoot) {
5360
console.log(`[SidworksDevTools] ${typeTag} ${eventTag} ${formattedFile}${suffix}`);
5461
}
5562

63+
function logTwigStatus(status, message, asError = false) {
64+
const typeTag = colorize('[TWIG]', ANSI.cyan);
65+
const statusColor = status === 'OK'
66+
? ANSI.green
67+
: status === 'ERR'
68+
? ANSI.red
69+
: ANSI.yellow;
70+
const statusTag = colorize(`[${status}]`, statusColor);
71+
const line = `[SidworksDevTools] ${typeTag} ${statusTag} ${message}`;
72+
73+
if (asError) {
74+
console.error(line);
75+
return;
76+
}
77+
78+
console.log(line);
79+
}
80+
5681
function isExistingDirectory(directoryPath) {
5782
return fs.existsSync(directoryPath) && fs.statSync(directoryPath).isDirectory();
5883
}
@@ -190,9 +215,67 @@ function createChangeFeedbackWatcher(projectRoot) {
190215
return now - previous < DUPLICATE_LOG_WINDOW_MS;
191216
}
192217

193-
function isCoreStorefrontJsFile(filePath) {
194-
const normalizedFile = path.resolve(filePath);
195-
return normalizedFile.startsWith(coreStorefrontJsRoot + path.sep);
218+
function summarizeFiles(files) {
219+
const uniqueFiles = [...new Set((files || []).filter((file) => typeof file === 'string' && file !== ''))];
220+
if (uniqueFiles.length === 0) {
221+
return '';
222+
}
223+
224+
if (uniqueFiles.length <= 3) {
225+
return uniqueFiles.join(', ');
226+
}
227+
228+
return `${uniqueFiles.slice(0, 3).join(', ')} +${uniqueFiles.length - 3} more`;
229+
}
230+
231+
function rememberTwigPending(eventType, formattedFile) {
232+
if (typeof eventType === 'string' && eventType !== '') {
233+
twigState.pendingEventType = eventType;
234+
}
235+
236+
if (typeof formattedFile === 'string' && formattedFile !== '') {
237+
twigState.pendingFiles.add(formattedFile);
238+
}
239+
}
240+
241+
function formatTwigReasonLabel() {
242+
const trigger = twigState.pendingEventType || 'change';
243+
const fileSummary = summarizeFiles([...twigState.pendingFiles]);
244+
return fileSummary ? `${trigger}: ${fileSummary}` : trigger;
245+
}
246+
247+
function flushTwigReloadFeedback() {
248+
const reasonLabel = formatTwigReasonLabel();
249+
const startedAt = Date.now();
250+
251+
twigState.pendingEventType = '';
252+
twigState.pendingFiles.clear();
253+
twigState.waitLogged = false;
254+
255+
logTwigStatus('RUN', `reloading (${reasonLabel})`);
256+
logTwigStatus('OK', `reloaded (${reasonLabel}) in ${Date.now() - startedAt}ms`);
257+
}
258+
259+
function scheduleTwigReloadFeedback(eventType, formattedFile) {
260+
rememberTwigPending(eventType, formattedFile);
261+
262+
if (twigState.timer) {
263+
if (!twigState.waitLogged) {
264+
const queuedFiles = summarizeFiles([...twigState.pendingFiles]);
265+
if (queuedFiles) {
266+
logTwigStatus('WAIT', `change queued while reload is running (${queuedFiles})`);
267+
} else {
268+
logTwigStatus('WAIT', 'change queued while reload is running');
269+
}
270+
twigState.waitLogged = true;
271+
}
272+
return;
273+
}
274+
275+
twigState.timer = setTimeout(() => {
276+
twigState.timer = null;
277+
flushTwigReloadFeedback();
278+
}, TWIG_DEBOUNCE_MS);
196279
}
197280

198281
function handleFileEvent(eventType, absoluteFilePath) {
@@ -202,13 +285,12 @@ function createChangeFeedbackWatcher(projectRoot) {
202285
}
203286

204287
const formattedFile = formatFilePath(absoluteFilePath);
205-
if (!formattedFile || shouldSkipDuplicate(eventType, formattedFile)) {
288+
if (!formattedFile) {
206289
return;
207290
}
208291

209292
if (fileType === 'js') {
210-
if (isCoreStorefrontJsFile(absoluteFilePath) && !disableJsCompilation) {
211-
// Core storefront JS is already logged via webpack compiler hooks.
293+
if (shouldSkipDuplicate(eventType, formattedFile)) {
212294
return;
213295
}
214296

@@ -222,17 +304,25 @@ function createChangeFeedbackWatcher(projectRoot) {
222304
return;
223305
}
224306

307+
if (jsCompileFeedbackEnabled) {
308+
return;
309+
}
310+
225311
logFileEvent('js', eventType, formattedFile);
226312
return;
227313
}
228314

229315
if (fileType === 'twig') {
230316
if (disableTwigWatch) {
317+
if (shouldSkipDuplicate(eventType, formattedFile)) {
318+
return;
319+
}
320+
231321
logFileEvent('twig', eventType, formattedFile, '(skipped: --no-twig)');
232322
return;
233323
}
234324

235-
logFileEvent('twig', eventType, formattedFile, '(live reload)');
325+
scheduleTwigReloadFeedback(eventType, formattedFile);
236326
}
237327
}
238328

@@ -263,6 +353,11 @@ function createChangeFeedbackWatcher(projectRoot) {
263353
}
264354

265355
function close() {
356+
if (twigState.timer) {
357+
clearTimeout(twigState.timer);
358+
twigState.timer = null;
359+
}
360+
266361
if (watchpack) {
267362
watchpack.close();
268363
watchpack = null;

0 commit comments

Comments
 (0)