From 0125367085b322529e2f904400d5cf49b5a5a9bb Mon Sep 17 00:00:00 2001 From: ThaumRystra Date: Sun, 12 Jan 2025 19:29:26 +0200 Subject: [PATCH] Migrate props to typed schemas --- .vscode/settings.json | 1 + app/imports/api/properties/Attributes.ts | 4 +- .../properties/{Branches.js => Branches.ts} | 15 +++-- .../{BuffRemovers.js => BuffRemovers.ts} | 11 +++- .../api/properties/{Buffs.js => Buffs.ts} | 0 .../{ClassLevels.js => ClassLevels.ts} | 11 +++- .../api/properties/{Classes.js => Classes.ts} | 17 +++-- .../properties/{Constants.js => Constants.ts} | 30 +++++---- .../{Containers.js => Containers.ts} | 13 ++-- .../api/properties/CreatureTemplates.ts | 9 ++- ...ageMultipliers.js => DamageMultipliers.ts} | 11 +++- .../api/properties/{Damages.js => Damages.ts} | 19 +++--- .../api/properties/{Effects.js => Effects.ts} | 17 +++-- app/imports/api/properties/Features.js | 36 ----------- app/imports/api/properties/Features.ts | 41 ++++++++++++ .../api/properties/{Folders.js => Folders.ts} | 17 +++-- app/imports/api/properties/Items.ts | 17 +++-- .../api/properties/{Notes.js => Notes.ts} | 19 +++--- .../properties/{PointBuys.js => PointBuys.ts} | 25 +++++--- .../{Proficiencies.js => Proficiencies.ts} | 11 +++- app/imports/api/properties/Properties.type.ts | 12 ---- .../{References.js => References.ts} | 12 ++-- .../api/properties/{Rolls.js => Rolls.ts} | 13 ++-- .../{SavingThrows.js => SavingThrows.ts} | 13 ++-- .../api/properties/{Skills.js => Skills.ts} | 25 +++++--- .../api/properties/{Slots.js => Slots.ts} | 27 ++++---- .../{SpellLists.js => SpellLists.ts} | 25 +++++--- app/imports/api/properties/Spells.ts | 63 +++++++------------ .../api/properties/{Toggles.js => Toggles.ts} | 9 ++- .../properties/{Triggers.js => Triggers.ts} | 53 ++++++++++++---- .../api/properties/propertySchemasIndex.js | 8 +-- .../{ErrorSchema.js => ErrorSchema.ts} | 4 +- ...rgetingSchema.js => TagTargetingSchema.ts} | 5 +- 33 files changed, 350 insertions(+), 243 deletions(-) rename app/imports/api/properties/{Branches.js => Branches.ts} (71%) rename app/imports/api/properties/{BuffRemovers.js => BuffRemovers.ts} (77%) rename app/imports/api/properties/{Buffs.js => Buffs.ts} (100%) rename app/imports/api/properties/{ClassLevels.js => ClassLevels.ts} (66%) rename app/imports/api/properties/{Classes.js => Classes.ts} (77%) rename app/imports/api/properties/{Constants.js => Constants.ts} (66%) rename app/imports/api/properties/{Containers.js => Containers.ts} (71%) rename app/imports/api/properties/{DamageMultipliers.js => DamageMultipliers.ts} (68%) rename app/imports/api/properties/{Damages.js => Damages.ts} (76%) rename app/imports/api/properties/{Effects.js => Effects.ts} (72%) delete mode 100644 app/imports/api/properties/Features.js create mode 100644 app/imports/api/properties/Features.ts rename app/imports/api/properties/{Folders.js => Folders.ts} (66%) rename app/imports/api/properties/{Notes.js => Notes.ts} (50%) rename app/imports/api/properties/{PointBuys.js => PointBuys.ts} (76%) rename app/imports/api/properties/{Proficiencies.js => Proficiencies.ts} (58%) delete mode 100644 app/imports/api/properties/Properties.type.ts rename app/imports/api/properties/{References.js => References.ts} (67%) rename app/imports/api/properties/{Rolls.js => Rolls.ts} (78%) rename app/imports/api/properties/{SavingThrows.js => SavingThrows.ts} (70%) rename app/imports/api/properties/{Skills.js => Skills.ts} (83%) rename app/imports/api/properties/{Slots.js => Slots.ts} (73%) rename app/imports/api/properties/{SpellLists.js => SpellLists.ts} (62%) rename app/imports/api/properties/{Toggles.js => Toggles.ts} (76%) rename app/imports/api/properties/{Triggers.js => Triggers.ts} (70%) rename app/imports/api/properties/subSchemas/{ErrorSchema.js => ErrorSchema.ts} (66%) rename app/imports/api/properties/subSchemas/{TagTargetingSchema.js => TagTargetingSchema.ts} (87%) diff --git a/.vscode/settings.json b/.vscode/settings.json index 93b727f4..6ceb4c8e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,6 +14,7 @@ "EJSON", "healthbar", "healthbars", + "Hitpoints", "jank", "meteortesting", "multigraph", diff --git a/app/imports/api/properties/Attributes.ts b/app/imports/api/properties/Attributes.ts index 1256cfc5..48e9626a 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 { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; /* * Attributes are numbered stats of a character @@ -33,7 +33,7 @@ const AttributeSchema = createPropertySchema({ 'resource', // Rages, sorcery points 'spellSlot', // Level 1, 2, 3... spell slots 'utility', // Aren't displayed, Jump height, Carry capacity - ], + ] as const, defaultValue: 'stat', index: 1, }, diff --git a/app/imports/api/properties/Branches.js b/app/imports/api/properties/Branches.ts similarity index 71% rename from app/imports/api/properties/Branches.js rename to app/imports/api/properties/Branches.ts index 4f65c8a3..aedd3480 100644 --- a/app/imports/api/properties/Branches.js +++ b/app/imports/api/properties/Branches.ts @@ -1,8 +1,9 @@ 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'; -let BranchSchema = createPropertySchema({ +const BranchSchema = createPropertySchema({ branchType: { type: String, allowedValues: [ @@ -24,7 +25,7 @@ let BranchSchema = createPropertySchema({ // Otherwise presents its own text with yes/no 'choice', //'option', - ], + ] as const, defaultValue: 'if', }, text: { @@ -33,7 +34,7 @@ let BranchSchema = createPropertySchema({ max: STORAGE_LIMITS.name, }, condition: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, parseLevel: 'compile', }, @@ -44,9 +45,9 @@ let BranchSchema = createPropertySchema({ }, }); -let ComputedOnlyBranchSchema = createPropertySchema({ +const ComputedOnlyBranchSchema = createPropertySchema({ condition: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, parseLevel: 'compile', }, @@ -56,4 +57,8 @@ const ComputedBranchSchema = new SimpleSchema({}) .extend(BranchSchema) .extend(ComputedOnlyBranchSchema); +export type Branch = InferType; +export type ComputedOnlyBranch = InferType; +export type ComputedBranch = Expand & InferType>; + export { BranchSchema, ComputedBranchSchema, ComputedOnlyBranchSchema } diff --git a/app/imports/api/properties/BuffRemovers.js b/app/imports/api/properties/BuffRemovers.ts similarity index 77% rename from app/imports/api/properties/BuffRemovers.js rename to app/imports/api/properties/BuffRemovers.ts index 8adce152..ee37e979 100644 --- a/app/imports/api/properties/BuffRemovers.js +++ b/app/imports/api/properties/BuffRemovers.ts @@ -1,8 +1,9 @@ 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'; -let BuffRemoverSchema = createPropertySchema({ +const BuffRemoverSchema = createPropertySchema({ name: { type: String, optional: true, @@ -75,10 +76,14 @@ let BuffRemoverSchema = createPropertySchema({ }, }); -let ComputedOnlyBuffRemoverSchema = createPropertySchema({}); +const ComputedOnlyBuffRemoverSchema = createPropertySchema({}); -const ComputedBuffRemoverSchema = new SimpleSchema() +const ComputedBuffRemoverSchema = new SimpleSchema({}) .extend(BuffRemoverSchema) .extend(ComputedOnlyBuffRemoverSchema); +export type BuffRemover = InferType; +export type ComputedOnlyBuffRemover = InferType; +export type ComputedBuffRemover = Expand & InferType>; + export { BuffRemoverSchema, ComputedOnlyBuffRemoverSchema, ComputedBuffRemoverSchema }; diff --git a/app/imports/api/properties/Buffs.js b/app/imports/api/properties/Buffs.ts similarity index 100% rename from app/imports/api/properties/Buffs.js rename to app/imports/api/properties/Buffs.ts diff --git a/app/imports/api/properties/ClassLevels.js b/app/imports/api/properties/ClassLevels.ts similarity index 66% rename from app/imports/api/properties/ClassLevels.js rename to app/imports/api/properties/ClassLevels.ts index 30c75cb5..f80a658a 100644 --- a/app/imports/api/properties/ClassLevels.js +++ b/app/imports/api/properties/ClassLevels.ts @@ -2,6 +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 { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; const ClassLevelSchema = createPropertySchema({ name: { @@ -10,7 +11,7 @@ const ClassLevelSchema = createPropertySchema({ max: STORAGE_LIMITS.name, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, // The name of this class level's variable @@ -30,13 +31,17 @@ const ClassLevelSchema = createPropertySchema({ const ComputedOnlyClassLevelSchema = createPropertySchema({ description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, }); -const ComputedClassLevelSchema = new SimpleSchema() +const ComputedClassLevelSchema = new SimpleSchema({}) .extend(ComputedOnlyClassLevelSchema) .extend(ClassLevelSchema); +export type ClassLevel = InferType; +export type ComputedOnlyClassLevel = InferType; +export type ComputedClassLevel = Expand & InferType>; + export { ClassLevelSchema, ComputedOnlyClassLevelSchema, ComputedClassLevelSchema }; diff --git a/app/imports/api/properties/Classes.js b/app/imports/api/properties/Classes.ts similarity index 77% rename from app/imports/api/properties/Classes.js rename to app/imports/api/properties/Classes.ts index 8242b1bc..9d8701fd 100644 --- a/app/imports/api/properties/Classes.js +++ b/app/imports/api/properties/Classes.ts @@ -1,17 +1,18 @@ 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'; // Classes are like slots, except they only take class levels and enforce that // lower levels are taken before higher levels -let ClassSchema = createPropertySchema({ +const ClassSchema = createPropertySchema({ name: { type: String, optional: true, max: STORAGE_LIMITS.name, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, // Only `classLevel`s with the same variable name can fill the class @@ -59,7 +60,7 @@ let ClassSchema = createPropertySchema({ max: STORAGE_LIMITS.tagLength, }, slotCondition: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, }); @@ -67,11 +68,11 @@ let ClassSchema = createPropertySchema({ const ComputedOnlyClassSchema = createPropertySchema({ // Computed fields description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, slotCondition: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, @@ -91,8 +92,12 @@ const ComputedOnlyClassSchema = createPropertySchema({ }, }); -const ComputedClassSchema = new SimpleSchema() +const ComputedClassSchema = new SimpleSchema({}) .extend(ClassSchema) .extend(ComputedOnlyClassSchema); +export type Class = InferType; +export type ComputedOnlyClass = InferType; +export type ComputedClass = Expand & InferType>; + export { ClassSchema, ComputedOnlyClassSchema, ComputedClassSchema }; diff --git a/app/imports/api/properties/Constants.js b/app/imports/api/properties/Constants.ts similarity index 66% rename from app/imports/api/properties/Constants.js rename to app/imports/api/properties/Constants.ts index 2ef18326..e6ecee61 100644 --- a/app/imports/api/properties/Constants.js +++ b/app/imports/api/properties/Constants.ts @@ -1,4 +1,3 @@ -import SimpleSchema from 'simpl-schema'; import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX'; import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema'; import { @@ -6,14 +5,17 @@ import { prettifyParseError, } from '/imports/parser/parser'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; +import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; import resolve from '/imports/parser/resolve'; -import Context from '../../parser/types/Context'; +import Context from '/imports/parser/types/Context'; import traverse from '/imports/parser/traverse'; +import type ResolveLevel from '/imports/parser/types/ResolveLevel'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; /* * Constants are primitive values that can be used elsewhere in computations */ -let ConstantSchema = new SimpleSchema({ +const ConstantSchema = createPropertySchema({ name: { type: String, optional: true, @@ -37,16 +39,16 @@ let ConstantSchema = new SimpleSchema({ errors: { type: Array, maxCount: STORAGE_LIMITS.errorCount, - autoValue() { - let calc = this.field('calculation'); + async autoValue() { + const calc = this.field('calculation'); if (!calc.isSet && this.isModifier) { this.unset() return; } - let string = calc.value; + const string = calc.value; if (!string) return []; // Evaluate the calculation with no scope - let { result, context } = parseString(string); + const { result, context } = await parseString(string); // Any existing errors will result in an early failure if (context && context.errors.length) return context.errors; // Ban variables in constants if necessary @@ -63,8 +65,8 @@ let ConstantSchema = new SimpleSchema({ }, }); -function parseString(string, fn = 'compile') { - let context = new Context(); +async function parseString(string, fn: ResolveLevel = 'compile') { + const context = new Context(); if (!string) { return { result: string, context }; } @@ -74,15 +76,19 @@ function parseString(string, fn = 'compile') { try { node = parse(string); } catch (e) { - let message = prettifyParseError(e); + const message = prettifyParseError(e as Error); context.error(message); return { context }; } if (!node) return { context }; - let { result } = resolve(fn, node, {/*empty scope*/ }, context); + const { result } = await resolve(fn, node, {/*empty scope*/ }, context); return { result, context } } -const ComputedOnlyConstantSchema = new SimpleSchema({}); +const ComputedOnlyConstantSchema = createPropertySchema({}); + +export type Constant = InferType; +export type ComputedOnlyConstant = InferType; +export type ComputedConstant = Expand & InferType>; export { ConstantSchema, ComputedOnlyConstantSchema }; diff --git a/app/imports/api/properties/Containers.js b/app/imports/api/properties/Containers.ts similarity index 71% rename from app/imports/api/properties/Containers.js rename to app/imports/api/properties/Containers.ts index e33f250e..69242679 100644 --- a/app/imports/api/properties/Containers.js +++ b/app/imports/api/properties/Containers.ts @@ -1,8 +1,9 @@ import SimpleSchema from 'simpl-schema'; 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'; -let ContainerSchema = createPropertySchema({ +const ContainerSchema = createPropertySchema({ name: { type: String, optional: true, @@ -29,14 +30,14 @@ let ContainerSchema = createPropertySchema({ optional: true, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, }); const ComputedOnlyContainerSchema = createPropertySchema({ description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, // Weight of all the contents. @@ -64,8 +65,12 @@ const ComputedOnlyContainerSchema = createPropertySchema({ }, }); -const ComputedContainerSchema = new SimpleSchema() +const ComputedContainerSchema = new SimpleSchema({}) .extend(ComputedOnlyContainerSchema) .extend(ContainerSchema); +export type Container = InferType; +export type ComputedOnlyContainer = InferType; +export type ComputedContainer = Expand & InferType>; + export { ContainerSchema, ComputedOnlyContainerSchema, ComputedContainerSchema }; diff --git a/app/imports/api/properties/CreatureTemplates.ts b/app/imports/api/properties/CreatureTemplates.ts index 7f48edf0..29e5668c 100644 --- a/app/imports/api/properties/CreatureTemplates.ts +++ b/app/imports/api/properties/CreatureTemplates.ts @@ -1,6 +1,7 @@ import SimpleSchema from 'simpl-schema'; 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'; // Creature templates represent creatures that don't yet exist // Used to store creatures in the library, or as templates for another creature to summon @@ -11,7 +12,7 @@ const CreatureTemplateSchema = createPropertySchema({ optional: true, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, picture: { @@ -28,7 +29,7 @@ const CreatureTemplateSchema = createPropertySchema({ const ComputedOnlyCreatureTemplateSchema = createPropertySchema({ description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, }); @@ -37,4 +38,8 @@ const ComputedCreatureTemplateSchema = new SimpleSchema({}) .extend(CreatureTemplateSchema) .extend(ComputedOnlyCreatureTemplateSchema); +export type CreatureTemplate = InferType; +export type ComputedOnlyCreatureTemplate = InferType; +export type ComputedCreatureTemplate = Expand & InferType>; + export { CreatureTemplateSchema, ComputedCreatureTemplateSchema, ComputedOnlyCreatureTemplateSchema }; diff --git a/app/imports/api/properties/DamageMultipliers.js b/app/imports/api/properties/DamageMultipliers.ts similarity index 68% rename from app/imports/api/properties/DamageMultipliers.js rename to app/imports/api/properties/DamageMultipliers.ts index c76f104f..8ffe18bf 100644 --- a/app/imports/api/properties/DamageMultipliers.js +++ b/app/imports/api/properties/DamageMultipliers.ts @@ -1,12 +1,13 @@ -import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX'; +import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; /* * DamageMultipliers are multipliers that affect how much damage is taken from * a given damage type */ -let DamageMultiplierSchema = new SimpleSchema({ +const DamageMultiplierSchema = createPropertySchema({ name: { type: String, optional: true, @@ -51,6 +52,10 @@ let DamageMultiplierSchema = new SimpleSchema({ }, }); -const ComputedOnlyDamageMultiplierSchema = new SimpleSchema({}); +const ComputedOnlyDamageMultiplierSchema = createPropertySchema({}); + +export type DamageMultiplier = InferType; +export type ComputedOnlyDamageMultiplier = InferType; +export type ComputedDamageMultiplier = Expand & InferType>; export { DamageMultiplierSchema, ComputedOnlyDamageMultiplierSchema }; diff --git a/app/imports/api/properties/Damages.js b/app/imports/api/properties/Damages.ts similarity index 76% rename from app/imports/api/properties/Damages.js rename to app/imports/api/properties/Damages.ts index 7964839f..f1670e0d 100644 --- a/app/imports/api/properties/Damages.js +++ b/app/imports/api/properties/Damages.ts @@ -2,12 +2,13 @@ import SimpleSchema from 'simpl-schema'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; const DamageSchema = createPropertySchema({ // The roll that determines how much to damage the attribute // This can be simplified, but only computed when applied amount: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, defaultValue: '1d8 + strength.modifier', parseLevel: 'compile', @@ -19,7 +20,7 @@ const DamageSchema = createPropertySchema({ allowedValues: [ 'self', 'target', - ], + ] as const, }, damageType: { type: String, @@ -39,7 +40,7 @@ const DamageSchema = createPropertySchema({ }, // The computed DC 'save.dc': { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, // The variable name of save to roll @@ -50,7 +51,7 @@ const DamageSchema = createPropertySchema({ }, // The damage to deal on a successful save 'save.damageFunction': { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, parseLevel: 'compile', }, @@ -58,7 +59,7 @@ const DamageSchema = createPropertySchema({ const ComputedOnlyDamageSchema = createPropertySchema({ amount: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, parseLevel: 'compile', }, @@ -67,12 +68,12 @@ const ComputedOnlyDamageSchema = createPropertySchema({ optional: true, }, 'save.dc': { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, parseLevel: 'compile', optional: true, }, 'save.damageFunction': { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, parseLevel: 'compile', optional: true, }, @@ -82,4 +83,8 @@ const ComputedDamageSchema = new SimpleSchema({}) .extend(DamageSchema) .extend(ComputedOnlyDamageSchema); +export type Damage = InferType; +export type ComputedOnlyDamage = InferType; +export type ComputedDamage = Expand & InferType>; + export { DamageSchema, ComputedDamageSchema, ComputedOnlyDamageSchema }; diff --git a/app/imports/api/properties/Effects.js b/app/imports/api/properties/Effects.ts similarity index 72% rename from app/imports/api/properties/Effects.js rename to app/imports/api/properties/Effects.ts index 347a4000..2a14f450 100644 --- a/app/imports/api/properties/Effects.js +++ b/app/imports/api/properties/Effects.ts @@ -2,12 +2,13 @@ import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; import TagTargetingSchema from '/imports/api/properties/subSchemas/TagTargetingSchema'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; /* * Effects are reason-value attached to skills and abilities * that modify their final value or presentation in some way */ -let EffectSchema = createPropertySchema({ +const EffectSchema = createPropertySchema({ name: { type: String, optional: true, @@ -28,17 +29,17 @@ let EffectSchema = createPropertySchema({ 'passiveAdd', 'fail', 'conditional', - ], + ] as const, }, amount: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, // Conditional benefits store just uncomputed text text: { type: String, optional: true, - max: STORAGE_LIMITS.effectCondition, + max: STORAGE_LIMITS.effectText, }, // Which stats the effect is applied to // Each entry is a variableName targeted by this effect @@ -55,13 +56,17 @@ let EffectSchema = createPropertySchema({ const ComputedOnlyEffectSchema = createPropertySchema({ amount: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, }); -const ComputedEffectSchema = new SimpleSchema() +const ComputedEffectSchema = new SimpleSchema({}) .extend(ComputedOnlyEffectSchema) .extend(EffectSchema); +export type Effect = InferType; +export type ComputedOnlyEffect = InferType; +export type ComputedEffect = Expand & InferType>; + export { EffectSchema, ComputedEffectSchema, ComputedOnlyEffectSchema }; diff --git a/app/imports/api/properties/Features.js b/app/imports/api/properties/Features.js deleted file mode 100644 index e4b467c1..00000000 --- a/app/imports/api/properties/Features.js +++ /dev/null @@ -1,36 +0,0 @@ -import SimpleSchema from 'simpl-schema'; -import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; -import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; - -let FeatureSchema = createPropertySchema({ - name: { - type: String, - max: STORAGE_LIMITS.name, - optional: true, - }, - summary: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, - description: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, -}); - -let ComputedOnlyFeatureSchema = createPropertySchema({ - summary: { - type: 'computedOnlyInlineCalculationField', - optional: true, - }, - description: { - type: 'computedOnlyInlineCalculationField', - optional: true, - }, -}); - -const ComputedFeatureSchema = new SimpleSchema() - .extend(FeatureSchema) - .extend(ComputedOnlyFeatureSchema); - -export { FeatureSchema, ComputedFeatureSchema, ComputedOnlyFeatureSchema } diff --git a/app/imports/api/properties/Features.ts b/app/imports/api/properties/Features.ts new file mode 100644 index 00000000..99f1a7c9 --- /dev/null +++ b/app/imports/api/properties/Features.ts @@ -0,0 +1,41 @@ +import SimpleSchema from 'simpl-schema'; +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'; + +const FeatureSchema = createPropertySchema({ + name: { + type: String, + max: STORAGE_LIMITS.name, + optional: true, + }, + summary: { + type: 'inlineCalculationFieldToCompute' as const, + optional: true, + }, + description: { + type: 'inlineCalculationFieldToCompute' as const, + optional: true, + }, +}); + +const ComputedOnlyFeatureSchema = createPropertySchema({ + summary: { + type: 'computedOnlyInlineCalculationField' as const, + optional: true, + }, + description: { + type: 'computedOnlyInlineCalculationField' as const, + optional: true, + }, +}); + +const ComputedFeatureSchema = new SimpleSchema({}) + .extend(FeatureSchema) + .extend(ComputedOnlyFeatureSchema); + +export type Feature = InferType; +export type ComputedOnlyFeature = InferType; +export type ComputedFeature = Expand & InferType>; + +export { FeatureSchema, ComputedFeatureSchema, ComputedOnlyFeatureSchema } diff --git a/app/imports/api/properties/Folders.js b/app/imports/api/properties/Folders.ts similarity index 66% rename from app/imports/api/properties/Folders.js rename to app/imports/api/properties/Folders.ts index 96bc2840..b24272c3 100644 --- a/app/imports/api/properties/Folders.js +++ b/app/imports/api/properties/Folders.ts @@ -1,17 +1,18 @@ import SimpleSchema from 'simpl-schema'; 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'; // Folders organize a character sheet into a tree, particularly to group things // like 'race' and 'background' -let FolderSchema = createPropertySchema({ +const FolderSchema = createPropertySchema({ name: { type: String, max: STORAGE_LIMITS.name, optional: true, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, groupStats: { @@ -27,26 +28,30 @@ let FolderSchema = createPropertySchema({ optional: true, allowedValues: [ 'stats', 'features', 'actions', 'spells', 'inventory', 'journal', 'build' - ], + ] as const, }, location: { type: String, optional: true, allowedValues: [ 'start', 'events', 'stats', 'skills', 'proficiencies', 'end' - ], + ] as const, }, }); const ComputedOnlyFolderSchema = createPropertySchema({ description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, }); -const ComputedFolderSchema = new SimpleSchema() +const ComputedFolderSchema = new SimpleSchema({}) .extend(FolderSchema) .extend(ComputedOnlyFolderSchema); +export type Folder = InferType; +export type ComputedOnlyFolder = InferType; +export type ComputedFolder = Expand & InferType>; + export { FolderSchema, ComputedFolderSchema, ComputedOnlyFolderSchema }; diff --git a/app/imports/api/properties/Items.ts b/app/imports/api/properties/Items.ts index d513b690..33566359 100644 --- a/app/imports/api/properties/Items.ts +++ b/app/imports/api/properties/Items.ts @@ -1,14 +1,7 @@ import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; -import { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties'; - -export interface Item extends CreatureProperty { - type: 'item' - name?: string - plural?: string - quantity: number -} +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; const ItemSchema = createPropertySchema({ name: { @@ -23,7 +16,7 @@ const ItemSchema = createPropertySchema({ max: STORAGE_LIMITS.name, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, // Number currently held @@ -102,7 +95,7 @@ const ItemSchema = createPropertySchema({ const ComputedOnlyItemSchema = createPropertySchema({ description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, }); @@ -111,4 +104,8 @@ const ComputedItemSchema = new SimpleSchema({}) .extend(ItemSchema) .extend(ComputedOnlyItemSchema); +export type Item = InferType; +export type ComputedOnlyItem = InferType; +export type ComputedItem = Expand & InferType>; + export { ItemSchema, ComputedItemSchema, ComputedOnlyItemSchema }; diff --git a/app/imports/api/properties/Notes.js b/app/imports/api/properties/Notes.ts similarity index 50% rename from app/imports/api/properties/Notes.js rename to app/imports/api/properties/Notes.ts index 699f981d..607918c9 100644 --- a/app/imports/api/properties/Notes.js +++ b/app/imports/api/properties/Notes.ts @@ -1,19 +1,20 @@ import SimpleSchema from 'simpl-schema'; 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'; -let NoteSchema = createPropertySchema({ +const NoteSchema = createPropertySchema({ name: { type: String, optional: true, max: STORAGE_LIMITS.name, }, summary: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, // Prevent the property from showing up in the log @@ -23,19 +24,23 @@ let NoteSchema = createPropertySchema({ }, }); -let ComputedOnlyNoteSchema = createPropertySchema({ +const ComputedOnlyNoteSchema = createPropertySchema({ summary: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, }); -const ComputedNoteSchema = new SimpleSchema() +const ComputedNoteSchema = new SimpleSchema({}) .extend(NoteSchema) .extend(ComputedOnlyNoteSchema); +export type Note = InferType; +export type ComputedOnlyNote = InferType; +export type ComputedNote = Expand & InferType>; + export { NoteSchema, ComputedNoteSchema, ComputedOnlyNoteSchema, }; diff --git a/app/imports/api/properties/PointBuys.js b/app/imports/api/properties/PointBuys.ts similarity index 76% rename from app/imports/api/properties/PointBuys.js rename to app/imports/api/properties/PointBuys.ts index 5c45aab4..04834421 100644 --- a/app/imports/api/properties/PointBuys.js +++ b/app/imports/api/properties/PointBuys.ts @@ -3,12 +3,13 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; /* * PointBuys are reason-value attached to skills and abilities * that modify their final value or presentation in some way */ -let PointBuySchema = createPropertySchema({ +const PointBuySchema = createPropertySchema({ name: { type: String, optional: true, @@ -50,19 +51,19 @@ let PointBuySchema = createPropertySchema({ optional: true, }, min: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, max: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, total: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, cost: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, parseLevel: 'compile', }, @@ -70,15 +71,15 @@ let PointBuySchema = createPropertySchema({ const ComputedOnlyPointBuySchema = createPropertySchema({ min: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, max: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, cost: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, parseLevel: 'compile', }, @@ -104,7 +105,7 @@ const ComputedOnlyPointBuySchema = createPropertySchema({ type: ErrorSchema, }, total: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, spent: { @@ -127,8 +128,12 @@ const ComputedOnlyPointBuySchema = createPropertySchema({ }, }); -const ComputedPointBuySchema = new SimpleSchema() +const ComputedPointBuySchema = new SimpleSchema({}) .extend(ComputedOnlyPointBuySchema) .extend(PointBuySchema); +export type PointBuy = InferType; +export type ComputedOnlyPointBuy = InferType; +export type ComputedPointBuy = Expand & InferType>; + export { PointBuySchema, ComputedPointBuySchema, ComputedOnlyPointBuySchema }; diff --git a/app/imports/api/properties/Proficiencies.js b/app/imports/api/properties/Proficiencies.ts similarity index 58% rename from app/imports/api/properties/Proficiencies.js rename to app/imports/api/properties/Proficiencies.ts index fe48b01b..a5be59d5 100644 --- a/app/imports/api/properties/Proficiencies.js +++ b/app/imports/api/properties/Proficiencies.ts @@ -1,8 +1,9 @@ -import SimpleSchema from 'simpl-schema'; +import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import TagTargetingSchema from '/imports/api/properties/subSchemas/TagTargetingSchema'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; -let ProficiencySchema = new SimpleSchema({ +const ProficiencySchema = createPropertySchema({ name: { type: String, optional: true, @@ -27,6 +28,10 @@ let ProficiencySchema = new SimpleSchema({ }, }).extend(TagTargetingSchema); -const ComputedOnlyProficiencySchema = new SimpleSchema({}); +const ComputedOnlyProficiencySchema = createPropertySchema({}); + +export type Proficiency = InferType; +export type ComputedOnlyProficiency = InferType; +export type ComputedProficiency = Expand & InferType>; export { ProficiencySchema, ComputedOnlyProficiencySchema }; diff --git a/app/imports/api/properties/Properties.type.ts b/app/imports/api/properties/Properties.type.ts deleted file mode 100644 index e7aaa73f..00000000 --- a/app/imports/api/properties/Properties.type.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { TreeDoc } from '/imports/api/parenting/ChildSchema'; - -export default interface Property extends TreeDoc { - _id: string - _migrationError?: string - tags: string[] - icon?: { - name: string - shape: string - }, - slotQuantityFilled?: number -} \ No newline at end of file diff --git a/app/imports/api/properties/References.js b/app/imports/api/properties/References.ts similarity index 67% rename from app/imports/api/properties/References.js rename to app/imports/api/properties/References.ts index 31459cdf..80ffd784 100644 --- a/app/imports/api/properties/References.js +++ b/app/imports/api/properties/References.ts @@ -1,14 +1,14 @@ -import SimpleSchema from 'simpl-schema'; 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'; -let ReferenceSchema = new SimpleSchema({ +const ReferenceSchema = createPropertySchema({ ref: { type: Object, defaultValue: {}, }, 'ref.id': { type: String, - regEx: SimpleSchema.RegEx.Id, optional: true, }, 'ref.collection': { @@ -62,6 +62,10 @@ let ReferenceSchema = new SimpleSchema({ }, }); -const ComputedOnlyReferenceSchema = new SimpleSchema({}); +const ComputedOnlyReferenceSchema = createPropertySchema({}); + +export type Reference = InferType; +export type ComputedOnlyReference = InferType; +export type ComputedReference = Expand & InferType>; export { ReferenceSchema, ComputedOnlyReferenceSchema }; diff --git a/app/imports/api/properties/Rolls.js b/app/imports/api/properties/Rolls.ts similarity index 78% rename from app/imports/api/properties/Rolls.js rename to app/imports/api/properties/Rolls.ts index 4dcb5367..5caac4c3 100644 --- a/app/imports/api/properties/Rolls.js +++ b/app/imports/api/properties/Rolls.ts @@ -2,6 +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'; /** * Rolls are children to actions or other rolls, they are triggered with 0 or @@ -21,7 +22,7 @@ import createPropertySchema from '/imports/api/properties/subSchemas/createPrope * If the roll fails to meet or exceed the target number, the adjustments and * child rolls are applied */ -let RollSchema = createPropertySchema({ +const RollSchema = createPropertySchema({ name: { type: String, defaultValue: 'New Roll', @@ -37,7 +38,7 @@ let RollSchema = createPropertySchema({ }, // The roll, can be simplified, but only computed in context roll: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, parseLevel: 'compile', optional: true, }, @@ -48,9 +49,9 @@ let RollSchema = createPropertySchema({ }, }); -let ComputedOnlyRollSchema = createPropertySchema({ +const ComputedOnlyRollSchema = createPropertySchema({ roll: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, parseLevel: 'compile', optional: true, }, @@ -60,4 +61,8 @@ const ComputedRollSchema = new SimpleSchema({}) .extend(RollSchema) .extend(ComputedOnlyRollSchema); +export type Roll = InferType; +export type ComputedOnlyRoll = InferType; +export type ComputedRoll = Expand & InferType>; + export { RollSchema, ComputedRollSchema, ComputedOnlyRollSchema }; diff --git a/app/imports/api/properties/SavingThrows.js b/app/imports/api/properties/SavingThrows.ts similarity index 70% rename from app/imports/api/properties/SavingThrows.js rename to app/imports/api/properties/SavingThrows.ts index 19442806..80777970 100644 --- a/app/imports/api/properties/SavingThrows.js +++ b/app/imports/api/properties/SavingThrows.ts @@ -1,10 +1,11 @@ import SimpleSchema from 'simpl-schema'; 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'; // These are the rolls made when saves are called for // For the saving throw bonus or proficiency, see ./Skills.js -let SavingThrowSchema = createPropertySchema({ +const SavingThrowSchema = createPropertySchema({ name: { type: String, optional: true, @@ -12,7 +13,7 @@ let SavingThrowSchema = createPropertySchema({ }, // The computed DC dc: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, // Who this saving throw applies to @@ -22,7 +23,7 @@ let SavingThrowSchema = createPropertySchema({ allowedValues: [ 'self', 'target', - ], + ] as const, }, // The variable name of save to roll stat: { @@ -39,7 +40,7 @@ let SavingThrowSchema = createPropertySchema({ const ComputedOnlySavingThrowSchema = createPropertySchema({ dc: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, parseLevel: 'compile', optional: true, }, @@ -49,4 +50,8 @@ const ComputedSavingThrowSchema = new SimpleSchema({}) .extend(SavingThrowSchema) .extend(ComputedOnlySavingThrowSchema); +export type SavingThrow = InferType; +export type ComputedOnlySavingThrow = InferType; +export type ComputedSavingThrow = Expand & InferType>; + export { SavingThrowSchema, ComputedOnlySavingThrowSchema, ComputedSavingThrowSchema }; diff --git a/app/imports/api/properties/Skills.js b/app/imports/api/properties/Skills.ts similarity index 83% rename from app/imports/api/properties/Skills.js rename to app/imports/api/properties/Skills.ts index a9204f9a..7d486773 100644 --- a/app/imports/api/properties/Skills.js +++ b/app/imports/api/properties/Skills.ts @@ -3,12 +3,13 @@ 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 TagTargetingSchema from '/imports/api/properties/subSchemas/TagTargetingSchema'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; /* * Skills are anything that results in a modifier to be added to a D20 * Skills have an ability score modifier that they use as their basis */ -let SkillSchema = createPropertySchema({ +const SkillSchema = createPropertySchema({ name: { type: String, optional: true, @@ -41,29 +42,29 @@ let SkillSchema = createPropertySchema({ 'armor', 'language', 'utility', //not displayed anywhere - ], + ] as const, defaultValue: 'skill', }, // The base proficiency of this skill baseProficiency: { type: Number, optional: true, - allowedValues: [0.49, 0.5, 1, 2], + allowedValues: [0.49, 0.5, 1, 2] as const, }, // The starting value, before effects baseValue: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, // Description of what the skill is used for description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, // Skills can apply their value to other calculations as a proficiency using tag targeting }).extend(TagTargetingSchema); -let ComputedOnlySkillSchema = createPropertySchema({ +const ComputedOnlySkillSchema = createPropertySchema({ // Computed value of skill to be added to skill rolls value: { type: Number, @@ -73,11 +74,11 @@ let ComputedOnlySkillSchema = createPropertySchema({ }, // The result of baseValueCalculation baseValue: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, // Computed value added by the ability @@ -90,7 +91,7 @@ let ComputedOnlySkillSchema = createPropertySchema({ advantage: { type: SimpleSchema.Integer, optional: true, - allowedValues: [-1, 0, 1], + allowedValues: [-1, 0, 1] as const, removeBeforeCompute: true, }, // Computed bonus to passive checks @@ -102,7 +103,7 @@ let ComputedOnlySkillSchema = createPropertySchema({ // Computed proficiency multiplier proficiency: { type: Number, - allowedValues: [0, 0.49, 0.5, 1, 2], + allowedValues: [0, 0.49, 0.5, 1, 2] as const, defaultValue: 0, removeBeforeCompute: true, }, @@ -174,4 +175,8 @@ const ComputedSkillSchema = new SimpleSchema({}) .extend(ComputedOnlySkillSchema) .extend(SkillSchema); +export type Skill = InferType; +export type ComputedOnlySkill = InferType; +export type ComputedSkill = Expand & InferType>; + export { SkillSchema, ComputedSkillSchema, ComputedOnlySkillSchema }; diff --git a/app/imports/api/properties/Slots.js b/app/imports/api/properties/Slots.ts similarity index 73% rename from app/imports/api/properties/Slots.js rename to app/imports/api/properties/Slots.ts index fd41c36c..0c47357f 100644 --- a/app/imports/api/properties/Slots.js +++ b/app/imports/api/properties/Slots.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 type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; -let SlotSchema = createPropertySchema({ +const SlotSchema = createPropertySchema({ name: { type: String, optional: true, max: STORAGE_LIMITS.name, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, slotType: { @@ -43,7 +44,7 @@ let SlotSchema = createPropertySchema({ }, 'extraTags.$.operation': { type: String, - allowedValues: ['OR', 'NOT'], + allowedValues: ['OR', 'NOT'] as const, defaultValue: 'OR', }, 'extraTags.$.tags': { @@ -56,7 +57,7 @@ let SlotSchema = createPropertySchema({ max: STORAGE_LIMITS.tagLength, }, quantityExpected: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, defaultValue: '1', }, @@ -65,7 +66,7 @@ let SlotSchema = createPropertySchema({ optional: true, }, slotCondition: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, hideWhenFull: { @@ -78,9 +79,9 @@ let SlotSchema = createPropertySchema({ allowedValues: [ // Can't choose the same slot filler twice in this slot 'uniqueInSlot', - // Can't choose the same slot filler twice accross the whole creature + // Can't choose the same slot filler twice across the whole creature 'uniqueInCreature' - ], + ] as const, optional: true, defaultValue: 'uniqueInSlot', }, @@ -89,15 +90,15 @@ let SlotSchema = createPropertySchema({ const ComputedOnlySlotSchema = createPropertySchema({ // Computed fields description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, quantityExpected: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, slotCondition: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, @@ -114,8 +115,12 @@ const ComputedOnlySlotSchema = createPropertySchema({ }, }); -const ComputedSlotSchema = new SimpleSchema() +const ComputedSlotSchema = new SimpleSchema({}) .extend(ComputedOnlySlotSchema) .extend(SlotSchema); +export type Slot = InferType; +export type ComputedOnlySlot = InferType; +export type ComputedSlot = Expand & InferType>; + export { SlotSchema, ComputedSlotSchema, ComputedOnlySlotSchema }; diff --git a/app/imports/api/properties/SpellLists.js b/app/imports/api/properties/SpellLists.ts similarity index 62% rename from app/imports/api/properties/SpellLists.js rename to app/imports/api/properties/SpellLists.ts index e99c6ff5..94354a54 100644 --- a/app/imports/api/properties/SpellLists.js +++ b/app/imports/api/properties/SpellLists.ts @@ -1,20 +1,21 @@ import SimpleSchema from 'simpl-schema'; 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'; -let SpellListSchema = createPropertySchema({ +const SpellListSchema = createPropertySchema({ name: { type: String, optional: true, max: STORAGE_LIMITS.name, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, // Calculation of how many spells in this list can be prepared maxPrepared: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, // The variable name of the ability this spell relies on @@ -25,23 +26,23 @@ let SpellListSchema = createPropertySchema({ }, // Calculation of The attack roll bonus used by spell attacks in this list attackRollBonus: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, // Calculation of the save dc used by spells in this list dc: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, }); const ComputedOnlySpellListSchema = createPropertySchema({ description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, maxPrepared: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, // Computed value determined by the ability @@ -51,17 +52,21 @@ const ComputedOnlySpellListSchema = createPropertySchema({ removeBeforeCompute: true, }, attackRollBonus: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, dc: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, }); -const ComputedSpellListSchema = new SimpleSchema() +const ComputedSpellListSchema = new SimpleSchema({}) .extend(SpellListSchema) .extend(ComputedOnlySpellListSchema); +export type SpellList = InferType; +export type ComputedOnlySpellList = InferType; +export type ComputedSpellList = Expand & InferType>; + export { SpellListSchema, ComputedOnlySpellListSchema, ComputedSpellListSchema }; diff --git a/app/imports/api/properties/Spells.ts b/app/imports/api/properties/Spells.ts index 1822aab6..0e44a7e6 100644 --- a/app/imports/api/properties/Spells.ts +++ b/app/imports/api/properties/Spells.ts @@ -1,45 +1,13 @@ -import { ActionBase, ActionSchema, ComputedOnlyActionSchema } from '/imports/api/properties/Actions'; +import { ActionSchema, ComputedOnlyActionSchema } from '/imports/api/properties/Actions'; import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; -import { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties'; +import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; +import { TypedSimpleSchema } from '../utility/TypedSimpleSchema'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; -export interface Spell extends ActionBase { - name?: string - type: 'spell' - alwaysPrepared?: boolean - prepared?: boolean - castWithoutSpellSlots?: boolean - hasAttackRoll?: boolean - castingTime?: string - range?: string - duration?: string - verbal?: boolean - somatic?: boolean - concentration?: boolean - material?: string - ritual?: boolean - level?: number - school?: string -} - -export function isSpell(prop: CreatureProperty): prop is Spell { - return prop.type === 'spell'; -} - -const magicSchools = [ - 'abjuration', - 'conjuration', - 'divination', - 'enchantment', - 'evocation', - 'illusion', - 'necromancy', - 'transmutation', -]; - -const SpellSchema = new SimpleSchema({}) +const SpellSchema = createPropertySchema({}) .extend(ActionSchema) - .extend({ + .extend(new TypedSimpleSchema({ name: { type: String, optional: true, @@ -111,15 +79,28 @@ const SpellSchema = new SimpleSchema({}) school: { type: String, defaultValue: 'abjuration', - allowedValues: magicSchools, + allowedValues: [ + 'abjuration', + 'conjuration', + 'divination', + 'enchantment', + 'evocation', + 'illusion', + 'necromancy', + 'transmutation', + ] as const, }, - }); + })); -const ComputedOnlySpellSchema = new SimpleSchema({}) +const ComputedOnlySpellSchema = createPropertySchema({}) .extend(ComputedOnlyActionSchema); const ComputedSpellSchema = new SimpleSchema({}) .extend(SpellSchema) .extend(ComputedOnlySpellSchema); +export type Spell = InferType; +export type ComputedOnlySpell = InferType; +export type ComputedSpell = Expand & InferType>; + export { SpellSchema, ComputedOnlySpellSchema, ComputedSpellSchema }; diff --git a/app/imports/api/properties/Toggles.js b/app/imports/api/properties/Toggles.ts similarity index 76% rename from app/imports/api/properties/Toggles.js rename to app/imports/api/properties/Toggles.ts index 398cf2f6..ca339413 100644 --- a/app/imports/api/properties/Toggles.js +++ b/app/imports/api/properties/Toggles.ts @@ -2,6 +2,7 @@ import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; import TagTargetingSchema from '/imports/api/properties/subSchemas/TagTargetingSchema'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; const ToggleSchema = createPropertySchema({ name: { @@ -29,7 +30,7 @@ const ToggleSchema = createPropertySchema({ // if neither disabled or enabled, the condition will be run to determine // if the children of the toggle should be active condition: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, }, // Prevent the property from showing up in the log @@ -41,11 +42,15 @@ const ToggleSchema = createPropertySchema({ const ComputedOnlyToggleSchema = createPropertySchema({ condition: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, }, }); +export type Toggle = InferType; +export type ComputedOnlyToggle = InferType; +export type ComputedToggle = Expand & InferType>; + const ComputedToggleSchema = new SimpleSchema({}) .extend(ComputedOnlyToggleSchema) .extend(ToggleSchema); diff --git a/app/imports/api/properties/Triggers.js b/app/imports/api/properties/Triggers.ts similarity index 70% rename from app/imports/api/properties/Triggers.js rename to app/imports/api/properties/Triggers.ts index f2bfa797..89f43e33 100644 --- a/app/imports/api/properties/Triggers.js +++ b/app/imports/api/properties/Triggers.ts @@ -1,6 +1,7 @@ import SimpleSchema from 'simpl-schema'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; +import type { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema'; const eventOptions = { doActionProperty: 'Do action', @@ -9,7 +10,7 @@ const eventOptions = { // flipToggle: 'Toggle changed', // itemEquipped: 'Item equipped' // itemUnequipped: 'Item unequipped' - damageProperty: 'Attribute damaged or healed', + damageProperty: 'Trigger damaged or healed', anyRest: 'Short or long rest', longRest: 'Long rest', shortRest: 'Short rest', @@ -24,7 +25,7 @@ const timingOptions = { const actionPropertyTypeOptions = { action: 'Action', ammo: 'Ammo used', - adjustment: 'Attribute damage', + adjustment: 'Trigger damage', branch: 'Branch', buff: 'Buff', buffRemover: 'Buff Removed', @@ -41,34 +42,58 @@ const actionPropertyTypeOptions = { * the sheet. Either during another action or as its own action after a sheet * event. The same trigger can't fire twice in the same action step. */ -let TriggerSchema = createPropertySchema({ +const TriggerSchema = createPropertySchema({ name: { type: String, optional: true, max: STORAGE_LIMITS.name, }, description: { - type: 'inlineCalculationFieldToCompute', + type: 'inlineCalculationFieldToCompute' as const, optional: true, }, event: { type: String, - allowedValues: Object.keys(eventOptions), + allowedValues: [ + 'doActionProperty', + 'check', + 'damageProperty', + 'anyRest', + 'longRest', + 'shortRest', + ] as const, defaultValue: 'doActionProperty', }, // Action type actionPropertyType: { type: String, - allowedValues: Object.keys(actionPropertyTypeOptions), + allowedValues: [ + 'action', + 'ammo', + 'adjustment', + 'branch', + 'buff', + 'buffRemover', + 'damage', + 'note', + 'roll', + 'savingThrow', + 'spell', + 'toggle', + ] as const, optional: true, }, timing: { type: String, - allowedValues: Object.keys(timingOptions), + allowedValues: [ + 'before', + 'after', + 'afterChildren', + ] as const, defaultValue: 'after', }, condition: { - type: 'fieldToCompute', + type: 'fieldToCompute' as const, optional: true, parseLevel: 'compile', }, @@ -99,7 +124,7 @@ let TriggerSchema = createPropertySchema({ }, 'extraTags.$.operation': { type: String, - allowedValues: ['OR', 'NOT'], + allowedValues: ['OR', 'NOT'] as const, defaultValue: 'OR', }, 'extraTags.$.tags': { @@ -120,15 +145,15 @@ let TriggerSchema = createPropertySchema({ const ComputedOnlyTriggerSchema = createPropertySchema({ summary: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, description: { - type: 'computedOnlyInlineCalculationField', + type: 'computedOnlyInlineCalculationField' as const, optional: true, }, condition: { - type: 'computedOnlyField', + type: 'computedOnlyField' as const, optional: true, parseLevel: 'compile', }, @@ -138,6 +163,10 @@ const ComputedTriggerSchema = new SimpleSchema({}) .extend(TriggerSchema) .extend(ComputedOnlyTriggerSchema); +export type Trigger = InferType; +export type ComputedOnlyTrigger = InferType; +export type ComputedTrigger = Expand & InferType>; + export { TriggerSchema, ComputedOnlyTriggerSchema, ComputedTriggerSchema, eventOptions, timingOptions, actionPropertyTypeOptions diff --git a/app/imports/api/properties/propertySchemasIndex.js b/app/imports/api/properties/propertySchemasIndex.js index 4e022b63..2dcf8e41 100644 --- a/app/imports/api/properties/propertySchemasIndex.js +++ b/app/imports/api/properties/propertySchemasIndex.js @@ -21,13 +21,13 @@ import { PointBuySchema } from '/imports/api/properties/PointBuys'; import { ProficiencySchema } from '/imports/api/properties/Proficiencies'; import { ReferenceSchema } from '/imports/api/properties/References'; import { RollSchema } from '/imports/api/properties/Rolls'; -import { SavingThrowSchema } from '/imports/api/properties/SavingThrows'; -import { SkillSchema } from '/imports/api/properties/Skills'; +import { SavingThrowSchema } from './SavingThrows'; +import { SkillSchema } from './Skills'; import { SlotSchema } from '/imports/api/properties/Slots'; -import { SpellListSchema } from '/imports/api/properties/SpellLists'; +import { SpellListSchema } from './SpellLists'; import { SpellSchema } from '/imports/api/properties/Spells'; import { ToggleSchema } from '/imports/api/properties/Toggles'; -import { TriggerSchema } from '/imports/api/properties/Triggers'; +import { TriggerSchema } from './Triggers'; const propertySchemasIndex = { action: ActionSchema, diff --git a/app/imports/api/properties/subSchemas/ErrorSchema.js b/app/imports/api/properties/subSchemas/ErrorSchema.ts similarity index 66% rename from app/imports/api/properties/subSchemas/ErrorSchema.js rename to app/imports/api/properties/subSchemas/ErrorSchema.ts index 636281e6..821dfc12 100644 --- a/app/imports/api/properties/subSchemas/ErrorSchema.js +++ b/app/imports/api/properties/subSchemas/ErrorSchema.ts @@ -1,7 +1,7 @@ -import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; +import { TypedSimpleSchema } from 'imports/api/utility/TypedSimpleSchema'; -const ErrorSchema = new SimpleSchema({ +const ErrorSchema = new TypedSimpleSchema({ message: { type: String, max: STORAGE_LIMITS.errorMessage, diff --git a/app/imports/api/properties/subSchemas/TagTargetingSchema.js b/app/imports/api/properties/subSchemas/TagTargetingSchema.ts similarity index 87% rename from app/imports/api/properties/subSchemas/TagTargetingSchema.js rename to app/imports/api/properties/subSchemas/TagTargetingSchema.ts index ea33d758..868c480c 100644 --- a/app/imports/api/properties/subSchemas/TagTargetingSchema.js +++ b/app/imports/api/properties/subSchemas/TagTargetingSchema.ts @@ -1,7 +1,8 @@ import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS'; +import { TypedSimpleSchema } from 'imports/api/utility/TypedSimpleSchema'; -const TagTargetingSchema = new SimpleSchema({ +const TagTargetingSchema = new TypedSimpleSchema({ // True when targeting by tags instead of stats targetByTags: { type: Boolean, @@ -40,7 +41,7 @@ const TagTargetingSchema = new SimpleSchema({ }, 'extraTags.$.operation': { type: String, - allowedValues: ['OR', 'NOT'], + allowedValues: ['OR', 'NOT'] as const, defaultValue: 'OR', }, 'extraTags.$.tags': {