diff --git a/app/imports/api/creature/creatureProperties/CreatureProperties.ts b/app/imports/api/creature/creatureProperties/CreatureProperties.ts index 3d673359..2dfcec5f 100644 --- a/app/imports/api/creature/creatureProperties/CreatureProperties.ts +++ b/app/imports/api/creature/creatureProperties/CreatureProperties.ts @@ -7,6 +7,7 @@ import propertySchemasIndex from '/imports/api/properties/computedPropertySchema import { storedIconsSchema } from '/imports/api/icons/Icons'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import { InferType, TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema'; +import type { ComputedProperty, ComputedPropertyTypeMap } from '/imports/api/properties/Property.type'; const PreComputeCreaturePropertySchema = new TypedSimpleSchema({ _id: { @@ -153,15 +154,15 @@ for (key in propertySchemasIndex) { } } -export type CreaturePropertyByType = - InferType +export type CreaturePropertyByType = + ComputedProperty & InferType & InferType & InferType & InferType type ConvertToUnion = T[keyof T]; -export type CreatureProperty = ConvertToUnion<{ [key in keyof typeof propertySchemasIndex]: CreaturePropertyByType }>; +export type CreatureProperty = ConvertToUnion<{ [key in keyof ComputedPropertyTypeMap]: CreaturePropertyByType }>; export default CreatureProperties; export { diff --git a/app/imports/api/engine/action/applyProperties/applyBuffRemoverProperty.ts b/app/imports/api/engine/action/applyProperties/applyBuffRemoverProperty.ts index d4547b33..1b8fd77f 100644 --- a/app/imports/api/engine/action/applyProperties/applyBuffRemoverProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyBuffRemoverProperty.ts @@ -1,5 +1,5 @@ import { PropTask } from '/imports/api/engine/action/tasks/Task'; -import TaskResult from 'imports/api/engine/action/tasks/TaskResult'; +import TaskResult from '/imports/api/engine/action/tasks/TaskResult'; import getPropertyTitle from '/imports/api/utility/getPropertyTitle'; import { findLast, filter, difference, intersection } from 'lodash'; import { getPropertiesOfType, getPropertyAncestors } from '/imports/api/engine/loadCreatures'; @@ -53,9 +53,10 @@ export default async function applyBuffRemoverProperty( } else { // Get all the buffs targeted by tags const allBuffs = getPropertiesOfType(targetId, 'buff'); - const targetedBuffs = filter(allBuffs, buff => { + const targetedBuffs = filter(allBuffs, (buff): boolean => { if (buff.inactive) return false; if (buffRemoverMatchTags(prop, buff)) return true; + return false; }); // Remove the buffs if (prop.removeAll) { @@ -65,7 +66,7 @@ export default async function applyBuffRemoverProperty( }); } else { // Sort in reverse order - targetedBuffs.sort((a, b) => b.order - a.order); + targetedBuffs.sort((a, b) => b.left - a.left); // Remove the one with the highest order const buff = targetedBuffs[0]; if (buff) { diff --git a/app/imports/api/engine/loadCreatures.ts b/app/imports/api/engine/loadCreatures.ts index 5e05df26..14e81735 100644 --- a/app/imports/api/engine/loadCreatures.ts +++ b/app/imports/api/engine/loadCreatures.ts @@ -1,9 +1,10 @@ import { debounce } from 'lodash'; import Creatures from '/imports/api/creature/creatures/Creatures'; import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables'; -import CreatureProperties, { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties'; +import CreatureProperties, { CreatureProperty, CreaturePropertyByType } from '/imports/api/creature/creatureProperties/CreatureProperties'; import computeCreature from './computeCreature'; import { getFilter } from '/imports/api/parenting/parentingFunctions'; +import { ComputedPropertyTypeMap } from '../properties/Property.type'; const COMPUTE_DEBOUNCE_TIME = 100; // ms export const loadedCreatures: Map = new Map(); // creatureId => {creature, properties, etc.} @@ -81,13 +82,13 @@ export function getProperties(creatureId: string): CreatureProperty[] { return props; } -export function getPropertiesOfType(creatureId, propType) { +export function getPropertiesOfType(creatureId, propType: T): CreaturePropertyByType[] { const creature = loadedCreatures.get(creatureId); if (creature) { const props = Array.from(creature.properties.values()) .filter(prop => !prop.removed && prop.type === propType) .sort((a, b) => a.left - b.left); - return EJSON.clone(props); + return EJSON.clone(props) as unknown as CreaturePropertyByType[]; } // console.time(`Cache miss on creature properties: ${creatureId}`) const props = CreatureProperties.find({ @@ -98,7 +99,7 @@ export function getPropertiesOfType(creatureId, propType) { sort: { left: 1 }, }).fetch(); // console.timeEnd(`Cache miss on creature properties: ${creatureId}`); - return props; + return props as unknown as CreaturePropertyByType[]; } /** diff --git a/app/imports/api/properties/Attributes.ts b/app/imports/api/properties/Attributes.ts index 48e9626a..0b3987aa 100644 --- a/app/imports/api/properties/Attributes.ts +++ b/app/imports/api/properties/Attributes.ts @@ -2,7 +2,7 @@ import SimpleSchema from 'simpl-schema'; import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; -import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; +import { Expand, InferType, TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema'; /* * Attributes are numbered stats of a character @@ -40,7 +40,7 @@ const AttributeSchema = createPropertySchema({ // For type hitDice, the size needs to be stored separately hitDiceSize: { type: String, - allowedValues: ['d1', 'd2', 'd4', 'd6', 'd8', 'd10', 'd12', 'd20', 'd100'], + allowedValues: ['d1', 'd2', 'd4', 'd6', 'd8', 'd10', 'd12', 'd20', 'd100'] as const, optional: true, }, // For type spellSlot, the level needs to be stored separately @@ -297,7 +297,7 @@ const ComputedOnlyAttributeSchema = createPropertySchema({ }, }); -const ComputedAttributeSchema = new SimpleSchema({}) +const ComputedAttributeSchema = new TypedSimpleSchema({}) .extend(ComputedOnlyAttributeSchema) .extend(AttributeSchema); diff --git a/app/imports/api/properties/Branches.ts b/app/imports/api/properties/Branches.ts index aedd3480..36c63817 100644 --- a/app/imports/api/properties/Branches.ts +++ b/app/imports/api/properties/Branches.ts @@ -1,7 +1,6 @@ -import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; -import { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; +import { Expand, InferType, TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema'; const BranchSchema = createPropertySchema({ branchType: { @@ -53,12 +52,12 @@ const ComputedOnlyBranchSchema = createPropertySchema({ }, }); -const ComputedBranchSchema = new SimpleSchema({}) +const ComputedBranchSchema = new TypedSimpleSchema({}) .extend(BranchSchema) .extend(ComputedOnlyBranchSchema); export type Branch = InferType; export type ComputedOnlyBranch = InferType; -export type ComputedBranch = Expand & InferType>; +export type ComputedBranch = Expand & InferType>; export { BranchSchema, ComputedBranchSchema, ComputedOnlyBranchSchema } diff --git a/app/imports/api/properties/Buffs.ts b/app/imports/api/properties/Buffs.ts index dab5594b..0d8a1389 100644 --- a/app/imports/api/properties/Buffs.ts +++ b/app/imports/api/properties/Buffs.ts @@ -1,15 +1,16 @@ import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; +import { Expand, InferType, TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema'; -let BuffSchema = createPropertySchema({ +const BuffSchema = createPropertySchema({ name: { type: String, optional: true, max: STORAGE_LIMITS.name, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, hideRemoveButton: { @@ -41,14 +42,14 @@ let BuffSchema = createPropertySchema({ }, }); -let ComputedOnlyBuffSchema = createPropertySchema({ +const ComputedOnlyBuffSchema = createPropertySchema({ description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, max: STORAGE_LIMITS.description, }, duration: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, durationSpent: { @@ -74,8 +75,12 @@ let ComputedOnlyBuffSchema = createPropertySchema({ }, }); -const ComputedBuffSchema = new SimpleSchema() +const ComputedBuffSchema = new TypedSimpleSchema({}) .extend(BuffSchema) .extend(ComputedOnlyBuffSchema); +export type Buff = InferType; +export type ComputedOnlyBuff = InferType; +export type ComputedBuff = Expand & InferType>; + export { BuffSchema, ComputedOnlyBuffSchema, ComputedBuffSchema }; diff --git a/app/imports/api/properties/Property.type.ts b/app/imports/api/properties/Property.type.ts new file mode 100644 index 00000000..6896f76f --- /dev/null +++ b/app/imports/api/properties/Property.type.ts @@ -0,0 +1,115 @@ +import { Attribute, ComputedAttribute, ComputedOnlyAttribute } from './Attributes'; +import { Branch, ComputedBranch, ComputedOnlyBranch } from './Branches'; +import { Buff, ComputedBuff, ComputedOnlyBuff } from './Buffs'; +import { Class, ComputedClass, ComputedOnlyClass } from './Classes'; +import { Constant, ComputedConstant, ComputedOnlyConstant } from './Constants'; +import { Container, ComputedContainer, ComputedOnlyContainer } from './Containers'; +import { CreatureTemplate, ComputedCreatureTemplate, ComputedOnlyCreatureTemplate } from './CreatureTemplates'; +import { Damage, ComputedDamage, ComputedOnlyDamage } from './Damages'; +import { DamageMultiplier, ComputedDamageMultiplier, ComputedOnlyDamageMultiplier } from './DamageMultipliers'; +import { Effect, ComputedEffect, ComputedOnlyEffect } from './Effects'; +import { Feature, ComputedFeature, ComputedOnlyFeature } from './Features'; +import { Folder, ComputedFolder, ComputedOnlyFolder } from './Folders'; +import { Item, ComputedItem, ComputedOnlyItem } from './Items'; +import { Note, ComputedNote, ComputedOnlyNote } from './Notes'; +import { PointBuy, ComputedPointBuy, ComputedOnlyPointBuy } from './PointBuys'; +import { Proficiency, ComputedProficiency, ComputedOnlyProficiency } from './Proficiencies'; +import { Reference, ComputedReference, ComputedOnlyReference } from './References'; +import { Roll, ComputedRoll, ComputedOnlyRoll } from './Rolls'; +import { SavingThrow, ComputedSavingThrow, ComputedOnlySavingThrow } from './SavingThrows'; +import { Skill, ComputedSkill, ComputedOnlySkill } from './Skills'; +import { Slot, ComputedSlot, ComputedOnlySlot } from './Slots'; +import { SpellList, ComputedSpellList, ComputedOnlySpellList } from './SpellLists'; +import { Spell, ComputedSpell, ComputedOnlySpell } from './Spells'; +import { Toggle, ComputedToggle, ComputedOnlyToggle } from './Toggles'; +import { Trigger, ComputedTrigger, ComputedOnlyTrigger } from './Triggers'; + +export type PropertyTypeMap = { + 'attribute': Attribute, + 'branch': Branch, + 'buff': Buff, + 'class': Class, + 'constant': Constant, + 'container': Container, + 'creatureTemplate': CreatureTemplate, + 'damage': Damage, + 'damageMultiplier': DamageMultiplier, + 'effect': Effect, + 'feature': Feature, + 'folder': Folder, + 'item': Item, + 'note': Note, + 'pointBuy': PointBuy, + 'proficiency': Proficiency, + 'reference': Reference, + 'roll': Roll, + 'savingThrow': SavingThrow, + 'skill': Skill, + 'slot': Slot, + 'spellList': SpellList, + 'spell': Spell, + 'toggle': Toggle, + 'trigger': Trigger, +} + +export type Property = PropertyTypeMap[T] + +export type ComputedPropertyTypeMap = { + 'attribute': ComputedAttribute, + 'branch': ComputedBranch, + 'buff': ComputedBuff, + 'class': ComputedClass, + 'constant': ComputedConstant, + 'container': ComputedContainer, + 'creatureTemplate': ComputedCreatureTemplate, + 'damage': ComputedDamage, + 'damageMultiplier': ComputedDamageMultiplier, + 'effect': ComputedEffect, + 'feature': ComputedFeature, + 'folder': ComputedFolder, + 'item': ComputedItem, + 'note': ComputedNote, + 'pointBuy': ComputedPointBuy, + 'proficiency': ComputedProficiency, + 'reference': ComputedReference, + 'roll': ComputedRoll, + 'savingThrow': ComputedSavingThrow, + 'skill': ComputedSkill, + 'slot': ComputedSlot, + 'spellList': ComputedSpellList, + 'spell': ComputedSpell, + 'toggle': ComputedToggle, + 'trigger': ComputedTrigger, +} + +export type ComputedProperty = ComputedPropertyTypeMap[T] + +export type ComputedOnlyPropertyTypeMap = { + 'attribute': ComputedOnlyAttribute, + 'branch': ComputedOnlyBranch, + 'buff': ComputedOnlyBuff, + 'class': ComputedOnlyClass, + 'constant': ComputedOnlyConstant, + 'container': ComputedOnlyContainer, + 'creatureTemplate': ComputedOnlyCreatureTemplate, + 'damage': ComputedOnlyDamage, + 'damageMultiplier': ComputedOnlyDamageMultiplier, + 'effect': ComputedOnlyEffect, + 'feature': ComputedOnlyFeature, + 'folder': ComputedOnlyFolder, + 'item': ComputedOnlyItem, + 'note': ComputedOnlyNote, + 'pointBuy': ComputedOnlyPointBuy, + 'proficiency': ComputedOnlyProficiency, + 'reference': ComputedOnlyReference, + 'roll': ComputedOnlyRoll, + 'savingThrow': ComputedOnlySavingThrow, + 'skill': ComputedOnlySkill, + 'slot': ComputedOnlySlot, + 'spellList': ComputedOnlySpellList, + 'spell': ComputedOnlySpell, + 'toggle': ComputedOnlyToggle, + 'trigger': ComputedOnlyTrigger, +} + +export type ComputedOnlyProperty = ComputedOnlyPropertyTypeMap[T] diff --git a/app/imports/api/properties/subSchemas/ErrorSchema.ts b/app/imports/api/properties/subSchemas/ErrorSchema.ts index 821dfc12..d0086f38 100644 --- a/app/imports/api/properties/subSchemas/ErrorSchema.ts +++ b/app/imports/api/properties/subSchemas/ErrorSchema.ts @@ -1,5 +1,5 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; -import { TypedSimpleSchema } from 'imports/api/utility/TypedSimpleSchema'; +import { TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema'; const ErrorSchema = new TypedSimpleSchema({ message: { diff --git a/app/imports/api/properties/subSchemas/TagTargetingSchema.ts b/app/imports/api/properties/subSchemas/TagTargetingSchema.ts index 868c480c..bdf9efa7 100644 --- a/app/imports/api/properties/subSchemas/TagTargetingSchema.ts +++ b/app/imports/api/properties/subSchemas/TagTargetingSchema.ts @@ -1,6 +1,6 @@ import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; -import { TypedSimpleSchema } from 'imports/api/utility/TypedSimpleSchema'; +import { TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema'; const TagTargetingSchema = new TypedSimpleSchema({ // True when targeting by tags instead of stats