@motion-proto/live-tokens 0.8.0 → 0.10.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/.claude/skills/live-tokens-add-component/SKILL.md +488 -0
- package/README.md +84 -29
- package/dist-plugin/index.cjs +177 -125
- package/dist-plugin/index.d.cts +3 -2
- package/dist-plugin/index.d.ts +3 -2
- package/dist-plugin/index.js +177 -125
- package/package.json +8 -2
- package/src/editor/component-editor/BadgeEditor.svelte +44 -42
- package/src/editor/component-editor/ButtonEditor.svelte +224 -0
- package/src/editor/component-editor/CollapsibleSectionEditor.svelte +1 -7
- package/src/editor/component-editor/CornerBadgeEditor.svelte +44 -34
- package/src/editor/component-editor/ImageLightboxEditor.svelte +58 -0
- package/src/editor/component-editor/InputEditor.svelte +272 -0
- package/src/editor/component-editor/NotificationEditor.svelte +44 -65
- package/src/editor/component-editor/ProgressBarEditor.svelte +71 -87
- package/src/editor/component-editor/SegmentedControlEditor.svelte +98 -37
- package/src/editor/component-editor/SideNavigationEditor.svelte +342 -0
- package/src/editor/component-editor/index.ts +16 -1
- package/src/editor/component-editor/registry.ts +138 -28
- package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +3 -2
- package/src/editor/component-editor/scaffolding/ComponentsTab.svelte +2 -2
- package/src/editor/component-editor/scaffolding/StateBlock.svelte +9 -10
- package/src/editor/component-editor/scaffolding/TokenLayout.svelte +60 -36
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +38 -1
- package/src/editor/component-editor/scaffolding/buildTypeGroupTokens.ts +1 -1
- package/src/editor/component-editor/scaffolding/componentSources.ts +3 -3
- package/src/editor/component-editor/scaffolding/defaultSections.ts +15 -10
- package/src/editor/component-editor/scaffolding/siblings.ts +2 -2
- package/src/editor/component-editor/scaffolding/types.ts +2 -1
- package/src/editor/core/components/componentConfigKeys.ts +14 -3
- package/src/editor/core/components/componentConfigService.ts +7 -6
- package/src/editor/core/manifests/manifestService.ts +5 -4
- package/src/editor/core/storage/apiBase.ts +15 -0
- package/src/editor/core/storage/files/versionedFileResourceClient.ts +1 -1
- package/src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts +28 -0
- package/src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts +41 -0
- package/src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts +59 -0
- package/src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts +29 -0
- package/src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts +46 -0
- package/src/editor/core/themes/migrations/index.ts +10 -0
- package/src/editor/core/themes/slices/components.ts +9 -0
- package/src/editor/core/themes/themeInit.ts +3 -2
- package/src/editor/core/themes/themeService.ts +3 -2
- package/src/editor/index.ts +10 -1
- package/src/editor/pages/ComponentEditorPage.svelte +53 -3
- package/src/editor/pages/EditorShell.svelte +53 -3
- package/src/editor/ui/UIEasingSelector.svelte +240 -0
- package/src/editor/ui/variantScales.ts +34 -0
- package/src/system/components/Button.svelte +34 -85
- package/src/system/components/CollapsibleSection.svelte +1 -48
- package/src/system/components/CornerBadge.svelte +72 -138
- package/src/system/components/Dialog.svelte +24 -4
- package/src/system/components/ImageLightbox.svelte +578 -0
- package/src/system/components/Input.svelte +387 -0
- package/src/system/components/ProgressBar.svelte +62 -258
- package/src/system/components/SectionDivider.svelte +117 -43
- package/src/system/components/SegmentedControl.svelte +81 -15
- package/src/system/components/SideNavigation.svelte +777 -0
- package/src/system/styles/tokens.css +43 -0
- package/src/system/styles/tokens.generated.css +4 -183
- package/src/editor/component-editor/StandardButtonsEditor.svelte +0 -190
package/dist-plugin/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// vite-plugin/themeFileApi.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import fs3 from "fs";
|
|
3
|
+
import path3 from "path";
|
|
4
4
|
|
|
5
5
|
// src/editor/core/themes/parsers/globalRootBlock.ts
|
|
6
6
|
function extractGlobalRootBody(source) {
|
|
@@ -520,18 +520,63 @@ function nextAvailableName(exists, baseName, maxAttempts = 1e3) {
|
|
|
520
520
|
throw new Error(`Could not allocate a non-colliding name for "${baseName}"`);
|
|
521
521
|
}
|
|
522
522
|
|
|
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
|
+
|
|
523
568
|
// vite-plugin/themeFileApi.ts
|
|
524
569
|
import { fileURLToPath } from "url";
|
|
525
570
|
var PKG_VERSION = (() => {
|
|
526
571
|
try {
|
|
527
|
-
let dir =
|
|
572
|
+
let dir = path3.dirname(fileURLToPath(import.meta.url));
|
|
528
573
|
for (let i = 0; i < 4; i++) {
|
|
529
|
-
const p =
|
|
530
|
-
if (
|
|
531
|
-
const json = JSON.parse(
|
|
574
|
+
const p = path3.join(dir, "package.json");
|
|
575
|
+
if (fs3.existsSync(p)) {
|
|
576
|
+
const json = JSON.parse(fs3.readFileSync(p, "utf-8"));
|
|
532
577
|
if (json?.name === "@motion-proto/live-tokens") return json.version ?? "";
|
|
533
578
|
}
|
|
534
|
-
const up =
|
|
579
|
+
const up = path3.dirname(dir);
|
|
535
580
|
if (up === dir) break;
|
|
536
581
|
dir = up;
|
|
537
582
|
}
|
|
@@ -540,15 +585,21 @@ var PKG_VERSION = (() => {
|
|
|
540
585
|
return "";
|
|
541
586
|
})();
|
|
542
587
|
function themeFileApi(opts) {
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const
|
|
550
|
-
const
|
|
551
|
-
const
|
|
588
|
+
const dataDirs = resolveDataDirs({
|
|
589
|
+
dataDir: opts.dataDir,
|
|
590
|
+
themesDir: opts.themesDir,
|
|
591
|
+
componentConfigsDir: opts.componentConfigsDir,
|
|
592
|
+
manifestsDir: opts.manifestsDir
|
|
593
|
+
});
|
|
594
|
+
const THEMES_DIR = dataDirs.themesDir;
|
|
595
|
+
const COMPONENT_CONFIGS_DIR = dataDirs.componentConfigsDir;
|
|
596
|
+
const MANIFESTS_DIR = dataDirs.manifestsDir;
|
|
597
|
+
const CSS_PATH = path3.resolve(opts.tokensCssPath);
|
|
598
|
+
const GENERATED_CSS_PATH = opts.tokensGeneratedCssPath ? path3.resolve(opts.tokensGeneratedCssPath) : path3.join(path3.dirname(CSS_PATH), "tokens.generated.css");
|
|
599
|
+
const FONTS_CSS_PATH = opts.fontsCssPath ? path3.resolve(opts.fontsCssPath) : path3.join(path3.dirname(CSS_PATH), "fonts.css");
|
|
600
|
+
const API_BASE = opts.apiBase ?? "/api/live-tokens";
|
|
601
|
+
const COMPONENTS_SRC_DIR = opts.componentsSrcDir ? path3.resolve(opts.componentsSrcDir) : path3.resolve("src/system/components");
|
|
602
|
+
const LEGACY_PRESETS_DIR = path3.resolve("presets");
|
|
552
603
|
const themesResource = versionedFileResourceServer({
|
|
553
604
|
dir: THEMES_DIR
|
|
554
605
|
});
|
|
@@ -556,7 +607,7 @@ function themeFileApi(opts) {
|
|
|
556
607
|
function componentResource(comp) {
|
|
557
608
|
let r = componentResourceCache.get(comp);
|
|
558
609
|
if (!r) {
|
|
559
|
-
r = versionedFileResourceServer({ dir:
|
|
610
|
+
r = versionedFileResourceServer({ dir: path3.join(COMPONENT_CONFIGS_DIR, comp) });
|
|
560
611
|
componentResourceCache.set(comp, r);
|
|
561
612
|
}
|
|
562
613
|
return r;
|
|
@@ -564,7 +615,7 @@ function themeFileApi(opts) {
|
|
|
564
615
|
const manifestsResource = versionedFileResourceServer({ dir: MANIFESTS_DIR });
|
|
565
616
|
function ensureThemesDir() {
|
|
566
617
|
themesResource.ensureDir();
|
|
567
|
-
if (!
|
|
618
|
+
if (!fs3.existsSync(path3.join(THEMES_DIR, "default.json"))) {
|
|
568
619
|
const defaultTheme = {
|
|
569
620
|
name: "Default Theme",
|
|
570
621
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -572,7 +623,7 @@ function themeFileApi(opts) {
|
|
|
572
623
|
editorConfigs: {},
|
|
573
624
|
cssVariables: {}
|
|
574
625
|
};
|
|
575
|
-
|
|
626
|
+
fs3.writeFileSync(path3.join(THEMES_DIR, "default.json"), JSON.stringify(defaultTheme, null, 2));
|
|
576
627
|
}
|
|
577
628
|
themesResource.ensureMeta();
|
|
578
629
|
}
|
|
@@ -637,10 +688,10 @@ function themeFileApi(opts) {
|
|
|
637
688
|
lines.push("/* tokens.css holds developer-authored defaults; this file holds editor overrides. */");
|
|
638
689
|
lines.push("");
|
|
639
690
|
const productionThemeName = themesResource.getProductionName();
|
|
640
|
-
const themePath =
|
|
691
|
+
const themePath = path3.join(THEMES_DIR, `${productionThemeName}.json`);
|
|
641
692
|
let themeVarCount = 0;
|
|
642
|
-
if (
|
|
643
|
-
const themeData = JSON.parse(
|
|
693
|
+
if (fs3.existsSync(themePath)) {
|
|
694
|
+
const themeData = JSON.parse(fs3.readFileSync(themePath, "utf-8"));
|
|
644
695
|
const cssVars = { ...themeData.cssVariables || {} };
|
|
645
696
|
Object.assign(cssVars, palettesToVars(themeData.editorConfigs ?? {}));
|
|
646
697
|
const resolvedFontVars = resolveFontStacks(themeData);
|
|
@@ -659,7 +710,7 @@ function themeFileApi(opts) {
|
|
|
659
710
|
}
|
|
660
711
|
}
|
|
661
712
|
let componentOverrideCount = 0;
|
|
662
|
-
if (
|
|
713
|
+
if (fs3.existsSync(COMPONENT_CONFIGS_DIR)) {
|
|
663
714
|
const blocks = [];
|
|
664
715
|
for (const comp of listComponentNames()) {
|
|
665
716
|
const prod = componentResource(comp).getProductionName();
|
|
@@ -693,21 +744,21 @@ function themeFileApi(opts) {
|
|
|
693
744
|
lines.push("");
|
|
694
745
|
}
|
|
695
746
|
}
|
|
696
|
-
if (!
|
|
697
|
-
|
|
747
|
+
if (!fs3.existsSync(path3.dirname(GENERATED_CSS_PATH))) {
|
|
748
|
+
fs3.mkdirSync(path3.dirname(GENERATED_CSS_PATH), { recursive: true });
|
|
698
749
|
}
|
|
699
|
-
|
|
750
|
+
fs3.writeFileSync(GENERATED_CSS_PATH, lines.join("\n"));
|
|
700
751
|
console.log(
|
|
701
|
-
`[regenerateTokensCss] Wrote ${
|
|
752
|
+
`[regenerateTokensCss] Wrote ${path3.basename(GENERATED_CSS_PATH)} (${themeVarCount} theme vars, ${componentOverrideCount} component overrides)`
|
|
702
753
|
);
|
|
703
754
|
}
|
|
704
755
|
function syncTokensToCss(_fileName) {
|
|
705
756
|
regenerateTokensCss();
|
|
706
757
|
}
|
|
707
758
|
function syncFontsToCss(fileName) {
|
|
708
|
-
const themePath =
|
|
709
|
-
if (!
|
|
710
|
-
const themeData = JSON.parse(
|
|
759
|
+
const themePath = path3.join(THEMES_DIR, `${fileName}.json`);
|
|
760
|
+
if (!fs3.existsSync(themePath)) return;
|
|
761
|
+
const themeData = JSON.parse(fs3.readFileSync(themePath, "utf-8"));
|
|
711
762
|
const sources = themeData.fontSources;
|
|
712
763
|
if (!sources) return;
|
|
713
764
|
const lines = [];
|
|
@@ -731,11 +782,11 @@ function themeFileApi(opts) {
|
|
|
731
782
|
lines.push("");
|
|
732
783
|
}
|
|
733
784
|
const content = lines.join("\n");
|
|
734
|
-
if (!
|
|
735
|
-
|
|
785
|
+
if (!fs3.existsSync(path3.dirname(FONTS_CSS_PATH))) {
|
|
786
|
+
fs3.mkdirSync(path3.dirname(FONTS_CSS_PATH), { recursive: true });
|
|
736
787
|
}
|
|
737
|
-
|
|
738
|
-
console.log(`[syncFontsToCss] Wrote ${sources.length} source(s) into ${
|
|
788
|
+
fs3.writeFileSync(FONTS_CSS_PATH, content);
|
|
789
|
+
console.log(`[syncFontsToCss] Wrote ${sources.length} source(s) into ${path3.basename(FONTS_CSS_PATH)}`);
|
|
739
790
|
}
|
|
740
791
|
function extractAliasDeclarations(body) {
|
|
741
792
|
const aliases = {};
|
|
@@ -745,35 +796,35 @@ function themeFileApi(opts) {
|
|
|
745
796
|
return aliases;
|
|
746
797
|
}
|
|
747
798
|
function componentNameFromFile(filePath) {
|
|
748
|
-
return
|
|
799
|
+
return path3.basename(filePath, ".svelte").toLowerCase();
|
|
749
800
|
}
|
|
750
801
|
function listComponentSourcePaths() {
|
|
751
|
-
if (!
|
|
752
|
-
return
|
|
802
|
+
if (!fs3.existsSync(COMPONENTS_SRC_DIR)) return [];
|
|
803
|
+
return fs3.readdirSync(COMPONENTS_SRC_DIR).filter((f) => f.endsWith(".svelte")).map((f) => path3.join(COMPONENTS_SRC_DIR, f));
|
|
753
804
|
}
|
|
754
805
|
function listComponentNames() {
|
|
755
806
|
return listComponentSourcePaths().map(componentNameFromFile);
|
|
756
807
|
}
|
|
757
808
|
function generateDefaultConfig(comp, sourcePath) {
|
|
758
|
-
if (!
|
|
809
|
+
if (!fs3.existsSync(sourcePath)) return;
|
|
759
810
|
const r = componentResource(comp);
|
|
760
811
|
r.ensureDir();
|
|
761
812
|
const defaultPath = r.filePath("default");
|
|
762
|
-
const sourceStat =
|
|
763
|
-
if (
|
|
764
|
-
const defaultStat =
|
|
813
|
+
const sourceStat = fs3.statSync(sourcePath);
|
|
814
|
+
if (fs3.existsSync(defaultPath)) {
|
|
815
|
+
const defaultStat = fs3.statSync(defaultPath);
|
|
765
816
|
if (defaultStat.mtimeMs >= sourceStat.mtimeMs) return;
|
|
766
817
|
}
|
|
767
|
-
const source =
|
|
818
|
+
const source = fs3.readFileSync(sourcePath, "utf-8");
|
|
768
819
|
const body = extractGlobalRootBody(source);
|
|
769
820
|
const aliases = extractAliasDeclarations(body);
|
|
770
821
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
771
822
|
let createdAt = now;
|
|
772
823
|
let existingUpdatedAt;
|
|
773
824
|
let existingAliases;
|
|
774
|
-
if (
|
|
825
|
+
if (fs3.existsSync(defaultPath)) {
|
|
775
826
|
try {
|
|
776
|
-
const existing = JSON.parse(
|
|
827
|
+
const existing = JSON.parse(fs3.readFileSync(defaultPath, "utf-8"));
|
|
777
828
|
if (existing.createdAt) createdAt = existing.createdAt;
|
|
778
829
|
if (typeof existing.updatedAt === "string") existingUpdatedAt = existing.updatedAt;
|
|
779
830
|
if (existing.aliases && typeof existing.aliases === "object") {
|
|
@@ -792,14 +843,14 @@ function themeFileApi(opts) {
|
|
|
792
843
|
};
|
|
793
844
|
if (aliasesUnchanged && existingUpdatedAt) {
|
|
794
845
|
const t = /* @__PURE__ */ new Date();
|
|
795
|
-
|
|
846
|
+
fs3.utimesSync(defaultPath, t, t);
|
|
796
847
|
return;
|
|
797
848
|
}
|
|
798
|
-
|
|
849
|
+
fs3.writeFileSync(defaultPath, JSON.stringify(defaultConfig, null, 2));
|
|
799
850
|
}
|
|
800
851
|
function ensureComponentConfigsDir() {
|
|
801
|
-
if (!
|
|
802
|
-
|
|
852
|
+
if (!fs3.existsSync(COMPONENT_CONFIGS_DIR)) {
|
|
853
|
+
fs3.mkdirSync(COMPONENT_CONFIGS_DIR, { recursive: true });
|
|
803
854
|
}
|
|
804
855
|
for (const sourcePath of listComponentSourcePaths()) {
|
|
805
856
|
const comp = componentNameFromFile(sourcePath);
|
|
@@ -810,14 +861,14 @@ function themeFileApi(opts) {
|
|
|
810
861
|
}
|
|
811
862
|
}
|
|
812
863
|
function ensureManifestsDir() {
|
|
813
|
-
if (!
|
|
814
|
-
|
|
815
|
-
const legacyProd =
|
|
816
|
-
if (
|
|
864
|
+
if (!fs3.existsSync(MANIFESTS_DIR) && fs3.existsSync(LEGACY_PRESETS_DIR)) {
|
|
865
|
+
fs3.renameSync(LEGACY_PRESETS_DIR, MANIFESTS_DIR);
|
|
866
|
+
const legacyProd = path3.join(MANIFESTS_DIR, "_production.json");
|
|
867
|
+
if (fs3.existsSync(legacyProd)) fs3.unlinkSync(legacyProd);
|
|
817
868
|
}
|
|
818
869
|
manifestsResource.ensureDir();
|
|
819
|
-
const defaultPath =
|
|
820
|
-
if (!
|
|
870
|
+
const defaultPath = path3.join(MANIFESTS_DIR, "default.json");
|
|
871
|
+
if (!fs3.existsSync(defaultPath)) {
|
|
821
872
|
const componentConfigs = {};
|
|
822
873
|
for (const comp of listComponentNames()) {
|
|
823
874
|
componentConfigs[comp] = componentResource(comp).getActiveName();
|
|
@@ -830,30 +881,30 @@ function themeFileApi(opts) {
|
|
|
830
881
|
theme: themesResource.getActiveName(),
|
|
831
882
|
componentConfigs
|
|
832
883
|
};
|
|
833
|
-
|
|
884
|
+
fs3.writeFileSync(defaultPath, JSON.stringify(defaultManifest, null, 2));
|
|
834
885
|
}
|
|
835
|
-
if (!
|
|
836
|
-
|
|
886
|
+
if (!fs3.existsSync(manifestsResource.activePath)) {
|
|
887
|
+
fs3.writeFileSync(
|
|
837
888
|
manifestsResource.activePath,
|
|
838
889
|
JSON.stringify({ activeFile: "default" })
|
|
839
890
|
);
|
|
840
891
|
} else {
|
|
841
892
|
const activeName = manifestsResource.getActiveName();
|
|
842
|
-
if (!
|
|
893
|
+
if (!fs3.existsSync(manifestsResource.filePath(activeName))) {
|
|
843
894
|
manifestsResource.setActiveName("default");
|
|
844
895
|
}
|
|
845
896
|
}
|
|
846
|
-
const stragglerProd =
|
|
847
|
-
if (
|
|
897
|
+
const stragglerProd = path3.join(MANIFESTS_DIR, "_production.json");
|
|
898
|
+
if (fs3.existsSync(stragglerProd)) fs3.unlinkSync(stragglerProd);
|
|
848
899
|
}
|
|
849
900
|
function patchActiveManifest(field, comp, fileName) {
|
|
850
901
|
const activeFile = manifestsResource.getActiveName();
|
|
851
902
|
if (activeFile === "default") return false;
|
|
852
903
|
const manifestPath = manifestsResource.filePath(activeFile);
|
|
853
|
-
if (!
|
|
904
|
+
if (!fs3.existsSync(manifestPath)) return false;
|
|
854
905
|
let manifest;
|
|
855
906
|
try {
|
|
856
|
-
manifest = JSON.parse(
|
|
907
|
+
manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
|
|
857
908
|
} catch {
|
|
858
909
|
return false;
|
|
859
910
|
}
|
|
@@ -864,7 +915,7 @@ function themeFileApi(opts) {
|
|
|
864
915
|
manifest.componentConfigs[comp] = fileName;
|
|
865
916
|
}
|
|
866
917
|
manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
867
|
-
|
|
918
|
+
fs3.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
868
919
|
return true;
|
|
869
920
|
}
|
|
870
921
|
function formatAliasGradient(v) {
|
|
@@ -896,9 +947,9 @@ function themeFileApi(opts) {
|
|
|
896
947
|
}
|
|
897
948
|
function readComponentConfig(comp, name) {
|
|
898
949
|
const filePath = componentResource(comp).filePath(name);
|
|
899
|
-
if (!
|
|
950
|
+
if (!fs3.existsSync(filePath)) return null;
|
|
900
951
|
try {
|
|
901
|
-
return JSON.parse(
|
|
952
|
+
return JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
902
953
|
} catch {
|
|
903
954
|
return null;
|
|
904
955
|
}
|
|
@@ -924,9 +975,9 @@ function themeFileApi(opts) {
|
|
|
924
975
|
const MANIFEST_BY_NAME_REGEX = new RegExp(`^${escapedBase}/manifests/([a-z0-9\\-_]+)$`);
|
|
925
976
|
async function handleListThemes(_ctx) {
|
|
926
977
|
const activeFile = themesResource.getActiveName();
|
|
927
|
-
const files =
|
|
928
|
-
const filePath =
|
|
929
|
-
const data = JSON.parse(
|
|
978
|
+
const files = fs3.readdirSync(THEMES_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
979
|
+
const filePath = path3.join(THEMES_DIR, f);
|
|
980
|
+
const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
930
981
|
const fileName = f.replace(".json", "");
|
|
931
982
|
return {
|
|
932
983
|
name: data.name || fileName,
|
|
@@ -940,18 +991,18 @@ function themeFileApi(opts) {
|
|
|
940
991
|
async function handleGetActiveTheme({ res }) {
|
|
941
992
|
const activeFile = themesResource.getActiveName();
|
|
942
993
|
const filePath = themesResource.filePath(activeFile);
|
|
943
|
-
if (!
|
|
994
|
+
if (!fs3.existsSync(filePath)) {
|
|
944
995
|
jsonResponse(res, 404, { error: "Active theme not found" });
|
|
945
996
|
return;
|
|
946
997
|
}
|
|
947
|
-
const data = normalizeTheme(JSON.parse(
|
|
998
|
+
const data = normalizeTheme(JSON.parse(fs3.readFileSync(filePath, "utf-8")));
|
|
948
999
|
data._fileName = activeFile;
|
|
949
1000
|
jsonResponse(res, 200, data);
|
|
950
1001
|
}
|
|
951
1002
|
async function handleSetActiveTheme({ req, res }) {
|
|
952
1003
|
const body = JSON.parse(await readBody(req));
|
|
953
1004
|
const fileName = sanitizeFileName(body.name || "default");
|
|
954
|
-
if (!
|
|
1005
|
+
if (!fs3.existsSync(themesResource.filePath(fileName))) {
|
|
955
1006
|
jsonResponse(res, 404, { error: "Theme not found" });
|
|
956
1007
|
return;
|
|
957
1008
|
}
|
|
@@ -961,11 +1012,11 @@ function themeFileApi(opts) {
|
|
|
961
1012
|
async function handleGetProductionTheme({ res }) {
|
|
962
1013
|
const prodFile = themesResource.getProductionName();
|
|
963
1014
|
const filePath = themesResource.filePath(prodFile);
|
|
964
|
-
if (!
|
|
1015
|
+
if (!fs3.existsSync(filePath)) {
|
|
965
1016
|
jsonResponse(res, 200, { fileName: prodFile, name: prodFile, cssVariables: {} });
|
|
966
1017
|
return;
|
|
967
1018
|
}
|
|
968
|
-
const data = normalizeTheme(JSON.parse(
|
|
1019
|
+
const data = normalizeTheme(JSON.parse(fs3.readFileSync(filePath, "utf-8")));
|
|
969
1020
|
jsonResponse(res, 200, {
|
|
970
1021
|
fileName: prodFile,
|
|
971
1022
|
name: data.name || prodFile,
|
|
@@ -976,7 +1027,7 @@ function themeFileApi(opts) {
|
|
|
976
1027
|
async function handleSetProductionTheme({ req, res }) {
|
|
977
1028
|
const body = JSON.parse(await readBody(req));
|
|
978
1029
|
const fileName = sanitizeFileName(body.name || "default");
|
|
979
|
-
if (!
|
|
1030
|
+
if (!fs3.existsSync(themesResource.filePath(fileName))) {
|
|
980
1031
|
jsonResponse(res, 404, { error: "Theme not found" });
|
|
981
1032
|
return;
|
|
982
1033
|
}
|
|
@@ -992,7 +1043,7 @@ function themeFileApi(opts) {
|
|
|
992
1043
|
syncFontsToCss(fileName);
|
|
993
1044
|
syncComponentsToCss();
|
|
994
1045
|
patchActiveManifest("theme", null, fileName);
|
|
995
|
-
const data = JSON.parse(
|
|
1046
|
+
const data = JSON.parse(fs3.readFileSync(themesResource.filePath(fileName), "utf-8"));
|
|
996
1047
|
jsonResponse(res, 200, {
|
|
997
1048
|
ok: true,
|
|
998
1049
|
fileName,
|
|
@@ -1004,11 +1055,11 @@ function themeFileApi(opts) {
|
|
|
1004
1055
|
const [fileName] = params;
|
|
1005
1056
|
const filePath = themesResource.filePath(fileName);
|
|
1006
1057
|
if (req.method === "GET") {
|
|
1007
|
-
if (!
|
|
1058
|
+
if (!fs3.existsSync(filePath)) {
|
|
1008
1059
|
jsonResponse(res, 404, { error: "Not found" });
|
|
1009
1060
|
return;
|
|
1010
1061
|
}
|
|
1011
|
-
const data = normalizeTheme(JSON.parse(
|
|
1062
|
+
const data = normalizeTheme(JSON.parse(fs3.readFileSync(filePath, "utf-8")));
|
|
1012
1063
|
data._fileName = fileName;
|
|
1013
1064
|
jsonResponse(res, 200, data);
|
|
1014
1065
|
return;
|
|
@@ -1016,15 +1067,15 @@ function themeFileApi(opts) {
|
|
|
1016
1067
|
if (req.method === "PUT") {
|
|
1017
1068
|
const body = JSON.parse(await readBody(req));
|
|
1018
1069
|
body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1019
|
-
if (
|
|
1070
|
+
if (fs3.existsSync(filePath)) {
|
|
1020
1071
|
try {
|
|
1021
|
-
const existing = JSON.parse(
|
|
1072
|
+
const existing = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
1022
1073
|
if (existing.createdAt) body.createdAt = existing.createdAt;
|
|
1023
1074
|
} catch {
|
|
1024
1075
|
}
|
|
1025
1076
|
}
|
|
1026
1077
|
if (!body.createdAt) body.createdAt = body.updatedAt;
|
|
1027
|
-
|
|
1078
|
+
fs3.writeFileSync(filePath, JSON.stringify(body, null, 2));
|
|
1028
1079
|
if (fileName === themesResource.getProductionName()) {
|
|
1029
1080
|
syncTokensToCss(fileName);
|
|
1030
1081
|
syncFontsToCss(fileName);
|
|
@@ -1045,8 +1096,8 @@ function themeFileApi(opts) {
|
|
|
1045
1096
|
});
|
|
1046
1097
|
return;
|
|
1047
1098
|
}
|
|
1048
|
-
if (
|
|
1049
|
-
|
|
1099
|
+
if (fs3.existsSync(filePath)) {
|
|
1100
|
+
fs3.unlinkSync(filePath);
|
|
1050
1101
|
if (themesResource.getActiveName() === fileName) {
|
|
1051
1102
|
themesResource.setActiveName("default");
|
|
1052
1103
|
}
|
|
@@ -1083,7 +1134,7 @@ function themeFileApi(opts) {
|
|
|
1083
1134
|
const fileName = sanitizeFileName(body.name || "default");
|
|
1084
1135
|
const r = componentResource(comp);
|
|
1085
1136
|
const configPath = r.filePath(fileName);
|
|
1086
|
-
if (!
|
|
1137
|
+
if (!fs3.existsSync(configPath)) {
|
|
1087
1138
|
jsonResponse(res, 404, { error: "Config not found" });
|
|
1088
1139
|
return;
|
|
1089
1140
|
}
|
|
@@ -1108,7 +1159,7 @@ function themeFileApi(opts) {
|
|
|
1108
1159
|
const fileName = sanitizeFileName(body.name || "default");
|
|
1109
1160
|
const r = componentResource(comp);
|
|
1110
1161
|
const configPath = r.filePath(fileName);
|
|
1111
|
-
if (!
|
|
1162
|
+
if (!fs3.existsSync(configPath)) {
|
|
1112
1163
|
jsonResponse(res, 404, { error: "Config not found" });
|
|
1113
1164
|
return;
|
|
1114
1165
|
}
|
|
@@ -1136,11 +1187,11 @@ function themeFileApi(opts) {
|
|
|
1136
1187
|
const r = componentResource(comp);
|
|
1137
1188
|
const configPath = r.filePath(name);
|
|
1138
1189
|
if (req.method === "GET") {
|
|
1139
|
-
if (!
|
|
1190
|
+
if (!fs3.existsSync(configPath)) {
|
|
1140
1191
|
jsonResponse(res, 404, { error: "Not found" });
|
|
1141
1192
|
return;
|
|
1142
1193
|
}
|
|
1143
|
-
const data = JSON.parse(
|
|
1194
|
+
const data = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
|
|
1144
1195
|
data._fileName = name;
|
|
1145
1196
|
jsonResponse(res, 200, data);
|
|
1146
1197
|
return;
|
|
@@ -1154,16 +1205,16 @@ function themeFileApi(opts) {
|
|
|
1154
1205
|
body.component = comp;
|
|
1155
1206
|
body.name = body.name || name;
|
|
1156
1207
|
body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1157
|
-
if (
|
|
1208
|
+
if (fs3.existsSync(configPath)) {
|
|
1158
1209
|
try {
|
|
1159
|
-
const existing = JSON.parse(
|
|
1210
|
+
const existing = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
|
|
1160
1211
|
if (existing.createdAt) body.createdAt = existing.createdAt;
|
|
1161
1212
|
} catch {
|
|
1162
1213
|
}
|
|
1163
1214
|
}
|
|
1164
1215
|
if (!body.createdAt) body.createdAt = body.updatedAt;
|
|
1165
1216
|
r.ensureDir();
|
|
1166
|
-
|
|
1217
|
+
fs3.writeFileSync(configPath, JSON.stringify(body, null, 2));
|
|
1167
1218
|
if (r.getProductionName() === name) {
|
|
1168
1219
|
syncComponentsToCss();
|
|
1169
1220
|
}
|
|
@@ -1175,8 +1226,8 @@ function themeFileApi(opts) {
|
|
|
1175
1226
|
jsonResponse(res, 403, { error: "Cannot delete default config" });
|
|
1176
1227
|
return;
|
|
1177
1228
|
}
|
|
1178
|
-
if (
|
|
1179
|
-
|
|
1229
|
+
if (fs3.existsSync(configPath)) {
|
|
1230
|
+
fs3.unlinkSync(configPath);
|
|
1180
1231
|
if (r.getActiveName() === name) {
|
|
1181
1232
|
r.setActiveName("default");
|
|
1182
1233
|
}
|
|
@@ -1192,15 +1243,15 @@ function themeFileApi(opts) {
|
|
|
1192
1243
|
async function handleListComponentConfigs({ params, res }) {
|
|
1193
1244
|
const [comp] = params;
|
|
1194
1245
|
const r = componentResource(comp);
|
|
1195
|
-
if (!
|
|
1246
|
+
if (!fs3.existsSync(r.dir)) {
|
|
1196
1247
|
jsonResponse(res, 404, { error: "Component not found" });
|
|
1197
1248
|
return;
|
|
1198
1249
|
}
|
|
1199
1250
|
const activeFile = r.getActiveName();
|
|
1200
1251
|
const productionFile = r.getProductionName();
|
|
1201
|
-
const files =
|
|
1202
|
-
const filePath =
|
|
1203
|
-
const data = JSON.parse(
|
|
1252
|
+
const files = fs3.readdirSync(r.dir).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
1253
|
+
const filePath = path3.join(r.dir, f);
|
|
1254
|
+
const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
1204
1255
|
const fileName = f.replace(".json", "");
|
|
1205
1256
|
return {
|
|
1206
1257
|
name: data.name || fileName,
|
|
@@ -1214,9 +1265,9 @@ function themeFileApi(opts) {
|
|
|
1214
1265
|
}
|
|
1215
1266
|
async function handleListManifests({ res }) {
|
|
1216
1267
|
const activeFile = manifestsResource.getActiveName();
|
|
1217
|
-
const files =
|
|
1218
|
-
const filePath =
|
|
1219
|
-
const data = JSON.parse(
|
|
1268
|
+
const files = fs3.readdirSync(MANIFESTS_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
|
|
1269
|
+
const filePath = path3.join(MANIFESTS_DIR, f);
|
|
1270
|
+
const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
1220
1271
|
const fileName = f.replace(".json", "");
|
|
1221
1272
|
return {
|
|
1222
1273
|
name: data.name || fileName,
|
|
@@ -1231,18 +1282,18 @@ function themeFileApi(opts) {
|
|
|
1231
1282
|
async function handleGetActiveManifest({ res }) {
|
|
1232
1283
|
const activeFile = manifestsResource.getActiveName();
|
|
1233
1284
|
const filePath = manifestsResource.filePath(activeFile);
|
|
1234
|
-
if (!
|
|
1285
|
+
if (!fs3.existsSync(filePath)) {
|
|
1235
1286
|
jsonResponse(res, 404, { error: "Active manifest not found" });
|
|
1236
1287
|
return;
|
|
1237
1288
|
}
|
|
1238
|
-
const data = JSON.parse(
|
|
1289
|
+
const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
1239
1290
|
data._fileName = activeFile;
|
|
1240
1291
|
jsonResponse(res, 200, data);
|
|
1241
1292
|
}
|
|
1242
1293
|
async function handleSetActiveManifest({ req, res }) {
|
|
1243
1294
|
const body = JSON.parse(await readBody(req));
|
|
1244
1295
|
const fileName = sanitizeFileName(body.name || "default");
|
|
1245
|
-
if (!
|
|
1296
|
+
if (!fs3.existsSync(manifestsResource.filePath(fileName))) {
|
|
1246
1297
|
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
1247
1298
|
return;
|
|
1248
1299
|
}
|
|
@@ -1253,11 +1304,11 @@ function themeFileApi(opts) {
|
|
|
1253
1304
|
const [fileName] = params;
|
|
1254
1305
|
const filePath = manifestsResource.filePath(fileName);
|
|
1255
1306
|
if (req.method === "GET") {
|
|
1256
|
-
if (!
|
|
1307
|
+
if (!fs3.existsSync(filePath)) {
|
|
1257
1308
|
jsonResponse(res, 404, { error: "Not found" });
|
|
1258
1309
|
return;
|
|
1259
1310
|
}
|
|
1260
|
-
const data = JSON.parse(
|
|
1311
|
+
const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
1261
1312
|
data._fileName = fileName;
|
|
1262
1313
|
jsonResponse(res, 200, data);
|
|
1263
1314
|
return;
|
|
@@ -1269,15 +1320,15 @@ function themeFileApi(opts) {
|
|
|
1269
1320
|
}
|
|
1270
1321
|
const body = JSON.parse(await readBody(req));
|
|
1271
1322
|
body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1272
|
-
if (
|
|
1323
|
+
if (fs3.existsSync(filePath)) {
|
|
1273
1324
|
try {
|
|
1274
|
-
const existing = JSON.parse(
|
|
1325
|
+
const existing = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
1275
1326
|
if (existing.createdAt) body.createdAt = existing.createdAt;
|
|
1276
1327
|
} catch {
|
|
1277
1328
|
}
|
|
1278
1329
|
}
|
|
1279
1330
|
if (!body.createdAt) body.createdAt = body.updatedAt;
|
|
1280
|
-
|
|
1331
|
+
fs3.writeFileSync(filePath, JSON.stringify(body, null, 2));
|
|
1281
1332
|
jsonResponse(res, 200, { ok: true, fileName });
|
|
1282
1333
|
return;
|
|
1283
1334
|
}
|
|
@@ -1286,8 +1337,8 @@ function themeFileApi(opts) {
|
|
|
1286
1337
|
jsonResponse(res, 403, { error: "Cannot delete the default manifest" });
|
|
1287
1338
|
return;
|
|
1288
1339
|
}
|
|
1289
|
-
if (
|
|
1290
|
-
|
|
1340
|
+
if (fs3.existsSync(filePath)) {
|
|
1341
|
+
fs3.unlinkSync(filePath);
|
|
1291
1342
|
if (manifestsResource.getActiveName() === fileName) {
|
|
1292
1343
|
manifestsResource.setActiveName("default");
|
|
1293
1344
|
}
|
|
@@ -1299,14 +1350,14 @@ function themeFileApi(opts) {
|
|
|
1299
1350
|
async function handleApplyManifest({ params, res }) {
|
|
1300
1351
|
const [fileName] = params;
|
|
1301
1352
|
const manifestPath = manifestsResource.filePath(fileName);
|
|
1302
|
-
if (!
|
|
1353
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
1303
1354
|
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
1304
1355
|
return;
|
|
1305
1356
|
}
|
|
1306
|
-
const manifest = JSON.parse(
|
|
1357
|
+
const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
|
|
1307
1358
|
const themeName = sanitizeFileName(manifest.theme || "default");
|
|
1308
1359
|
const themePath = themesResource.filePath(themeName);
|
|
1309
|
-
if (!
|
|
1360
|
+
if (!fs3.existsSync(themePath)) {
|
|
1310
1361
|
jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
|
|
1311
1362
|
return;
|
|
1312
1363
|
}
|
|
@@ -1319,7 +1370,7 @@ function themeFileApi(opts) {
|
|
|
1319
1370
|
const sanitized = sanitizeFileName(String(configFile) || "default");
|
|
1320
1371
|
const r = componentResource(comp);
|
|
1321
1372
|
const cfgPath = r.filePath(sanitized);
|
|
1322
|
-
if (!
|
|
1373
|
+
if (!fs3.existsSync(cfgPath)) {
|
|
1323
1374
|
jsonResponse(res, 422, {
|
|
1324
1375
|
error: `Manifest references missing config: ${comp}/${sanitized}`
|
|
1325
1376
|
});
|
|
@@ -1331,7 +1382,7 @@ function themeFileApi(opts) {
|
|
|
1331
1382
|
themesResource.setProductionName(themeName);
|
|
1332
1383
|
syncTokensToCss(themeName);
|
|
1333
1384
|
syncFontsToCss(themeName);
|
|
1334
|
-
const themeData = normalizeTheme(JSON.parse(
|
|
1385
|
+
const themeData = normalizeTheme(JSON.parse(fs3.readFileSync(themePath, "utf-8")));
|
|
1335
1386
|
themeData._fileName = themeName;
|
|
1336
1387
|
for (const [comp, configFile] of apply) {
|
|
1337
1388
|
const r = componentResource(comp);
|
|
@@ -1358,18 +1409,18 @@ function themeFileApi(opts) {
|
|
|
1358
1409
|
async function handleExportManifest({ params, res }) {
|
|
1359
1410
|
const [fileName] = params;
|
|
1360
1411
|
const manifestPath = manifestsResource.filePath(fileName);
|
|
1361
|
-
if (!
|
|
1412
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
1362
1413
|
jsonResponse(res, 404, { error: "Manifest not found" });
|
|
1363
1414
|
return;
|
|
1364
1415
|
}
|
|
1365
|
-
const manifest = JSON.parse(
|
|
1416
|
+
const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
|
|
1366
1417
|
const themeName = sanitizeFileName(manifest.theme || "default");
|
|
1367
1418
|
const themePath = themesResource.filePath(themeName);
|
|
1368
|
-
if (!
|
|
1419
|
+
if (!fs3.existsSync(themePath)) {
|
|
1369
1420
|
jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
|
|
1370
1421
|
return;
|
|
1371
1422
|
}
|
|
1372
|
-
const theme = JSON.parse(
|
|
1423
|
+
const theme = JSON.parse(fs3.readFileSync(themePath, "utf-8"));
|
|
1373
1424
|
const knownComponents = new Set(listComponentNames());
|
|
1374
1425
|
const componentConfigs = {};
|
|
1375
1426
|
for (const [comp, configFile] of Object.entries(manifest.componentConfigs ?? {})) {
|
|
@@ -1377,13 +1428,13 @@ function themeFileApi(opts) {
|
|
|
1377
1428
|
const sanitized = sanitizeFileName(String(configFile) || "default");
|
|
1378
1429
|
if (sanitized === "default") continue;
|
|
1379
1430
|
const cfgPath = componentResource(comp).filePath(sanitized);
|
|
1380
|
-
if (!
|
|
1431
|
+
if (!fs3.existsSync(cfgPath)) {
|
|
1381
1432
|
jsonResponse(res, 422, {
|
|
1382
1433
|
error: `Manifest references missing config: ${comp}/${sanitized}`
|
|
1383
1434
|
});
|
|
1384
1435
|
return;
|
|
1385
1436
|
}
|
|
1386
|
-
const cfg = JSON.parse(
|
|
1437
|
+
const cfg = JSON.parse(fs3.readFileSync(cfgPath, "utf-8"));
|
|
1387
1438
|
componentConfigs[`${comp}/${sanitized}`] = cfg;
|
|
1388
1439
|
}
|
|
1389
1440
|
const bundle = {
|
|
@@ -1405,7 +1456,7 @@ function themeFileApi(opts) {
|
|
|
1405
1456
|
}
|
|
1406
1457
|
function nextAvailableName2(resourceFilePath, baseName) {
|
|
1407
1458
|
return nextAvailableName(
|
|
1408
|
-
(n) =>
|
|
1459
|
+
(n) => fs3.existsSync(resourceFilePath(n)),
|
|
1409
1460
|
sanitizeFileName(baseName)
|
|
1410
1461
|
);
|
|
1411
1462
|
}
|
|
@@ -1447,7 +1498,7 @@ function themeFileApi(opts) {
|
|
|
1447
1498
|
themeBody.updatedAt = now;
|
|
1448
1499
|
if (!themeBody.createdAt) themeBody.createdAt = now;
|
|
1449
1500
|
themesResource.ensureDir();
|
|
1450
|
-
|
|
1501
|
+
fs3.writeFileSync(themesResource.filePath(finalThemeName), JSON.stringify(themeBody, null, 2));
|
|
1451
1502
|
const knownComponents = new Set(listComponentNames());
|
|
1452
1503
|
const componentRenames = {};
|
|
1453
1504
|
for (const [key, cfgValue] of Object.entries(bundle.componentConfigs)) {
|
|
@@ -1469,7 +1520,7 @@ function themeFileApi(opts) {
|
|
|
1469
1520
|
cfgBody.updatedAt = now;
|
|
1470
1521
|
if (!cfgBody.createdAt) cfgBody.createdAt = now;
|
|
1471
1522
|
r.ensureDir();
|
|
1472
|
-
|
|
1523
|
+
fs3.writeFileSync(r.filePath(finalName), JSON.stringify(cfgBody, null, 2));
|
|
1473
1524
|
}
|
|
1474
1525
|
const rewrittenManifest = {
|
|
1475
1526
|
...bundle.manifest,
|
|
@@ -1496,7 +1547,7 @@ function themeFileApi(opts) {
|
|
|
1496
1547
|
renames[`manifest:${originalManifestName}`] = finalManifestName;
|
|
1497
1548
|
}
|
|
1498
1549
|
manifestsResource.ensureDir();
|
|
1499
|
-
|
|
1550
|
+
fs3.writeFileSync(
|
|
1500
1551
|
manifestsResource.filePath(finalManifestName),
|
|
1501
1552
|
JSON.stringify(rewrittenManifest, null, 2)
|
|
1502
1553
|
);
|
|
@@ -1569,7 +1620,8 @@ function themeFileApi(opts) {
|
|
|
1569
1620
|
return {
|
|
1570
1621
|
define: {
|
|
1571
1622
|
__PROJECT_ROOT__: JSON.stringify(process.cwd()),
|
|
1572
|
-
__APP_VERSION__: JSON.stringify(PKG_VERSION)
|
|
1623
|
+
__APP_VERSION__: JSON.stringify(PKG_VERSION),
|
|
1624
|
+
__LIVE_TOKENS_API_BASE__: JSON.stringify(API_BASE)
|
|
1573
1625
|
}
|
|
1574
1626
|
};
|
|
1575
1627
|
},
|
|
@@ -1584,7 +1636,7 @@ function themeFileApi(opts) {
|
|
|
1584
1636
|
});
|
|
1585
1637
|
},
|
|
1586
1638
|
handleHotUpdate(ctx) {
|
|
1587
|
-
const normalized =
|
|
1639
|
+
const normalized = path3.resolve(ctx.file);
|
|
1588
1640
|
if (!normalized.startsWith(COMPONENTS_SRC_DIR)) return;
|
|
1589
1641
|
if (!normalized.endsWith(".svelte")) return;
|
|
1590
1642
|
const comp = componentNameFromFile(normalized);
|