@spicemod/creator 0.0.26 → 0.0.28
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/dist/bin.mjs +188 -150
- package/dist/templates/custom-app/shared/spice.config.js +6 -0
- package/dist/templates/custom-app/shared/spice.config.ts +6 -0
- package/dist/templates/custom-app/shared/tsconfig.app.json +33 -0
- package/dist/templates/custom-app/shared/tsconfig.node.json +25 -0
- package/dist/templates/custom-app/ts/react/src/extension/index.tsx +1 -1
- package/dist/templates/extension/js/react/src/app.jsx +1 -1
- package/dist/templates/extension/shared/spice.config.js +6 -0
- package/dist/templates/extension/shared/spice.config.ts +6 -0
- package/dist/templates/extension/shared/tsconfig.app.json +33 -0
- package/dist/templates/extension/shared/tsconfig.node.json +25 -0
- package/dist/templates/extension/ts/react/src/app.tsx +1 -1
- package/dist/templates/hmrCustomApp.js +284 -0
- package/dist/templates/liveReload.js +298 -45
- package/dist/templates/theme/js/react/src/app.jsx +1 -1
- package/dist/templates/theme/shared/spice.config.js +6 -0
- package/dist/templates/theme/shared/spice.config.ts +6 -0
- package/dist/templates/theme/shared/tsconfig.app.json +33 -0
- package/dist/templates/theme/shared/tsconfig.node.json +25 -0
- package/dist/templates/theme/ts/react/src/app.tsx +1 -1
- package/package.json +1 -1
- package/templates/custom-app/shared/spice.config.js +6 -0
- package/templates/custom-app/shared/spice.config.ts +6 -0
- package/templates/custom-app/shared/tsconfig.app.json +33 -0
- package/templates/custom-app/shared/tsconfig.node.json +25 -0
- package/templates/custom-app/ts/react/src/extension/index.tsx +1 -1
- package/templates/extension/js/react/src/app.jsx +1 -1
- package/templates/extension/shared/spice.config.js +6 -0
- package/templates/extension/shared/spice.config.ts +6 -0
- package/templates/extension/shared/tsconfig.app.json +33 -0
- package/templates/extension/shared/tsconfig.node.json +25 -0
- package/templates/extension/ts/react/src/app.tsx +1 -1
- package/templates/hmrCustomApp.js +284 -0
- package/templates/liveReload.js +298 -45
- package/templates/theme/js/react/src/app.jsx +1 -1
- package/templates/theme/shared/spice.config.js +6 -0
- package/templates/theme/shared/spice.config.ts +6 -0
- package/templates/theme/shared/tsconfig.app.json +33 -0
- package/templates/theme/shared/tsconfig.node.json +25 -0
- package/templates/theme/ts/react/src/app.tsx +1 -1
package/dist/bin.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { Command, Option } from "commander";
|
|
|
3
3
|
import * as v from "valibot";
|
|
4
4
|
import path, { basename, dirname, extname, join, relative, resolve } from "node:path";
|
|
5
5
|
import { build, context, transform } from "esbuild";
|
|
6
|
-
import { createReadStream, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
6
|
+
import fs, { createReadStream, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { watchConfig } from "c12";
|
|
8
8
|
import { globSync } from "tinyglobby";
|
|
9
9
|
import { URL as URL$1, fileURLToPath } from "node:url";
|
|
@@ -13,7 +13,7 @@ import * as p from "@clack/prompts";
|
|
|
13
13
|
import { cancel, log, spinner } from "@clack/prompts";
|
|
14
14
|
import pc from "picocolors";
|
|
15
15
|
import "dotenv/config";
|
|
16
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
16
|
+
import { readFile, unlink, writeFile } from "node:fs/promises";
|
|
17
17
|
import { parse } from "ini";
|
|
18
18
|
import { gzipSync } from "node:zlib";
|
|
19
19
|
import postcssMinify from "@csstools/postcss-minify";
|
|
@@ -137,13 +137,14 @@ const frameworks = frameworkTypes.map((name) => ({
|
|
|
137
137
|
}));
|
|
138
138
|
const frameworkOptions = toOptions(frameworks);
|
|
139
139
|
const liveReloadFilePath = dist(`templates/liveReload.js`, import.meta.url);
|
|
140
|
+
const hmrCustomAppFilePath = dist(`templates/hmrCustomApp.js`, import.meta.url);
|
|
140
141
|
const templateWrapperFilePath = dist("templates/wrapper.js", import.meta.url);
|
|
141
142
|
const customAppEntryFilePath = dist("templates/customAppEntry.js", import.meta.url);
|
|
142
143
|
|
|
143
144
|
//#endregion
|
|
144
145
|
//#region package.json
|
|
145
146
|
var name = "@spicemod/creator";
|
|
146
|
-
var version = "0.0.
|
|
147
|
+
var version = "0.0.28";
|
|
147
148
|
|
|
148
149
|
//#endregion
|
|
149
150
|
//#region src/utils/common.ts
|
|
@@ -779,15 +780,48 @@ function getTime(start) {
|
|
|
779
780
|
}
|
|
780
781
|
|
|
781
782
|
//#endregion
|
|
782
|
-
//#region src/esbuild/plugins/
|
|
783
|
-
|
|
784
|
-
|
|
783
|
+
//#region src/esbuild/plugins/buildErrorReporter.ts
|
|
784
|
+
function buildErrorReporter({ server }) {
|
|
785
|
+
return {
|
|
786
|
+
name: "spice_internal__build-error-reporter",
|
|
787
|
+
setup(build) {
|
|
788
|
+
build.onEnd(async (result) => {
|
|
789
|
+
const errors = result.errors;
|
|
790
|
+
const warnings = result.warnings;
|
|
791
|
+
if (errors.length === 0) {
|
|
792
|
+
server?.broadcast({
|
|
793
|
+
type: "build-success",
|
|
794
|
+
errors: [],
|
|
795
|
+
warnings
|
|
796
|
+
});
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
server?.broadcast({
|
|
800
|
+
type: "build-error",
|
|
801
|
+
errors,
|
|
802
|
+
warnings
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
//#endregion
|
|
810
|
+
//#region src/esbuild/plugins/clean.ts
|
|
811
|
+
const clean = (cache, logger = createLogger("plugin:clean")) => ({
|
|
812
|
+
name: "clean",
|
|
785
813
|
setup(build) {
|
|
814
|
+
const outdir = resolve(build.initialOptions.outdir || "./dist");
|
|
786
815
|
build.onStart(() => {
|
|
787
|
-
if (existsSync(
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
816
|
+
if (fs.existsSync(outdir)) try {
|
|
817
|
+
fs.rmSync(outdir, {
|
|
818
|
+
recursive: true,
|
|
819
|
+
force: true
|
|
820
|
+
});
|
|
821
|
+
logger.log(`Removed: ${outdir}`);
|
|
822
|
+
} catch (err) {
|
|
823
|
+
logger.error(`Error removing ${outdir}:`, err);
|
|
824
|
+
}
|
|
791
825
|
});
|
|
792
826
|
}
|
|
793
827
|
});
|
|
@@ -847,6 +881,37 @@ const externalGlobal = (externals, namespace = "spicetify-global") => {
|
|
|
847
881
|
|
|
848
882
|
//#endregion
|
|
849
883
|
//#region src/esbuild/plugins/spicetifyHandlers.ts
|
|
884
|
+
async function removeFile(logger, targetPath) {
|
|
885
|
+
try {
|
|
886
|
+
await unlink(targetPath);
|
|
887
|
+
logger.debug(pc.green(`${CHECK} Removed: ${targetPath}`));
|
|
888
|
+
} catch (err) {
|
|
889
|
+
if (err.code !== "ENOENT") logger.error(pc.red(`${CROSS} Failed to remove file: ${err instanceof Error ? err.message : String(err)}`));
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
async function copyFiles(logger, destDirs, cacheFiles) {
|
|
893
|
+
const tasks = [];
|
|
894
|
+
for (const filePath of cacheFiles.keys()) {
|
|
895
|
+
const fileData = cacheFiles.get(filePath);
|
|
896
|
+
if (!fileData) continue;
|
|
897
|
+
for (const destDir of destDirs) {
|
|
898
|
+
const targetPath = resolve(destDir, basename(filePath));
|
|
899
|
+
tasks.push((async () => {
|
|
900
|
+
await mkdirp(destDir);
|
|
901
|
+
await writeFile(targetPath, fileData.contents);
|
|
902
|
+
})());
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
await Promise.all(tasks);
|
|
906
|
+
}
|
|
907
|
+
async function removeDeletedFiles(logger, destDirs, removedFiles) {
|
|
908
|
+
const tasks = [];
|
|
909
|
+
for (const removedPath of removedFiles) for (const destDir of destDirs) {
|
|
910
|
+
const targetPath = resolve(destDir, basename(removedPath));
|
|
911
|
+
tasks.push(removeFile(logger, targetPath));
|
|
912
|
+
}
|
|
913
|
+
await Promise.all(tasks);
|
|
914
|
+
}
|
|
850
915
|
const spicetifyHandler = ({ config, options, cache, logger = createLogger("plugin:spicetify-handler") }) => ({
|
|
851
916
|
name: "spice_internal__spicetify-build-handler",
|
|
852
917
|
async setup(build) {
|
|
@@ -855,82 +920,58 @@ const spicetifyHandler = ({ config, options, cache, logger = createLogger("plugi
|
|
|
855
920
|
const isExtension = config.template === "extension";
|
|
856
921
|
const isCustomApp = config.template === "custom-app";
|
|
857
922
|
const identifier = isExtension ? `${urlSlugify(config.name)}.js` : urlSlugify(getEnName(config.name));
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
923
|
+
const getDestDirs = () => {
|
|
924
|
+
const dirs = [resolve(outDir)];
|
|
925
|
+
if (copy) dirs.push(isExtension ? getExtensionDir() : isCustomApp ? resolve(getCustomAppsDir(), identifier) : resolve(getThemesDir(), identifier));
|
|
926
|
+
return dirs;
|
|
927
|
+
};
|
|
928
|
+
if (env.skipSpicetify) logger.info(pc.yellow("Skipping Spicetify operations..."));
|
|
929
|
+
else {
|
|
930
|
+
const spiceConfig = await getSpicetifyConfig();
|
|
931
|
+
logger.debug(pc.green("Spicetify Config: "), spiceConfig);
|
|
932
|
+
if (apply) {
|
|
933
|
+
const defaultTheme = spiceConfig?.Setting?.current_theme || "SpicetifyDefault";
|
|
934
|
+
const spiceIdentifier = remove ? `${identifier}-` : identifier;
|
|
935
|
+
runSpice([
|
|
936
|
+
"config",
|
|
937
|
+
isExtension ? "extensions" : isCustomApp ? "custom_apps" : "current_theme",
|
|
938
|
+
spiceIdentifier
|
|
939
|
+
]);
|
|
940
|
+
if (!isExtension && !remove) {
|
|
941
|
+
const cleanup = () => {
|
|
942
|
+
if (isCustomApp) runSpice([
|
|
943
|
+
"config",
|
|
944
|
+
"custom_apps",
|
|
945
|
+
`${identifier}-`
|
|
946
|
+
]);
|
|
947
|
+
else runSpice([
|
|
948
|
+
"config",
|
|
949
|
+
"current_theme",
|
|
950
|
+
defaultTheme
|
|
951
|
+
]);
|
|
952
|
+
process.exit();
|
|
953
|
+
};
|
|
954
|
+
process.once("SIGINT", cleanup);
|
|
955
|
+
process.once("SIGTERM", cleanup);
|
|
878
956
|
}
|
|
879
|
-
});
|
|
880
|
-
return;
|
|
881
|
-
}
|
|
882
|
-
const spiceConfig = await getSpicetifyConfig();
|
|
883
|
-
logger.debug(pc.green("Spicetify Config: "), spiceConfig);
|
|
884
|
-
if (apply) {
|
|
885
|
-
const defaultTheme = spiceConfig?.Setting?.current_theme || "SpicetifyDefault";
|
|
886
|
-
const spiceIdentifier = remove ? `${identifier}-` : identifier;
|
|
887
|
-
runSpice([
|
|
888
|
-
"config",
|
|
889
|
-
isExtension ? "extensions" : isCustomApp ? "custom_apps" : "current_theme",
|
|
890
|
-
spiceIdentifier
|
|
891
|
-
]);
|
|
892
|
-
if (!isExtension && !remove) {
|
|
893
|
-
const cleanup = () => {
|
|
894
|
-
if (isCustomApp) runSpice([
|
|
895
|
-
"config",
|
|
896
|
-
"custom_apps",
|
|
897
|
-
`${identifier}-`
|
|
898
|
-
]);
|
|
899
|
-
else runSpice([
|
|
900
|
-
"config",
|
|
901
|
-
"current_theme",
|
|
902
|
-
defaultTheme
|
|
903
|
-
]);
|
|
904
|
-
process.exit();
|
|
905
|
-
};
|
|
906
|
-
process.once("SIGINT", cleanup);
|
|
907
|
-
process.once("SIGTERM", cleanup);
|
|
908
957
|
}
|
|
909
958
|
}
|
|
910
959
|
build.onEnd(async (result) => {
|
|
911
960
|
if (result.errors.length > 0) return;
|
|
912
|
-
|
|
913
|
-
const destDirs = [resolve(outDir)];
|
|
914
|
-
if (copy) destDirs.push(isExtension ? getExtensionDir() : isCustomApp ? resolve(getCustomAppsDir(), identifier) : resolve(getThemesDir(), identifier));
|
|
915
|
-
const tasks = [];
|
|
916
|
-
for (const filePath of cache.changed) {
|
|
917
|
-
const fileData = cache.files.get(filePath);
|
|
918
|
-
if (!fileData) continue;
|
|
919
|
-
for (const destDir of destDirs) {
|
|
920
|
-
const targetPath = resolve(destDir, basename(filePath));
|
|
921
|
-
tasks.push((async () => {
|
|
922
|
-
await mkdirp(destDir);
|
|
923
|
-
await writeFile(targetPath, fileData.contents);
|
|
924
|
-
})());
|
|
925
|
-
}
|
|
926
|
-
}
|
|
961
|
+
const destDirs = getDestDirs();
|
|
927
962
|
try {
|
|
928
|
-
await
|
|
929
|
-
logger.debug(pc.green(`${CHECK}
|
|
963
|
+
await copyFiles(logger, destDirs, cache.files);
|
|
964
|
+
logger.debug(pc.green(`${CHECK} Built files written to ${outDir}`));
|
|
930
965
|
} catch (err) {
|
|
931
966
|
logger.error(pc.red(`${CROSS} Failed to copy files: ${err instanceof Error ? err.message : String(err)}`));
|
|
932
967
|
return;
|
|
933
968
|
}
|
|
969
|
+
if (cache.removed.size > 0) {
|
|
970
|
+
await removeDeletedFiles(logger, destDirs, cache.removed);
|
|
971
|
+
cache.hasChanges = true;
|
|
972
|
+
}
|
|
973
|
+
cache.removed.clear();
|
|
974
|
+
if (env.skipSpicetify) return;
|
|
934
975
|
if (apply && cache.hasChanges && (!applyOnce || !hasAppliedOnce)) {
|
|
935
976
|
const { stdout, stderr, status } = runSpice(["apply"]);
|
|
936
977
|
if (status !== 0) logger.error(pc.red(`${CROSS} Spicetify apply failed:`), stdout, stderr);
|
|
@@ -951,16 +992,32 @@ function wrapWithLoader({ config, cache, outFiles, server, dev = false, logger =
|
|
|
951
992
|
name: namespace,
|
|
952
993
|
setup(build$3) {
|
|
953
994
|
if (build$3.initialOptions.write !== false) throw new Error(`[${namespace}] This plugin requires "write: false" in build options.`);
|
|
995
|
+
build$3.onStart(() => {
|
|
996
|
+
cache.changed.clear();
|
|
997
|
+
cache.removed.clear();
|
|
998
|
+
cache.hasChanges = false;
|
|
999
|
+
});
|
|
954
1000
|
build$3.onEnd(async (res) => {
|
|
955
1001
|
try {
|
|
956
1002
|
if (res.errors.length > 0 || !res.outputFiles) return;
|
|
957
|
-
cache.changed.clear();
|
|
958
|
-
cache.hasChanges = false;
|
|
959
1003
|
const filesChanged = [];
|
|
960
1004
|
const outdir = resolve(build$3.initialOptions.outdir || "./dist");
|
|
961
1005
|
const bundledCss = getBundledCss(res.outputFiles, outdir, type, dev);
|
|
962
1006
|
const minify = build$3.initialOptions.minify;
|
|
963
1007
|
const slug = varSlugify(`${name}_${version}`);
|
|
1008
|
+
const currentFilePaths = /* @__PURE__ */ new Set();
|
|
1009
|
+
for (const file of res.outputFiles) {
|
|
1010
|
+
const isJs = file.path.endsWith(".js");
|
|
1011
|
+
const isCss = file.path.endsWith(".css");
|
|
1012
|
+
if (!dev && isCss && type === "extension") continue;
|
|
1013
|
+
const relPath = file.path.slice(outdir.length);
|
|
1014
|
+
const isCustomAppExtension = type === "custom-app" && isExtensionDir(relPath);
|
|
1015
|
+
let targetName;
|
|
1016
|
+
if (isJs) targetName = isCustomAppExtension ? outFiles.jsExtension ?? "extension.js" : outFiles.js;
|
|
1017
|
+
else if (isCss && !isCustomAppExtension) targetName = outFiles.css;
|
|
1018
|
+
if (targetName) currentFilePaths.add(join(outdir, targetName));
|
|
1019
|
+
}
|
|
1020
|
+
for (const cachedPath of cache.files.keys()) if (!currentFilePaths.has(cachedPath)) cache.removed.add(cachedPath);
|
|
964
1021
|
const transformPromises = res.outputFiles.map(async (file) => {
|
|
965
1022
|
const isJs = file.path.endsWith(".js");
|
|
966
1023
|
const isCss = file.path.endsWith(".css");
|
|
@@ -1120,8 +1177,9 @@ function getBundledCss(files, outdir, type, dev) {
|
|
|
1120
1177
|
//#region src/esbuild/plugins/index.ts
|
|
1121
1178
|
const plugins = {
|
|
1122
1179
|
css,
|
|
1123
|
-
|
|
1180
|
+
clean,
|
|
1124
1181
|
buildLogger,
|
|
1182
|
+
buildErrorReporter,
|
|
1125
1183
|
externalGlobal,
|
|
1126
1184
|
wrapWithLoader,
|
|
1127
1185
|
spicetifyHandler
|
|
@@ -1140,13 +1198,20 @@ const defaultBuildOptions = {
|
|
|
1140
1198
|
target: ["es2022", "chrome120"]
|
|
1141
1199
|
};
|
|
1142
1200
|
const getCommonPlugins = (opts) => {
|
|
1143
|
-
const { template, minify,
|
|
1201
|
+
const { template, minify, buildOptions, outFiles, server, dev } = opts;
|
|
1144
1202
|
const inline = !dev && template === "extension";
|
|
1145
|
-
|
|
1203
|
+
const cache = {
|
|
1204
|
+
files: /* @__PURE__ */ new Map(),
|
|
1205
|
+
changed: /* @__PURE__ */ new Set(),
|
|
1206
|
+
removed: /* @__PURE__ */ new Set(),
|
|
1207
|
+
hasChanges: true
|
|
1208
|
+
};
|
|
1209
|
+
const p = [
|
|
1146
1210
|
...plugins.css({
|
|
1147
1211
|
minify,
|
|
1148
1212
|
inline
|
|
1149
1213
|
}),
|
|
1214
|
+
plugins.clean(cache),
|
|
1150
1215
|
plugins.externalGlobal({
|
|
1151
1216
|
react: "Spicetify.React",
|
|
1152
1217
|
"react-dom": "Spicetify.ReactDOM",
|
|
@@ -1168,6 +1233,8 @@ const getCommonPlugins = (opts) => {
|
|
|
1168
1233
|
}),
|
|
1169
1234
|
plugins.buildLogger({ cache })
|
|
1170
1235
|
];
|
|
1236
|
+
if (dev) p.push(plugins.buildErrorReporter({ server }));
|
|
1237
|
+
return p;
|
|
1171
1238
|
};
|
|
1172
1239
|
function getEntryPoints(config) {
|
|
1173
1240
|
if (config.template === "theme") return [config.entry.js, config.entry.css];
|
|
@@ -1227,11 +1294,6 @@ function getJSBuildOptions(config, options) {
|
|
|
1227
1294
|
const entryPoints = getEntryPoints(config);
|
|
1228
1295
|
const minify = options.watch ? false : options.minify;
|
|
1229
1296
|
const outDir = resolve(config.outDir);
|
|
1230
|
-
const cache = {
|
|
1231
|
-
files: /* @__PURE__ */ new Map(),
|
|
1232
|
-
changed: /* @__PURE__ */ new Set(),
|
|
1233
|
-
hasChanges: true
|
|
1234
|
-
};
|
|
1235
1297
|
const outFiles = getOutFiles(config);
|
|
1236
1298
|
const overrides = {
|
|
1237
1299
|
...defaultBuildOptions,
|
|
@@ -1253,7 +1315,6 @@ function getJSBuildOptions(config, options) {
|
|
|
1253
1315
|
plugins: [...config.esbuildOptions?.plugins ? config.esbuildOptions.plugins : [], ...getCommonPlugins({
|
|
1254
1316
|
...config,
|
|
1255
1317
|
minify,
|
|
1256
|
-
cache,
|
|
1257
1318
|
buildOptions: {
|
|
1258
1319
|
apply: options.apply,
|
|
1259
1320
|
copy: options.copy,
|
|
@@ -1358,10 +1419,16 @@ function createPackageJSON(options) {
|
|
|
1358
1419
|
dependencies: {},
|
|
1359
1420
|
devDependencies: { "@spicetify/creator": "latest" }
|
|
1360
1421
|
};
|
|
1361
|
-
if (options.language === "ts")
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1422
|
+
if (options.language === "ts") {
|
|
1423
|
+
result.devDependencies = {
|
|
1424
|
+
...result.devDependencies,
|
|
1425
|
+
...options.packageManager === "bun" ? { "@types/bun": "^1.3.10" } : { "@types/node": "^25.5.0" }
|
|
1426
|
+
};
|
|
1427
|
+
result.peerDependencies = {
|
|
1428
|
+
...result.peerDependencies,
|
|
1429
|
+
typescript: "^5"
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1365
1432
|
const slices = [FRAMEWORKS$1[options.framework], LINTERS$1[options.linter]];
|
|
1366
1433
|
Object.values(INTERSECTIONS).forEach((intersection) => {
|
|
1367
1434
|
if (intersection.condition(options)) slices.push(intersection);
|
|
@@ -1430,7 +1497,7 @@ const SHARED_FILES = (opts) => {
|
|
|
1430
1497
|
{
|
|
1431
1498
|
from: "DOT-gitignore",
|
|
1432
1499
|
to: ".gitignore",
|
|
1433
|
-
isShared
|
|
1500
|
+
isShared
|
|
1434
1501
|
},
|
|
1435
1502
|
{
|
|
1436
1503
|
from: `spice.config.${ext(opts.language)}`,
|
|
@@ -1478,11 +1545,23 @@ const LANGUAGE_FILES = {
|
|
|
1478
1545
|
to: "jsconfig.json",
|
|
1479
1546
|
isShared: true
|
|
1480
1547
|
}],
|
|
1481
|
-
ts: [
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1548
|
+
ts: [
|
|
1549
|
+
{
|
|
1550
|
+
from: "tsconfig.json",
|
|
1551
|
+
to: "tsconfig.json",
|
|
1552
|
+
isShared: true
|
|
1553
|
+
},
|
|
1554
|
+
{
|
|
1555
|
+
from: "tsconfig.app.json",
|
|
1556
|
+
to: "tsconfig.app.json",
|
|
1557
|
+
isShared: true
|
|
1558
|
+
},
|
|
1559
|
+
{
|
|
1560
|
+
from: "tsconfig.node.json",
|
|
1561
|
+
to: "tsconfig.node.json",
|
|
1562
|
+
isShared: true
|
|
1563
|
+
}
|
|
1564
|
+
]
|
|
1486
1565
|
};
|
|
1487
1566
|
const FRAMEWORKS = {
|
|
1488
1567
|
react: ({ language, template }) => {
|
|
@@ -1648,7 +1727,7 @@ function tryGitInit(root) {
|
|
|
1648
1727
|
const downloads = { spicetify: {
|
|
1649
1728
|
from: "https://raw.githubusercontent.com/spicetify/cli/main/globals.d.ts",
|
|
1650
1729
|
to: "./src/types/spicetify.d.ts",
|
|
1651
|
-
action: (content) => content.replace("const React: any;", "const React: typeof import(\"react\");").replace("const ReactDOM: any;", "const ReactDOM: typeof import(\"react-dom/client\");").replace("const ReactDOMServer: any;", "const ReactDOMServer: typeof import(\"react-dom/server\");")
|
|
1730
|
+
action: (content) => content.replace("const React: any;", "const React: typeof import(\"react\");").replace("const ReactDOM: any;", "const ReactDOM: typeof import(\"react-dom/client\");").replace("const ReactJSX: any;", "const ReactJSX: typeof import(\"react/jsx-runtime\");").replace("const ReactDOMServer: any;", "const ReactDOMServer: typeof import(\"react-dom/server\");")
|
|
1652
1731
|
} };
|
|
1653
1732
|
async function updateTypes(isUpdating = true, cwd = process.cwd()) {
|
|
1654
1733
|
const s = spinner();
|
|
@@ -1960,7 +2039,7 @@ async function createHmrServer(config, logger = createLogger("hmrServer")) {
|
|
|
1960
2039
|
});
|
|
1961
2040
|
});
|
|
1962
2041
|
function broadcast(data) {
|
|
1963
|
-
const message =
|
|
2042
|
+
const message = JSON.stringify(data);
|
|
1964
2043
|
for (const client of clients) if (client.readyState === WebSocket.OPEN) client.send(message);
|
|
1965
2044
|
}
|
|
1966
2045
|
return {
|
|
@@ -2033,7 +2112,8 @@ const injectHMRExtension = async (rootLink, wsLink, outFiles) => {
|
|
|
2033
2112
|
_SERVER_URL: JSON.stringify(rootLink),
|
|
2034
2113
|
_HOT_RELOAD_LINK: JSON.stringify(wsLink),
|
|
2035
2114
|
_JS_PATH: JSON.stringify(`/files/${outFiles.js}`),
|
|
2036
|
-
_CSS_PATH: JSON.stringify(outFiles.css ? `/files/${outFiles.css}` : `/files/app.css`)
|
|
2115
|
+
_CSS_PATH: JSON.stringify(outFiles.css ? `/files/${outFiles.css}` : `/files/app.css`),
|
|
2116
|
+
_REMOVE_CMD: JSON.stringify(`spicetify config extensions sc-live-reload-helper.js- && spicetify apply`)
|
|
2037
2117
|
}
|
|
2038
2118
|
});
|
|
2039
2119
|
writeFileSync(outDir, code);
|
|
@@ -2083,56 +2163,20 @@ const injectHMRCustomApp = async (rootLink, wsLink, outFiles, config) => {
|
|
|
2083
2163
|
mkdirp(destDir);
|
|
2084
2164
|
const indexJsPath = resolve(destDir, "index.js");
|
|
2085
2165
|
const extensionJsPath = resolve(destDir, outFiles.jsExtension ?? "extension.js");
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
return null;
|
|
2093
|
-
});
|
|
2094
|
-
};
|
|
2095
|
-
|
|
2096
|
-
const AppWrapper = ({ appPromise }) => {
|
|
2097
|
-
const [App, setApp] = React.useState(null);
|
|
2098
|
-
|
|
2099
|
-
React.useEffect(() => {
|
|
2100
|
-
let mounted = true;
|
|
2101
|
-
|
|
2102
|
-
appPromise.then((app) => {
|
|
2103
|
-
if (mounted && app) {
|
|
2104
|
-
setApp(() => app);
|
|
2105
|
-
}
|
|
2106
|
-
});
|
|
2107
|
-
|
|
2108
|
-
return () => {
|
|
2109
|
-
mounted = false;
|
|
2110
|
-
};
|
|
2111
|
-
}, [appPromise]);
|
|
2112
|
-
|
|
2113
|
-
if (!App) {
|
|
2114
|
-
return React.createElement(
|
|
2115
|
-
"div",
|
|
2116
|
-
{ className: "loading" },
|
|
2117
|
-
"Loading app..."
|
|
2118
|
-
);
|
|
2119
|
-
}
|
|
2120
|
-
|
|
2121
|
-
return React.createElement(App);
|
|
2122
|
-
};
|
|
2123
|
-
|
|
2124
|
-
const render = () => {
|
|
2125
|
-
const appPromise = waitForImport();
|
|
2126
|
-
return React.createElement(AppWrapper, { appPromise });
|
|
2127
|
-
};
|
|
2128
|
-
`);
|
|
2166
|
+
const { code: transformedIndexCode } = await transform(readFileSync(hmrCustomAppFilePath, "utf8"), {
|
|
2167
|
+
loader: "js",
|
|
2168
|
+
define: { _IMPORT_LINK: JSON.stringify(`${rootLink}/files/${outFiles.js}`) },
|
|
2169
|
+
platform: "browser"
|
|
2170
|
+
});
|
|
2171
|
+
writeFileSync(indexJsPath, transformedIndexCode);
|
|
2129
2172
|
const { code: extensionCode } = await transform(readFileSync(liveReloadFilePath, "utf8"), {
|
|
2130
2173
|
loader: "js",
|
|
2131
2174
|
define: {
|
|
2132
2175
|
_SERVER_URL: JSON.stringify(rootLink),
|
|
2133
2176
|
_HOT_RELOAD_LINK: JSON.stringify(wsLink),
|
|
2134
2177
|
_JS_PATH: JSON.stringify(`/files/${outFiles.jsExtension ?? "extension.js"}`),
|
|
2135
|
-
_CSS_PATH: JSON.stringify(outFiles.css ? `/files/${outFiles.css}` : `/files/app.css`)
|
|
2178
|
+
_CSS_PATH: JSON.stringify(outFiles.css ? `/files/${outFiles.css}` : `/files/app.css`),
|
|
2179
|
+
_REMOVE_CMD: JSON.stringify(`spicetify config custom_apps ${customAppId}- && spicetify apply`)
|
|
2136
2180
|
}
|
|
2137
2181
|
});
|
|
2138
2182
|
writeFileSync(extensionJsPath, extensionCode);
|
|
@@ -2205,11 +2249,6 @@ async function dev$1(options) {
|
|
|
2205
2249
|
function getJSDevOptions(config, options) {
|
|
2206
2250
|
const entryPoints = getEntryPoints(config);
|
|
2207
2251
|
const minify = false;
|
|
2208
|
-
const cache = {
|
|
2209
|
-
files: /* @__PURE__ */ new Map(),
|
|
2210
|
-
changed: /* @__PURE__ */ new Set(),
|
|
2211
|
-
hasChanges: true
|
|
2212
|
-
};
|
|
2213
2252
|
const overrides = {
|
|
2214
2253
|
...defaultBuildOptions,
|
|
2215
2254
|
outdir: outDir,
|
|
@@ -2228,7 +2267,6 @@ function getJSDevOptions(config, options) {
|
|
|
2228
2267
|
plugins: [...config.esbuildOptions?.plugins ? config.esbuildOptions.plugins : [], ...getCommonPlugins({
|
|
2229
2268
|
...config,
|
|
2230
2269
|
minify,
|
|
2231
|
-
cache,
|
|
2232
2270
|
buildOptions: {
|
|
2233
2271
|
copy: true,
|
|
2234
2272
|
apply: false,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
1
2
|
import { defineConfig } from "@spicetify/creator";
|
|
2
3
|
|
|
3
4
|
// Learn more: {{config-reference-link}}
|
|
@@ -7,4 +8,9 @@ export default defineConfig({
|
|
|
7
8
|
linter: "{{linter}}",
|
|
8
9
|
template: "{{template}}",
|
|
9
10
|
packageManager: "{{package-manager}}",
|
|
11
|
+
esbuildOptions: {
|
|
12
|
+
alias: {
|
|
13
|
+
"@": resolve(__dirname, "src"),
|
|
14
|
+
},
|
|
15
|
+
},
|
|
10
16
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
1
2
|
import { defineConfig } from "@spicetify/creator";
|
|
2
3
|
|
|
3
4
|
// Learn more: {{config-reference-link}}
|
|
@@ -7,4 +8,9 @@ export default defineConfig({
|
|
|
7
8
|
linter: "{{linter}}",
|
|
8
9
|
template: "{{template}}",
|
|
9
10
|
packageManager: "{{package-manager}}",
|
|
11
|
+
esbuildOptions: {
|
|
12
|
+
alias: {
|
|
13
|
+
"@": resolve(__dirname, "src"),
|
|
14
|
+
},
|
|
15
|
+
},
|
|
10
16
|
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"types": ["@spicetify/creator/client"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
|
+
|
|
18
|
+
/* Linting */
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noUnusedLocals": true,
|
|
21
|
+
"noUnusedParameters": true,
|
|
22
|
+
"erasableSyntaxOnly": true,
|
|
23
|
+
"noFallthroughCasesInSwitch": true,
|
|
24
|
+
"noUncheckedSideEffectImports": true,
|
|
25
|
+
|
|
26
|
+
// Paths
|
|
27
|
+
"baseUrl": ".",
|
|
28
|
+
"paths": {
|
|
29
|
+
"@/*": ["./src/*"]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"include": ["src"]
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2023",
|
|
4
|
+
"lib": ["ES2023"],
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"types": ["node"],
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
|
+
"moduleDetection": "force",
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
|
|
16
|
+
/* Linting */
|
|
17
|
+
"strict": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"erasableSyntaxOnly": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true,
|
|
22
|
+
"noUncheckedSideEffectImports": true
|
|
23
|
+
},
|
|
24
|
+
"include": ["spice.config.ts"]
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "@/extension/app.css";
|
|
2
2
|
import { createRoot } from "react-dom/client";
|
|
3
|
-
// you can use aliases too ! (
|
|
3
|
+
// you can use aliases too ! (checkout tsconfig.app.json)
|
|
4
4
|
import Onboarding from "@/components/Onboarding";
|
|
5
5
|
|
|
6
6
|
const config = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "@/app.css";
|
|
2
2
|
import { createRoot } from "react-dom/client";
|
|
3
|
-
// you can use aliases too ! (
|
|
3
|
+
// you can use aliases too ! (checkout tsconfig.app.json)
|
|
4
4
|
import OnboardingCard from "@/components/Onboarding";
|
|
5
5
|
|
|
6
6
|
const config = {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
1
2
|
import { defineConfig } from "@spicetify/creator";
|
|
2
3
|
|
|
3
4
|
// Learn more: {{config-reference-link}}
|
|
@@ -7,4 +8,9 @@ export default defineConfig({
|
|
|
7
8
|
linter: "{{linter}}",
|
|
8
9
|
template: "{{template}}",
|
|
9
10
|
packageManager: "{{package-manager}}",
|
|
11
|
+
esbuildOptions: {
|
|
12
|
+
alias: {
|
|
13
|
+
"@": resolve(__dirname, "src"),
|
|
14
|
+
},
|
|
15
|
+
},
|
|
10
16
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
1
2
|
import { defineConfig } from "@spicetify/creator";
|
|
2
3
|
|
|
3
4
|
// Learn more: {{config-reference-link}}
|
|
@@ -7,4 +8,9 @@ export default defineConfig({
|
|
|
7
8
|
linter: "{{linter}}",
|
|
8
9
|
template: "{{template}}",
|
|
9
10
|
packageManager: "{{package-manager}}",
|
|
11
|
+
esbuildOptions: {
|
|
12
|
+
alias: {
|
|
13
|
+
"@": resolve(__dirname, "src"),
|
|
14
|
+
},
|
|
15
|
+
},
|
|
10
16
|
});
|