@kanso-labs/unplugin-style-dictionary 0.10.5 → 0.10.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/colour.js +16 -0
- package/dist/colour.js.map +1 -0
- package/dist/compile.js +114 -0
- package/dist/compile.js.map +1 -0
- package/dist/config.js +113 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.js +75 -440
- package/dist/index.js.map +1 -1
- package/dist/patterns.js +69 -0
- package/dist/patterns.js.map +1 -0
- package/dist/scheduler.js +44 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/size-report.js +38 -0
- package/dist/size-report.js.map +1 -0
- package/dist/types.d.ts +9 -1
- package/dist/up-to-date.js +61 -0
- package/dist/up-to-date.js.map +1 -0
- package/dist/watch-filter.js +4 -1
- package/dist/watch-filter.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,50 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { colourAllowed, paint } from "./colour.js";
|
|
2
|
+
import { asError, errorMessage } from "./errors.js";
|
|
3
|
+
import { resolveConfigOption } from "./config.js";
|
|
4
|
+
import { expandPatterns, watchPatternsOf } from "./patterns.js";
|
|
5
|
+
import { runBuilds } from "./compile.js";
|
|
6
|
+
import { createScheduler } from "./scheduler.js";
|
|
7
|
+
import { isWatchedSource } from "./watch-filter.js";
|
|
3
8
|
import fs from "node:fs";
|
|
4
9
|
import path from "node:path";
|
|
5
|
-
import { pathToFileURL } from "node:url";
|
|
6
|
-
import zlib from "node:zlib";
|
|
7
|
-
import StyleDictionary from "style-dictionary";
|
|
8
|
-
import { glob } from "tinyglobby";
|
|
9
10
|
import { createUnplugin } from "unplugin";
|
|
10
11
|
//#region src/index.ts
|
|
11
|
-
function asError(error) {
|
|
12
|
-
return error instanceof Error ? error : new Error(errorMessage(error));
|
|
13
|
-
}
|
|
14
|
-
function colourAllowed(stream) {
|
|
15
|
-
if (process.env.NO_COLOR) return false;
|
|
16
|
-
const forced = process.env.FORCE_COLOR;
|
|
17
|
-
if (forced === "0") return false;
|
|
18
|
-
if (forced !== void 0 && forced !== "") return true;
|
|
19
|
-
if (process.env.TERM === "dumb") return false;
|
|
20
|
-
return stream.isTTY === true;
|
|
21
|
-
}
|
|
22
12
|
function discardTemporaryFile(temporary) {
|
|
23
13
|
try {
|
|
24
14
|
fs.rmSync(temporary, { force: true });
|
|
25
15
|
} catch {}
|
|
26
16
|
}
|
|
27
|
-
function errorMessage(error) {
|
|
28
|
-
return error instanceof Error ? error.message : String(error);
|
|
29
|
-
}
|
|
30
|
-
function isConfig(value) {
|
|
31
|
-
return typeof value === "object" && value !== null;
|
|
32
|
-
}
|
|
33
17
|
function isMessageChannel(value) {
|
|
34
18
|
return typeof value === "function";
|
|
35
19
|
}
|
|
36
|
-
function isThenable(value) {
|
|
37
|
-
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
38
|
-
}
|
|
39
|
-
function looksLikeConfig(value) {
|
|
40
|
-
if (typeof value !== "object" || value === null) return false;
|
|
41
|
-
return [
|
|
42
|
-
"include",
|
|
43
|
-
"platforms",
|
|
44
|
-
"source",
|
|
45
|
-
"tokens"
|
|
46
|
-
].some((key) => key in value);
|
|
47
|
-
}
|
|
48
20
|
function nodeModulesNegations(paths) {
|
|
49
21
|
const negations = /* @__PURE__ */ new Set();
|
|
50
22
|
for (const file of paths) {
|
|
@@ -62,25 +34,6 @@ function nodeModulesWatchDirectories(paths) {
|
|
|
62
34
|
}
|
|
63
35
|
return Array.from(directories);
|
|
64
36
|
}
|
|
65
|
-
function paint(code, value, allowed) {
|
|
66
|
-
return allowed ? `\u001B[${code}m${value}\u001B[0m` : value;
|
|
67
|
-
}
|
|
68
|
-
async function patternsMatchingNothing(patterns) {
|
|
69
|
-
const barren = [];
|
|
70
|
-
for (const pattern of patterns) {
|
|
71
|
-
if (!GLOB_CHARACTERS.test(pattern)) {
|
|
72
|
-
if (!fs.existsSync(pattern)) barren.push(pattern);
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
if ((await glob([pattern], { absolute: true })).length === 0) barren.push(pattern);
|
|
77
|
-
} catch {}
|
|
78
|
-
}
|
|
79
|
-
return barren;
|
|
80
|
-
}
|
|
81
|
-
function unwrapDefault(value) {
|
|
82
|
-
return typeof value === "object" && value !== null && "default" in value ? value.default ?? value : value;
|
|
83
|
-
}
|
|
84
37
|
let temporaryFileCounter = 0;
|
|
85
38
|
async function rendersWhatIsAlreadyThere(temporary, destination) {
|
|
86
39
|
try {
|
|
@@ -188,23 +141,6 @@ const atomicVolume = Object.create(fs, {
|
|
|
188
141
|
promises: { value: Object.create(fs.promises, { writeFile: { value: writeFileAtomic } }) },
|
|
189
142
|
writeFileSync: { value: writeFileSyncAtomic }
|
|
190
143
|
});
|
|
191
|
-
const GLOB_CHARACTERS = /[!*?[\]{}]/;
|
|
192
|
-
const IMPORTED_CONFIG_EXTENSIONS = [
|
|
193
|
-
".js",
|
|
194
|
-
".mjs",
|
|
195
|
-
".ts"
|
|
196
|
-
];
|
|
197
|
-
function describeConfig(item, index) {
|
|
198
|
-
return item.file ? `The configuration ${item.file}` : `The configuration at position ${index + 1}`;
|
|
199
|
-
}
|
|
200
|
-
function isImportedConfig(file) {
|
|
201
|
-
return IMPORTED_CONFIG_EXTENSIONS.some((extension) => file.endsWith(extension));
|
|
202
|
-
}
|
|
203
|
-
function staticParentOf(pattern) {
|
|
204
|
-
const segments = pattern.split("/");
|
|
205
|
-
const firstGlob = segments.findIndex((segment) => GLOB_CHARACTERS.test(segment));
|
|
206
|
-
return firstGlob === -1 ? path.posix.dirname(pattern) : segments.slice(0, firstGlob).join("/");
|
|
207
|
-
}
|
|
208
144
|
const compiledFingerprints = /* @__PURE__ */ new Set();
|
|
209
145
|
const compilesInFlight = /* @__PURE__ */ new Map();
|
|
210
146
|
function buildKey(root, resolved) {
|
|
@@ -214,34 +150,12 @@ function buildKey(root, resolved) {
|
|
|
214
150
|
return null;
|
|
215
151
|
}
|
|
216
152
|
}
|
|
217
|
-
function sourcePatternsOf(configObj) {
|
|
218
|
-
const patterns = [];
|
|
219
|
-
const add = (pattern) => {
|
|
220
|
-
if (typeof pattern === "string") patterns.push((path.isAbsolute(pattern) ? pattern : path.resolve(process.cwd(), pattern)).replace(/\\/g, "/"));
|
|
221
|
-
};
|
|
222
|
-
for (const value of [configObj.source, configObj.include]) if (Array.isArray(value)) value.forEach(add);
|
|
223
|
-
else add(value);
|
|
224
|
-
return patterns;
|
|
225
|
-
}
|
|
226
|
-
function statOrNull(file) {
|
|
227
|
-
try {
|
|
228
|
-
return fs.statSync(file);
|
|
229
|
-
} catch {
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
153
|
const unpluginFactory = (options = {}, meta) => {
|
|
234
154
|
const isWebpack = meta.framework === "webpack" || meta.framework === "rspack";
|
|
235
155
|
const { cache = true, errorOverlay = true, failOnError = "build", logLevel, onBuildEnd, onBuildError, onBuildStart, platforms: platformsOption, report = true, root: rootOption, silent = false } = options;
|
|
236
156
|
const level = logLevel ?? (silent ? "silent" : void 0);
|
|
237
157
|
const quiet = level === "silent" || level === "warn";
|
|
238
158
|
const verbosity = level === void 0 ? void 0 : level === "verbose" ? "verbose" : level === "silent" ? "silent" : "default";
|
|
239
|
-
const platformsFor = (context) => {
|
|
240
|
-
if (platformsOption === void 0) return void 0;
|
|
241
|
-
if (Array.isArray(platformsOption)) return platformsOption;
|
|
242
|
-
return context === void 0 ? platformsOption.build : platformsOption.watch;
|
|
243
|
-
};
|
|
244
|
-
const failsTheBuild = (context) => failOnError === true || (context === void 0 ? failOnError === "build" : failOnError === "serve");
|
|
245
159
|
let hostCommand = "build";
|
|
246
160
|
let hostMode;
|
|
247
161
|
let isWatching = false;
|
|
@@ -262,22 +176,6 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
262
176
|
let watchRebuild = false;
|
|
263
177
|
let hasCompiled = false;
|
|
264
178
|
let hostClosed = false;
|
|
265
|
-
const expandPatterns = async (patterns) => {
|
|
266
|
-
const paths = /* @__PURE__ */ new Set();
|
|
267
|
-
const globs = [];
|
|
268
|
-
for (const pattern of patterns) if (GLOB_CHARACTERS.test(pattern)) {
|
|
269
|
-
globs.push(pattern);
|
|
270
|
-
const parent = staticParentOf(pattern);
|
|
271
|
-
if (parent && fs.existsSync(parent)) paths.add(parent);
|
|
272
|
-
} else paths.add(pattern);
|
|
273
|
-
if (globs.length > 0) try {
|
|
274
|
-
for (const match of await glob(globs, { absolute: true })) paths.add(match.replace(/\\/g, "/"));
|
|
275
|
-
} catch (err) {
|
|
276
|
-
log(`Failed to expand watch patterns: ${errorMessage(err)}`, "error");
|
|
277
|
-
}
|
|
278
|
-
return Array.from(paths);
|
|
279
|
-
};
|
|
280
|
-
const isWatchedSource = (file, patterns) => !generatedDestinations.has(file.replace(/\\/g, "/")) && matchesWatchedFile(file, patterns);
|
|
281
179
|
const stdoutColour = colourAllowed(process.stdout);
|
|
282
180
|
const stderrColour = colourAllowed(process.stderr);
|
|
283
181
|
let host;
|
|
@@ -312,292 +210,50 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
312
210
|
}
|
|
313
211
|
console.log(paint(type === "success" ? "32" : "36", `${prefix} ${message}`, stdoutColour));
|
|
314
212
|
};
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
if (!isThenable(result)) return;
|
|
324
|
-
Promise.resolve(result).catch((err) => {
|
|
325
|
-
log(`The ${name} hook rejected: ${errorMessage(err)}`, "error");
|
|
326
|
-
});
|
|
327
|
-
};
|
|
328
|
-
const resolveConfigs = async () => {
|
|
329
|
-
let rawConfig = options.config;
|
|
330
|
-
if (rawConfig === false) return [];
|
|
331
|
-
if (!rawConfig) {
|
|
332
|
-
const defaults = [
|
|
333
|
-
"sd.config.json",
|
|
334
|
-
"config.json",
|
|
335
|
-
"sd.config.js",
|
|
336
|
-
"sd.config.mjs"
|
|
337
|
-
];
|
|
338
|
-
const rejected = [];
|
|
339
|
-
for (const file of defaults) {
|
|
340
|
-
const fullPath = path.resolve(root, file);
|
|
341
|
-
if (!fs.existsSync(fullPath)) continue;
|
|
342
|
-
if (!looksLikeConfig(await readConfigObject({
|
|
343
|
-
config: fullPath,
|
|
344
|
-
file: fullPath
|
|
345
|
-
}, false))) {
|
|
346
|
-
rejected.push(file);
|
|
347
|
-
continue;
|
|
348
|
-
}
|
|
349
|
-
if (!announcedDiscovery) {
|
|
350
|
-
announcedDiscovery = true;
|
|
351
|
-
log(`Using the configuration it found at ${fullPath}`, "info");
|
|
352
|
-
}
|
|
353
|
-
rawConfig = file;
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
if (rejected.length > 0) log(`Ignored ${rejected.join(", ")} in ${root}: nothing there declares platforms, source, include or tokens, so it does not look like a Style Dictionary configuration. Name it with the config option if it is one, or set config to false to stop looking.`, "error");
|
|
357
|
-
}
|
|
358
|
-
if (!rawConfig) {
|
|
359
|
-
log("No configuration specified and no default config file found. Style Dictionary will not compile.", "error");
|
|
360
|
-
return [];
|
|
361
|
-
}
|
|
362
|
-
if (typeof rawConfig === "function") rawConfig = await rawConfig(configContext());
|
|
363
|
-
return (Array.isArray(rawConfig) ? rawConfig : [rawConfig]).map((conf) => {
|
|
364
|
-
if (typeof conf === "string") {
|
|
365
|
-
const fullPath = path.resolve(root, conf);
|
|
366
|
-
return {
|
|
367
|
-
config: fullPath,
|
|
368
|
-
file: fullPath
|
|
369
|
-
};
|
|
370
|
-
} else return { config: conf };
|
|
371
|
-
});
|
|
372
|
-
};
|
|
373
|
-
const importConfigModule = async (file) => {
|
|
374
|
-
let version;
|
|
375
|
-
try {
|
|
376
|
-
version = fs.statSync(file).mtimeMs;
|
|
377
|
-
} catch {
|
|
378
|
-
version = Date.now();
|
|
379
|
-
}
|
|
380
|
-
const key = String(version).replace(".", "_");
|
|
381
|
-
return unwrapDefault(await import(`${pathToFileURL(file).href}?t=${key}`));
|
|
382
|
-
};
|
|
383
|
-
const readConfigObject = async (item, reportErrors) => {
|
|
384
|
-
if (typeof item.config !== "string") return item.config;
|
|
385
|
-
try {
|
|
386
|
-
const loaded = isImportedConfig(item.config) ? await importConfigModule(item.config) : JSON5.parse(fs.readFileSync(item.config, "utf-8"));
|
|
387
|
-
if (isConfig(loaded)) return loaded;
|
|
388
|
-
if (reportErrors) log(`Config file did not resolve to a configuration object: ${item.config}`, "error");
|
|
389
|
-
} catch (err) {
|
|
390
|
-
if (reportErrors) log(`Failed to parse config file: ${item.config}. Error: ${errorMessage(err)}`, "error");
|
|
391
|
-
}
|
|
392
|
-
return null;
|
|
393
|
-
};
|
|
213
|
+
const resolveConfigs = async () => resolveConfigOption({
|
|
214
|
+
config: options.config,
|
|
215
|
+
configContext,
|
|
216
|
+
discovery,
|
|
217
|
+
log,
|
|
218
|
+
root
|
|
219
|
+
});
|
|
394
220
|
const getWatchTargets = async (resolvedConfigs) => {
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
const addPattern = (pattern) => {
|
|
401
|
-
if (typeof pattern === "string") {
|
|
402
|
-
const normalized = (path.isAbsolute(pattern) ? pattern : path.resolve(process.cwd(), pattern)).replace(/\\/g, "/");
|
|
403
|
-
filesToWatch.add(normalized);
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
if (configObj.source) {
|
|
407
|
-
if (Array.isArray(configObj.source)) configObj.source.forEach(addPattern);
|
|
408
|
-
else addPattern(configObj.source);
|
|
409
|
-
}
|
|
410
|
-
if (configObj.include) {
|
|
411
|
-
if (Array.isArray(configObj.include)) configObj.include.forEach(addPattern);
|
|
412
|
-
else addPattern(configObj.include);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
if (options.watch) {
|
|
417
|
-
const extraWatches = Array.isArray(options.watch) ? options.watch : [options.watch];
|
|
418
|
-
for (const pattern of extraWatches) {
|
|
419
|
-
const absolutePattern = path.isAbsolute(pattern) ? pattern : path.resolve(root, pattern);
|
|
420
|
-
filesToWatch.add(absolutePattern.replace(/\\/g, "/"));
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
const patterns = Array.from(filesToWatch);
|
|
221
|
+
const patterns = await watchPatternsOf({
|
|
222
|
+
log,
|
|
223
|
+
root,
|
|
224
|
+
watch: options.watch
|
|
225
|
+
}, resolvedConfigs);
|
|
424
226
|
cachedPatterns = patterns;
|
|
425
227
|
return {
|
|
426
|
-
paths: await expandPatterns(patterns),
|
|
228
|
+
paths: await expandPatterns(patterns, log),
|
|
427
229
|
patterns
|
|
428
230
|
};
|
|
429
231
|
};
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return destinations;
|
|
451
|
-
};
|
|
452
|
-
const configFingerprint = (item) => {
|
|
453
|
-
try {
|
|
454
|
-
return JSON.stringify([root, item.file ?? item.config], (_key, value) => typeof value === "function" ? `[fn]${String(value)}` : value);
|
|
455
|
-
} catch {
|
|
456
|
-
return null;
|
|
457
|
-
}
|
|
458
|
-
};
|
|
459
|
-
const isUpToDate = async (item, configObj, only) => {
|
|
460
|
-
if (Object.values(configObj.platforms ?? {}).some((platform) => (platform.actions?.length ?? 0) > 0)) return false;
|
|
461
|
-
const destinations = declaredDestinations(configObj, only);
|
|
462
|
-
if (destinations.length === 0) return false;
|
|
463
|
-
const extraWatches = options.watch ? Array.isArray(options.watch) ? options.watch : [options.watch] : [];
|
|
464
|
-
const sources = await expandPatterns([...sourcePatternsOf(configObj), ...extraWatches.map((pattern) => (path.isAbsolute(pattern) ? pattern : path.resolve(root, pattern)).replace(/\\/g, "/"))]);
|
|
465
|
-
if (item.file) sources.push(item.file.replace(/\\/g, "/"));
|
|
466
|
-
if (sources.length === 0) return false;
|
|
467
|
-
let newestSource = -Infinity;
|
|
468
|
-
let sawFile = false;
|
|
469
|
-
for (const source of sources) {
|
|
470
|
-
const stats = statOrNull(source);
|
|
471
|
-
if (!stats) return false;
|
|
472
|
-
if (stats.isDirectory()) continue;
|
|
473
|
-
sawFile = true;
|
|
474
|
-
newestSource = Math.max(newestSource, stats.mtimeMs);
|
|
475
|
-
}
|
|
476
|
-
if (!sawFile) return false;
|
|
477
|
-
let oldestDestination = Infinity;
|
|
478
|
-
for (const destination of destinations) {
|
|
479
|
-
const stats = statOrNull(destination);
|
|
480
|
-
if (!stats) return false;
|
|
481
|
-
oldestDestination = Math.min(oldestDestination, stats.mtimeMs);
|
|
482
|
-
}
|
|
483
|
-
if (oldestDestination <= newestSource) return false;
|
|
484
|
-
if (item.file) return true;
|
|
485
|
-
const fingerprint = configFingerprint(item);
|
|
486
|
-
return fingerprint !== null && compiledFingerprints.has(fingerprint);
|
|
487
|
-
};
|
|
488
|
-
const reportSizes = (generatedFiles) => {
|
|
489
|
-
const fileInfos = [];
|
|
490
|
-
for (const filePath of generatedFiles) if (fs.existsSync(filePath)) {
|
|
491
|
-
const displayPath = path.relative(root, filePath).replace(/\\/g, "/");
|
|
492
|
-
const dir = path.dirname(displayPath);
|
|
493
|
-
const base = path.basename(displayPath);
|
|
494
|
-
const coloredPath = dir === "." ? paint("32", base, stdoutColour) : paint("90", `${dir}/`, stdoutColour) + paint("32", base, stdoutColour);
|
|
495
|
-
try {
|
|
496
|
-
const sizeStr = `${(fs.statSync(filePath).size / 1024).toFixed(2)} kB`;
|
|
497
|
-
const content = fs.readFileSync(filePath);
|
|
498
|
-
const gzipSizeStr = `${(zlib.gzipSync(content).length / 1024).toFixed(2)} kB`;
|
|
499
|
-
fileInfos.push({
|
|
500
|
-
coloredPath,
|
|
501
|
-
gzipSizeStr,
|
|
502
|
-
relativeDisplayPath: displayPath,
|
|
503
|
-
sizeStr
|
|
504
|
-
});
|
|
505
|
-
} catch {}
|
|
506
|
-
}
|
|
507
|
-
if (fileInfos.length > 0) {
|
|
508
|
-
const longestPathLength = Math.max(...fileInfos.map((f) => f.relativeDisplayPath.length), 0);
|
|
509
|
-
const longestSizeLength = Math.max(...fileInfos.map((f) => f.sizeStr.length), 0);
|
|
510
|
-
for (const info of fileInfos) {
|
|
511
|
-
const pathPadding = " ".repeat(Math.max(2, longestPathLength - info.relativeDisplayPath.length + 2));
|
|
512
|
-
const sizePadded = info.sizeStr.padStart(longestSizeLength);
|
|
513
|
-
console.log(info.coloredPath + pathPadding + paint("90", `${sizePadded} │ gzip: ${info.gzipSizeStr}`, stdoutColour));
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
};
|
|
517
|
-
const runBuilds = async (resolvedConfigs, context) => {
|
|
518
|
-
const startTime = Date.now();
|
|
519
|
-
const generatedFiles = /* @__PURE__ */ new Set();
|
|
520
|
-
let skipped = 0;
|
|
521
|
-
try {
|
|
522
|
-
if (!context) log("Compiling design tokens...", "info");
|
|
523
|
-
if (onBuildStart) callHook("onBuildStart", onBuildStart);
|
|
524
|
-
for (const [index, item] of resolvedConfigs.entries()) {
|
|
525
|
-
const declared = cache ? await readConfigObject(item, false) : null;
|
|
526
|
-
const selectedPlatforms = platformsFor(context);
|
|
527
|
-
if (declared && await isUpToDate(item, declared, selectedPlatforms)) {
|
|
528
|
-
for (const destination of declaredDestinations(declared)) generatedFiles.add(destination);
|
|
529
|
-
skipped++;
|
|
530
|
-
continue;
|
|
531
|
-
}
|
|
532
|
-
const sd = new StyleDictionary(await configForBuild(item), { init: false });
|
|
533
|
-
await sd.extend(void 0, {
|
|
534
|
-
mutateOriginal: true,
|
|
535
|
-
verbosity
|
|
536
|
-
});
|
|
537
|
-
if (sd.allTokens.length === 0) {
|
|
538
|
-
const asObject = await readConfigObject(item, false);
|
|
539
|
-
const barren = asObject ? await patternsMatchingNothing(sourcePatternsOf(asObject)) : [];
|
|
540
|
-
throw new Error([
|
|
541
|
-
`${describeConfig(item, index)} resolved no tokens, so its output would be emptied.`,
|
|
542
|
-
barren.length > 0 ? `These patterns matched no files: ${barren.join(", ")}` : `It declares no source or include patterns that matched anything.`,
|
|
543
|
-
`Nothing was written. Set failOnError to false to build anyway.`
|
|
544
|
-
].join(" "));
|
|
545
|
-
}
|
|
546
|
-
sd.volume = atomicVolume;
|
|
547
|
-
if (selectedPlatforms === void 0) await sd.buildAllPlatforms();
|
|
548
|
-
else {
|
|
549
|
-
const defined = Object.keys(sd.platforms);
|
|
550
|
-
const unknown = selectedPlatforms.filter((name) => !defined.includes(name));
|
|
551
|
-
if (unknown.length > 0) throw new Error(`${describeConfig(item, index)} does not define the platform(s) ${unknown.join(", ")}. It defines ${defined.join(", ")}.`);
|
|
552
|
-
for (const name of selectedPlatforms) await sd.buildPlatform(name);
|
|
553
|
-
}
|
|
554
|
-
for (const platform of Object.values(sd.platforms)) {
|
|
555
|
-
const buildPath = platform.buildPath ?? "";
|
|
556
|
-
for (const file of platform.files ?? []) if (file.destination) {
|
|
557
|
-
const absoluteBuildPath = path.isAbsolute(buildPath) ? buildPath : path.resolve(root, buildPath);
|
|
558
|
-
const absoluteDestination = path.isAbsolute(file.destination) ? file.destination : path.resolve(absoluteBuildPath, file.destination);
|
|
559
|
-
generatedFiles.add(absoluteDestination);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
const fingerprint = configFingerprint(item);
|
|
563
|
-
if (fingerprint !== null) compiledFingerprints.add(fingerprint);
|
|
564
|
-
}
|
|
565
|
-
generatedDestinations.clear();
|
|
566
|
-
for (const destination of generatedFiles) generatedDestinations.add(destination.replace(/\\/g, "/"));
|
|
567
|
-
} catch (err) {
|
|
568
|
-
const duration = Date.now() - startTime;
|
|
569
|
-
log(`Compilation failed after ${duration}ms: ${errorMessage(err)}`, "error");
|
|
570
|
-
notifyBuildOutcome?.(asError(err));
|
|
571
|
-
if (onBuildError) callHook("onBuildError", onBuildError, err);
|
|
572
|
-
if (failsTheBuild(context)) throw err;
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
notifyBuildOutcome?.(null);
|
|
576
|
-
const duration = Date.now() - startTime;
|
|
577
|
-
if (onBuildEnd) {
|
|
578
|
-
const files = Array.from(generatedFiles).sort((left, right) => left.localeCompare(right));
|
|
579
|
-
callHook("onBuildEnd", onBuildEnd, files, duration);
|
|
580
|
-
}
|
|
581
|
-
const everythingSkipped = skipped === resolvedConfigs.length;
|
|
582
|
-
if (context) {
|
|
583
|
-
log(everythingSkipped ? `Design tokens already up to date after change in ${context} (${duration}ms)` : `Rebuilt design tokens due to change in ${context} (${duration}ms)`, "success");
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
if (report && !quiet && !everythingSkipped && generatedFiles.size > 0) try {
|
|
587
|
-
reportSizes(generatedFiles);
|
|
588
|
-
} catch (err) {
|
|
589
|
-
log(`Failed to report generated file sizes: ${errorMessage(err)}`, "error");
|
|
590
|
-
}
|
|
591
|
-
if (everythingSkipped) {
|
|
592
|
-
log(`Design tokens are already up to date (${duration}ms)`, "success");
|
|
593
|
-
return;
|
|
594
|
-
}
|
|
595
|
-
log(skipped > 0 ? `Compiled successfully! (${duration}ms, ${skipped} already up to date)` : `Compiled successfully! (${duration}ms)`, "success");
|
|
232
|
+
const instance = {
|
|
233
|
+
cache,
|
|
234
|
+
compiledFingerprints,
|
|
235
|
+
failOnError,
|
|
236
|
+
generatedDestinations,
|
|
237
|
+
log,
|
|
238
|
+
notifyBuildOutcome: (error) => {
|
|
239
|
+
notifyBuildOutcome?.(error);
|
|
240
|
+
},
|
|
241
|
+
onBuildEnd,
|
|
242
|
+
onBuildError,
|
|
243
|
+
onBuildStart,
|
|
244
|
+
platformsOption,
|
|
245
|
+
quiet,
|
|
246
|
+
report,
|
|
247
|
+
root: () => root,
|
|
248
|
+
stdoutColour,
|
|
249
|
+
verbosity,
|
|
250
|
+
volume: atomicVolume,
|
|
251
|
+
watch: options.watch
|
|
596
252
|
};
|
|
597
253
|
const compileOnceAcrossInstances = async (resolvedConfigs) => {
|
|
598
254
|
const key = buildKey(root, resolvedConfigs);
|
|
599
255
|
if (key === null) {
|
|
600
|
-
await runBuilds(resolvedConfigs);
|
|
256
|
+
await runBuilds(instance, resolvedConfigs);
|
|
601
257
|
return;
|
|
602
258
|
}
|
|
603
259
|
const running = compilesInFlight.get(key);
|
|
@@ -605,7 +261,7 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
605
261
|
await running;
|
|
606
262
|
return;
|
|
607
263
|
}
|
|
608
|
-
const compile = runBuilds(resolvedConfigs);
|
|
264
|
+
const compile = runBuilds(instance, resolvedConfigs);
|
|
609
265
|
compilesInFlight.set(key, compile);
|
|
610
266
|
try {
|
|
611
267
|
await compile;
|
|
@@ -613,59 +269,35 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
613
269
|
compilesInFlight.delete(key);
|
|
614
270
|
}
|
|
615
271
|
};
|
|
616
|
-
const REBUILD_DEBOUNCE_MS = 50;
|
|
617
|
-
let debounceTimer;
|
|
618
|
-
let pendingReason;
|
|
619
|
-
let inFlight;
|
|
620
|
-
let waiting = [];
|
|
621
272
|
let refreshServerWatchList;
|
|
622
|
-
let
|
|
273
|
+
let closeOwnWatchers;
|
|
274
|
+
const discovery = { announced: false };
|
|
623
275
|
let startupResolved;
|
|
624
276
|
let notifyBuildOutcome;
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
await refreshServerWatchList?.(resolved);
|
|
641
|
-
}
|
|
642
|
-
} catch (err) {
|
|
643
|
-
failure = { error: err };
|
|
644
|
-
if (!compiling) {
|
|
645
|
-
log(`Rebuild failed: ${errorMessage(err)}`, "error");
|
|
646
|
-
notifyBuildOutcome?.(asError(err));
|
|
647
|
-
}
|
|
277
|
+
const rebuild = async (reason) => {
|
|
278
|
+
let compiling = false;
|
|
279
|
+
try {
|
|
280
|
+
const resolved = await resolveConfigs();
|
|
281
|
+
if (resolved.length > 0) {
|
|
282
|
+
compiling = true;
|
|
283
|
+
await runBuilds(instance, resolved, reason);
|
|
284
|
+
compiling = false;
|
|
285
|
+
hasCompiled = true;
|
|
286
|
+
await refreshServerWatchList?.(resolved);
|
|
287
|
+
}
|
|
288
|
+
} catch (err) {
|
|
289
|
+
if (!compiling) {
|
|
290
|
+
log(`Rebuild failed: ${errorMessage(err)}`, "error");
|
|
291
|
+
notifyBuildOutcome?.(asError(err));
|
|
648
292
|
}
|
|
649
|
-
|
|
293
|
+
throw err;
|
|
650
294
|
}
|
|
651
295
|
};
|
|
652
|
-
const schedule =
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
if (failure) reject(asError(failure.error));
|
|
658
|
-
else resolve();
|
|
659
|
-
});
|
|
660
|
-
});
|
|
661
|
-
if (debounceTimer) clearTimeout(debounceTimer);
|
|
662
|
-
debounceTimer = setTimeout(() => {
|
|
663
|
-
debounceTimer = void 0;
|
|
664
|
-
inFlight = (inFlight ?? Promise.resolve()).then(drain);
|
|
665
|
-
}, REBUILD_DEBOUNCE_MS);
|
|
666
|
-
debounceTimer.unref();
|
|
667
|
-
return covered;
|
|
668
|
-
};
|
|
296
|
+
const schedule = createScheduler({
|
|
297
|
+
debounceMs: 50,
|
|
298
|
+
isClosed: () => hostClosed,
|
|
299
|
+
run: rebuild
|
|
300
|
+
});
|
|
669
301
|
const closeWatcher = () => {
|
|
670
302
|
hostClosed = true;
|
|
671
303
|
};
|
|
@@ -719,6 +351,9 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
719
351
|
rollup: { closeWatcher },
|
|
720
352
|
rspack: adoptCompiler,
|
|
721
353
|
vite: {
|
|
354
|
+
buildEnd() {
|
|
355
|
+
closeOwnWatchers?.();
|
|
356
|
+
},
|
|
722
357
|
closeWatcher,
|
|
723
358
|
async configResolved(config) {
|
|
724
359
|
if (rootOption === void 0) root = config.root || process.cwd();
|
|
@@ -771,7 +406,7 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
771
406
|
const watcher = fs.watch(directory, (_event, filename) => {
|
|
772
407
|
if (filename === null) return;
|
|
773
408
|
const changed = path.posix.join(directory, filename);
|
|
774
|
-
if (!isWatchedSource(changed, targets.patterns)) return;
|
|
409
|
+
if (!isWatchedSource(changed, targets.patterns, generatedDestinations)) return;
|
|
775
410
|
schedule(path.basename(changed)).catch(() => {});
|
|
776
411
|
});
|
|
777
412
|
watcher.unref();
|
|
@@ -780,10 +415,10 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
780
415
|
}
|
|
781
416
|
};
|
|
782
417
|
watchNodeModules(targets.paths);
|
|
783
|
-
|
|
418
|
+
closeOwnWatchers = () => {
|
|
784
419
|
for (const watcher of ownWatchers.values()) watcher.close();
|
|
785
420
|
ownWatchers.clear();
|
|
786
|
-
}
|
|
421
|
+
};
|
|
787
422
|
refreshServerWatchList = async (rebuilt) => {
|
|
788
423
|
targets = await getWatchTargets(rebuilt);
|
|
789
424
|
server.watcher.add(targets.paths);
|
|
@@ -813,7 +448,7 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
813
448
|
};
|
|
814
449
|
}
|
|
815
450
|
server.watcher.on("all", (_event, file) => {
|
|
816
|
-
if (!isWatchedSource(file, targets.patterns)) return;
|
|
451
|
+
if (!isWatchedSource(file, targets.patterns, generatedDestinations)) return;
|
|
817
452
|
schedule(path.basename(file)).catch(() => {});
|
|
818
453
|
});
|
|
819
454
|
}
|
|
@@ -823,13 +458,13 @@ const unpluginFactory = (options = {}, meta) => {
|
|
|
823
458
|
adoptWatchMode(this);
|
|
824
459
|
if (hostClosed) return;
|
|
825
460
|
watchRebuild = true;
|
|
826
|
-
if (cachedPatterns && !isWatchedSource(id, cachedPatterns)) return;
|
|
461
|
+
if (cachedPatterns && !isWatchedSource(id, cachedPatterns, generatedDestinations)) return;
|
|
827
462
|
const resolved = await resolveConfigs();
|
|
828
463
|
if (resolved.length === 0) return;
|
|
829
464
|
const { patterns } = await getWatchTargets(resolved);
|
|
830
|
-
if (!isWatchedSource(id, patterns)) return;
|
|
465
|
+
if (!isWatchedSource(id, patterns, generatedDestinations)) return;
|
|
831
466
|
if (!isWebpack) await schedule(path.basename(id));
|
|
832
|
-
for (const file of await expandPatterns(patterns)) this.addWatchFile(file);
|
|
467
|
+
for (const file of await expandPatterns(patterns, log)) this.addWatchFile(file);
|
|
833
468
|
},
|
|
834
469
|
webpack: adoptCompiler
|
|
835
470
|
};
|