Hi friends. One of our first V14 epics is complete. This is an internal API change which eliminates special string operation keys for DataModel#updateSource and Document#update workflows.
A brief overview of the change is below, with more technical details and related issues mentioned in the following GitHub issue:
https://github.com/foundryvtt/foundryvtt/issues/13090
Please use this thread for any questions you have about how this upcoming change works or how it will affect your systems and modules.
Overview of Change
This change eliminates special database operation keys like {==key: replacement} or {-=key: null} in favor of explicit special operations which share the actual field name. Specifically:
- {-=key: null}
+ {key: ForcedDeletion.create()}
- {==key: replacement}
+ {key: ForcedReplacement.create(replacement)}
The paramount advantage of this is that special operation keys share the same key as regular operations, and we avoid situations where a database update might contain something like {key: "foo", "-=key": null, "==key": "bar"} leading to significant ambiguity in what actual operation will be performed. This issue also manifests in downstream code where understanding what fields changed requires you to test things like:
if ( ("key" in data) || ("==key" in data) || ("-=key" in data) ) {
...
}
This change is labeled as BREAKING because it changes the way that developers should interact with DataModel#updateSource and Document#update APIs. It is not immediately breaking, as a deprecation period preserves full compatibility for special deletion and replacement keys until Version 16.
GlobalThis References
We have added these globalThis shorthand references to make it more convenient to interact with these special operators:
/**
* A singleton ForcedDeletion operator instance that can be reused.
* @type {foundry.data.operators.ForcedDeletion}
*/
globalThis._del = new foundry.data.operators.ForcedDeletion();
/**
* A reference for ForcedReplacement.create that can be easily referenced.
* @type {foundry.data.operators.ForcedReplacement.create}
*/
globalThis._replace = foundry.data.operators.ForcedReplacement.create;
Checking Whether You Are Impacted
The following regex pattern is a good one to use to look for possible usages of a legacy forced deletion (-=) or forced replacement (==) key:
["'`\.][=-]=
Example Usages
Example 1 - Reset a field back to its initial value
model.updateSource({someField: foundry.data.operators.ForcedDeletion.create()});
doc.update({"system.attributes.strength.value": _del}};
Example 2 - Forcibly replace a certain value
model.updateSource({someField: foundry.data.operators.ForcedReplacement.create("foo")});
doc.update({"system.attributes.strength.value": _replace(17)}};
Example 3 - Forced Replacement of an entire object
model.updateSource({innerSchema: foundry.data.operators.ForcedReplacement.create({foo: "bar"})});
doc.update({"system.attributes.strength": _replace({value: 17, bonus: 2)}};
