vite-plugin-fvtt 0.2.1 → 0.2.3
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/CHANGELOG.md +22 -1
- package/README.md +2 -1
- package/dist/index.js +68 -86
- package/package.json +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.3] - 2025-09-20
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Return absolute paths from globbing.
|
|
8
|
+
- Refactor path-utils import and usage across codebase, for better Windows support.
|
|
9
|
+
- Refactor logger to use static Logger class methods.
|
|
10
|
+
- Bump dependencies.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add Vitest and fixture-based build test.
|
|
15
|
+
|
|
16
|
+
## [0.2.2] - 2025-09-10
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Improve windows path resolution.
|
|
21
|
+
|
|
3
22
|
## [0.2.1] - 2025-09-09
|
|
4
23
|
|
|
5
24
|
### Fixed
|
|
@@ -69,7 +88,9 @@
|
|
|
69
88
|
|
|
70
89
|
- Initial Release
|
|
71
90
|
|
|
72
|
-
[unreleased]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.2.
|
|
91
|
+
[unreleased]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.2.3...HEAD
|
|
92
|
+
[0.2.3]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.2.2...v0.2.3
|
|
93
|
+
[0.2.2]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.2.1...v0.2.2
|
|
73
94
|
[0.2.1]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.2.0...v0.2.1
|
|
74
95
|
[0.2.0]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.1.4...v0.2.0
|
|
75
96
|
[0.1.4]: https://github.com/MatyeusM/vite-plugin-fvtt/compare/v0.1.3...v0.1.4
|
package/README.md
CHANGED
|
@@ -104,7 +104,8 @@ Merging follows your manifest’s declared language paths, searching in root or
|
|
|
104
104
|
|
|
105
105
|
### **6. Packs**
|
|
106
106
|
|
|
107
|
-
Packs are tried to be auto-discovered in the source directory. If the paths match, they are
|
|
107
|
+
Packs are tried to be auto-discovered in the source directory. If the paths match, they are
|
|
108
|
+
automatically compiled.
|
|
108
109
|
|
|
109
110
|
**Note:** Packs are currently not watched for changes.
|
|
110
111
|
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import fs from "fs-extra";
|
|
2
|
-
import
|
|
2
|
+
import path from "path";
|
|
3
3
|
import dotenv from "dotenv";
|
|
4
4
|
import { globSync } from "tinyglobby";
|
|
5
5
|
import { compilePack } from "@foundryvtt/foundryvtt-cli";
|
|
@@ -12,7 +12,7 @@ const context = {};
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/config/env.ts
|
|
14
14
|
function loadEnv() {
|
|
15
|
-
const envPath =
|
|
15
|
+
const envPath = path.resolve(process.cwd(), ".env.foundryvtt.local");
|
|
16
16
|
const { parsed } = dotenv.config({
|
|
17
17
|
path: envPath,
|
|
18
18
|
quiet: true
|
|
@@ -25,49 +25,52 @@ function loadEnv() {
|
|
|
25
25
|
|
|
26
26
|
//#endregion
|
|
27
27
|
//#region src/utils/logger.ts
|
|
28
|
-
var Logger = class {
|
|
29
|
-
namespace;
|
|
30
|
-
colors = {
|
|
31
|
-
info: "\x1B[
|
|
28
|
+
var Logger = class Logger {
|
|
29
|
+
static namespace = "vite-plugin-fvtt";
|
|
30
|
+
static colors = {
|
|
31
|
+
info: "\x1B[36m",
|
|
32
32
|
warn: "\x1B[33m",
|
|
33
33
|
error: "\x1B[31m"
|
|
34
34
|
};
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
static reset = "\x1B[0m";
|
|
36
|
+
initialize(namespace = "vite-plugin-fvtt") {
|
|
37
|
+
Logger.namespace = namespace;
|
|
37
38
|
}
|
|
38
|
-
format(level, message) {
|
|
39
|
-
|
|
40
|
-
const reset = "\x1B[0m";
|
|
41
|
-
return `${color}[${this.namespace}] [${level.toUpperCase()}]${reset} ${message}`;
|
|
39
|
+
static format(level, message) {
|
|
40
|
+
return `${Logger.colors[level] ?? ""}[${Logger.namespace}] [${level.toUpperCase()}]${Logger.reset} ${message}`;
|
|
42
41
|
}
|
|
43
|
-
info(message) {
|
|
44
|
-
console.log(
|
|
42
|
+
static info(message) {
|
|
43
|
+
console.log(Logger.format("info", message));
|
|
45
44
|
}
|
|
46
|
-
warn(message) {
|
|
47
|
-
console.warn(
|
|
45
|
+
static warn(message) {
|
|
46
|
+
console.warn(Logger.format("warn", message));
|
|
48
47
|
}
|
|
49
|
-
error(message) {
|
|
50
|
-
console.error(
|
|
48
|
+
static error(message) {
|
|
49
|
+
console.error(Logger.format("error", message));
|
|
51
50
|
}
|
|
52
|
-
fail(message) {
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
static fail(message) {
|
|
52
|
+
const formatted = Logger.format("error", Logger.stringify(message));
|
|
53
|
+
console.error(formatted);
|
|
54
|
+
throw new Error(formatted);
|
|
55
|
+
}
|
|
56
|
+
static stringify(message) {
|
|
57
|
+
if (message instanceof Error) return message.stack ?? message.message;
|
|
58
|
+
return typeof message === "string" ? message : JSON.stringify(message, null, 2);
|
|
55
59
|
}
|
|
56
60
|
};
|
|
57
|
-
var logger_default =
|
|
61
|
+
var logger_default = Logger;
|
|
58
62
|
|
|
59
63
|
//#endregion
|
|
60
64
|
//#region src/config/foundryvtt-manifest.ts
|
|
61
65
|
function loadManifest(config) {
|
|
62
66
|
if (context?.manifest) return context.manifest;
|
|
63
67
|
const publicDir = config.publicDir || "public";
|
|
64
|
-
const
|
|
68
|
+
const foundPath = [
|
|
65
69
|
"system.json",
|
|
66
70
|
"module.json",
|
|
67
71
|
`${publicDir}/system.json`,
|
|
68
72
|
`${publicDir}/module.json`
|
|
69
|
-
];
|
|
70
|
-
const foundPath = MANIFEST_LOCATIONS.map((relPath) => posix.resolve(process.cwd(), relPath)).find((absPath) => fs.pathExistsSync(absPath));
|
|
73
|
+
].map((relPath) => path.resolve(process.cwd(), relPath)).find((absPath) => fs.pathExistsSync(absPath));
|
|
71
74
|
if (!foundPath) logger_default.fail(`Could not find a manifest file (system.json or module.json) in project root or ${publicDir}/.`);
|
|
72
75
|
try {
|
|
73
76
|
const data = fs.readJsonSync(foundPath);
|
|
@@ -75,7 +78,7 @@ function loadManifest(config) {
|
|
|
75
78
|
const hasEsmodules = Array.isArray(data.esmodules) && data.esmodules.length > 0;
|
|
76
79
|
const hasScripts = Array.isArray(data.scripts) && data.scripts.length > 0;
|
|
77
80
|
if (hasEsmodules === hasScripts) logger_default.fail(`Manifest at ${foundPath} must define exactly one of "esmodules" or "scripts".`);
|
|
78
|
-
|
|
81
|
+
return {
|
|
79
82
|
manifestType: foundPath.includes("module.json") ? "module" : "system",
|
|
80
83
|
id: data.id,
|
|
81
84
|
esmodules: Array.isArray(data.esmodules) ? data.esmodules : [],
|
|
@@ -84,7 +87,6 @@ function loadManifest(config) {
|
|
|
84
87
|
languages: Array.isArray(data.languages) ? data.languages : [],
|
|
85
88
|
packs: Array.isArray(data.packs) ? data.packs : []
|
|
86
89
|
};
|
|
87
|
-
return result;
|
|
88
90
|
} catch (err) {
|
|
89
91
|
logger_default.fail(`Failed to read manifest at ${foundPath}: ${err?.message || err}`);
|
|
90
92
|
}
|
|
@@ -121,8 +123,7 @@ function createPartialViteConfig(config) {
|
|
|
121
123
|
rollupOptions: { output: {
|
|
122
124
|
entryFileNames: fileName,
|
|
123
125
|
assetFileNames: (assetInfo) => {
|
|
124
|
-
|
|
125
|
-
if (names.some((n) => n.endsWith(".css"))) return cssFileName;
|
|
126
|
+
if ((assetInfo.names ?? []).some((n) => n.endsWith(".css"))) return cssFileName;
|
|
126
127
|
return "[name][extname]";
|
|
127
128
|
}
|
|
128
129
|
} }
|
|
@@ -171,7 +172,7 @@ var AbstractFileTracker = class {
|
|
|
171
172
|
});
|
|
172
173
|
}
|
|
173
174
|
addFile(value, filePath) {
|
|
174
|
-
const absPath =
|
|
175
|
+
const absPath = path.resolve(filePath);
|
|
175
176
|
if (!this.tracked.has(absPath)) {
|
|
176
177
|
this.tracked.set(absPath, value);
|
|
177
178
|
this.watcher?.add(absPath);
|
|
@@ -212,75 +213,69 @@ var PathUtils = class PathUtils {
|
|
|
212
213
|
static getDecodedBase() {
|
|
213
214
|
if (!PathUtils._decodedBase) {
|
|
214
215
|
const config = PathUtils.getConfig();
|
|
215
|
-
PathUtils._decodedBase =
|
|
216
|
+
PathUtils._decodedBase = path.posix.normalize(decodeURI(config.base));
|
|
216
217
|
}
|
|
217
218
|
return PathUtils._decodedBase;
|
|
218
219
|
}
|
|
219
220
|
static getSourceDirectory() {
|
|
220
221
|
if (!PathUtils._sourceDirectory) {
|
|
221
222
|
const config = PathUtils.getConfig();
|
|
222
|
-
const
|
|
223
|
-
const segments = normalizedEntry.split(posix.sep).filter(Boolean).filter((s) => s !== ".");
|
|
223
|
+
const segments = path.normalize(config.build.lib.entry.toString()).split(path.sep).filter(Boolean).filter((s) => s !== ".");
|
|
224
224
|
const firstFolder = segments.length > 0 ? segments[0] : ".";
|
|
225
|
-
PathUtils._sourceDirectory =
|
|
225
|
+
PathUtils._sourceDirectory = path.join(config.root, firstFolder);
|
|
226
226
|
}
|
|
227
227
|
return PathUtils._sourceDirectory;
|
|
228
228
|
}
|
|
229
229
|
static getPublicDir() {
|
|
230
230
|
if (!PathUtils._publicDir) {
|
|
231
231
|
const config = PathUtils.getConfig();
|
|
232
|
-
PathUtils._publicDir =
|
|
232
|
+
PathUtils._publicDir = path.resolve(config.publicDir);
|
|
233
233
|
}
|
|
234
234
|
return PathUtils._publicDir;
|
|
235
235
|
}
|
|
236
236
|
static getOutDir() {
|
|
237
237
|
if (!PathUtils._outDir) {
|
|
238
238
|
const config = PathUtils.getConfig();
|
|
239
|
-
PathUtils._outDir =
|
|
239
|
+
PathUtils._outDir = path.resolve(config.build.outDir);
|
|
240
240
|
}
|
|
241
241
|
return PathUtils._outDir;
|
|
242
242
|
}
|
|
243
243
|
static getRoot() {
|
|
244
244
|
if (!PathUtils._root) {
|
|
245
245
|
const config = PathUtils.getConfig();
|
|
246
|
-
PathUtils._root =
|
|
246
|
+
PathUtils._root = path.resolve(config.root);
|
|
247
247
|
}
|
|
248
248
|
return PathUtils._root;
|
|
249
249
|
}
|
|
250
250
|
static getOutDirFile(p) {
|
|
251
|
-
const file =
|
|
251
|
+
const file = path.join(PathUtils.getOutDir(), p);
|
|
252
252
|
return fs.existsSync(file) ? file : "";
|
|
253
253
|
}
|
|
254
254
|
static getPublicDirFile(p) {
|
|
255
|
-
const file =
|
|
255
|
+
const file = path.join(PathUtils.getPublicDir(), p);
|
|
256
256
|
return fs.existsSync(file) ? file : "";
|
|
257
257
|
}
|
|
258
|
-
static normalize(p) {
|
|
259
|
-
return posix.normalize(p);
|
|
260
|
-
}
|
|
261
258
|
static findLocalFilePath(p) {
|
|
262
|
-
|
|
259
|
+
return [
|
|
263
260
|
PathUtils.getPublicDir(),
|
|
264
261
|
PathUtils.getSourceDirectory(),
|
|
265
262
|
PathUtils.getRoot()
|
|
266
|
-
].map((pth) =>
|
|
267
|
-
return fileCandidates.find((pth) => fs.existsSync(pth)) ?? null;
|
|
263
|
+
].map((pth) => path.join(pth, p)).find((pth) => fs.existsSync(pth)) ?? null;
|
|
268
264
|
}
|
|
269
265
|
static isFoundryVTTUrl(p) {
|
|
270
266
|
const decodedBase = PathUtils.getDecodedBase();
|
|
271
|
-
|
|
272
|
-
return pathToCheck.startsWith(decodedBase);
|
|
267
|
+
return path.posix.normalize(p).startsWith(decodedBase);
|
|
273
268
|
}
|
|
274
269
|
static foundryVTTUrlToLocal(p) {
|
|
275
270
|
const decodedBase = PathUtils.getDecodedBase();
|
|
276
|
-
let pathToTransform =
|
|
271
|
+
let pathToTransform = path.posix.normalize("/" + p);
|
|
277
272
|
if (!pathToTransform.startsWith(decodedBase)) return null;
|
|
278
|
-
pathToTransform =
|
|
273
|
+
pathToTransform = path.relative(decodedBase, pathToTransform);
|
|
279
274
|
return PathUtils.findLocalFilePath(pathToTransform);
|
|
280
275
|
}
|
|
281
276
|
static localToFoundryVTTUrl(p) {
|
|
282
277
|
const decodedBase = PathUtils.getDecodedBase();
|
|
283
|
-
let pathToTransform =
|
|
278
|
+
let pathToTransform = path.normalize(p);
|
|
284
279
|
[
|
|
285
280
|
PathUtils.getPublicDir(),
|
|
286
281
|
PathUtils.getSourceDirectory(),
|
|
@@ -288,13 +283,12 @@ var PathUtils = class PathUtils {
|
|
|
288
283
|
].forEach((pth) => {
|
|
289
284
|
if (pathToTransform.startsWith(pth)) pathToTransform = pathToTransform.slice(pth.length);
|
|
290
285
|
});
|
|
291
|
-
return
|
|
286
|
+
return path.join(decodedBase, pathToTransform);
|
|
292
287
|
}
|
|
293
288
|
static getLanguageSourcePath(p, lang) {
|
|
294
|
-
const dir =
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
return posix.join(PathUtils.getSourceDirectory(), finalSegments);
|
|
289
|
+
const dir = path.parse(p).dir;
|
|
290
|
+
const finalSegments = path.basename(dir) === lang ? dir : path.join(dir, lang);
|
|
291
|
+
return path.join(PathUtils.getSourceDirectory(), finalSegments);
|
|
298
292
|
}
|
|
299
293
|
};
|
|
300
294
|
var path_utils_default = PathUtils;
|
|
@@ -302,14 +296,10 @@ var path_utils_default = PathUtils;
|
|
|
302
296
|
//#endregion
|
|
303
297
|
//#region src/language/loader.ts
|
|
304
298
|
function getLocalLanguageFiles(lang, outDir = false) {
|
|
305
|
-
const
|
|
306
|
-
const language = manifest.languages.find((l) => l.lang === lang);
|
|
299
|
+
const language = context.manifest.languages.find((l) => l.lang === lang);
|
|
307
300
|
if (!language) logger_default.fail(`Cannot find language "${lang}"`);
|
|
308
301
|
const langPath = language?.path ?? "";
|
|
309
|
-
if (outDir)
|
|
310
|
-
const languageFile = path_utils_default.getOutDirFile(langPath);
|
|
311
|
-
return [languageFile];
|
|
312
|
-
}
|
|
302
|
+
if (outDir) return [path_utils_default.getOutDirFile(langPath)];
|
|
313
303
|
const publicDirFile = path_utils_default.getPublicDirFile(langPath);
|
|
314
304
|
if (publicDirFile !== "") return [publicDirFile];
|
|
315
305
|
const sourcePath = path_utils_default.getLanguageSourcePath(langPath, lang);
|
|
@@ -317,7 +307,7 @@ function getLocalLanguageFiles(lang, outDir = false) {
|
|
|
317
307
|
logger_default.warn(`No language folder found at: ${sourcePath}`);
|
|
318
308
|
return [];
|
|
319
309
|
}
|
|
320
|
-
return globSync(
|
|
310
|
+
return globSync(path.join(sourcePath, "**/*.json"), { absolute: true });
|
|
321
311
|
}
|
|
322
312
|
function loadLanguage(lang, outDir = false) {
|
|
323
313
|
const files = getLocalLanguageFiles(lang, outDir);
|
|
@@ -378,15 +368,15 @@ function validator() {
|
|
|
378
368
|
if (lang.lang === "en") continue;
|
|
379
369
|
const currentLanguageData = loadLanguage(lang.lang, true);
|
|
380
370
|
if (currentLanguageData.size === 0) {
|
|
381
|
-
|
|
371
|
+
logger_default.warn(`Summary for language [${lang.lang}]: Could not be loaded.`);
|
|
382
372
|
continue;
|
|
383
373
|
}
|
|
384
374
|
const current = flattenKeys(currentLanguageData.values().next().value);
|
|
385
375
|
const missing = Object.keys(base).filter((key) => !(key in current));
|
|
386
376
|
const extra = Object.keys(current).filter((key) => !(key in base));
|
|
387
|
-
|
|
388
|
-
if (missing.length) console.warn(
|
|
389
|
-
if (extra.length) console.warn(
|
|
377
|
+
logger_default.info(`Summary for language [${lang.lang}]:`);
|
|
378
|
+
if (missing.length) console.warn(`Missing keys: ${missing.length}`, missing.slice(0, 5));
|
|
379
|
+
if (extra.length) console.warn(`Extra keys: ${extra.length}`, extra.slice(0, 5));
|
|
390
380
|
if (!missing.length && !extra.length) console.log(" ✅ All keys match.");
|
|
391
381
|
}
|
|
392
382
|
}
|
|
@@ -396,18 +386,17 @@ function validator() {
|
|
|
396
386
|
async function compileManifestPacks() {
|
|
397
387
|
if (!context.manifest?.packs) return;
|
|
398
388
|
for (const pack of context.manifest.packs) {
|
|
399
|
-
const srcCandidates = [
|
|
400
|
-
const dest =
|
|
389
|
+
const srcCandidates = [path.resolve(path_utils_default.getSourceDirectory(), pack.path), path.resolve(path_utils_default.getRoot(), pack.path)];
|
|
390
|
+
const dest = path.resolve(path_utils_default.getOutDir(), pack.path);
|
|
401
391
|
const chosenSrc = srcCandidates.find((candidate) => fs.existsSync(candidate) && fs.statSync(candidate).isDirectory());
|
|
402
392
|
if (!chosenSrc) {
|
|
403
393
|
logger_default.warn(`Pack path not found for ${pack.path}, skipped.`);
|
|
404
394
|
continue;
|
|
405
395
|
}
|
|
406
|
-
const
|
|
396
|
+
const hasYaml = fs.readdirSync(chosenSrc, {
|
|
407
397
|
recursive: true,
|
|
408
398
|
encoding: "utf8"
|
|
409
|
-
});
|
|
410
|
-
const hasYaml = entries.some((entry) => entry.endsWith(".yaml") || entry.endsWith(".yml"));
|
|
399
|
+
}).some((entry) => entry.endsWith(".yaml") || entry.endsWith(".yml"));
|
|
411
400
|
await compilePack(chosenSrc, dest, {
|
|
412
401
|
yaml: hasYaml,
|
|
413
402
|
recursive: true
|
|
@@ -440,13 +429,13 @@ function httpMiddlewareHook(server) {
|
|
|
440
429
|
}
|
|
441
430
|
const cssFileName = config.build.lib.cssFileName;
|
|
442
431
|
const cssEntry = cssFileName ? path_utils_default.localToFoundryVTTUrl(`${cssFileName}.css`) : null;
|
|
443
|
-
if (
|
|
432
|
+
if (path.posix.normalize(req.url ?? "") === cssEntry) {
|
|
444
433
|
logger_default.info(`Blocking CSS entry to ${req.url}`);
|
|
445
434
|
res.setHeader("Content-Type", "text/css");
|
|
446
435
|
res.end("/* The cake is in another castle. */");
|
|
447
436
|
return;
|
|
448
437
|
}
|
|
449
|
-
const languages = context.manifest.languages.filter((lang) => path_utils_default.localToFoundryVTTUrl(lang.path) ===
|
|
438
|
+
const languages = context.manifest.languages.filter((lang) => path_utils_default.localToFoundryVTTUrl(lang.path) === path.posix.normalize(req.url ?? ""));
|
|
450
439
|
if (languages.length === 1) {
|
|
451
440
|
const lang = languages[0].lang;
|
|
452
441
|
const language = loadLanguage(lang);
|
|
@@ -463,8 +452,7 @@ function httpMiddlewareHook(server) {
|
|
|
463
452
|
//#region src/server/socket-proxy.ts
|
|
464
453
|
function socketProxy(server) {
|
|
465
454
|
const env = context.env;
|
|
466
|
-
|
|
467
|
-
ioProxy.on("connection", (socket) => {
|
|
455
|
+
new Server(server.httpServer, { path: "/socket.io" }).on("connection", (socket) => {
|
|
468
456
|
const upstream = io(`http://${env.foundryUrl}:${env.foundryPort}`, {
|
|
469
457
|
transports: ["websocket"],
|
|
470
458
|
upgrade: false,
|
|
@@ -488,8 +476,7 @@ function socketProxy(server) {
|
|
|
488
476
|
});
|
|
489
477
|
});
|
|
490
478
|
upstream.onAny((event, ...args) => {
|
|
491
|
-
const
|
|
492
|
-
const maybeAck = typeof lastArg === "function" ? args.pop() : null;
|
|
479
|
+
const maybeAck = typeof args[args.length - 1] === "function" ? args.pop() : null;
|
|
493
480
|
socket.emit(event, ...args, (response) => {
|
|
494
481
|
if (maybeAck) maybeAck(response);
|
|
495
482
|
});
|
|
@@ -601,7 +588,7 @@ function foundryVTTPlugin(options = { buildPacks: true }) {
|
|
|
601
588
|
async generateBundle() {
|
|
602
589
|
const manifestCandidates = ["system.json", "module.json"];
|
|
603
590
|
for (const file of manifestCandidates) {
|
|
604
|
-
const src =
|
|
591
|
+
const src = path.resolve(file);
|
|
605
592
|
if (!path_utils_default.getPublicDirFile(file) && fs.existsSync(src)) {
|
|
606
593
|
this.addWatchFile(src);
|
|
607
594
|
const manifest = fs.readJsonSync(src);
|
|
@@ -620,7 +607,7 @@ function foundryVTTPlugin(options = { buildPacks: true }) {
|
|
|
620
607
|
const languageData = transform(languageDataRaw);
|
|
621
608
|
this.emitFile({
|
|
622
609
|
type: "asset",
|
|
623
|
-
fileName:
|
|
610
|
+
fileName: path.join(language.path),
|
|
624
611
|
source: JSON.stringify(languageData, null, 2)
|
|
625
612
|
});
|
|
626
613
|
}
|
|
@@ -629,17 +616,12 @@ function foundryVTTPlugin(options = { buildPacks: true }) {
|
|
|
629
616
|
if (options.buildPacks) await compileManifestPacks();
|
|
630
617
|
},
|
|
631
618
|
closeBundle() {
|
|
632
|
-
|
|
633
|
-
if (languages.length > 0) validator();
|
|
619
|
+
if ((context.manifest?.languages ?? []).length > 0) validator();
|
|
634
620
|
},
|
|
635
621
|
load(id) {
|
|
636
622
|
const config = context.config;
|
|
637
623
|
const jsFileName = (config.build.rollupOptions?.output).entryFileNames;
|
|
638
|
-
if (id === jsFileName || id === `/${jsFileName}`) {
|
|
639
|
-
const entryPath = posix.resolve(config.build.lib.entry);
|
|
640
|
-
const viteId = `/@fs/${entryPath}`;
|
|
641
|
-
return `import '${viteId}';\n${hmr_client_default}`;
|
|
642
|
-
}
|
|
624
|
+
if (id === jsFileName || id === `/${jsFileName}`) return `import '${`/@fs/${path.resolve(config.build.lib.entry)}`}';\n${hmr_client_default}`;
|
|
643
625
|
},
|
|
644
626
|
configureServer: setupDevServer
|
|
645
627
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-fvtt",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "A Vite plugin for module and system development for Foundry VTT",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
30
|
"dev": "tsdown --watch",
|
|
31
|
-
"build": "tsdown"
|
|
31
|
+
"build": "tsdown",
|
|
32
|
+
"test": "vitest"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"@eslint/js": "^9.34.0",
|
|
@@ -36,10 +37,11 @@
|
|
|
36
37
|
"@types/node": "^24.3.0",
|
|
37
38
|
"eslint": "^9.34.0",
|
|
38
39
|
"prettier": "^3.6.2",
|
|
39
|
-
"tsdown": "^0.
|
|
40
|
+
"tsdown": "^0.15.1",
|
|
40
41
|
"typescript": "^5.9.2",
|
|
41
42
|
"typescript-eslint": "^8.41.0",
|
|
42
|
-
"vite": "*"
|
|
43
|
+
"vite": "*",
|
|
44
|
+
"vitest": "^3.2.4"
|
|
43
45
|
},
|
|
44
46
|
"dependencies": {
|
|
45
47
|
"@foundryvtt/foundryvtt-cli": "^3.0.0",
|
|
@@ -47,7 +49,7 @@
|
|
|
47
49
|
"fs-extra": "^11.3.1",
|
|
48
50
|
"socket.io": "^4.8.1",
|
|
49
51
|
"socket.io-client": "^4.8.1",
|
|
50
|
-
"tinyglobby": "^0.2.
|
|
52
|
+
"tinyglobby": "^0.2.15"
|
|
51
53
|
},
|
|
52
54
|
"peerDependencies": {
|
|
53
55
|
"vite": "^7.0.0"
|