@motion-proto/live-tokens 0.16.1 → 0.17.0
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/bin/cli.mjs +25 -3
- package/bin/migrate.mjs +113 -0
- package/dist-plugin/chunk-UBS57IYV.js +249 -0
- package/dist-plugin/index.cjs +200 -3
- package/dist-plugin/index.d.cts +1 -0
- package/dist-plugin/index.d.ts +1 -0
- package/dist-plugin/index.js +165 -182
- package/dist-plugin/tokensCssMigrations/index.cjs +279 -0
- package/dist-plugin/tokensCssMigrations/index.d.cts +144 -0
- package/dist-plugin/tokensCssMigrations/index.d.ts +144 -0
- package/dist-plugin/tokensCssMigrations/index.js +24 -0
- package/package.json +1 -1
- package/src/system/components/CollapsibleSection.svelte +47 -4
package/dist-plugin/index.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
TOKENS_CSS_MIGRATIONS,
|
|
3
|
+
extractGlobalRootBody,
|
|
4
|
+
resolveDataDirs,
|
|
5
|
+
runTokensCssMigrations,
|
|
6
|
+
validateTokensCss
|
|
7
|
+
} from "./chunk-UBS57IYV.js";
|
|
4
8
|
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const bodies = [];
|
|
9
|
-
let m;
|
|
10
|
-
while ((m = re.exec(source)) !== null) {
|
|
11
|
-
bodies.push(m[1]);
|
|
12
|
-
}
|
|
13
|
-
return bodies.join("\n");
|
|
14
|
-
}
|
|
9
|
+
// vite-plugin/themeFileApi.ts
|
|
10
|
+
import fs2 from "fs";
|
|
11
|
+
import path2 from "path";
|
|
15
12
|
|
|
16
13
|
// src/editor/core/storage/files/versionedFileResourceClient.ts
|
|
17
14
|
function sanitizeFileName(name) {
|
|
@@ -520,63 +517,18 @@ function nextAvailableName(exists, baseName, maxAttempts = 1e3) {
|
|
|
520
517
|
throw new Error(`Could not allocate a non-colliding name for "${baseName}"`);
|
|
521
518
|
}
|
|
522
519
|
|
|
523
|
-
// vite-plugin/files/dataPaths.ts
|
|
524
|
-
import fs2 from "fs";
|
|
525
|
-
import path2 from "path";
|
|
526
|
-
var DEFAULT_DATA_DIR = "src/live-tokens/data";
|
|
527
|
-
var KNOWN_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
528
|
-
"dataDir",
|
|
529
|
-
"themesDir",
|
|
530
|
-
"componentConfigsDir",
|
|
531
|
-
"manifestsDir"
|
|
532
|
-
]);
|
|
533
|
-
var cached = null;
|
|
534
|
-
function readLiveTokensConfig() {
|
|
535
|
-
if (cached) return cached;
|
|
536
|
-
try {
|
|
537
|
-
const configPath = path2.resolve("live-tokens.config.json");
|
|
538
|
-
if (!fs2.existsSync(configPath)) return cached = {};
|
|
539
|
-
const parsed = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
|
|
540
|
-
if (!parsed || typeof parsed !== "object") return cached = {};
|
|
541
|
-
const unknown = Object.keys(parsed).filter(
|
|
542
|
-
(k) => k !== "$schema" && !KNOWN_CONFIG_KEYS.has(k)
|
|
543
|
-
);
|
|
544
|
-
if (unknown.length > 0) {
|
|
545
|
-
console.warn(
|
|
546
|
-
`[live-tokens] Unknown key(s) in live-tokens.config.json: ${unknown.join(", ")}. Known keys: ${Array.from(KNOWN_CONFIG_KEYS).join(", ")}.`
|
|
547
|
-
);
|
|
548
|
-
}
|
|
549
|
-
cached = parsed;
|
|
550
|
-
return cached;
|
|
551
|
-
} catch {
|
|
552
|
-
return cached = {};
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
function resolveDataDirs(opts = {}) {
|
|
556
|
-
const fileConfig = readLiveTokensConfig();
|
|
557
|
-
const dataDirRaw = opts.dataDir ?? fileConfig.dataDir ?? DEFAULT_DATA_DIR;
|
|
558
|
-
const dataDir = path2.resolve(dataDirRaw);
|
|
559
|
-
const sub = (name) => path2.resolve(dataDir, name);
|
|
560
|
-
return {
|
|
561
|
-
dataDir,
|
|
562
|
-
themesDir: opts.themesDir ? path2.resolve(opts.themesDir) : fileConfig.themesDir ? path2.resolve(fileConfig.themesDir) : sub("themes"),
|
|
563
|
-
componentConfigsDir: opts.componentConfigsDir ? path2.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? path2.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
|
|
564
|
-
manifestsDir: opts.manifestsDir ? path2.resolve(opts.manifestsDir) : fileConfig.manifestsDir ? path2.resolve(fileConfig.manifestsDir) : sub("manifests")
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
|
|
568
520
|
// vite-plugin/themeFileApi.ts
|
|
569
521
|
import { fileURLToPath } from "url";
|
|
570
522
|
var PKG_VERSION = (() => {
|
|
571
523
|
try {
|
|
572
|
-
let dir =
|
|
524
|
+
let dir = path2.dirname(fileURLToPath(import.meta.url));
|
|
573
525
|
for (let i = 0; i < 4; i++) {
|
|
574
|
-
const p =
|
|
575
|
-
if (
|
|
576
|
-
const json = JSON.parse(
|
|
526
|
+
const p = path2.join(dir, "package.json");
|
|
527
|
+
if (fs2.existsSync(p)) {
|
|
528
|
+
const json = JSON.parse(fs2.readFileSync(p, "utf-8"));
|
|
577
529
|
if (json?.name === "@motion-proto/live-tokens") return json.version ?? "";
|
|
578
530
|
}
|
|
579
|
-
const up =
|
|
531
|
+
const up = path2.dirname(dir);
|
|
580
532
|
if (up === dir) break;
|
|
581
533
|
dir = up;
|
|
582
534
|
}
|
|
@@ -594,23 +546,23 @@ function themeFileApi(opts) {
|
|
|
594
546
|
const THEMES_DIR = dataDirs.themesDir;
|
|
595
547
|
const COMPONENT_CONFIGS_DIR = dataDirs.componentConfigsDir;
|
|
596
548
|
const MANIFESTS_DIR = dataDirs.manifestsDir;
|
|
597
|
-
const CSS_PATH =
|
|
598
|
-
const GENERATED_CSS_PATH = opts.tokensGeneratedCssPath ?
|
|
599
|
-
const FONTS_CSS_PATH = opts.fontsCssPath ?
|
|
549
|
+
const CSS_PATH = path2.resolve(opts.tokensCssPath);
|
|
550
|
+
const GENERATED_CSS_PATH = opts.tokensGeneratedCssPath ? path2.resolve(opts.tokensGeneratedCssPath) : path2.join(dataDirs.dataDir, "tokens.generated.css");
|
|
551
|
+
const FONTS_CSS_PATH = opts.fontsCssPath ? path2.resolve(opts.fontsCssPath) : path2.join(path2.dirname(CSS_PATH), "fonts.css");
|
|
600
552
|
const API_BASE = opts.apiBase ?? "/api/live-tokens";
|
|
601
|
-
const consumerComponentDirs = opts.componentsSrcDir ? [
|
|
602
|
-
const packageComponentsDir =
|
|
603
|
-
|
|
553
|
+
const consumerComponentDirs = opts.componentsSrcDir ? [path2.resolve(opts.componentsSrcDir)] : [path2.resolve("src/components"), path2.resolve("src/system/components")];
|
|
554
|
+
const packageComponentsDir = path2.resolve(
|
|
555
|
+
path2.dirname(fileURLToPath(import.meta.url)),
|
|
604
556
|
"..",
|
|
605
557
|
"src",
|
|
606
558
|
"system",
|
|
607
559
|
"components"
|
|
608
560
|
);
|
|
609
561
|
const COMPONENTS_SCAN_DIRS = [...consumerComponentDirs];
|
|
610
|
-
if (!COMPONENTS_SCAN_DIRS.includes(packageComponentsDir) &&
|
|
562
|
+
if (!COMPONENTS_SCAN_DIRS.includes(packageComponentsDir) && fs2.existsSync(packageComponentsDir)) {
|
|
611
563
|
COMPONENTS_SCAN_DIRS.push(packageComponentsDir);
|
|
612
564
|
}
|
|
613
|
-
const LEGACY_PRESETS_DIR =
|
|
565
|
+
const LEGACY_PRESETS_DIR = path2.resolve("presets");
|
|
614
566
|
const themesResource = versionedFileResourceServer({
|
|
615
567
|
dir: THEMES_DIR
|
|
616
568
|
});
|
|
@@ -618,7 +570,7 @@ function themeFileApi(opts) {
|
|
|
618
570
|
function componentResource(comp) {
|
|
619
571
|
let r = componentResourceCache.get(comp);
|
|
620
572
|
if (!r) {
|
|
621
|
-
r = versionedFileResourceServer({ dir:
|
|
573
|
+
r = versionedFileResourceServer({ dir: path2.join(COMPONENT_CONFIGS_DIR, comp) });
|
|
622
574
|
componentResourceCache.set(comp, r);
|
|
623
575
|
}
|
|
624
576
|
return r;
|
|
@@ -626,7 +578,7 @@ function themeFileApi(opts) {
|
|
|
626
578
|
const manifestsResource = versionedFileResourceServer({ dir: MANIFESTS_DIR });
|
|
627
579
|
function ensureThemesDir() {
|
|
628
580
|
themesResource.ensureDir();
|
|
629
|
-
if (!
|
|
581
|
+
if (!fs2.existsSync(path2.join(THEMES_DIR, "default.json"))) {
|
|
630
582
|
const defaultTheme = {
|
|
631
583
|
name: "Default Theme",
|
|
632
584
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -634,7 +586,7 @@ function themeFileApi(opts) {
|
|
|
634
586
|
editorConfigs: {},
|
|
635
587
|
cssVariables: {}
|
|
636
588
|
};
|
|
637
|
-
|
|
589
|
+
fs2.writeFileSync(path2.join(THEMES_DIR, "default.json"), JSON.stringify(defaultTheme, null, 2));
|
|
638
590
|
}
|
|
639
591
|
themesResource.ensureMeta();
|
|
640
592
|
}
|
|
@@ -699,10 +651,10 @@ function themeFileApi(opts) {
|
|
|
699
651
|
lines.push("/* tokens.css holds developer-authored defaults; this file holds editor overrides. */");
|
|
700
652
|
lines.push("");
|
|
701
653
|
const productionThemeName = themesResource.getProductionName();
|
|
702
|
-
const themePath =
|
|
654
|
+
const themePath = path2.join(THEMES_DIR, `${productionThemeName}.json`);
|
|
703
655
|
let themeVarCount = 0;
|
|
704
|
-
if (
|
|
705
|
-
const themeData = JSON.parse(
|
|
656
|
+
if (fs2.existsSync(themePath)) {
|
|
657
|
+
const themeData = JSON.parse(fs2.readFileSync(themePath, "utf-8"));
|
|
706
658
|
const cssVars = { ...themeData.cssVariables || {} };
|
|
707
659
|
Object.assign(cssVars, palettesToVars(themeData.editorConfigs ?? {}));
|
|
708
660
|
const resolvedFontVars = resolveFontStacks(themeData);
|
|
@@ -721,7 +673,7 @@ function themeFileApi(opts) {
|
|
|
721
673
|
}
|
|
722
674
|
}
|
|
723
675
|
let componentOverrideCount = 0;
|
|
724
|
-
if (
|
|
676
|
+
if (fs2.existsSync(COMPONENT_CONFIGS_DIR)) {
|
|
725
677
|
const blocks = [];
|
|
726
678
|
for (const comp of listComponentNames()) {
|
|
727
679
|
const prod = componentResource(comp).getProductionName();
|
|
@@ -755,21 +707,21 @@ function themeFileApi(opts) {
|
|
|
755
707
|
lines.push("");
|
|
756
708
|
}
|
|
757
709
|
}
|
|
758
|
-
if (!
|
|
759
|
-
|
|
710
|
+
if (!fs2.existsSync(path2.dirname(GENERATED_CSS_PATH))) {
|
|
711
|
+
fs2.mkdirSync(path2.dirname(GENERATED_CSS_PATH), { recursive: true });
|
|
760
712
|
}
|
|
761
|
-
|
|
713
|
+
fs2.writeFileSync(GENERATED_CSS_PATH, lines.join("\n"));
|
|
762
714
|
console.log(
|
|
763
|
-
`[regenerateTokensCss] Wrote ${
|
|
715
|
+
`[regenerateTokensCss] Wrote ${path2.basename(GENERATED_CSS_PATH)} (${themeVarCount} theme vars, ${componentOverrideCount} component overrides)`
|
|
764
716
|
);
|
|
765
717
|
}
|
|
766
718
|
function syncTokensToCss(_fileName) {
|
|
767
719
|
regenerateTokensCss();
|
|
768
720
|
}
|
|
769
721
|
function syncFontsToCss(fileName) {
|
|
770
|
-
const themePath =
|
|
771
|
-
if (!
|
|
772
|
-
const themeData = JSON.parse(
|
|
722
|
+
const themePath = path2.join(THEMES_DIR, `${fileName}.json`);
|
|
723
|
+
if (!fs2.existsSync(themePath)) return;
|
|
724
|
+
const themeData = JSON.parse(fs2.readFileSync(themePath, "utf-8"));
|
|
773
725
|
const sources = themeData.fontSources;
|
|
774
726
|
if (!sources) return;
|
|
775
727
|
const lines = [];
|
|
@@ -793,11 +745,11 @@ function themeFileApi(opts) {
|
|
|
793
745
|
lines.push("");
|
|
794
746
|
}
|
|
795
747
|
const content = lines.join("\n");
|
|
796
|
-
if (!
|
|
797
|
-
|
|
748
|
+
if (!fs2.existsSync(path2.dirname(FONTS_CSS_PATH))) {
|
|
749
|
+
fs2.mkdirSync(path2.dirname(FONTS_CSS_PATH), { recursive: true });
|
|
798
750
|
}
|
|
799
|
-
|
|
800
|
-
console.log(`[syncFontsToCss] Wrote ${sources.length} source(s) into ${
|
|
751
|
+
fs2.writeFileSync(FONTS_CSS_PATH, content);
|
|
752
|
+
console.log(`[syncFontsToCss] Wrote ${sources.length} source(s) into ${path2.basename(FONTS_CSS_PATH)}`);
|
|
801
753
|
}
|
|
802
754
|
function extractAliasDeclarations(body) {
|
|
803
755
|
const aliases = {};
|
|
@@ -807,11 +759,11 @@ function themeFileApi(opts) {
|
|
|
807
759
|
return aliases;
|
|
808
760
|
}
|
|
809
761
|
function componentNameFromFile(filePath) {
|
|
810
|
-
return
|
|
762
|
+
return path2.basename(filePath, ".svelte").toLowerCase();
|
|
811
763
|
}
|
|
812
764
|
function isThemeAwareComponent(filePath) {
|
|
813
765
|
try {
|
|
814
|
-
const source =
|
|
766
|
+
const source = fs2.readFileSync(filePath, "utf-8");
|
|
815
767
|
return /:global\(:root\)\s*\{/.test(source);
|
|
816
768
|
} catch {
|
|
817
769
|
return false;
|
|
@@ -820,10 +772,10 @@ function themeFileApi(opts) {
|
|
|
820
772
|
function listComponentSourcePaths() {
|
|
821
773
|
const byName = /* @__PURE__ */ new Map();
|
|
822
774
|
for (const dir of COMPONENTS_SCAN_DIRS) {
|
|
823
|
-
if (!
|
|
824
|
-
for (const f of
|
|
775
|
+
if (!fs2.existsSync(dir)) continue;
|
|
776
|
+
for (const f of fs2.readdirSync(dir)) {
|
|
825
777
|
if (!f.endsWith(".svelte")) continue;
|
|
826
|
-
const full =
|
|
778
|
+
const full = path2.join(dir, f);
|
|
827
779
|
if (!isThemeAwareComponent(full)) continue;
|
|
828
780
|
const name = componentNameFromFile(f);
|
|
829
781
|
if (!byName.has(name)) byName.set(name, full);
|
|
@@ -834,26 +786,53 @@ function themeFileApi(opts) {
|
|
|
834
786
|
function listComponentNames() {
|
|
835
787
|
return listComponentSourcePaths().map(componentNameFromFile);
|
|
836
788
|
}
|
|
789
|
+
function warnOnTokenDrift(log) {
|
|
790
|
+
let tokensCss = "";
|
|
791
|
+
try {
|
|
792
|
+
tokensCss = fs2.readFileSync(CSS_PATH, "utf-8");
|
|
793
|
+
} catch {
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
let generatedCss = "";
|
|
797
|
+
try {
|
|
798
|
+
generatedCss = fs2.readFileSync(GENERATED_CSS_PATH, "utf-8");
|
|
799
|
+
} catch {
|
|
800
|
+
}
|
|
801
|
+
const componentSources = listComponentSourcePaths().map((p) => ({
|
|
802
|
+
name: componentNameFromFile(p),
|
|
803
|
+
source: fs2.readFileSync(p, "utf-8")
|
|
804
|
+
}));
|
|
805
|
+
const missing = validateTokensCss({ tokensCss, generatedCss, componentSources });
|
|
806
|
+
if (missing.length === 0) return;
|
|
807
|
+
const lines = missing.map(
|
|
808
|
+
(m) => ` ${m.token} (referenced by ${m.referencedBy.join(", ")})`
|
|
809
|
+
);
|
|
810
|
+
log(
|
|
811
|
+
`[live-tokens] ${missing.length} token(s) referenced by components are not defined in ${path2.relative(process.cwd(), CSS_PATH)}:
|
|
812
|
+
${lines.join("\n")}
|
|
813
|
+
These render as blank/empty editor slots. Run \`npx live-tokens migrate\` to reconcile.`
|
|
814
|
+
);
|
|
815
|
+
}
|
|
837
816
|
function generateDefaultConfig(comp, sourcePath) {
|
|
838
|
-
if (!
|
|
817
|
+
if (!fs2.existsSync(sourcePath)) return;
|
|
839
818
|
const r = componentResource(comp);
|
|
840
819
|
r.ensureDir();
|
|
841
820
|
const defaultPath = r.filePath("default");
|
|
842
|
-
const sourceStat =
|
|
843
|
-
if (
|
|
844
|
-
const defaultStat =
|
|
821
|
+
const sourceStat = fs2.statSync(sourcePath);
|
|
822
|
+
if (fs2.existsSync(defaultPath)) {
|
|
823
|
+
const defaultStat = fs2.statSync(defaultPath);
|
|
845
824
|
if (defaultStat.mtimeMs >= sourceStat.mtimeMs) return;
|
|
846
825
|
}
|
|
847
|
-
const source =
|
|
826
|
+
const source = fs2.readFileSync(sourcePath, "utf-8");
|
|
848
827
|
const body = extractGlobalRootBody(source);
|
|
849
828
|
const aliases = extractAliasDeclarations(body);
|
|
850
829
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
851
830
|
let createdAt = now;
|
|
852
831
|
let existingUpdatedAt;
|
|
853
832
|
let existingAliases;
|
|
854
|
-
if (
|
|
833
|
+
if (fs2.existsSync(defaultPath)) {
|
|
855
834
|
try {
|
|
856
|
-
const existing = JSON.parse(
|
|
835
|
+
const existing = JSON.parse(fs2.readFileSync(defaultPath, "utf-8"));
|
|
857
836
|
if (existing.createdAt) createdAt = existing.createdAt;
|
|
858
837
|
if (typeof existing.updatedAt === "string") existingUpdatedAt = existing.updatedAt;
|
|
859
838
|
if (existing.aliases && typeof existing.aliases === "object") {
|
|
@@ -872,14 +851,14 @@ function themeFileApi(opts) {
|
|
|
872
851
|
};
|
|
873
852
|
if (aliasesUnchanged && existingUpdatedAt) {
|
|
874
853
|
const t = /* @__PURE__ */ new Date();
|
|
875
|
-
|
|
854
|
+
fs2.utimesSync(defaultPath, t, t);
|
|
876
855
|
return;
|
|
877
856
|
}
|
|
878
|
-
|
|
857
|
+
fs2.writeFileSync(defaultPath, JSON.stringify(defaultConfig, null, 2));
|
|
879
858
|
}
|
|
880
859
|
function ensureComponentConfigsDir() {
|
|
881
|
-
if (!
|
|
882
|
-
|
|
860
|
+
if (!fs2.existsSync(COMPONENT_CONFIGS_DIR)) {
|
|
861
|
+
fs2.mkdirSync(COMPONENT_CONFIGS_DIR, { recursive: true });
|
|
883
862
|
}
|
|
884
863
|
for (const sourcePath of listComponentSourcePaths()) {
|
|
885
864
|
const comp = componentNameFromFile(sourcePath);
|
|
@@ -890,14 +869,14 @@ function themeFileApi(opts) {
|
|
|
890
869
|
}
|
|
891
870
|
}
|
|
892
871
|
function ensureManifestsDir() {
|
|
893
|
-
if (!
|
|
894
|
-
|
|
895
|
-
const legacyProd =
|
|
896
|
-
if (
|
|
872
|
+
if (!fs2.existsSync(MANIFESTS_DIR) && fs2.existsSync(LEGACY_PRESETS_DIR)) {
|
|
873
|
+
fs2.renameSync(LEGACY_PRESETS_DIR, MANIFESTS_DIR);
|
|
874
|
+
const legacyProd = path2.join(MANIFESTS_DIR, "_production.json");
|
|
875
|
+
if (fs2.existsSync(legacyProd)) fs2.unlinkSync(legacyProd);
|
|
897
876
|
}
|
|
898
877
|
manifestsResource.ensureDir();
|
|
899
|
-
const defaultPath =
|
|
900
|
-
if (!
|
|
878
|
+
const defaultPath = path2.join(MANIFESTS_DIR, "default.json");
|
|
879
|
+
if (!fs2.existsSync(defaultPath)) {
|
|
901
880
|
const componentConfigs = {};
|
|
902
881
|
for (const comp of listComponentNames()) {
|
|
903
882
|
componentConfigs[comp] = componentResource(comp).getActiveName();
|
|
@@ -910,30 +889,30 @@ function themeFileApi(opts) {
|
|
|
910
889
|
theme: themesResource.getActiveName(),
|
|
911
890
|
componentConfigs
|
|
912
891
|
};
|
|
913
|
-
|
|
892
|
+
fs2.writeFileSync(defaultPath, JSON.stringify(defaultManifest, null, 2));
|
|
914
893
|
}
|
|
915
|
-
if (!
|
|
916
|
-
|
|
894
|
+
if (!fs2.existsSync(manifestsResource.activePath)) {
|
|
895
|
+
fs2.writeFileSync(
|
|
917
896
|
manifestsResource.activePath,
|
|
918
897
|
JSON.stringify({ activeFile: "default" })
|
|
919
898
|
);
|
|
920
899
|
} else {
|
|
921
900
|
const activeName = manifestsResource.getActiveName();
|
|
922
|
-
if (!
|
|
901
|
+
if (!fs2.existsSync(manifestsResource.filePath(activeName))) {
|
|
923
902
|
manifestsResource.setActiveName("default");
|
|
924
903
|
}
|
|
925
904
|
}
|
|
926
|
-
const stragglerProd =
|
|
927
|
-
if (
|
|
905
|
+
const stragglerProd = path2.join(MANIFESTS_DIR, "_production.json");
|
|
906
|
+
if (fs2.existsSync(stragglerProd)) fs2.unlinkSync(stragglerProd);
|
|
928
907
|
}
|
|
929
908
|
function patchActiveManifest(field, comp, fileName) {
|
|
930
909
|
const activeFile = manifestsResource.getActiveName();
|
|
931
910
|
if (activeFile === "default") return false;
|
|
932
911
|
const manifestPath = manifestsResource.filePath(activeFile);
|
|
933
|
-
if (!
|
|
912
|
+
if (!fs2.existsSync(manifestPath)) return false;
|
|
934
913
|
let manifest;
|
|
935
914
|
try {
|
|
936
|
-
manifest = JSON.parse(
|
|
915
|
+
manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
|
|
937
916
|
} catch {
|
|
938
917
|
return false;
|
|
939
918
|
}
|
|
@@ -944,7 +923,7 @@ function themeFileApi(opts) {
|
|
|
944
923
|
manifest.componentConfigs[comp] = fileName;
|
|
945
924
|
}
|
|
946
925
|
manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
947
|
-
|
|
926
|
+
fs2.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
948
927
|
return true;
|
|
949
928
|
}
|
|
950
929
|
function formatAliasGradient(v) {
|
|
@@ -976,9 +955,9 @@ function themeFileApi(opts) {
|
|
|
976
955
|
}
|
|
977
956
|
function readComponentConfig(comp, name) {
|
|
978
957
|
const filePath = componentResource(comp).filePath(name);
|
|
979
|
-
if (!
|
|
958
|
+
if (!fs2.existsSync(filePath)) return null;
|
|
980
959
|
try {
|
|
981
|
-
return JSON.parse(
|
|
960
|
+
return JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
982
961
|
} catch {
|
|
983
962
|
return null;
|
|
984
963
|
}
|
|
@@ -1004,9 +983,9 @@ function themeFileApi(opts) {
|
|
|
1004
983
|
const MANIFEST_BY_NAME_REGEX = new RegExp(`^${escapedBase}/manifests/([a-z0-9\\-_]+)$`);
|
|
1005
984
|
async function handleListThemes(_ctx) {
|
|
1006
985
|
const activeFile = themesResource.getActiveName();
|
|
1007
|
-
const files =
|
|
1008
|
-
const filePath =
|
|
1009
|
-
const data = JSON.parse(
|
|
986
|
+
const files = fs2.readdirSync(THEMES_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
987
|
+
const filePath = path2.join(THEMES_DIR, f);
|
|
988
|
+
const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
1010
989
|
const fileName = f.replace(".json", "");
|
|
1011
990
|
return {
|
|
1012
991
|
name: data.name || fileName,
|
|
@@ -1020,18 +999,18 @@ function themeFileApi(opts) {
|
|
|
1020
999
|
async function handleGetActiveTheme({ res }) {
|
|
1021
1000
|
const activeFile = themesResource.getActiveName();
|
|
1022
1001
|
const filePath = themesResource.filePath(activeFile);
|
|
1023
|
-
if (!
|
|
1002
|
+
if (!fs2.existsSync(filePath)) {
|
|
1024
1003
|
jsonResponse(res, 404, { error: "Active theme not found" });
|
|
1025
1004
|
return;
|
|
1026
1005
|
}
|
|
1027
|
-
const data = normalizeTheme(JSON.parse(
|
|
1006
|
+
const data = normalizeTheme(JSON.parse(fs2.readFileSync(filePath, "utf-8")));
|
|
1028
1007
|
data._fileName = activeFile;
|
|
1029
1008
|
jsonResponse(res, 200, data);
|
|
1030
1009
|
}
|
|
1031
1010
|
async function handleSetActiveTheme({ req, res }) {
|
|
1032
1011
|
const body = JSON.parse(await readBody(req));
|
|
1033
1012
|
const fileName = sanitizeFileName(body.name || "default");
|
|
1034
|
-
if (!
|
|
1013
|
+
if (!fs2.existsSync(themesResource.filePath(fileName))) {
|
|
1035
1014
|
jsonResponse(res, 404, { error: "Theme not found" });
|
|
1036
1015
|
return;
|
|
1037
1016
|
}
|
|
@@ -1041,11 +1020,11 @@ function themeFileApi(opts) {
|
|
|
1041
1020
|
async function handleGetProductionTheme({ res }) {
|
|
1042
1021
|
const prodFile = themesResource.getProductionName();
|
|
1043
1022
|
const filePath = themesResource.filePath(prodFile);
|
|
1044
|
-
if (!
|
|
1023
|
+
if (!fs2.existsSync(filePath)) {
|
|
1045
1024
|
jsonResponse(res, 200, { fileName: prodFile, name: prodFile, cssVariables: {} });
|
|
1046
1025
|
return;
|
|
1047
1026
|
}
|
|
1048
|
-
const data = normalizeTheme(JSON.parse(
|
|
1027
|
+
const data = normalizeTheme(JSON.parse(fs2.readFileSync(filePath, "utf-8")));
|
|
1049
1028
|
jsonResponse(res, 200, {
|
|
1050
1029
|
fileName: prodFile,
|
|
1051
1030
|
name: data.name || prodFile,
|
|
@@ -1056,7 +1035,7 @@ function themeFileApi(opts) {
|
|
|
1056
1035
|
async function handleSetProductionTheme({ req, res }) {
|
|
1057
1036
|
const body = JSON.parse(await readBody(req));
|
|
1058
1037
|
const fileName = sanitizeFileName(body.name || "default");
|
|
1059
|
-
if (!
|
|
1038
|
+
if (!fs2.existsSync(themesResource.filePath(fileName))) {
|
|
1060
1039
|
jsonResponse(res, 404, { error: "Theme not found" });
|
|
1061
1040
|
return;
|
|
1062
1041
|
}
|
|
@@ -1072,7 +1051,7 @@ function themeFileApi(opts) {
|
|
|
1072
1051
|
syncFontsToCss(fileName);
|
|
1073
1052
|
syncComponentsToCss();
|
|
1074
1053
|
patchActiveManifest("theme", null, fileName);
|
|
1075
|
-
const data = JSON.parse(
|
|
1054
|
+
const data = JSON.parse(fs2.readFileSync(themesResource.filePath(fileName), "utf-8"));
|
|
1076
1055
|
jsonResponse(res, 200, {
|
|
1077
1056
|
ok: true,
|
|
1078
1057
|
fileName,
|
|
@@ -1084,11 +1063,11 @@ function themeFileApi(opts) {
|
|
|
1084
1063
|
const [fileName] = params;
|
|
1085
1064
|
const filePath = themesResource.filePath(fileName);
|
|
1086
1065
|
if (req.method === "GET") {
|
|
1087
|
-
if (!
|
|
1066
|
+
if (!fs2.existsSync(filePath)) {
|
|
1088
1067
|
jsonResponse(res, 404, { error: "Not found" });
|
|
1089
1068
|
return;
|
|
1090
1069
|
}
|
|
1091
|
-
const data = normalizeTheme(JSON.parse(
|
|
1070
|
+
const data = normalizeTheme(JSON.parse(fs2.readFileSync(filePath, "utf-8")));
|
|
1092
1071
|
data._fileName = fileName;
|
|
1093
1072
|
jsonResponse(res, 200, data);
|
|
1094
1073
|
return;
|
|
@@ -1096,15 +1075,15 @@ function themeFileApi(opts) {
|
|
|
1096
1075
|
if (req.method === "PUT") {
|
|
1097
1076
|
const body = JSON.parse(await readBody(req));
|
|
1098
1077
|
body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1099
|
-
if (
|
|
1078
|
+
if (fs2.existsSync(filePath)) {
|
|
1100
1079
|
try {
|
|
1101
|
-
const existing = JSON.parse(
|
|
1080
|
+
const existing = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
1102
1081
|
if (existing.createdAt) body.createdAt = existing.createdAt;
|
|
1103
1082
|
} catch {
|
|
1104
1083
|
}
|
|
1105
1084
|
}
|
|
1106
1085
|
if (!body.createdAt) body.createdAt = body.updatedAt;
|
|
1107
|
-
|
|
1086
|
+
fs2.writeFileSync(filePath, JSON.stringify(body, null, 2));
|
|
1108
1087
|
if (fileName === themesResource.getProductionName()) {
|
|
1109
1088
|
syncTokensToCss(fileName);
|
|
1110
1089
|
syncFontsToCss(fileName);
|
|
@@ -1125,8 +1104,8 @@ function themeFileApi(opts) {
|
|
|
1125
1104
|
});
|
|
1126
1105
|
return;
|
|
1127
1106
|
}
|
|
1128
|
-
if (
|
|
1129
|
-
|
|
1107
|
+
if (fs2.existsSync(filePath)) {
|
|
1108
|
+
fs2.unlinkSync(filePath);
|
|
1130
1109
|
if (themesResource.getActiveName() === fileName) {
|
|
1131
1110
|
themesResource.setActiveName("default");
|
|
1132
1111
|
}
|
|
@@ -1163,7 +1142,7 @@ function themeFileApi(opts) {
|
|
|
1163
1142
|
const fileName = sanitizeFileName(body.name || "default");
|
|
1164
1143
|
const r = componentResource(comp);
|
|
1165
1144
|
const configPath = r.filePath(fileName);
|
|
1166
|
-
if (!
|
|
1145
|
+
if (!fs2.existsSync(configPath)) {
|
|
1167
1146
|
jsonResponse(res, 404, { error: "Config not found" });
|
|
1168
1147
|
return;
|
|
1169
1148
|
}
|
|
@@ -1188,7 +1167,7 @@ function themeFileApi(opts) {
|
|
|
1188
1167
|
const fileName = sanitizeFileName(body.name || "default");
|
|
1189
1168
|
const r = componentResource(comp);
|
|
1190
1169
|
const configPath = r.filePath(fileName);
|
|
1191
|
-
if (!
|
|
1170
|
+
if (!fs2.existsSync(configPath)) {
|
|
1192
1171
|
jsonResponse(res, 404, { error: "Config not found" });
|
|
1193
1172
|
return;
|
|
1194
1173
|
}
|
|
@@ -1216,11 +1195,11 @@ function themeFileApi(opts) {
|
|
|
1216
1195
|
const r = componentResource(comp);
|
|
1217
1196
|
const configPath = r.filePath(name);
|
|
1218
1197
|
if (req.method === "GET") {
|
|
1219
|
-
if (!
|
|
1198
|
+
if (!fs2.existsSync(configPath)) {
|
|
1220
1199
|
jsonResponse(res, 404, { error: "Not found" });
|
|
1221
1200
|
return;
|
|
1222
1201
|
}
|
|
1223
|
-
const data = JSON.parse(
|
|
1202
|
+
const data = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
|
|
1224
1203
|
data._fileName = name;
|
|
1225
1204
|
jsonResponse(res, 200, data);
|
|
1226
1205
|
return;
|
|
@@ -1234,16 +1213,16 @@ function themeFileApi(opts) {
|
|
|
1234
1213
|
body.component = comp;
|
|
1235
1214
|
body.name = body.name || name;
|
|
1236
1215
|
body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1237
|
-
if (
|
|
1216
|
+
if (fs2.existsSync(configPath)) {
|
|
1238
1217
|
try {
|
|
1239
|
-
const existing = JSON.parse(
|
|
1218
|
+
const existing = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
|
|
1240
1219
|
if (existing.createdAt) body.createdAt = existing.createdAt;
|
|
1241
1220
|
} catch {
|
|
1242
1221
|
}
|
|
1243
1222
|
}
|
|
1244
1223
|
if (!body.createdAt) body.createdAt = body.updatedAt;
|
|
1245
1224
|
r.ensureDir();
|
|
1246
|
-
|
|
1225
|
+
fs2.writeFileSync(configPath, JSON.stringify(body, null, 2));
|
|
1247
1226
|
if (r.getProductionName() === name) {
|
|
1248
1227
|
syncComponentsToCss();
|
|
1249
1228
|
}
|
|
@@ -1255,8 +1234,8 @@ function themeFileApi(opts) {
|
|
|
1255
1234
|
jsonResponse(res, 403, { error: "Cannot delete default config" });
|
|
1256
1235
|
return;
|
|
1257
1236
|
}
|
|
1258
|
-
if (
|
|
1259
|
-
|
|
1237
|
+
if (fs2.existsSync(configPath)) {
|
|
1238
|
+
fs2.unlinkSync(configPath);
|
|
1260
1239
|
if (r.getActiveName() === name) {
|
|
1261
1240
|
r.setActiveName("default");
|
|
1262
1241
|
}
|
|
@@ -1272,15 +1251,15 @@ function themeFileApi(opts) {
|
|
|
1272
1251
|
async function handleListComponentConfigs({ params, res }) {
|
|
1273
1252
|
const [comp] = params;
|
|
1274
1253
|
const r = componentResource(comp);
|
|
1275
|
-
if (!
|
|
1254
|
+
if (!fs2.existsSync(r.dir)) {
|
|
1276
1255
|
jsonResponse(res, 404, { error: "Component not found" });
|
|
1277
1256
|
return;
|
|
1278
1257
|
}
|
|
1279
1258
|
const activeFile = r.getActiveName();
|
|
1280
1259
|
const productionFile = r.getProductionName();
|
|
1281
|
-
const files =
|
|
1282
|
-
const filePath =
|
|
1283
|
-
const data = JSON.parse(
|
|
1260
|
+
const files = fs2.readdirSync(r.dir).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
1261
|
+
const filePath = path2.join(r.dir, f);
|
|
1262
|
+
const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
1284
1263
|
const fileName = f.replace(".json", "");
|
|
1285
1264
|
return {
|
|
1286
1265
|
name: data.name || fileName,
|
|
@@ -1294,9 +1273,9 @@ function themeFileApi(opts) {
|
|
|
1294
1273
|
}
|
|
1295
1274
|
async function handleListManifests({ res }) {
|
|
1296
1275
|
const activeFile = manifestsResource.getActiveName();
|
|
1297
|
-
const files =
|
|
1298
|
-
const filePath =
|
|
1299
|
-
const data = JSON.parse(
|
|
1276
|
+
const files = fs2.readdirSync(MANIFESTS_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
1277
|
+
const filePath = path2.join(MANIFESTS_DIR, f);
|
|
1278
|
+
const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
1300
1279
|
const fileName = f.replace(".json", "");
|
|
1301
1280
|
return {
|
|
1302
1281
|
name: data.name || fileName,
|
|
@@ -1311,18 +1290,18 @@ function themeFileApi(opts) {
|
|
|
1311
1290
|
async function handleGetActiveManifest({ res }) {
|
|
1312
1291
|
const activeFile = manifestsResource.getActiveName();
|
|
1313
1292
|
const filePath = manifestsResource.filePath(activeFile);
|
|
1314
|
-
if (!
|
|
1293
|
+
if (!fs2.existsSync(filePath)) {
|
|
1315
1294
|
jsonResponse(res, 404, { error: "Active manifest not found" });
|
|
1316
1295
|
return;
|
|
1317
1296
|
}
|
|
1318
|
-
const data = JSON.parse(
|
|
1297
|
+
const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
1319
1298
|
data._fileName = activeFile;
|
|
1320
1299
|
jsonResponse(res, 200, data);
|
|
1321
1300
|
}
|
|
1322
1301
|
async function handleSetActiveManifest({ req, res }) {
|
|
1323
1302
|
const body = JSON.parse(await readBody(req));
|
|
1324
1303
|
const fileName = sanitizeFileName(body.name || "default");
|
|
1325
|
-
if (!
|
|
1304
|
+
if (!fs2.existsSync(manifestsResource.filePath(fileName))) {
|
|
1326
1305
|
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
1327
1306
|
return;
|
|
1328
1307
|
}
|
|
@@ -1333,11 +1312,11 @@ function themeFileApi(opts) {
|
|
|
1333
1312
|
const [fileName] = params;
|
|
1334
1313
|
const filePath = manifestsResource.filePath(fileName);
|
|
1335
1314
|
if (req.method === "GET") {
|
|
1336
|
-
if (!
|
|
1315
|
+
if (!fs2.existsSync(filePath)) {
|
|
1337
1316
|
jsonResponse(res, 404, { error: "Not found" });
|
|
1338
1317
|
return;
|
|
1339
1318
|
}
|
|
1340
|
-
const data = JSON.parse(
|
|
1319
|
+
const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
1341
1320
|
data._fileName = fileName;
|
|
1342
1321
|
jsonResponse(res, 200, data);
|
|
1343
1322
|
return;
|
|
@@ -1349,15 +1328,15 @@ function themeFileApi(opts) {
|
|
|
1349
1328
|
}
|
|
1350
1329
|
const body = JSON.parse(await readBody(req));
|
|
1351
1330
|
body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1352
|
-
if (
|
|
1331
|
+
if (fs2.existsSync(filePath)) {
|
|
1353
1332
|
try {
|
|
1354
|
-
const existing = JSON.parse(
|
|
1333
|
+
const existing = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
1355
1334
|
if (existing.createdAt) body.createdAt = existing.createdAt;
|
|
1356
1335
|
} catch {
|
|
1357
1336
|
}
|
|
1358
1337
|
}
|
|
1359
1338
|
if (!body.createdAt) body.createdAt = body.updatedAt;
|
|
1360
|
-
|
|
1339
|
+
fs2.writeFileSync(filePath, JSON.stringify(body, null, 2));
|
|
1361
1340
|
jsonResponse(res, 200, { ok: true, fileName });
|
|
1362
1341
|
return;
|
|
1363
1342
|
}
|
|
@@ -1366,8 +1345,8 @@ function themeFileApi(opts) {
|
|
|
1366
1345
|
jsonResponse(res, 403, { error: "Cannot delete the default manifest" });
|
|
1367
1346
|
return;
|
|
1368
1347
|
}
|
|
1369
|
-
if (
|
|
1370
|
-
|
|
1348
|
+
if (fs2.existsSync(filePath)) {
|
|
1349
|
+
fs2.unlinkSync(filePath);
|
|
1371
1350
|
if (manifestsResource.getActiveName() === fileName) {
|
|
1372
1351
|
manifestsResource.setActiveName("default");
|
|
1373
1352
|
}
|
|
@@ -1379,14 +1358,14 @@ function themeFileApi(opts) {
|
|
|
1379
1358
|
async function handleApplyManifest({ params, res }) {
|
|
1380
1359
|
const [fileName] = params;
|
|
1381
1360
|
const manifestPath = manifestsResource.filePath(fileName);
|
|
1382
|
-
if (!
|
|
1361
|
+
if (!fs2.existsSync(manifestPath)) {
|
|
1383
1362
|
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
1384
1363
|
return;
|
|
1385
1364
|
}
|
|
1386
|
-
const manifest = JSON.parse(
|
|
1365
|
+
const manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
|
|
1387
1366
|
const themeName = sanitizeFileName(manifest.theme || "default");
|
|
1388
1367
|
const themePath = themesResource.filePath(themeName);
|
|
1389
|
-
if (!
|
|
1368
|
+
if (!fs2.existsSync(themePath)) {
|
|
1390
1369
|
jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
|
|
1391
1370
|
return;
|
|
1392
1371
|
}
|
|
@@ -1399,7 +1378,7 @@ function themeFileApi(opts) {
|
|
|
1399
1378
|
const sanitized = sanitizeFileName(String(configFile) || "default");
|
|
1400
1379
|
const r = componentResource(comp);
|
|
1401
1380
|
const cfgPath = r.filePath(sanitized);
|
|
1402
|
-
if (!
|
|
1381
|
+
if (!fs2.existsSync(cfgPath)) {
|
|
1403
1382
|
jsonResponse(res, 422, {
|
|
1404
1383
|
error: `Manifest references missing config: ${comp}/${sanitized}`
|
|
1405
1384
|
});
|
|
@@ -1411,7 +1390,7 @@ function themeFileApi(opts) {
|
|
|
1411
1390
|
themesResource.setProductionName(themeName);
|
|
1412
1391
|
syncTokensToCss(themeName);
|
|
1413
1392
|
syncFontsToCss(themeName);
|
|
1414
|
-
const themeData = normalizeTheme(JSON.parse(
|
|
1393
|
+
const themeData = normalizeTheme(JSON.parse(fs2.readFileSync(themePath, "utf-8")));
|
|
1415
1394
|
themeData._fileName = themeName;
|
|
1416
1395
|
for (const [comp, configFile] of apply) {
|
|
1417
1396
|
const r = componentResource(comp);
|
|
@@ -1438,18 +1417,18 @@ function themeFileApi(opts) {
|
|
|
1438
1417
|
async function handleExportManifest({ params, res }) {
|
|
1439
1418
|
const [fileName] = params;
|
|
1440
1419
|
const manifestPath = manifestsResource.filePath(fileName);
|
|
1441
|
-
if (!
|
|
1420
|
+
if (!fs2.existsSync(manifestPath)) {
|
|
1442
1421
|
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
1443
1422
|
return;
|
|
1444
1423
|
}
|
|
1445
|
-
const manifest = JSON.parse(
|
|
1424
|
+
const manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
|
|
1446
1425
|
const themeName = sanitizeFileName(manifest.theme || "default");
|
|
1447
1426
|
const themePath = themesResource.filePath(themeName);
|
|
1448
|
-
if (!
|
|
1427
|
+
if (!fs2.existsSync(themePath)) {
|
|
1449
1428
|
jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
|
|
1450
1429
|
return;
|
|
1451
1430
|
}
|
|
1452
|
-
const theme = JSON.parse(
|
|
1431
|
+
const theme = JSON.parse(fs2.readFileSync(themePath, "utf-8"));
|
|
1453
1432
|
const knownComponents = new Set(listComponentNames());
|
|
1454
1433
|
const componentConfigs = {};
|
|
1455
1434
|
for (const [comp, configFile] of Object.entries(manifest.componentConfigs ?? {})) {
|
|
@@ -1457,13 +1436,13 @@ function themeFileApi(opts) {
|
|
|
1457
1436
|
const sanitized = sanitizeFileName(String(configFile) || "default");
|
|
1458
1437
|
if (sanitized === "default") continue;
|
|
1459
1438
|
const cfgPath = componentResource(comp).filePath(sanitized);
|
|
1460
|
-
if (!
|
|
1439
|
+
if (!fs2.existsSync(cfgPath)) {
|
|
1461
1440
|
jsonResponse(res, 422, {
|
|
1462
1441
|
error: `Manifest references missing config: ${comp}/${sanitized}`
|
|
1463
1442
|
});
|
|
1464
1443
|
return;
|
|
1465
1444
|
}
|
|
1466
|
-
const cfg = JSON.parse(
|
|
1445
|
+
const cfg = JSON.parse(fs2.readFileSync(cfgPath, "utf-8"));
|
|
1467
1446
|
componentConfigs[`${comp}/${sanitized}`] = cfg;
|
|
1468
1447
|
}
|
|
1469
1448
|
const bundle = {
|
|
@@ -1485,7 +1464,7 @@ function themeFileApi(opts) {
|
|
|
1485
1464
|
}
|
|
1486
1465
|
function nextAvailableName2(resourceFilePath, baseName) {
|
|
1487
1466
|
return nextAvailableName(
|
|
1488
|
-
(n) =>
|
|
1467
|
+
(n) => fs2.existsSync(resourceFilePath(n)),
|
|
1489
1468
|
sanitizeFileName(baseName)
|
|
1490
1469
|
);
|
|
1491
1470
|
}
|
|
@@ -1527,7 +1506,7 @@ function themeFileApi(opts) {
|
|
|
1527
1506
|
themeBody.updatedAt = now;
|
|
1528
1507
|
if (!themeBody.createdAt) themeBody.createdAt = now;
|
|
1529
1508
|
themesResource.ensureDir();
|
|
1530
|
-
|
|
1509
|
+
fs2.writeFileSync(themesResource.filePath(finalThemeName), JSON.stringify(themeBody, null, 2));
|
|
1531
1510
|
const knownComponents = new Set(listComponentNames());
|
|
1532
1511
|
const componentRenames = {};
|
|
1533
1512
|
for (const [key, cfgValue] of Object.entries(bundle.componentConfigs)) {
|
|
@@ -1549,7 +1528,7 @@ function themeFileApi(opts) {
|
|
|
1549
1528
|
cfgBody.updatedAt = now;
|
|
1550
1529
|
if (!cfgBody.createdAt) cfgBody.createdAt = now;
|
|
1551
1530
|
r.ensureDir();
|
|
1552
|
-
|
|
1531
|
+
fs2.writeFileSync(r.filePath(finalName), JSON.stringify(cfgBody, null, 2));
|
|
1553
1532
|
}
|
|
1554
1533
|
const rewrittenManifest = {
|
|
1555
1534
|
...bundle.manifest,
|
|
@@ -1576,7 +1555,7 @@ function themeFileApi(opts) {
|
|
|
1576
1555
|
renames[`manifest:${originalManifestName}`] = finalManifestName;
|
|
1577
1556
|
}
|
|
1578
1557
|
manifestsResource.ensureDir();
|
|
1579
|
-
|
|
1558
|
+
fs2.writeFileSync(
|
|
1580
1559
|
manifestsResource.filePath(finalManifestName),
|
|
1581
1560
|
JSON.stringify(rewrittenManifest, null, 2)
|
|
1582
1561
|
);
|
|
@@ -1659,13 +1638,14 @@ function themeFileApi(opts) {
|
|
|
1659
1638
|
ensureComponentConfigsDir();
|
|
1660
1639
|
ensureManifestsDir();
|
|
1661
1640
|
regenerateTokensCss();
|
|
1641
|
+
warnOnTokenDrift((msg) => server.config.logger.warn(msg));
|
|
1662
1642
|
server.middlewares.use(async (req, res, next) => {
|
|
1663
1643
|
const handled = await dispatch(req, res, routes);
|
|
1664
1644
|
if (!handled) next();
|
|
1665
1645
|
});
|
|
1666
1646
|
},
|
|
1667
1647
|
handleHotUpdate(ctx) {
|
|
1668
|
-
const normalized =
|
|
1648
|
+
const normalized = path2.resolve(ctx.file);
|
|
1669
1649
|
if (!COMPONENTS_SCAN_DIRS.some((d) => normalized.startsWith(d))) return;
|
|
1670
1650
|
if (!normalized.endsWith(".svelte")) return;
|
|
1671
1651
|
if (!isThemeAwareComponent(normalized)) return;
|
|
@@ -1675,5 +1655,8 @@ function themeFileApi(opts) {
|
|
|
1675
1655
|
};
|
|
1676
1656
|
}
|
|
1677
1657
|
export {
|
|
1678
|
-
|
|
1658
|
+
TOKENS_CSS_MIGRATIONS,
|
|
1659
|
+
runTokensCssMigrations,
|
|
1660
|
+
themeFileApi,
|
|
1661
|
+
validateTokensCss
|
|
1679
1662
|
};
|