@fluid-app/fluid-cli-theme-dev 0.1.3 → 0.1.5
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/.turbo/turbo-build.log +7 -9
- package/dist/index.mjs +144 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
- package/src/commands/dev.ts +8 -16
- package/src/commands/navigate.ts +13 -7
- package/src/commands/pull.ts +9 -13
- package/src/commands/push.ts +44 -21
- package/src/theme/syncer.ts +23 -28
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @fluid-app/fluid-cli-theme-dev@0.1.
|
|
2
|
+
> @fluid-app/fluid-cli-theme-dev@0.1.5 build /home/runner/_work/fluid-mono/fluid-mono/packages/cli/theme-dev
|
|
3
3
|
> tsdown
|
|
4
4
|
|
|
5
5
|
[34mℹ[39m tsdown [2mv0.21.0[22m powered by rolldown [2mv1.0.0-rc.7[22m
|
|
@@ -8,11 +8,9 @@
|
|
|
8
8
|
[34mℹ[39m target: [34mnode18[39m
|
|
9
9
|
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
10
10
|
[34mℹ[39m Build start
|
|
11
|
-
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [
|
|
12
|
-
[34mℹ[39m [2mdist/[22mindex.mjs.map [
|
|
13
|
-
[34mℹ[39m [2mdist/[22mindex.d.mts.map [2m
|
|
14
|
-
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m
|
|
15
|
-
[34mℹ[39m 4 files, total:
|
|
16
|
-
[
|
|
17
|
-
|
|
18
|
-
[32m✔[39m Build complete in [32m3302ms[39m
|
|
11
|
+
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [2m 42.13 kB[22m [2m│ gzip: 11.81 kB[22m
|
|
12
|
+
[34mℹ[39m [2mdist/[22mindex.mjs.map [2m112.29 kB[22m [2m│ gzip: 24.77 kB[22m
|
|
13
|
+
[34mℹ[39m [2mdist/[22mindex.d.mts.map [2m 0.11 kB[22m [2m│ gzip: 0.12 kB[22m
|
|
14
|
+
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m 0.19 kB[22m [2m│ gzip: 0.16 kB[22m
|
|
15
|
+
[34mℹ[39m 4 files, total: 154.73 kB
|
|
16
|
+
[32m✔[39m Build complete in [32m1283ms[39m
|
package/dist/index.mjs
CHANGED
|
@@ -610,6 +610,92 @@ function watchTheme(root, handler) {
|
|
|
610
610
|
return () => watcher.close();
|
|
611
611
|
}
|
|
612
612
|
//#endregion
|
|
613
|
+
//#region ../../api-clients/themes/src/namespaces/v0.ts
|
|
614
|
+
/**
|
|
615
|
+
* List application themes
|
|
616
|
+
* Get all application themes with optional filters
|
|
617
|
+
*
|
|
618
|
+
* @param client - Fetch client instance
|
|
619
|
+
* @param [params] - params
|
|
620
|
+
*/
|
|
621
|
+
async function listApplicationThemes(client, params) {
|
|
622
|
+
return client.get(`/api/application_themes`, params);
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Create an application theme
|
|
626
|
+
*
|
|
627
|
+
*
|
|
628
|
+
* @param client - Fetch client instance
|
|
629
|
+
* @param body - body
|
|
630
|
+
*/
|
|
631
|
+
async function createApplicationTheme(client, body) {
|
|
632
|
+
return client.post(`/api/application_themes`, body);
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Get an application theme
|
|
636
|
+
*
|
|
637
|
+
*
|
|
638
|
+
* @param client - Fetch client instance
|
|
639
|
+
* @param id - id
|
|
640
|
+
* @param [params] - params
|
|
641
|
+
*/
|
|
642
|
+
async function getApplicationTheme(client, id, params) {
|
|
643
|
+
return client.get(`/api/application_themes/${id}`, params);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Returns available themeables for a given type scoped to the theme's company
|
|
647
|
+
*
|
|
648
|
+
*
|
|
649
|
+
* @param client - Fetch client instance
|
|
650
|
+
* @param id - id
|
|
651
|
+
* @param [params] - params
|
|
652
|
+
*/
|
|
653
|
+
async function getApplicationThemeAvailableThemeables(client, id, params) {
|
|
654
|
+
return client.get(`/api/application_themes/${id}/available_themeables`, params);
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Publishes the theme
|
|
658
|
+
*
|
|
659
|
+
*
|
|
660
|
+
* @param client - Fetch client instance
|
|
661
|
+
* @param id - id
|
|
662
|
+
*/
|
|
663
|
+
async function publishApplicationTheme(client, id) {
|
|
664
|
+
return client.post(`/api/application_themes/${id}/publish`);
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Lists all theme resources
|
|
668
|
+
*
|
|
669
|
+
*
|
|
670
|
+
* @param client - Fetch client instance
|
|
671
|
+
* @param application_theme_id - application_theme_id
|
|
672
|
+
*/
|
|
673
|
+
async function listThemeResources(client, application_theme_id) {
|
|
674
|
+
return client.get(`/api/application_themes/${application_theme_id}/resources`);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Updates a theme resource
|
|
678
|
+
*
|
|
679
|
+
*
|
|
680
|
+
* @param client - Fetch client instance
|
|
681
|
+
* @param application_theme_id - application_theme_id
|
|
682
|
+
* @param body - body
|
|
683
|
+
*/
|
|
684
|
+
async function updateThemeResource(client, application_theme_id, body) {
|
|
685
|
+
return client.put(`/api/application_themes/${application_theme_id}/resources`, body);
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Deletes a theme resource
|
|
689
|
+
*
|
|
690
|
+
*
|
|
691
|
+
* @param client - Fetch client instance
|
|
692
|
+
* @param application_theme_id - application_theme_id
|
|
693
|
+
* @param body - body
|
|
694
|
+
*/
|
|
695
|
+
async function deleteThemeResource(client, application_theme_id, body) {
|
|
696
|
+
return client.delete(`/api/application_themes/${application_theme_id}/resources`, { body });
|
|
697
|
+
}
|
|
698
|
+
//#endregion
|
|
613
699
|
//#region src/theme/syncer.ts
|
|
614
700
|
var Syncer = class {
|
|
615
701
|
checksums = /* @__PURE__ */ new Map();
|
|
@@ -619,11 +705,11 @@ var Syncer = class {
|
|
|
619
705
|
this.themeRoot = themeRoot;
|
|
620
706
|
}
|
|
621
707
|
async fetchChecksums() {
|
|
622
|
-
const body = await this.api
|
|
708
|
+
const body = await listThemeResources(this.api, this.themeId);
|
|
623
709
|
this.updateChecksums(body.application_theme_resources ?? []);
|
|
624
710
|
}
|
|
625
711
|
updateChecksums(resources) {
|
|
626
|
-
for (const r of resources) if (r.key) this.checksums.set(r.key, r.checksum);
|
|
712
|
+
for (const r of resources) if (r.key && r.checksum) this.checksums.set(r.key, r.checksum);
|
|
627
713
|
for (const key of this.checksums.keys()) if (this.checksums.has(`${key}.liquid`)) this.checksums.delete(key);
|
|
628
714
|
}
|
|
629
715
|
hasChanged(file) {
|
|
@@ -633,14 +719,13 @@ var Syncer = class {
|
|
|
633
719
|
return [...this.checksums.keys()];
|
|
634
720
|
}
|
|
635
721
|
async uploadFile(file) {
|
|
636
|
-
|
|
637
|
-
if (file.isText) await this.api.put(path, { application_theme_resource: {
|
|
722
|
+
if (file.isText) await updateThemeResource(this.api, this.themeId, { application_theme_resource: {
|
|
638
723
|
key: file.relativePath,
|
|
639
724
|
content: file.read()
|
|
640
725
|
} });
|
|
641
|
-
else await this.uploadBinaryFile(file
|
|
726
|
+
else await this.uploadBinaryFile(file);
|
|
642
727
|
}
|
|
643
|
-
async uploadBinaryFile(file
|
|
728
|
+
async uploadBinaryFile(file) {
|
|
644
729
|
const asset = (await this.api.post("/api/dam/assets", { placeholder_asset: {
|
|
645
730
|
description: `Uploaded via Fluid CLI: ${file.name}`,
|
|
646
731
|
mime_type: file.mime.name,
|
|
@@ -675,7 +760,7 @@ var Syncer = class {
|
|
|
675
760
|
if (ikBody.height) backfillPayload["asset"]["height"] = ikBody.height;
|
|
676
761
|
if (ikBody.width) backfillPayload["asset"]["width"] = ikBody.width;
|
|
677
762
|
const backfillBody = await this.api.post("/api/dam/assets/backfill_imagekit", backfillPayload);
|
|
678
|
-
await this.api.
|
|
763
|
+
await updateThemeResource(this.api, this.themeId, { application_theme_resource: {
|
|
679
764
|
key: file.relativePath,
|
|
680
765
|
dam_asset: {
|
|
681
766
|
dam_asset_code: backfillBody.asset.code,
|
|
@@ -702,13 +787,13 @@ var Syncer = class {
|
|
|
702
787
|
}[category] ?? "files"}/${assetCode}`;
|
|
703
788
|
}
|
|
704
789
|
async deleteRemoteFile(relativePath) {
|
|
705
|
-
await this.api
|
|
790
|
+
await deleteThemeResource(this.api, this.themeId, { application_theme_resource: { key: relativePath } });
|
|
706
791
|
this.checksums.delete(relativePath);
|
|
707
792
|
}
|
|
708
793
|
async downloadAll() {
|
|
709
|
-
const
|
|
710
|
-
this.updateChecksums(
|
|
711
|
-
return
|
|
794
|
+
const resources = (await listThemeResources(this.api, this.themeId)).application_theme_resources ?? [];
|
|
795
|
+
this.updateChecksums(resources);
|
|
796
|
+
return resources;
|
|
712
797
|
}
|
|
713
798
|
async downloadBinaryAsset(url) {
|
|
714
799
|
const resp = await fetch(url);
|
|
@@ -767,7 +852,10 @@ var Syncer = class {
|
|
|
767
852
|
if (resource.resource_type === "FileResource" && resource.url) {
|
|
768
853
|
const buf = await this.downloadBinaryAsset(resource.url);
|
|
769
854
|
file.write(buf);
|
|
770
|
-
} else if (resource.content !== void 0
|
|
855
|
+
} else if (resource.content !== void 0 && resource.content !== null) {
|
|
856
|
+
const content = typeof resource.content === "string" ? resource.content : JSON.stringify(resource.content);
|
|
857
|
+
file.write(content);
|
|
858
|
+
}
|
|
771
859
|
result.downloaded++;
|
|
772
860
|
} catch (e) {
|
|
773
861
|
result.errors.push(`Download ${resource.key}: ${e}`);
|
|
@@ -856,7 +944,7 @@ async function startDevServer(api, theme, themeRoot, opts, onReady) {
|
|
|
856
944
|
//#region src/commands/dev.ts
|
|
857
945
|
async function ensureDevTheme(api, identifier) {
|
|
858
946
|
if (identifier) {
|
|
859
|
-
const body = await
|
|
947
|
+
const body = await listApplicationThemes(api);
|
|
860
948
|
const found = (body.application_themes ?? []).find((t) => String(t.id) === identifier) ?? (body.application_themes ?? []).find((t) => t.name.toLowerCase() === identifier.toLowerCase());
|
|
861
949
|
if (!found) {
|
|
862
950
|
console.error(`Theme not found: ${identifier}`);
|
|
@@ -866,17 +954,16 @@ async function ensureDevTheme(api, identifier) {
|
|
|
866
954
|
}
|
|
867
955
|
const { devThemeId } = getPluginState();
|
|
868
956
|
if (devThemeId) try {
|
|
869
|
-
const body = await
|
|
957
|
+
const body = await getApplicationTheme(api, devThemeId);
|
|
870
958
|
if (body.application_theme) {
|
|
871
959
|
console.log(`Using existing dev theme #${devThemeId}`);
|
|
872
960
|
return body.application_theme;
|
|
873
961
|
}
|
|
874
962
|
} catch {}
|
|
875
963
|
const { hostname } = await import("node:os");
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
role: "development"
|
|
964
|
+
const theme = (await createApplicationTheme(api, { application_theme: {
|
|
965
|
+
name: `Development (${hostname().split(".")[0] ?? "dev"}-${Math.random().toString(36).slice(2, 8)})`.slice(0, 50),
|
|
966
|
+
status: "development"
|
|
880
967
|
} })).application_theme;
|
|
881
968
|
setPluginState({
|
|
882
969
|
devThemeId: theme.id,
|
|
@@ -917,7 +1004,7 @@ function createDevCommand() {
|
|
|
917
1004
|
id: theme.id,
|
|
918
1005
|
name: theme.name,
|
|
919
1006
|
company,
|
|
920
|
-
editorUrl: theme.editor_url
|
|
1007
|
+
editorUrl: theme.editor_url ?? void 0
|
|
921
1008
|
}, themeRoot, {
|
|
922
1009
|
host: opts.host,
|
|
923
1010
|
port,
|
|
@@ -934,8 +1021,8 @@ function createDevCommand() {
|
|
|
934
1021
|
//#endregion
|
|
935
1022
|
//#region src/commands/push.ts
|
|
936
1023
|
async function selectTheme(api) {
|
|
937
|
-
const
|
|
938
|
-
if (!
|
|
1024
|
+
const themeList = (await listApplicationThemes(api)).application_themes ?? [];
|
|
1025
|
+
if (!themeList.length) {
|
|
939
1026
|
console.error("No themes found.");
|
|
940
1027
|
process.exit(1);
|
|
941
1028
|
}
|
|
@@ -943,7 +1030,7 @@ async function selectTheme(api) {
|
|
|
943
1030
|
type: "select",
|
|
944
1031
|
name: "id",
|
|
945
1032
|
message: "Select a theme to push to",
|
|
946
|
-
choices:
|
|
1033
|
+
choices: themeList.map((t) => ({
|
|
947
1034
|
title: `${t.name} (#${t.id})`,
|
|
948
1035
|
value: t.id
|
|
949
1036
|
}))
|
|
@@ -952,11 +1039,11 @@ async function selectTheme(api) {
|
|
|
952
1039
|
console.error("No theme selected.");
|
|
953
1040
|
process.exit(1);
|
|
954
1041
|
}
|
|
955
|
-
return
|
|
1042
|
+
return themeList.find((t) => t.id === id);
|
|
956
1043
|
}
|
|
957
1044
|
async function findTheme(api, identifier) {
|
|
958
|
-
const
|
|
959
|
-
const found =
|
|
1045
|
+
const themeList = (await listApplicationThemes(api)).application_themes ?? [];
|
|
1046
|
+
const found = themeList.find((t) => String(t.id) === identifier) ?? themeList.find((t) => t.name.toLowerCase() === identifier.toLowerCase());
|
|
960
1047
|
if (!found) {
|
|
961
1048
|
console.error(`No theme found with identifier: ${identifier}`);
|
|
962
1049
|
process.exit(1);
|
|
@@ -964,7 +1051,7 @@ async function findTheme(api, identifier) {
|
|
|
964
1051
|
return found;
|
|
965
1052
|
}
|
|
966
1053
|
function createPushCommand() {
|
|
967
|
-
return new Command("push").description("Push local theme files to a remote theme").option("-t, --theme <name-or-id>", "Theme name or ID to push to").option("-n, --nodelete", "Do not delete remote files missing locally").option("-f, --force", "Skip schema validation").option("-p, --publish", "Publish the theme after pushing").option("--root <path>", "Theme root directory", ".").action(async (opts) => {
|
|
1054
|
+
return new Command("push").description("Push local theme files to a remote theme").option("-t, --theme <name-or-id>", "Theme name or ID to push to").option("-n, --nodelete", "Do not delete remote files missing locally").option("-f, --force", "Skip schema validation").option("-p, --publish", "Publish the theme after pushing").option("-u, --unpublished", "Create a new unpublished theme and push to it").option("--root <path>", "Theme root directory", ".").action(async (opts) => {
|
|
968
1055
|
requireToken();
|
|
969
1056
|
const themeRoot = new ThemeRoot(opts.root);
|
|
970
1057
|
if (!themeRoot.isValid()) {
|
|
@@ -972,7 +1059,23 @@ function createPushCommand() {
|
|
|
972
1059
|
process.exit(1);
|
|
973
1060
|
}
|
|
974
1061
|
const api = createApiClient();
|
|
975
|
-
|
|
1062
|
+
let theme;
|
|
1063
|
+
if (opts.unpublished) {
|
|
1064
|
+
const { name } = await prompts({
|
|
1065
|
+
type: "text",
|
|
1066
|
+
name: "name",
|
|
1067
|
+
message: "Name for the new theme"
|
|
1068
|
+
}, { onCancel: () => process.exit(130) });
|
|
1069
|
+
if (!name) {
|
|
1070
|
+
console.error("Theme name is required.");
|
|
1071
|
+
process.exit(1);
|
|
1072
|
+
}
|
|
1073
|
+
theme = (await createApplicationTheme(api, { application_theme: {
|
|
1074
|
+
name,
|
|
1075
|
+
status: "draft"
|
|
1076
|
+
} })).application_theme;
|
|
1077
|
+
console.log(`Created unpublished theme: ${theme.name} (#${theme.id})`);
|
|
1078
|
+
} else theme = opts.theme ? await findTheme(api, opts.theme) : await selectTheme(api);
|
|
976
1079
|
const syncer = new Syncer(api, theme.id, themeRoot);
|
|
977
1080
|
const spinner = ora(`Pushing to ${theme.name} (#${theme.id})…`).start();
|
|
978
1081
|
const result = await syncer.uploadTheme({
|
|
@@ -988,7 +1091,7 @@ function createPushCommand() {
|
|
|
988
1091
|
if (opts.publish) {
|
|
989
1092
|
const pubSpinner = ora("Publishing theme…").start();
|
|
990
1093
|
try {
|
|
991
|
-
await
|
|
1094
|
+
await publishApplicationTheme(api, theme.id);
|
|
992
1095
|
pubSpinner.succeed("Theme published.");
|
|
993
1096
|
} catch (e) {
|
|
994
1097
|
pubSpinner.fail(`Publish failed: ${e}`);
|
|
@@ -999,13 +1102,13 @@ function createPushCommand() {
|
|
|
999
1102
|
//#endregion
|
|
1000
1103
|
//#region src/commands/pull.ts
|
|
1001
1104
|
async function selectOrFindTheme(api, identifier) {
|
|
1002
|
-
const
|
|
1003
|
-
if (!
|
|
1105
|
+
const themeList = (await listApplicationThemes(api)).application_themes ?? [];
|
|
1106
|
+
if (!themeList.length) {
|
|
1004
1107
|
console.error("No themes found.");
|
|
1005
1108
|
process.exit(1);
|
|
1006
1109
|
}
|
|
1007
1110
|
if (identifier) {
|
|
1008
|
-
const found =
|
|
1111
|
+
const found = themeList.find((t) => String(t.id) === identifier) ?? themeList.find((t) => t.name.toLowerCase() === identifier.toLowerCase());
|
|
1009
1112
|
if (!found) {
|
|
1010
1113
|
console.error(`No theme found with identifier: ${identifier}`);
|
|
1011
1114
|
process.exit(1);
|
|
@@ -1016,7 +1119,7 @@ async function selectOrFindTheme(api, identifier) {
|
|
|
1016
1119
|
type: "select",
|
|
1017
1120
|
name: "id",
|
|
1018
1121
|
message: "Select a theme to pull",
|
|
1019
|
-
choices:
|
|
1122
|
+
choices: themeList.map((t) => ({
|
|
1020
1123
|
title: `${t.name} (#${t.id})`,
|
|
1021
1124
|
value: t.id
|
|
1022
1125
|
}))
|
|
@@ -1025,7 +1128,7 @@ async function selectOrFindTheme(api, identifier) {
|
|
|
1025
1128
|
console.error("No theme selected.");
|
|
1026
1129
|
process.exit(1);
|
|
1027
1130
|
}
|
|
1028
|
-
return
|
|
1131
|
+
return themeList.find((t) => t.id === id);
|
|
1029
1132
|
}
|
|
1030
1133
|
function createPullCommand() {
|
|
1031
1134
|
return new Command("pull").description("Pull a remote theme to your local directory").option("-t, --theme <name-or-id>", "Theme name or ID to pull").option("-n, --nodelete", "Do not delete local files missing on remote").option("--root <path>", "Theme root directory", ".").action(async (opts) => {
|
|
@@ -1159,6 +1262,12 @@ const RESOURCE_ROUTES = [
|
|
|
1159
1262
|
type: "enrollment_pack",
|
|
1160
1263
|
template: "/home/enrollments/%s",
|
|
1161
1264
|
fallback: "/home/join"
|
|
1265
|
+
},
|
|
1266
|
+
{
|
|
1267
|
+
label: "Page",
|
|
1268
|
+
type: "page",
|
|
1269
|
+
template: "/home/pages/%s",
|
|
1270
|
+
fallback: "/home/pages"
|
|
1162
1271
|
}
|
|
1163
1272
|
];
|
|
1164
1273
|
function createNavigateCommand() {
|
|
@@ -1193,7 +1302,7 @@ function createNavigateCommand() {
|
|
|
1193
1302
|
let path;
|
|
1194
1303
|
if (typeof dest === "string") path = dest;
|
|
1195
1304
|
else {
|
|
1196
|
-
const resources = (await createApiClient()
|
|
1305
|
+
const resources = (await getApplicationThemeAvailableThemeables(createApiClient(), themeId, {
|
|
1197
1306
|
themeable: dest.resourceType,
|
|
1198
1307
|
per_page: 50
|
|
1199
1308
|
})).available_themeables ?? [];
|
|
@@ -1206,7 +1315,7 @@ function createNavigateCommand() {
|
|
|
1206
1315
|
name: "slug",
|
|
1207
1316
|
message: `Select a ${dest.label.toLowerCase()}`,
|
|
1208
1317
|
choices: resources.map((r) => ({
|
|
1209
|
-
title: r.title ?? r.slug,
|
|
1318
|
+
title: r.title ?? r.slug ?? "Untitled",
|
|
1210
1319
|
value: r.slug
|
|
1211
1320
|
}))
|
|
1212
1321
|
}, { onCancel });
|