Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove type and usage of global foundry helpers #12221

Merged
merged 1 commit into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/lib/compendium-pack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { isObject, recursiveReplaceString, setHasElement, sluggify, tupleHasValu
import fs from "fs";
import path from "path";
import coreIconsJSON from "../core-icons.json" assert { type: "json" };
import "./core-helpers.ts";
import "./foundry-utils.ts";
import { getFilesRecursively, PackError } from "./helpers.ts";
import { DBFolder, LevelDatabase } from "./level-database.ts";
import { PackEntry } from "./types.ts";
Expand Down
27 changes: 0 additions & 27 deletions build/lib/core-helpers.ts

This file was deleted.

59 changes: 51 additions & 8 deletions tests/fixtures/foundryshim.ts → build/lib/foundry-utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
/**
* Quickly clone a simple piece of data, returning a copy which can be mutated safely.
* This method DOES support recursive data structures containing inner objects or arrays.
* This method DOES NOT support advanced object types like Set, Map, or other specialized classes.
* @param original Some sort of data
* @return The clone of that data
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function deepClone<T>(original: T): T extends Set<any> | Map<any, any> | Collection<any> ? never : T {
// Simple types
if (typeof original !== "object" || original === null)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return original as T extends Set<any> | Map<any, any> | Collection<any> ? never : T;

// Arrays
if (original instanceof Array)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return original.map(deepClone) as unknown as T extends Set<any> | Map<any, any> | Collection<any> ? never : T;

// Dates
if (original instanceof Date)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return new Date(original) as unknown as T extends Set<any> | Map<any, any> | Collection<any> ? never : T;

// Unsupported advanced objects
if ((original as { constructor: unknown }).constructor !== Object)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return original as T extends Set<any> | Map<any, any> | Collection<any> ? never : T;

// Other objects
const clone: Record<string, unknown> = {};
for (const k of Object.keys(original)) {
clone[k] = deepClone(original[k as keyof typeof original]);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return clone as unknown as T extends Set<any> | Map<any, any> | Collection<any> ? never : T;
}

/**
* A helper function which searches through an object to assign a value using a string key
* This string key supports the notation a.b.c which would target object[a][b][c]
Expand Down Expand Up @@ -112,7 +150,7 @@ export function mergeObject(
Object.keys(original).forEach((k) => delete (original as Record<string, unknown>)[k]);
Object.assign(original, expanded);
} else original = expanded;
} else if (!inplace) original = deepClone(original);
} else if (!inplace) original = foundry.utils.deepClone(original);
}

// Iterate over the other object
Expand Down Expand Up @@ -246,10 +284,15 @@ function diffObject(original: any, other: any, { inner = false } = {}): any {
);
}

export function populateFoundryUtilFunctions(): void {
global.setProperty = setProperty;
global.getType = getType;
global.mergeObject = mergeObject;
global.diffObject = diffObject;
global.duplicate = duplicate;
}
const f = (global.foundry = {
utils: {
deepClone,
diffObject,
duplicate,
expandObject,
mergeObject,
setProperty,
},
} as typeof foundry);

global.fu = f.utils;
17 changes: 7 additions & 10 deletions build/run-migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { sluggify } from "@util";
import fs from "fs-extra";
import { JSDOM } from "jsdom";
import path from "path";
import { populateFoundryUtilFunctions } from "../tests/fixtures/foundryshim.ts";
import "./lib/core-helpers.ts";
import "./lib/foundry-utils.ts";
import { getFilesRecursively } from "./lib/helpers.ts";

import { Migration890RMClassItemClassDC } from "@module/migration/migrations/890-rm-class-item-class-dc.ts";
Expand Down Expand Up @@ -175,7 +174,7 @@ async function migrate() {
pruneFlags(item);
}

update.items = update.items.map((i) => mergeObject({}, i, { performDeletions: true }));
update.items = update.items.map((i) => fu.mergeObject({}, i, { performDeletions: true }));
for (const updatedItem of update.items) {
delete (updatedItem.system as { _migrations?: object })._migrations;
if (updatedItem.type === "consumable" && !updatedItem.system.spell) {
Expand All @@ -184,7 +183,7 @@ async function migrate() {
pruneFlags(updatedItem);
}

return mergeObject(source, update, { inplace: false, performDeletions: true });
return fu.mergeObject(source, update, { inplace: false, performDeletions: true });
} else if (isItemData(source)) {
source.system.slug = sluggify(source.name);
const update = await migrationRunner.getUpdatedItem(source, migrationRunner.migrations);
Expand All @@ -198,22 +197,22 @@ async function migrate() {
pruneFlags(source);
pruneFlags(update);

return mergeObject(source, update, { inplace: false, performDeletions: true });
return fu.mergeObject(source, update, { inplace: false, performDeletions: true });
} else if (isJournalEntryData(source)) {
const update = await migrationRunner.getUpdatedJournalEntry(source, migrationRunner.migrations);
pruneFlags(source);
pruneFlags(update);
return mergeObject(source, update, { inplace: false, performDeletions: true });
return fu.mergeObject(source, update, { inplace: false, performDeletions: true });
} else if (isMacroData(source)) {
const update = await migrationRunner.getUpdatedMacro(source, migrationRunner.migrations);
pruneFlags(source);
pruneFlags(update);
return mergeObject(source, update, { inplace: false, performDeletions: true });
return fu.mergeObject(source, update, { inplace: false, performDeletions: true });
} else if (isTableData(source)) {
const update = await migrationRunner.getUpdatedTable(source, migrationRunner.migrations);
pruneFlags(source);
pruneFlags(update);
return mergeObject(source, update, { inplace: false, performDeletions: true });
return fu.mergeObject(source, update, { inplace: false, performDeletions: true });
} else {
pruneFlags(source);
return source;
Expand Down Expand Up @@ -249,6 +248,4 @@ function pruneFlags(source: { flags?: Record<string, Record<string, unknown> | u
}
}

populateFoundryUtilFunctions();

migrate().catch((err) => console.error(err));
2 changes: 2 additions & 0 deletions src/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ declare global {
namespace globalThis {
// eslint-disable-next-line no-var
var game: GamePF2e;
// eslint-disable-next-line no-var
var fu: typeof foundry.utils;

// eslint-disable-next-line no-var
var ui: FoundryUI<
Expand Down
26 changes: 13 additions & 13 deletions src/module/actor/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
},
// Add debounced checkAreaEffects method
checkAreaEffects: {
value: foundry.utils.debounce(checkAreaEffects, 50),
value: fu.debounce(checkAreaEffects, 50),
},
});
}
Expand Down Expand Up @@ -425,7 +425,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n

return this.clone(
{
items: [deepClone(this._source.items), applicableEffects].flat(),
items: [fu.deepClone(this._source.items), applicableEffects].flat(),
flags: { pf2e: { rollOptions: { all: rollOptionsAll } } },
},
{ keepId: true },
Expand Down Expand Up @@ -471,7 +471,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
},
};

const source = mergeObject(effect.toObject(), { flags });
const source = fu.mergeObject(effect.toObject(), { flags });
source.system.level.value = aura.level ?? source.system.level.value;
source.system.duration.unit = "unlimited";
source.system.duration.expiry = null;
Expand Down Expand Up @@ -568,7 +568,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
linkable &&
(source.prototypeToken?.flags?.pf2e?.autoscale ??
(linkToActorSize && game.settings.get("pf2e", "tokens.autoscale")));
const merged = mergeObject(source, {
const merged = fu.mergeObject(source, {
ownership: source.ownership ?? { default: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE },
prototypeToken: {
flags: {
Expand Down Expand Up @@ -665,7 +665,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
weaponPotency: {},
preparationWarnings: {
add: (warning: string) => preparationWarnings.add(warning),
flush: foundry.utils.debounce(() => {
flush: fu.debounce(() => {
for (const warning of preparationWarnings) {
console.warn(warning);
}
Expand All @@ -691,7 +691,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
if (options?.pack && initialized._id) {
const uuid: CompendiumUUID = `Compendium.${options.pack}.${initialized._id}`;
const art = game.pf2e.system.moduleArt.map.get(uuid) ?? {};
return mergeObject(initialized, art);
return fu.mergeObject(initialized, art);
}

return initialized;
Expand Down Expand Up @@ -746,7 +746,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
this.system.attributes.flanking = { canFlank: false, canGangUp: [], flankable: false, offGuardable: false };

const { attributes, details } = this.system;
attributes.hp &&= mergeObject(attributes.hp, { negativeHealing: false, unrecoverable: 0 });
attributes.hp &&= fu.mergeObject(attributes.hp, { negativeHealing: false, unrecoverable: 0 });
attributes.immunities = attributes.immunities?.map((i) => new Immunity(i)) ?? [];
attributes.weaknesses = attributes.weaknesses?.map((w) => new Weakness(w)) ?? [];
attributes.resistances = attributes.resistances?.map((r) => new Resistance(r)) ?? [];
Expand All @@ -756,7 +756,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
if (traits?.size) traits.size = new ActorSizePF2e(traits.size);

// Setup the basic structure of pf2e flags with roll options
this.flags.pf2e = mergeObject(this.flags.pf2e ?? {}, {
this.flags.pf2e = fu.mergeObject(this.flags.pf2e ?? {}, {
rollOptions: {
all: {
[`self:type:${this.type}`]: true,
Expand Down Expand Up @@ -856,7 +856,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n

/** Set defaults for this actor's prototype token */
private preparePrototypeToken(): void {
this.prototypeToken.flags = mergeObject(
this.prototypeToken.flags = fu.mergeObject(
{ pf2e: { linkToActorSize: SIZE_LINKABLE_ACTOR_TYPES.has(this.type) } },
this.prototypeToken.flags,
);
Expand Down Expand Up @@ -1451,7 +1451,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
persistent: persistentCreated.map((c) => c.id),
updates: Object.entries(damageResult.updates)
.map(([path, newValue]) => {
const preUpdateValue = getProperty(preUpdateSource, path);
const preUpdateValue = fu.getProperty(preUpdateSource, path);
if (typeof preUpdateValue === "number") {
const difference = preUpdateValue - newValue;
if (difference === 0) {
Expand Down Expand Up @@ -1494,7 +1494,7 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n

const actorUpdates: Record<string, number | Record<string, number | string>[]> = {};
for (const update of updates) {
const currentValue = getProperty(this, update.path);
const currentValue = fu.getProperty(this, update.path);
if (typeof currentValue === "number") {
actorUpdates[update.path] = currentValue + update.value;
}
Expand Down Expand Up @@ -1706,11 +1706,11 @@ class ActorPF2e<TParent extends TokenDocumentPF2e | null = TokenDocumentPF2e | n
for (const prop of ["abilities", "attributes", "details", "skills", "saves"] as const) {
Object.defineProperty(rollData, prop, {
get: () => {
foundry.utils.logCompatibilityWarning(`@${prop} is deprecated`, {
fu.logCompatibilityWarning(`@${prop} is deprecated`, {
since: "5.0.1",
until: "6",
});
return objectHasKey(this.system, prop) ? deepClone(this.system[prop]) : null;
return objectHasKey(this.system, prop) ? fu.deepClone(this.system[prop]) : null;
},
});
}
Expand Down
8 changes: 4 additions & 4 deletions src/module/actor/character/attribute-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AttributeString } from "@actor/types.ts";
import { ATTRIBUTE_ABBREVIATIONS } from "@actor/values.ts";
import { AncestryPF2e, BackgroundPF2e, ClassPF2e } from "@item";
import { maintainFocusInRender } from "@module/sheet/helpers.ts";
import { ErrorPF2e, addSign, htmlClosest, htmlQuery, htmlQueryAll, setHasElement, tupleHasValue } from "@util";
import { ErrorPF2e, htmlClosest, htmlQuery, htmlQueryAll, setHasElement, signedInteger, tupleHasValue } from "@util";
import * as R from "remeda";

class AttributeBuilder extends Application {
Expand Down Expand Up @@ -49,7 +49,7 @@ class AttributeBuilder extends Application {
// Allow decimal values in manual mode (to track partial boosts)
const mod = build.manual ? actor._source.system.abilities?.[attribute].mod ?? 0 : value.base;
return {
mod: addSign(Number(mod.toFixed(1))),
mod: Number(mod.toFixed(1)).signedString(),
label: CONFIG.PF2E.abilities[attribute],
};
}),
Expand Down Expand Up @@ -316,7 +316,7 @@ class AttributeBuilder extends Application {
if (input.type === "number" && input.dataset.dtype === "Number") {
input.type = "text";
const newValue = Math.clamped(Number(input.value) || 0, -5, 10);
input.value = addSign(newValue);
input.value = signedInteger(newValue);

const propertyPath = input.dataset.property;
if (!propertyPath) throw ErrorPF2e("Empty property path");
Expand Down Expand Up @@ -473,7 +473,7 @@ class AttributeBuilder extends Application {
return;
}

const buildSource = mergeObject(actor.toObject().system.build ?? {}, { attributes: { boosts: {} } });
const buildSource = fu.mergeObject(actor.toObject().system.build ?? {}, { attributes: { boosts: {} } });
const boosts = (buildSource.attributes.boosts[level] ??= []);
if (boosts.includes(attribute)) {
boosts.splice(boosts.indexOf(attribute), 1);
Expand Down
Loading