mirror of
https://gitgud.io/BondageProjects/Bondage-College.git
synced 2026-07-09 16:09:03 +00:00
CI: Pretty parallel CI
This commit is contained in:
parent
ac7a6cb0d4
commit
763be34927
10 changed files with 627 additions and 13 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -6,6 +6,7 @@
|
|||
.DS_Store
|
||||
|
||||
node_modules
|
||||
BondageClub/.cache/
|
||||
web.config
|
||||
/BondageClub/Tools/Node/.imagemin-cache
|
||||
BondageClub/1 - prepare.bat
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@ check:
|
|||
only:
|
||||
- merge_requests
|
||||
image: node:20
|
||||
cache:
|
||||
key:
|
||||
files:
|
||||
- BondageClub/package-lock.json
|
||||
paths:
|
||||
- BondageClub/node_modules/
|
||||
- BondageClub/.cache/
|
||||
script:
|
||||
- npm --prefix $NPM_PREFIX ci
|
||||
- npm --prefix $NPM_PREFIX ci --no-fund --no-audit --loglevel=error
|
||||
- npm --prefix $NPM_PREFIX run checks
|
||||
|
|
|
|||
201
BondageClub/Tools/Node/Checks.js
Normal file
201
BondageClub/Tools/Node/Checks.js
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
import { spawn } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import path from "node:path";
|
||||
import {
|
||||
colorizeOutput,
|
||||
formatDivider,
|
||||
formatFailureHeading,
|
||||
formatRunningHeader,
|
||||
formatStatusLine,
|
||||
formatSummaryCounts,
|
||||
formatWarningHeading,
|
||||
outputHasWarnings,
|
||||
} from "./ChecksFormat.js";
|
||||
|
||||
// #region Configuration
|
||||
|
||||
const ROOT = path.resolve(fileURLToPath(import.meta.url), "../..");
|
||||
|
||||
/** @typedef {{ name: string, code: number, output: string, duration?: number }} CheckResult */
|
||||
|
||||
/** @type {readonly string[]} */
|
||||
const CHEAP_CHECKS = [
|
||||
"assets:typecheck",
|
||||
"assets:check",
|
||||
"assets:prettier",
|
||||
"assets:eslint",
|
||||
"scripts:typecheck:tsc",
|
||||
"scripts:typecheck:strict",
|
||||
"scripts:lint",
|
||||
"files:case",
|
||||
"files:csvtypescript",
|
||||
];
|
||||
|
||||
/** @type {readonly string[]} */
|
||||
const FULL_CHECKS = [
|
||||
...CHEAP_CHECKS,
|
||||
"scripts:typecheck-expensive",
|
||||
"styles:prettier",
|
||||
];
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Check execution
|
||||
|
||||
/**
|
||||
* Creates a child process, buffering the output and resolving with the result.
|
||||
* @param {string} name
|
||||
* @returns {Promise<CheckResult>}
|
||||
*/
|
||||
function runCheck(name) {
|
||||
return new Promise((resolve) => {
|
||||
/** @type {string[]} */
|
||||
const output = [];
|
||||
const npmExecPath = process.env.npm_execpath;
|
||||
const useNodeForNpm = typeof npmExecPath === "string" && /\.m?js$/i.test(npmExecPath);
|
||||
const command = useNodeForNpm ? process.execPath : "npm";
|
||||
/** @type {string[]} */
|
||||
const args = useNodeForNpm
|
||||
? [npmExecPath, "run", "--silent", name]
|
||||
: ["run", "--silent", name];
|
||||
|
||||
const env = { ...process.env };
|
||||
if (name === "scripts:typecheck:strict") {
|
||||
// kill tsc-strict spinner
|
||||
env.CI = "1";
|
||||
}
|
||||
|
||||
const startTime = performance.now();
|
||||
const child = spawn(command, args, {
|
||||
cwd: ROOT,
|
||||
env,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
child.stdout.setEncoding("utf8");
|
||||
child.stderr.setEncoding("utf8");
|
||||
child.stdout.on("data", (chunk) => output.push(chunk));
|
||||
child.stderr.on("data", (chunk) => output.push(chunk));
|
||||
|
||||
child.on("close", (code) => {
|
||||
resolve({
|
||||
name,
|
||||
code: code ?? 1,
|
||||
output: output.join("").trimEnd(),
|
||||
duration: performance.now() - startTime,
|
||||
});
|
||||
});
|
||||
|
||||
child.on("error", (err) => {
|
||||
resolve({
|
||||
name,
|
||||
code: 1,
|
||||
output: String(err),
|
||||
duration: performance.now() - startTime,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all checks in parallel and returns the results.
|
||||
* @param {readonly string[]} names
|
||||
* @returns {Promise<CheckResult[]>}
|
||||
*/
|
||||
async function runChecks(names) {
|
||||
/** @type {Map<string, CheckResult>} */
|
||||
const resultsByName = new Map();
|
||||
|
||||
await Promise.all(
|
||||
names.map(async (name) => {
|
||||
resultsByName.set(name, await runCheck(name));
|
||||
}),
|
||||
);
|
||||
|
||||
return names.map((name) => resultsByName.get(name) ?? {
|
||||
name,
|
||||
code: 1,
|
||||
output: "Check did not run",
|
||||
});
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Console output
|
||||
|
||||
/**
|
||||
* Prints the failure output for a check result.
|
||||
* @param {CheckResult} result
|
||||
*/
|
||||
function printFailureOutput(result) {
|
||||
console.log("\u200B");
|
||||
console.log(formatFailureHeading(result.name));
|
||||
console.log(colorizeOutput(result.output));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the warning output for a check that passed but reported warnings.
|
||||
* @param {CheckResult} result
|
||||
*/
|
||||
function printWarningOutput(result) {
|
||||
console.log("\u200B");
|
||||
console.log(formatWarningHeading(result.name));
|
||||
console.log(colorizeOutput(result.output));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the summary of the check results.
|
||||
* @param {readonly CheckResult[]} results
|
||||
*/
|
||||
function printSummary(results) {
|
||||
const failed = results.filter((result) => result.code !== 0);
|
||||
const passed = results.length - failed.length;
|
||||
|
||||
console.log("\u200B");
|
||||
console.log(formatDivider());
|
||||
console.log(formatSummaryCounts(passed, failed.length));
|
||||
console.log("\u200B");
|
||||
|
||||
for (const result of results) {
|
||||
console.log(formatStatusLine(result));
|
||||
}
|
||||
|
||||
console.log(formatDivider());
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Entry point
|
||||
|
||||
/**
|
||||
* @param {readonly string[]} names
|
||||
* @param {boolean} silent
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
async function main(names, silent) {
|
||||
if (!silent) {
|
||||
console.log(formatRunningHeader(names.length));
|
||||
}
|
||||
|
||||
const results = await runChecks(names);
|
||||
|
||||
for (const result of results) {
|
||||
if (result.code !== 0) {
|
||||
printFailureOutput(result);
|
||||
} else if (outputHasWarnings(result.output)) {
|
||||
printWarningOutput(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
printSummary(results);
|
||||
}
|
||||
|
||||
return results.some((result) => result.code !== 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
const cheap = process.argv.includes("--cheap") || process.argv.includes("-c");
|
||||
const isSilent = process.argv.includes("--silent") || process.argv.includes("-s");
|
||||
process.exitCode = await main(cheap ? CHEAP_CHECKS : FULL_CHECKS, isSilent);
|
||||
|
||||
// #endregion
|
||||
392
BondageClub/Tools/Node/ChecksFormat.js
Normal file
392
BondageClub/Tools/Node/ChecksFormat.js
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
import colors from "ansi-colors";
|
||||
|
||||
/** @typedef {{ name: string, code: number, output: string, duration?: number }} CheckResult */
|
||||
|
||||
// #region Patterns
|
||||
|
||||
/** @type {RegExp} */
|
||||
const QUOTED_STRING_RE = /"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g;
|
||||
|
||||
/** @type {RegExp} */
|
||||
const FILE_PATH_RE =
|
||||
/(?:\.\.?\/|\/|[A-Za-z]:[\\/])?[\w./\\-]+\.(?:js|ts|tsx|mts|cts|css|png|csv|json|md|yml|yaml|txt|html|svg|jpe?g|gif|webp)\b/g;
|
||||
|
||||
const DIVIDER = "─".repeat(60);
|
||||
|
||||
/** Placeholder byte used while stashing quoted strings during colorization. */
|
||||
const STASH = String.fromCharCode(0);
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Primitives
|
||||
|
||||
/**
|
||||
* Returns whether the output has color.
|
||||
* @param {string} output
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function outputHasColor(output) {
|
||||
return output.includes("\x1b[");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the style for a severity.
|
||||
* @param {string} severity
|
||||
* @returns {(value: string) => string}
|
||||
*/
|
||||
function severityStyle(severity) {
|
||||
return severity.toLowerCase() === "error" ? colors.red : colors.yellow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the duration of a check.
|
||||
* @param {number | undefined} durationMs
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatDuration(durationMs) {
|
||||
if (durationMs === undefined) {
|
||||
return colors.gray("(—)");
|
||||
}
|
||||
return colors.gray(`(${durationMs.toFixed(0)}ms)`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily replaces quoted strings so other patterns do not match inside them.
|
||||
* @param {string} text
|
||||
* @returns {{ text: string, restore: (value: string) => string }}
|
||||
*/
|
||||
function stashQuotedStrings(text) {
|
||||
/** @type {string[]} */
|
||||
const quoted = [];
|
||||
const stashed = text.replace(QUOTED_STRING_RE, (match) => {
|
||||
quoted.push(match);
|
||||
return `${STASH}${quoted.length - 1}${STASH}`;
|
||||
});
|
||||
return {
|
||||
text: stashed,
|
||||
restore: (value) =>
|
||||
value.replace(new RegExp(`${STASH}(\\d+)${STASH}`, "g"), (_, index) => colors.green(quoted[Number(index)] ?? "")),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorizes the output of an identifier.
|
||||
* @param {string} part
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorizeIdentifier(part) {
|
||||
return part === "null" ? colors.dim("null") : colors.cyan(part);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies generic inline highlights to plain text.
|
||||
* @param {string} text
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorizeInline(text) {
|
||||
const { text: stashed, restore } = stashQuotedStrings(text);
|
||||
let result = stashed.replace(FILE_PATH_RE, (match) => colors.cyan(match));
|
||||
result = result.replace(/\b(TS\d+)\b/g, (_, code) => colors.red.bold(code));
|
||||
result = result.replace(/\bnull\b/g, (match) => colors.dim(match));
|
||||
return restore(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorizes the output of a prefixed line.
|
||||
* @param {string} line
|
||||
* @param {string} prefix
|
||||
* @param {(value: string) => string} stylePrefix
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorizePrefixedLine(line, prefix, stylePrefix) {
|
||||
const match = line.match(/^(\s*)(.+)$/);
|
||||
if (!match) {
|
||||
return line;
|
||||
}
|
||||
|
||||
const [, indent, body] = match;
|
||||
const prefixMatch = body.match(new RegExp(`^(${prefix})(\\s*)(.*)$`, "i"));
|
||||
if (!prefixMatch) {
|
||||
return line;
|
||||
}
|
||||
|
||||
const [, label, spacing, rest] = prefixMatch;
|
||||
return `${indent}${stylePrefix(label)}${spacing}${colorizeInline(rest)}`;
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Tool-specific line formatters
|
||||
|
||||
/**
|
||||
* Colorizes the output of an AssetCheck error line.
|
||||
* @param {string} line
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorizeAssetErrorLine(line) {
|
||||
const match = line.match(
|
||||
/^(\s*)ERROR:\s*(.+):\s*(Missing asset)\s+("(?:[^"\\]|\\.)*")\s*$/i,
|
||||
);
|
||||
if (!match) {
|
||||
return colorizePrefixedLine(line, "ERROR:", colors.red.bold);
|
||||
}
|
||||
|
||||
const [, indent, ids, label, quotedPath] = match;
|
||||
const coloredIds = ids.split(":").map(colorizeIdentifier).join(colors.dim(":"));
|
||||
return `${indent}${colors.red.bold("ERROR:")} ${coloredIds}${colors.dim(":")} ${colors.dim(label)} ${colors.green(quotedPath)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorizes the output of a TypeScript check result.
|
||||
* @param {string} line
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorizeTypeScriptLine(line) {
|
||||
const parenMatch = line.match(/^(.+?\(\d+,\d+\)):\s*(error|warning)\s+(TS\d+):\s*(.*)$/i);
|
||||
if (parenMatch) {
|
||||
const [, location, severity, code, message] = parenMatch;
|
||||
const style = severityStyle(severity);
|
||||
return `${colors.cyan(location)}: ${style(severity)} ${colors.red.bold(code)}: ${colorizeInline(message)}`;
|
||||
}
|
||||
|
||||
const colonMatch = line.match(/^(.+?):(\d+):(\d+)\s*-\s*(error|warning)\s+(TS\d+):\s*(.*)$/i);
|
||||
if (colonMatch) {
|
||||
const [, file, lineNo, column, severity, code, message] = colonMatch;
|
||||
const style = severityStyle(severity);
|
||||
return `${colors.cyan(file)}:${colors.yellow(`${lineNo}:${column}`)} - ${style(severity)} ${colors.red.bold(code)}: ${colorizeInline(message)}`;
|
||||
}
|
||||
|
||||
if (/error TS\d+:/i.test(line)) {
|
||||
return colorizePrefixedLine(line, "error TS\\d+:", colors.red);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorizes the output of an ESLint check result.
|
||||
* @param {string} line
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorizeEslintLine(line) {
|
||||
const detailMatch = line.match(
|
||||
/^(\s*)(\d+):(\d+)\s+(error|warning)\s+(.+?)\s+([@\w-]+(?:\/[\w-]+)?)\s*$/,
|
||||
);
|
||||
if (detailMatch) {
|
||||
const [, indent, lineNo, column, severity, message, rule] = detailMatch;
|
||||
const style = severityStyle(severity);
|
||||
return `${indent}${colors.yellow(`${lineNo}:${column}`)} ${style(severity)} ${colorizeInline(message)} ${colors.magenta.dim(rule)}`;
|
||||
}
|
||||
|
||||
const trimmed = line.trim();
|
||||
if (/^(?:\.\.?\/|\/|[A-Za-z]:)/.test(trimmed) && FILE_PATH_RE.test(trimmed)) {
|
||||
return colors.cyan.underline(trimmed);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorizes the output of a Prettier check result.
|
||||
* @param {string} line
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorizePrettierLine(line) {
|
||||
const match = line.match(/^(\[(?:warn|error)\])\s+(.+)$/i);
|
||||
if (match) {
|
||||
const [, tag, file] = match;
|
||||
const tagColor = /error/i.test(tag) ? colors.red : colors.yellow;
|
||||
return `${tagColor(tag)} ${colors.cyan(file)}`;
|
||||
}
|
||||
|
||||
if (/^Checking formatting\.\.\.$/i.test(line.trim())) {
|
||||
return colors.dim(line);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Output colorization
|
||||
|
||||
/**
|
||||
* Colorizes a single line of check output.
|
||||
* @param {string} line
|
||||
* @returns {string}
|
||||
*/
|
||||
function colorizeLine(line) {
|
||||
// we don't want to colorize colored output (e.g. AssetCheck, FileCase)
|
||||
if (outputHasColor(line)) {
|
||||
return line;
|
||||
}
|
||||
|
||||
if (/^\s*ERROR:/i.test(line)) {
|
||||
return colorizeAssetErrorLine(line);
|
||||
}
|
||||
|
||||
if (/^\s*(WARNING|WARN):/i.test(line)) {
|
||||
return colorizePrefixedLine(line, "(WARNING|WARN):", colors.yellow.bold);
|
||||
}
|
||||
|
||||
if (/\berror TS\d+:/i.test(line) || /\(\d+,\d+\):/.test(line)) {
|
||||
const colored = colorizeTypeScriptLine(line);
|
||||
if (colored !== line) {
|
||||
return colored;
|
||||
}
|
||||
}
|
||||
|
||||
if (/^\s*\d+:\d+\s+(error|warning)\s+/i.test(line)) {
|
||||
const colored = colorizeEslintLine(line);
|
||||
if (colored !== line) {
|
||||
return colored;
|
||||
}
|
||||
}
|
||||
|
||||
if (/^\[(?:warn|error)\]/i.test(line.trim()) || /^Checking formatting/i.test(line.trim())) {
|
||||
const colored = colorizePrettierLine(line);
|
||||
if (colored !== line) {
|
||||
return colored;
|
||||
}
|
||||
}
|
||||
|
||||
const trimmed = line.trim();
|
||||
if (trimmed && FILE_PATH_RE.test(trimmed) && !/[:]\s/.test(trimmed)) {
|
||||
return colors.cyan.underline(trimmed);
|
||||
}
|
||||
|
||||
return colorizeInline(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorizes the output of a check result.
|
||||
* @param {string} output
|
||||
* @returns {string}
|
||||
*/
|
||||
export function colorizeOutput(output) {
|
||||
// not sure if this can happen, but anyway
|
||||
if (!output) {
|
||||
return colors.dim("(no output)");
|
||||
}
|
||||
|
||||
return output.split("\n").map(colorizeLine).join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a line of check output is a warning (not an error).
|
||||
* @param {string} line
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function lineHasWarning(line) {
|
||||
if (!line.trim()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (/^\s*(WARNING|WARN):/i.test(line)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (/:\s*warning\s+TS\d+:/i.test(line) || / - warning TS\d+:/i.test(line)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (/^\s*\d+:\d+\s+warning\s+/i.test(line)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (/^\[warn\]/i.test(line.trim())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (/\(\d+ errors?, \d+ warnings?\)/i.test(line) || /^\s*✖.*\b\d+\s+warning/i.test(line)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether check output contains any warnings.
|
||||
* @param {string} output
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function outputHasWarnings(output) {
|
||||
return output.split("\n").some(lineHasWarning);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Summary & status formatting
|
||||
|
||||
/**
|
||||
* Formats the name of a check.
|
||||
* @param {string} name
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatCheckName(name) {
|
||||
const colon = name.indexOf(":");
|
||||
if (colon === -1) {
|
||||
return colors.bold(name);
|
||||
}
|
||||
return colors.dim(name.slice(0, colon + 1)) + colors.bold(name.slice(colon + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the status line for a check result.
|
||||
* @param {CheckResult} result
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatStatusLine(result) {
|
||||
/** @type {string} */
|
||||
const icon = result.code !== 0
|
||||
? colors.red("✗")
|
||||
: outputHasWarnings(result.output)
|
||||
? colors.yellow("⚠")
|
||||
: colors.green("✓");
|
||||
return ` ${icon} ${formatCheckName(result.name)} ${formatDuration(result.duration)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the summary counts for the check results.
|
||||
* @param {number} passed
|
||||
* @param {number} failed
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatSummaryCounts(passed, failed) {
|
||||
const failedText = failed ? colors.red(String(failed)) : colors.green("0");
|
||||
return colors.bold(`Summary: ${colors.green(String(passed))} passed, ${failedText} failed`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the header for the running checks.
|
||||
* @param {number} count
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatRunningHeader(count) {
|
||||
return colors.bold(`Running ${colors.cyan(String(count))} checks…`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the heading for a failed check.
|
||||
* @param {string} name
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatFailureHeading(name) {
|
||||
return colors.red.bold.underline(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the heading for a passed check that reported warnings.
|
||||
* @param {string} name
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatWarningHeading(name) {
|
||||
return colors.yellow.bold.underline(name);
|
||||
}
|
||||
|
||||
/** @returns {string} */
|
||||
export function formatDivider() {
|
||||
return colors.bold(DIVIDER);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
|
@ -108,7 +108,7 @@ export const errorState = {
|
|||
* @param {string} text The error
|
||||
*/
|
||||
export function error(text) {
|
||||
console.log("ERROR:", text);
|
||||
console.error("ERROR:", text);
|
||||
process.exitCode = 1;
|
||||
errorState.local = true;
|
||||
errorState.global = true;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "../../.cache/tsc-asset.tsbuildinfo",
|
||||
"module": "commonjs",
|
||||
"target": "ES2021",
|
||||
"lib": ["es2021", "dom", "DOM.Iterable"],
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
"types": [],
|
||||
"strict": false,
|
||||
"skipLibCheck": true,
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "../../.cache/tsc-csvtypescript.tsbuildinfo",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "typescript-strict-plugin"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "../../.cache/tsc-expensive.tsbuildinfo",
|
||||
"module": "commonjs",
|
||||
"target": "ES2021",
|
||||
"lib": ["es2021", "dom", "DOM.Iterable"],
|
||||
|
|
|
|||
|
|
@ -8,22 +8,27 @@
|
|||
"scripts": {
|
||||
"changelog:generate": "cd Tools/Node && node GenerateChangelog generate",
|
||||
"changelog:prepare": "cd Tools/Node && node GenerateChangelog prepare",
|
||||
"checks": "npm-run-all -c assets:typecheck scripts:typecheck scripts:typecheck-expensive assets:check scripts:lint styles:prettier assets:lint files:case files:csvtypescript",
|
||||
"checks:cheap": "npm-run-all -c assets:typecheck scripts:typecheck assets:check scripts:lint assets:lint files:case files:csvtypescript",
|
||||
"checks:expensive": "npm-run-all -c checks",
|
||||
"checks": "node --unhandled-rejections=strict Tools/Node/Checks.js",
|
||||
"checks:cheap": "node --unhandled-rejections=strict Tools/Node/Checks.js --cheap",
|
||||
"checks:expensive": "node --unhandled-rejections=strict Tools/Node/Checks.js",
|
||||
"assets:checks": "run-p -cs --aggregate-output assets:typecheck assets:check assets:lint",
|
||||
"assets:typecheck-check": "run-p -cs --aggregate-output assets:typecheck assets:check",
|
||||
"assets:clean": "gulp --gulpfile Tools/Node/gulpfile.js clean",
|
||||
"assets:minify": "gulp --gulpfile Tools/Node/gulpfile.js assetMinify --max-old-space-size=8192",
|
||||
"assets:prettier": "prettier --write Assets/Female3DCG/Female3DCG.js Assets/Female3DCG/Female3DCGExtended.js && git diff --exit-code Assets/Female3DCG/Female3DCG.js Assets/Female3DCG/Female3DCGExtended.js",
|
||||
"assets:eslint": "eslint Assets/Female3DCG/Female3DCG.js Assets/Female3DCG/Female3DCGExtended.js",
|
||||
"assets:lint": "npm run assets:prettier && npm run assets:eslint",
|
||||
"assets:prettier": "prettier --check Assets/Female3DCG/Female3DCG.js Assets/Female3DCG/Female3DCGExtended.js",
|
||||
"assets:prettier:fix": "prettier --write Assets/Female3DCG/Female3DCG.js Assets/Female3DCG/Female3DCGExtended.js",
|
||||
"assets:eslint": "eslint --cache --cache-location .cache/eslint Assets/Female3DCG/Female3DCG.js Assets/Female3DCG/Female3DCGExtended.js",
|
||||
"assets:lint": "run-s -cn assets:prettier assets:eslint",
|
||||
"assets:lint:fix": "prettier-eslint --write Assets/Female3DCG/Female3DCG.js Assets/Female3DCG/Female3DCGExtended.js",
|
||||
"assets:check": "cd Tools/Node && node --unhandled-rejections=strict AssetCheck",
|
||||
"assets:typecheck": "cd ../ && tsc -p BondageClub/Tools/Node/tsconfig-assetcheck.json",
|
||||
"assets:typecheck": "tsc -p Tools/Node/tsconfig-assetcheck.json",
|
||||
"assets:posemapping": "cd Tools/Node && node --unhandled-rejections=strict PoseMapping",
|
||||
"scripts:lint": "eslint \"Scripts/**/*.js\" \"Screens/**/*.js\" \"Tools/**/*.js\" \"Backgrounds/Backgrounds.js\"",
|
||||
"scripts:lint:fix": "eslint --fix \"Scripts/**/*.js\" \"Screens/**/*.js\" \"Tools/**/*.js\" \"Backgrounds/Backgrounds.js\"",
|
||||
"scripts:typecheck": "cd ../ && tsc -p BondageClub/tsconfig.json && tsc-strict -p BondageClub/tsconfig.json",
|
||||
"scripts:typecheck-expensive": "cd ../ && tsc -p BondageClub/Tools/Node/tsconfig-typecheckexpensive.json",
|
||||
"scripts:lint": "eslint --cache --cache-location .cache/eslint \"Scripts/**/*.js\" \"Screens/**/*.js\" \"Tools/**/*.js\" \"Backgrounds/Backgrounds.js\"",
|
||||
"scripts:lint:fix": "eslint --cache --cache-location .cache/eslint --fix \"Scripts/**/*.js\" \"Screens/**/*.js\" \"Tools/**/*.js\" \"Backgrounds/Backgrounds.js\"",
|
||||
"scripts:typecheck": "run-p -cs --aggregate-output scripts:typecheck:tsc scripts:typecheck:strict",
|
||||
"scripts:typecheck:tsc": "tsc -p tsconfig.json",
|
||||
"scripts:typecheck:strict": "CI=1 tsc-strict -p tsconfig.json",
|
||||
"scripts:typecheck-expensive": "tsc -p Tools/Node/tsconfig-typecheckexpensive.json",
|
||||
"styles:prettier": "prettier --check --print-width 120 CSS/",
|
||||
"styles:prettier:fix": "prettier --write --print-width 120 CSS/",
|
||||
"files:case": "cd Tools/Node && node --unhandled-rejections=strict FileCase",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
"lib": ["es2021", "dom", "DOM.Iterable"],
|
||||
"checkJs": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": ".cache/tsc-main.tsbuildinfo",
|
||||
"types": [],
|
||||
"strict": false,
|
||||
"skipLibCheck": true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue