Merge branch 'remove-gulp' into 'master'
chore: replace gulp by a pure rollup based build See merge request dungeonslayers/ds4!159
This commit is contained in:
commit
43385299c4
17 changed files with 1784 additions and 2584 deletions
|
@ -24,7 +24,7 @@ module.exports = {
|
|||
|
||||
overrides: [
|
||||
{
|
||||
files: ["./*.js"],
|
||||
files: ["./*.cjs", "./*.js"],
|
||||
rules: {
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
},
|
10
README.md
10
README.md
|
@ -27,9 +27,7 @@ https://git.f3l.de/api/v4/projects/dungeonslayers%2Fds4/packages/generic/ds4/lat
|
|||
|
||||
In order to build this system, recent versions of `node` and `yarn` are
|
||||
required. Most likely using `npm` also works but only `yarn` is officially
|
||||
supported. We recommend using the latest lts version of `node`, which is
|
||||
`v14.17.1` at the time of writing. If you use `nvm` to manage your `node`
|
||||
versions, you can simply run
|
||||
supported. We recommend using the latest lts version of `node`. If you use `nvm` to manage your `node` versions, you can simply run
|
||||
|
||||
```
|
||||
nvm install
|
||||
|
@ -37,7 +35,7 @@ nvm install
|
|||
|
||||
in the project's root directory.
|
||||
|
||||
You also need to install the the project's dependencies. To do so, run
|
||||
You also need to install the project's dependencies. To do so, run
|
||||
|
||||
```
|
||||
yarn install
|
||||
|
@ -54,7 +52,7 @@ yarn build
|
|||
Alternatively, you can run
|
||||
|
||||
```
|
||||
yarn build:watch
|
||||
yarn watch
|
||||
```
|
||||
|
||||
to watch for changes and automatically build as necessary.
|
||||
|
@ -77,7 +75,7 @@ On platforms other than Linux you need to adjust the path accordingly.
|
|||
Then run
|
||||
|
||||
```
|
||||
yarn link-project
|
||||
yarn link-package
|
||||
```
|
||||
|
||||
### Running the tests
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const config = require("conventional-changelog-conventionalcommits");
|
||||
|
||||
module.exports = config();
|
344
gulpfile.js
344
gulpfile.js
|
@ -1,344 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const { rollup } = require("rollup");
|
||||
const argv = require("yargs").argv;
|
||||
const fs = require("fs-extra");
|
||||
const gulp = require("gulp");
|
||||
const path = require("path");
|
||||
const rollupConfig = require("./rollup.config");
|
||||
const semver = require("semver");
|
||||
const sass = require("gulp-sass")(require("sass"));
|
||||
const Datastore = require("@seald-io/nedb");
|
||||
const { Transform } = require("stream");
|
||||
|
||||
/********************/
|
||||
/* CONFIGURATION */
|
||||
/********************/
|
||||
|
||||
const name = path.basename(path.resolve("."));
|
||||
const sourceDirectory = "./src";
|
||||
const distDirectory = "./dist";
|
||||
const stylesDirectory = path.join(sourceDirectory, "scss");
|
||||
const packsDirectory = path.join(sourceDirectory, "packs");
|
||||
const stylesExtension = ".scss";
|
||||
const sourceFileExtension = ".ts";
|
||||
const staticFiles = ["assets", "fonts", "lang", "templates", "system.json", "template.json"];
|
||||
const getDownloadURL = (version) => `https://git.f3l.de/dungeonslayers/ds4/-/releases/${version}/downloads/ds4.zip`;
|
||||
const getChangelogURL = (version) => `https://git.f3l.de/dungeonslayers/ds4/-/releases/${version}`;
|
||||
|
||||
/********************/
|
||||
/* BUILD */
|
||||
/********************/
|
||||
|
||||
/**
|
||||
* Build the distributable JavaScript code
|
||||
*/
|
||||
async function buildCode() {
|
||||
const build = await rollup({ input: rollupConfig.input, plugins: rollupConfig.plugins });
|
||||
return build.write(rollupConfig.output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build style sheets
|
||||
*/
|
||||
function buildStyles() {
|
||||
return gulp
|
||||
.src(path.join(stylesDirectory, `${name}${stylesExtension}`))
|
||||
.pipe(sass().on("error", sass.logError))
|
||||
.pipe(gulp.dest(path.join(distDirectory, "css")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove unwanted data from a pack entry
|
||||
*/
|
||||
function cleanPackEntry(entry, cleanSourceId = true) {
|
||||
if (cleanSourceId) {
|
||||
delete entry.flags?.core?.sourceId;
|
||||
}
|
||||
Object.keys(entry.flags).forEach((scope) => {
|
||||
if (Object.keys(entry.flags[scope]).length === 0) {
|
||||
delete entry.flags[scope];
|
||||
}
|
||||
});
|
||||
if (entry.permission) entry.permission = { default: 0 };
|
||||
|
||||
const embeddedDocumentCollections = [
|
||||
"drawings",
|
||||
"effects",
|
||||
"items",
|
||||
"lights",
|
||||
"notes",
|
||||
"results",
|
||||
"sounds",
|
||||
"templates",
|
||||
"tiles",
|
||||
"tokens",
|
||||
"walls",
|
||||
];
|
||||
embeddedDocumentCollections
|
||||
.flatMap((embeddedDocumentCollection) => entry[embeddedDocumentCollection] ?? [])
|
||||
.forEach((embeddedEntry) => cleanPackEntry(embeddedEntry, false));
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a stream of JSON files to NeDB files
|
||||
*/
|
||||
const jsonToNeDB = () =>
|
||||
new Transform({
|
||||
transform(file, _, callback) {
|
||||
try {
|
||||
file.contents = Buffer.from(
|
||||
JSON.parse(file.contents.toString())
|
||||
.map((entry) => cleanPackEntry(entry))
|
||||
.map((entry) => JSON.stringify(entry))
|
||||
.join("\n") + "\n",
|
||||
);
|
||||
file.path = path.join(
|
||||
path.dirname(file.path),
|
||||
path.basename(file.path, path.extname(file.path)) + ".db",
|
||||
);
|
||||
callback(undefined, file);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
},
|
||||
objectMode: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* build compendium packs
|
||||
*/
|
||||
function buildPacks() {
|
||||
return gulp
|
||||
.src(path.join(packsDirectory, "*.json"))
|
||||
.pipe(jsonToNeDB())
|
||||
.pipe(gulp.dest(path.join(distDirectory, "packs")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a stream of NeDB files to JSON files
|
||||
*/
|
||||
const neDBToJSON = () =>
|
||||
new Transform({
|
||||
transform(file, _, callback) {
|
||||
try {
|
||||
const db = new Datastore({ filename: file.path, autoload: true });
|
||||
db.find({}, (err, docs) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
file.contents = Buffer.from(
|
||||
JSON.stringify(
|
||||
docs.map((entry) => cleanPackEntry(entry)),
|
||||
undefined,
|
||||
4,
|
||||
) + "\n",
|
||||
);
|
||||
file.path = path.join(
|
||||
path.dirname(file.path),
|
||||
path.basename(file.path, path.extname(file.path)) + ".json",
|
||||
);
|
||||
callback(undefined, file);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
},
|
||||
objectMode: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* Generate JSON files from the compendium packs in the distribution directory
|
||||
*/
|
||||
function generateJSONsFromPacks() {
|
||||
return gulp
|
||||
.src(path.join(distDirectory, "packs", "*.db"))
|
||||
.pipe(neDBToJSON())
|
||||
.pipe(gulp.dest(path.join(packsDirectory)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy static files
|
||||
*/
|
||||
async function copyFiles() {
|
||||
for (const file of staticFiles) {
|
||||
if (fs.existsSync(path.join(sourceDirectory, file))) {
|
||||
await fs.copy(path.join(sourceDirectory, file), path.join(distDirectory, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch for changes for each build step
|
||||
*/
|
||||
function buildWatch() {
|
||||
gulp.watch(
|
||||
path.join(sourceDirectory, "**", `*${sourceFileExtension}`).replace(/\\/g, "/"),
|
||||
{ ignoreInitial: false },
|
||||
buildCode,
|
||||
);
|
||||
gulp.watch(
|
||||
path.join(stylesDirectory, "**", `*${stylesExtension}`).replace(/\\/g, "/"),
|
||||
{ ignoreInitial: false },
|
||||
buildStyles,
|
||||
);
|
||||
gulp.watch(path.join(packsDirectory, "**", "*.json").replace(/\\/g, "/"), { ignoreInitial: false }, buildPacks);
|
||||
gulp.watch(
|
||||
staticFiles.map((file) => path.join(sourceDirectory, file).replace(/\\/g, "/")),
|
||||
{ ignoreInitial: false },
|
||||
copyFiles,
|
||||
);
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* CLEAN */
|
||||
/********************/
|
||||
|
||||
/**
|
||||
* Remove built files from `dist` folder while ignoring source files
|
||||
*/
|
||||
async function clean() {
|
||||
const files = [...staticFiles, "packs", "module"];
|
||||
|
||||
if (fs.existsSync(path.join(stylesDirectory, `${name}${stylesExtension}`))) {
|
||||
files.push("css");
|
||||
}
|
||||
|
||||
console.log(" ", "Files to clean:");
|
||||
console.log(" ", files.join("\n "));
|
||||
|
||||
for (const filePath of files) {
|
||||
await fs.remove(path.join(distDirectory, filePath));
|
||||
}
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* LINK */
|
||||
/********************/
|
||||
|
||||
/**
|
||||
* Get the data path of Foundry VTT based on what is configured in `foundryconfig.json`
|
||||
*/
|
||||
function getDataPath() {
|
||||
const config = fs.readJSONSync("foundryconfig.json");
|
||||
|
||||
if (config?.dataPath) {
|
||||
if (!fs.existsSync(path.resolve(config.dataPath))) {
|
||||
throw new Error("User Data path invalid, no Data directory found");
|
||||
}
|
||||
|
||||
return path.resolve(config.dataPath);
|
||||
} else {
|
||||
throw new Error("No User Data path defined in foundryconfig.json");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Link build to User Data folder
|
||||
*/
|
||||
async function linkUserData() {
|
||||
let destinationDirectory;
|
||||
if (fs.existsSync(path.resolve(".", sourceDirectory, "system.json"))) {
|
||||
destinationDirectory = "systems";
|
||||
} else {
|
||||
throw new Error("Could not find system.json");
|
||||
}
|
||||
|
||||
const linkDirectory = path.resolve(getDataPath(), destinationDirectory, name);
|
||||
|
||||
if (argv.clean || argv.c) {
|
||||
console.log(`Removing build in ${linkDirectory}.`);
|
||||
|
||||
await fs.remove(linkDirectory);
|
||||
} else if (!fs.existsSync(linkDirectory)) {
|
||||
console.log(`Copying build to ${linkDirectory}.`);
|
||||
await fs.ensureDir(path.resolve(linkDirectory, ".."));
|
||||
await fs.symlink(path.resolve(".", distDirectory), linkDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* VERSIONING */
|
||||
/********************/
|
||||
|
||||
/**
|
||||
* Get the contents of the manifest file as object.
|
||||
*/
|
||||
function getManifest() {
|
||||
const manifestPath = path.join(sourceDirectory, "system.json");
|
||||
|
||||
if (fs.existsSync(manifestPath)) {
|
||||
return {
|
||||
file: fs.readJSONSync(manifestPath),
|
||||
name: "system.json",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target version based on on the current version and the argument passed as release.
|
||||
*/
|
||||
function getTargetVersion(currentVersion, release) {
|
||||
if (["major", "premajor", "minor", "preminor", "patch", "prepatch", "prerelease"].includes(release)) {
|
||||
return semver.inc(currentVersion, release);
|
||||
} else {
|
||||
return semver.valid(release);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update version and download URL.
|
||||
*/
|
||||
function bumpVersion(cb) {
|
||||
const packageJson = fs.readJSONSync("package.json");
|
||||
const manifest = getManifest();
|
||||
|
||||
if (!manifest) cb(Error("Manifest JSON not found"));
|
||||
|
||||
try {
|
||||
const release = argv.release || argv.r;
|
||||
|
||||
const currentVersion = packageJson.version;
|
||||
|
||||
if (!release) {
|
||||
return cb(Error("Missing release type"));
|
||||
}
|
||||
|
||||
const targetVersion = getTargetVersion(currentVersion, release);
|
||||
|
||||
if (!targetVersion) {
|
||||
return cb(new Error("Error: Incorrect version arguments"));
|
||||
}
|
||||
|
||||
if (targetVersion === currentVersion) {
|
||||
return cb(new Error("Error: Target version is identical to current version"));
|
||||
}
|
||||
|
||||
console.log(`Updating version number to '${targetVersion}'`);
|
||||
|
||||
packageJson.version = targetVersion;
|
||||
fs.writeJSONSync("package.json", packageJson, { spaces: 4 });
|
||||
|
||||
manifest.file.version = targetVersion;
|
||||
manifest.file.download = getDownloadURL(targetVersion);
|
||||
manifest.file.changelog = getChangelogURL(targetVersion);
|
||||
fs.writeJSONSync(path.join(sourceDirectory, manifest.name), manifest.file, { spaces: 4 });
|
||||
|
||||
return cb();
|
||||
} catch (err) {
|
||||
cb(err);
|
||||
}
|
||||
}
|
||||
|
||||
const execBuild = gulp.parallel(buildCode, buildStyles, buildPacks, copyFiles);
|
||||
|
||||
exports.build = gulp.series(clean, execBuild);
|
||||
exports.watch = buildWatch;
|
||||
exports.clean = clean;
|
||||
exports.link = linkUserData;
|
||||
exports.bumpVersion = bumpVersion;
|
||||
exports.generateJSONsFromPacks = generateJSONsFromPacks;
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
preset: "ts-jest",
|
||||
globals: {
|
||||
"ts-jest": {
|
||||
|
|
34
package.json
34
package.json
|
@ -36,26 +36,31 @@
|
|||
"name": "Sascha Martens"
|
||||
}
|
||||
],
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "gulp build",
|
||||
"build:watch": "gulp watch",
|
||||
"link-project": "gulp link",
|
||||
"clean": "gulp clean",
|
||||
"clean:link": "gulp link --clean",
|
||||
"bump-version": "gulp bumpVersion",
|
||||
"lint": "eslint --ext .ts,.js .",
|
||||
"lint:fix": "eslint --ext .ts,.js --fix .",
|
||||
"build": "run-s clean:files build:files",
|
||||
"build:files": "rollup -c",
|
||||
"watch": "rollup -c -w",
|
||||
"link-package": "node ./tools/link-package.js",
|
||||
"clean": "run-p clean:files clean:link",
|
||||
"clean:files": "rimraf dist",
|
||||
"clean:link": "node ./tools/link-package.js --clean",
|
||||
"lint": "eslint --ext .ts,.js,.cjs,.mjs .",
|
||||
"lint:fix": "eslint --ext .ts,.js,.cjs,.mjs --fix .",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:ci": "jest --ci --reporters=default --reporters=jest-junit",
|
||||
"format": "prettier --write \"./**/*.(ts|js|json|scss|yml)\"",
|
||||
"format": "prettier --write \"./**/*.(ts|js|cjs|mjs|json|scss|yml)\"",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"bump-version": "node ./tools/bump-version.js",
|
||||
"convert-packs-to-json": "node ./tools/convert-packs-to-json.js",
|
||||
"postinstall": "husky install",
|
||||
"changelog": "conventional-changelog -n changelog.config.js -o CHANGELOG.md -r 2"
|
||||
"changelog": "conventional-changelog -p conventionalcommits -o CHANGELOG.md -r 2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "15.0.0",
|
||||
"@commitlint/config-conventional": "15.0.0",
|
||||
"@guanghechen/rollup-plugin-copy": "1.8.4",
|
||||
"@league-of-foundry-developers/foundry-vtt-types": "0.8.9-7",
|
||||
"@seald-io/nedb": "2.2.0",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
|
@ -69,26 +74,27 @@
|
|||
"eslint-plugin-jest": "25.3.0",
|
||||
"eslint-plugin-prettier": "4.0.0",
|
||||
"fs-extra": "10.0.0",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-sass": "5.0.0",
|
||||
"husky": "7.0.4",
|
||||
"jest": "27.4.2",
|
||||
"jest-junit": "13.0.0",
|
||||
"lint-staged": "12.1.2",
|
||||
"npm-run-all": "4.1.5",
|
||||
"prettier": "2.5.0",
|
||||
"rimraf": "3.0.2",
|
||||
"rollup": "2.60.2",
|
||||
"rollup-plugin-sourcemaps": "0.6.3",
|
||||
"rollup-plugin-styles": "3.14.1",
|
||||
"rollup-plugin-terser": "7.0.2",
|
||||
"rollup-plugin-typescript2": "0.31.1",
|
||||
"sass": "1.44.0",
|
||||
"semver": "7.3.5",
|
||||
"ts-jest": "27.0.7",
|
||||
"tslib": "2.3.1",
|
||||
"typescript": "4.5.2",
|
||||
"typescript": "4.4.4",
|
||||
"yargs": "17.2.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.ts": "eslint --cache --fix",
|
||||
"*.(ts|js|cjs|mjs)": "eslint --cache --fix",
|
||||
"*.(json|scss|yml)": "prettier --write"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["config:base", ":automergeAll", ":automergeBranch", ":prHourlyLimitNone", ":prConcurrentLimitNone"]
|
||||
"extends": ["config:base", ":automergeAll", ":automergeBranch", ":prHourlyLimitNone", ":prConcurrentLimitNone"],
|
||||
"ignoreDeps": ["typescript"]
|
||||
}
|
||||
|
|
|
@ -2,25 +2,50 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const typescript = require("rollup-plugin-typescript2");
|
||||
const sourcemaps = require("rollup-plugin-sourcemaps");
|
||||
const { terser } = require("rollup-plugin-terser");
|
||||
import copy from "@guanghechen/rollup-plugin-copy";
|
||||
import typescript from "rollup-plugin-typescript2";
|
||||
import sourcemaps from "rollup-plugin-sourcemaps";
|
||||
import styles from "rollup-plugin-styles";
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
import { distDirectory, name, sourceDirectory } from "./tools/const.js";
|
||||
import { convertJSONToPack } from "./tools/json-pack-tools.js";
|
||||
|
||||
const staticFiles = ["template.json", "system.json", "assets", "fonts", "lang", "templates"];
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
/**
|
||||
* @type {import('rollup').RollupOptions}
|
||||
*/
|
||||
const config = {
|
||||
input: "src/module/ds4.ts",
|
||||
input: { [`module/${name}`]: `${sourceDirectory}/module/${name}.ts` },
|
||||
output: {
|
||||
dir: "dist/module",
|
||||
dir: distDirectory,
|
||||
format: "es",
|
||||
sourcemap: true,
|
||||
assetFileNames: "[name].[ext]",
|
||||
},
|
||||
plugins: [
|
||||
sourcemaps(),
|
||||
typescript({}),
|
||||
process.env.NODE_ENV === "production" && terser({ ecma: 2020, keep_fnames: true }),
|
||||
typescript(),
|
||||
styles({
|
||||
mode: ["extract", `css/${name}.css`],
|
||||
url: false,
|
||||
sourceMap: true,
|
||||
minimize: isProduction,
|
||||
}),
|
||||
copy({
|
||||
targets: [
|
||||
{ src: staticFiles.map((file) => `${sourceDirectory}/${file}`), dest: distDirectory },
|
||||
{
|
||||
src: [`${sourceDirectory}/packs/*.json`],
|
||||
dest: `${distDirectory}/packs`,
|
||||
rename: (name) => `${name}.db`,
|
||||
transform: convertJSONToPack,
|
||||
},
|
||||
],
|
||||
}),
|
||||
isProduction && terser({ ecma: 2020, keep_fnames: true }),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
export default config;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import "../scss/ds4.scss";
|
||||
import registerForHooks from "./hooks/hooks";
|
||||
|
||||
registerForHooks();
|
||||
|
|
84
tools/bump-version.js
Normal file
84
tools/bump-version.js
Normal file
|
@ -0,0 +1,84 @@
|
|||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import fs from "fs-extra";
|
||||
import path from "node:path";
|
||||
import semver from "semver";
|
||||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
|
||||
import { sourceDirectory } from "./const.js";
|
||||
|
||||
const getDownloadURL = (version) => `https://git.f3l.de/dungeonslayers/ds4/-/releases/${version}/downloads/ds4.zip`;
|
||||
const getChangelogURL = (version) => `https://git.f3l.de/dungeonslayers/ds4/-/releases/${version}`;
|
||||
|
||||
/**
|
||||
* Get the contents of the manifest file as object.
|
||||
* @returns {{file: unknown, name: string}} An object describing the manifest
|
||||
*/
|
||||
function getManifest() {
|
||||
const manifestPath = path.join(sourceDirectory, "system.json");
|
||||
|
||||
if (fs.existsSync(manifestPath)) {
|
||||
return {
|
||||
file: fs.readJSONSync(manifestPath),
|
||||
name: "system.json",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target version based on on the current version and the argument passed as release.
|
||||
* @param {string} currentVersion The current version
|
||||
* @param {semver.ReleaseType | string} release Either a semver release type or a valid semver version
|
||||
* @returns {string | null} The target version
|
||||
*/
|
||||
function getTargetVersion(currentVersion, release) {
|
||||
if (["major", "premajor", "minor", "preminor", "patch", "prepatch", "prerelease"].includes(release)) {
|
||||
return semver.inc(currentVersion, release);
|
||||
} else {
|
||||
return semver.valid(release);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update version and download URL.
|
||||
* @param {semver.ReleaseType | string} release Either a semver release type or a valid semver version
|
||||
*/
|
||||
function bumpVersion(release) {
|
||||
if (!release) {
|
||||
throw new Error("Missing release type");
|
||||
}
|
||||
|
||||
const packageJson = fs.readJSONSync("package.json");
|
||||
const manifest = getManifest();
|
||||
if (!manifest) throw new Error("Manifest JSON not found");
|
||||
|
||||
const currentVersion = packageJson.version;
|
||||
const targetVersion = getTargetVersion(currentVersion, release);
|
||||
|
||||
if (!targetVersion) {
|
||||
throw new Error("Incorrect version arguments");
|
||||
}
|
||||
if (targetVersion === currentVersion) {
|
||||
throw new Error("Target version is identical to current version");
|
||||
}
|
||||
|
||||
console.log(`Bumping version number to '${targetVersion}'`);
|
||||
packageJson.version = targetVersion;
|
||||
fs.writeJSONSync("package.json", packageJson, { spaces: 4 });
|
||||
manifest.file.version = targetVersion;
|
||||
manifest.file.download = getDownloadURL(targetVersion);
|
||||
manifest.file.changelog = getChangelogURL(targetVersion);
|
||||
fs.writeJSONSync(path.join(sourceDirectory, manifest.name), manifest.file, { spaces: 4 });
|
||||
}
|
||||
|
||||
const argv = yargs(hideBin(process.argv)).usage("Usage: $0").option("release", {
|
||||
alias: "r",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
description: "Either a semver release type or a valid semver version",
|
||||
}).argv;
|
||||
const release = argv.r;
|
||||
bumpVersion(release);
|
9
tools/const.js
Normal file
9
tools/const.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
export const name = "ds4";
|
||||
export const sourceDirectory = "./src";
|
||||
export const distDirectory = "./dist";
|
||||
export const destinationDirectory = "systems";
|
||||
export const foundryconfigFile = "./foundryconfig.json";
|
20
tools/convert-packs-to-json.js
Normal file
20
tools/convert-packs-to-json.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import promises from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
import { distDirectory, sourceDirectory } from "./const.js";
|
||||
import { convertPackFileToJSONFile } from "./json-pack-tools.js";
|
||||
|
||||
const packsDistDirectory = path.join(distDirectory, "packs");
|
||||
const packsSourceDirectory = path.join(sourceDirectory, "packs");
|
||||
|
||||
console.log(`Converting pack files in ${packsDistDirectory} to json files in ${packsSourceDirectory}:`);
|
||||
|
||||
const conversionPromises = (await promises.readdir(packsDistDirectory, { withFileTypes: true }))
|
||||
.filter((dirent) => dirent.isFile() && path.extname(dirent.name))
|
||||
.map(async (dirent) => convertPackFileToJSONFile(path.join(packsDistDirectory, dirent.name), packsSourceDirectory));
|
||||
|
||||
await Promise.all(conversionPromises);
|
95
tools/json-pack-tools.js
Normal file
95
tools/json-pack-tools.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import promises from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import Datastore from "@seald-io/nedb";
|
||||
|
||||
/**
|
||||
* Removes unwanted data from a pack entry
|
||||
*/
|
||||
function cleanPackEntry(entry, cleanSourceId = true) {
|
||||
if (cleanSourceId) {
|
||||
delete entry.flags?.core?.sourceId;
|
||||
}
|
||||
Object.keys(entry.flags).forEach((scope) => {
|
||||
if (Object.keys(entry.flags[scope]).length === 0) {
|
||||
delete entry.flags[scope];
|
||||
}
|
||||
});
|
||||
if (entry.permission) entry.permission = { default: 0 };
|
||||
|
||||
const embeddedDocumentCollections = [
|
||||
"drawings",
|
||||
"effects",
|
||||
"items",
|
||||
"lights",
|
||||
"notes",
|
||||
"results",
|
||||
"sounds",
|
||||
"templates",
|
||||
"tiles",
|
||||
"tokens",
|
||||
"walls",
|
||||
];
|
||||
embeddedDocumentCollections
|
||||
.flatMap((embeddedDocumentCollection) => entry[embeddedDocumentCollection] ?? [])
|
||||
.forEach((embeddedEntry) => cleanPackEntry(embeddedEntry, false));
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JSON string containing an array to a Pack (NeDB) string.
|
||||
* @param {string} jsonString The input JSON string
|
||||
* @returns {string} The resulting Pack string
|
||||
*/
|
||||
export function convertJSONToPack(jsonString) {
|
||||
return (
|
||||
JSON.parse(jsonString)
|
||||
.map((entry) => cleanPackEntry(entry))
|
||||
.map((entry) => JSON.stringify(entry))
|
||||
.join("\n") + "\n"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a pack file (NeDB) to a JSON string.
|
||||
* @param {string} filename The name of the pack file
|
||||
* @returns {Promise<Array<unknown>>} A promise that resolves to an array of the documents in the pack file
|
||||
*/
|
||||
function convertPackFileToJSON(filename) {
|
||||
const db = new Datastore({ filename, autoload: true });
|
||||
return new Promise((resolve, reject) => {
|
||||
db.find({}, (err, docs) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(
|
||||
JSON.stringify(
|
||||
docs.map((entry) => cleanPackEntry(entry)),
|
||||
undefined,
|
||||
4,
|
||||
) + "\n",
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a pack file (NeDB) to a JSON file and puts it in the given directory. If no directory is given, it is put
|
||||
* into the same directory as the pack file.
|
||||
* @param {string} filename The name of the pack file
|
||||
* @param {string} [directory] A directory to put the json file into
|
||||
* @returns {Promise<void>} A promise that resolves once the JSON file has been written
|
||||
*/
|
||||
export async function convertPackFileToJSONFile(filename, directory) {
|
||||
if (directory === undefined) {
|
||||
directory = path.dirname(filename);
|
||||
}
|
||||
console.log(" ", path.basename(filename));
|
||||
const jsonFilePath = path.join(directory, `${path.basename(filename, path.extname(filename))}.json`);
|
||||
const json = await convertPackFileToJSON(filename);
|
||||
await promises.writeFile(jsonFilePath, json);
|
||||
}
|
55
tools/link-package.js
Normal file
55
tools/link-package.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import fs from "fs-extra";
|
||||
import path from "node:path";
|
||||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
|
||||
import { destinationDirectory, distDirectory, foundryconfigFile, name, sourceDirectory } from "./const.js";
|
||||
|
||||
/**
|
||||
* Get the data path of Foundry VTT based on what is configured in the {@link foundryconfigFile}.
|
||||
*/
|
||||
function getDataPath() {
|
||||
const config = fs.readJSONSync(foundryconfigFile);
|
||||
|
||||
if (config?.dataPath) {
|
||||
if (!fs.existsSync(path.resolve(config.dataPath))) {
|
||||
throw new Error("User data path invalid, no Data directory found");
|
||||
}
|
||||
return path.resolve(config.dataPath);
|
||||
} else {
|
||||
throw new Error(`No user data path defined in ${foundryconfigFile}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Link the built package to the user data folder.
|
||||
* @param {boolean} clean Whether to remove the link instead of creating it
|
||||
*/
|
||||
async function linkPackage(clean) {
|
||||
if (!fs.existsSync(path.resolve(sourceDirectory, "system.json"))) {
|
||||
throw new Error("Could not find system.json");
|
||||
}
|
||||
|
||||
const linkDirectory = path.resolve(getDataPath(), destinationDirectory, name);
|
||||
|
||||
if (clean) {
|
||||
console.log(`Removing link to built package at ${linkDirectory}.`);
|
||||
await fs.remove(linkDirectory);
|
||||
} else if (!fs.existsSync(linkDirectory)) {
|
||||
console.log(`Linking built package to ${linkDirectory}.`);
|
||||
await fs.ensureDir(path.resolve(linkDirectory, ".."));
|
||||
await fs.symlink(path.resolve(".", distDirectory), linkDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
const argv = yargs(hideBin(process.argv)).usage("Usage: $0").option("clean", {
|
||||
alias: "c",
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Remove the link instead of creating it",
|
||||
}).argv;
|
||||
const clean = argv.c;
|
||||
await linkPackage(clean);
|
Loading…
Reference in a new issue