Skip to content

Commit 55769ed

Browse files
Merge pull request #3 from sidworks-dev/v109
V109
2 parents 8f75881 + a9e5d7a commit 55769ed

7 files changed

Lines changed: 789 additions & 692 deletions

File tree

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

Lines changed: 33 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ const {
77
resolveStorefrontApp,
88
createStorefrontRequire,
99
} = require('./runtime-paths');
10-
11-
const ANSI = {
12-
reset: '\x1b[0m',
13-
red: '\x1b[31m',
14-
gray: '\x1b[90m',
15-
green: '\x1b[32m',
16-
yellow: '\x1b[33m',
17-
cyan: '\x1b[36m',
18-
};
10+
const {
11+
ANSI,
12+
colorize,
13+
formatFilePath,
14+
summarizeFiles,
15+
createLogger,
16+
} = require('./utils');
1917

2018
function createChangeFeedbackWatcher(projectRoot) {
2119
const DUPLICATE_LOG_WINDOW_MS = 2000;
@@ -28,6 +26,7 @@ function createChangeFeedbackWatcher(projectRoot) {
2826
const disableJsCompilation = process.env.SHOPWARE_STOREFRONT_DISABLE_JS === '1';
2927
const jsCompileFeedbackEnabled = process.env.SHOPWARE_STOREFRONT_JS_COMPILE_FEEDBACK !== '0';
3028
const disableTwigWatch = process.env.SHOPWARE_STOREFRONT_DISABLE_TWIG === '1';
29+
const twigLog = createLogger('TWIG');
3130

3231
let watchpack = null;
3332
const recentlyLogged = new Map();
@@ -38,48 +37,21 @@ function createChangeFeedbackWatcher(projectRoot) {
3837
pendingFiles: new Set(),
3938
};
4039

41-
function hasInteractiveTty() {
42-
return Boolean(process.stdout && process.stdout.isTTY);
43-
}
44-
45-
function colorize(text, colorCode) {
46-
if (!hasInteractiveTty()) {
47-
return text;
48-
}
49-
50-
return `${colorCode}${text}${ANSI.reset}`;
51-
}
52-
5340
function logFileEvent(fileType, eventType, formattedFile, details = '') {
54-
const typeColor = ANSI.cyan;
5541
const eventColor = eventType === 'remove' ? ANSI.yellow : ANSI.green;
56-
const typeTag = colorize(`[${fileType.toUpperCase()}]`, typeColor);
42+
const typeTag = colorize(`[${fileType.toUpperCase()}]`, ANSI.cyan);
5743
const eventTag = colorize(`[${eventType.toUpperCase()}]`, eventColor);
5844
const suffix = details ? ` ${colorize(details, ANSI.gray)}` : '';
5945

6046
console.log(`[SidworksDevTools] ${typeTag} ${eventTag} ${formattedFile}${suffix}`);
6147
}
6248

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-
8149
function isExistingDirectory(directoryPath) {
82-
return fs.existsSync(directoryPath) && fs.statSync(directoryPath).isDirectory();
50+
try {
51+
return fs.statSync(directoryPath).isDirectory();
52+
} catch (_error) {
53+
return false;
54+
}
8355
}
8456

8557
function isPathInside(childPath, parentPath) {
@@ -91,9 +63,6 @@ function createChangeFeedbackWatcher(projectRoot) {
9163

9264
function readPluginsConfig() {
9365
const pluginsConfigPath = path.resolve(rootPath, 'var/plugins.json');
94-
if (!fs.existsSync(pluginsConfigPath)) {
95-
return [];
96-
}
9766

9867
try {
9968
const parsed = JSON.parse(fs.readFileSync(pluginsConfigPath, 'utf8'));
@@ -111,25 +80,21 @@ function createChangeFeedbackWatcher(projectRoot) {
11180
return rootPath;
11281
}
11382

114-
return path.isAbsolute(basePath)
115-
? basePath
116-
: path.resolve(rootPath, basePath);
83+
return path.isAbsolute(basePath) ? basePath : path.resolve(rootPath, basePath);
11784
}
11885

11986
function collectWatchDirectories() {
12087
const directories = new Set();
12188
const storefrontViewsRoot = path.resolve(storefrontApp, '..', '..', 'views');
12289

123-
const baseDirectories = [
90+
[
12491
path.resolve(storefrontApp, 'src'),
12592
path.resolve(rootPath, 'src/Resources/views'),
12693
path.resolve(rootPath, 'templates'),
12794
storefrontViewsRoot,
12895
path.resolve(rootPath, 'custom/plugins'),
12996
path.resolve(rootPath, 'custom/apps'),
130-
].filter(isExistingDirectory);
131-
132-
baseDirectories.forEach((directoryPath) => directories.add(directoryPath));
97+
].filter(isExistingDirectory).forEach((d) => directories.add(d));
13398

13499
const pluginConfigs = readPluginsConfig();
135100
for (const pluginConfig of pluginConfigs) {
@@ -141,59 +106,36 @@ function createChangeFeedbackWatcher(projectRoot) {
141106
continue;
142107
}
143108

144-
const resolvedViewDirectory = path.resolve(pluginBasePath, viewDirectory);
145-
if (
146-
isExistingDirectory(resolvedViewDirectory) &&
147-
![...directories].some((directoryPath) => isPathInside(resolvedViewDirectory, directoryPath))
148-
) {
149-
directories.add(resolvedViewDirectory);
109+
const resolved = path.resolve(pluginBasePath, viewDirectory);
110+
if (isExistingDirectory(resolved) && ![...directories].some((d) => isPathInside(resolved, d))) {
111+
directories.add(resolved);
150112
}
151113
}
152114

153115
const storefrontPath = typeof pluginConfig?.storefront?.path === 'string'
154116
? pluginConfig.storefront.path
155117
: '';
156118
if (storefrontPath !== '') {
157-
const resolvedStorefrontPath = path.resolve(pluginBasePath, storefrontPath);
158-
if (
159-
isExistingDirectory(resolvedStorefrontPath) &&
160-
![...directories].some((directoryPath) => isPathInside(resolvedStorefrontPath, directoryPath))
161-
) {
162-
directories.add(resolvedStorefrontPath);
119+
const resolved = path.resolve(pluginBasePath, storefrontPath);
120+
if (isExistingDirectory(resolved) && ![...directories].some((d) => isPathInside(resolved, d))) {
121+
directories.add(resolved);
163122
}
164123
}
165124

166125
const entryFilePath = typeof pluginConfig?.storefront?.entryFilePath === 'string'
167126
? pluginConfig.storefront.entryFilePath
168127
: '';
169128
if (entryFilePath !== '') {
170-
const resolvedEntryDirectory = path.dirname(path.resolve(pluginBasePath, entryFilePath));
171-
if (
172-
isExistingDirectory(resolvedEntryDirectory) &&
173-
![...directories].some((directoryPath) => isPathInside(resolvedEntryDirectory, directoryPath))
174-
) {
175-
directories.add(resolvedEntryDirectory);
129+
const resolved = path.dirname(path.resolve(pluginBasePath, entryFilePath));
130+
if (isExistingDirectory(resolved) && ![...directories].some((d) => isPathInside(resolved, d))) {
131+
directories.add(resolved);
176132
}
177133
}
178134
}
179135

180136
return [...directories];
181137
}
182138

183-
function formatFilePath(absoluteFilePath) {
184-
if (typeof absoluteFilePath !== 'string' || absoluteFilePath === '') {
185-
return '';
186-
}
187-
188-
const normalizedRoot = path.resolve(rootPath);
189-
const normalizedFile = path.resolve(absoluteFilePath);
190-
if (normalizedFile.startsWith(normalizedRoot + path.sep)) {
191-
return path.relative(normalizedRoot, normalizedFile).replace(/\\/g, '/');
192-
}
193-
194-
return absoluteFilePath.replace(/\\/g, '/');
195-
}
196-
197139
function classifyFile(filePath) {
198140
const extension = path.extname(filePath).toLowerCase();
199141
if (extension === '.twig') {
@@ -215,19 +157,6 @@ function createChangeFeedbackWatcher(projectRoot) {
215157
return now - previous < DUPLICATE_LOG_WINDOW_MS;
216158
}
217159

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-
231160
function rememberTwigPending(eventType, formattedFile) {
232161
if (typeof eventType === 'string' && eventType !== '') {
233162
twigState.pendingEventType = eventType;
@@ -238,22 +167,18 @@ function createChangeFeedbackWatcher(projectRoot) {
238167
}
239168
}
240169

241-
function formatTwigReasonLabel() {
170+
function flushTwigReloadFeedback() {
242171
const trigger = twigState.pendingEventType || 'change';
243172
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();
173+
const reasonLabel = fileSummary ? `${trigger}: ${fileSummary}` : trigger;
250174

251175
twigState.pendingEventType = '';
252176
twigState.pendingFiles.clear();
253177
twigState.waitLogged = false;
254178

255-
logTwigStatus('RUN', `reloading (${reasonLabel})`);
256-
logTwigStatus('OK', `reloaded (${reasonLabel}) in ${Date.now() - startedAt}ms`);
179+
const startedAt = Date.now();
180+
twigLog.status('RUN', `reloading (${reasonLabel})`);
181+
twigLog.status('OK', `reloaded (${reasonLabel}) in ${Date.now() - startedAt}ms`);
257182
}
258183

259184
function scheduleTwigReloadFeedback(eventType, formattedFile) {
@@ -262,11 +187,7 @@ function createChangeFeedbackWatcher(projectRoot) {
262187
if (twigState.timer) {
263188
if (!twigState.waitLogged) {
264189
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-
}
190+
twigLog.status('WAIT', `change queued while reload is running${queuedFiles ? ` (${queuedFiles})` : ''}`);
270191
twigState.waitLogged = true;
271192
}
272193
return;
@@ -284,7 +205,7 @@ function createChangeFeedbackWatcher(projectRoot) {
284205
return;
285206
}
286207

287-
const formattedFile = formatFilePath(absoluteFilePath);
208+
const formattedFile = formatFilePath(absoluteFilePath, rootPath);
288209
if (!formattedFile) {
289210
return;
290211
}

0 commit comments

Comments
 (0)