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

feat: TS migration for GraphQL Resolvers #342

Merged
merged 14 commits into from
Dec 15, 2022
Merged
381 changes: 158 additions & 223 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"supertest": "^6.2.2",
"ts-jest": "^27.1.3",
"ts-node": "^10.5.0",
"typedoc": "^0.22.12",
"typescript": "^4.5.5"
"typedoc": "^0.23.21",
"typescript": "^4.9.3"
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import SkillModel from '../../models/skill/index.js';
import { coalesceFilters, getMongoSortDirection, resolveContainsStringFilter } from './common.js';
import { AbilityScore } from '../../models/abilityScore/types';

type SortParams = Record<string, 1 | -1>;
type Args = {
name?: string;
order_direction?: string;
};

const AbilityScoreResolver = {
skills: async (abilityScore, args) => {
const filters = [{ index: { $in: abilityScore.skills.map(s => s.index) } }];
skills: async (abilityScore: AbilityScore, args: Args) => {
const filters: any[] = [{ index: { $in: abilityScore.skills?.map(s => s.index) } }];

if (args.name) {
filters.push(resolveContainsStringFilter(args.name));
}

const sort = {};
const sort: SortParams = {};
if (args.order_direction) {
sort.name = getMongoSortDirection(args.order_direction);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import EquipmentCategoryModel from '../../models/equipmentCategory/index.js';
import { Equipment } from '../../models/equipment/types';
import { equipmentFieldResolvers } from './common.js';

const Armor = {
...equipmentFieldResolvers,
armor_category: async armor => {
let index = armor.armor_category.toLowerCase();
armor_category: async (armor: Equipment) => {
let index = armor.armor_category?.toLowerCase();
index += index === 'shield' ? 's' : '-armor';
return await EquipmentCategoryModel.findOne({ index }).lean();
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ import LanguageModel from '../../models/language/index.js';
import ProficiencyModel from '../../models/proficiency/index.js';
import { coalesceFilters, resolveChoice, resolveContainsStringFilter } from './common.js';

import { Background } from '../../models/background/types';

type Args = {
name?: string;
order_direction?: string;
};

const Background = {
starting_equipment: async (background, args) => {
starting_equipment: async (background: Background, args: Args) => {
const starting_equipment = background.starting_equipment;
const filters = [
const filters: any[] = [
{
index: { $in: starting_equipment.map(se => se.equipment.index) },
},
Expand All @@ -25,8 +32,8 @@ const Background = {
equipment: equipment.find(e => e.index === se.equipment.index),
}));
},
starting_proficiencies: async (background, args) => {
const filters = [
starting_proficiencies: async (background: Background, args: Args) => {
const filters: any[] = [
{
index: { $in: background.starting_proficiencies.map(sp => sp.index) },
},
Expand All @@ -38,7 +45,7 @@ const Background = {

return await ProficiencyModel.find(coalesceFilters(filters)).lean();
},
language_options: async background =>
language_options: async (background: Background) =>
resolveChoice(
background.language_options,
{
Expand All @@ -50,23 +57,33 @@ const Background = {
},
true
),
starting_equipment_options: async background =>
background.starting_equipment_options.map(async option =>
resolveChoice(option, {
equipment_category: await EquipmentCategoryModel.findOne({
index: option.from.equipment_category.index,
}).lean(),
})
),
ideals: async background =>
resolveChoice(background.ideals, {
options: background.ideals.from.options.map(async option => ({
...option,
alignments: await AlignmentModel.find({
index: { $in: option.alignments.map(a => a.index) },
}).lean(),
})),
starting_equipment_options: async (background: Background) =>
background.starting_equipment_options.map(async option => {
if ('equipment_category' in option.from) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this if is necessary. Also, since it's inside a map function, it's a bit strange seeing that if the if failed the function wouldn't return a value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to do this in a lot places due to how types for choices are currently setup. Otherwise I get:

Property 'equipment_category' does not exist on type 'OptionSet'.
  Property 'equipment_category' does not exist on type 'OptionsArrayOptionSet'.

return resolveChoice(option, {
equipment_category: await EquipmentCategoryModel.findOne({
index: option.from.equipment_category.index,
}).lean(),
});
}
}),
ideals: async (background: Background) => {
if ('options' in background.ideals.from) {
const options = background.ideals.from.options.map(async option => {
if ('alignments' in option) {
return {
...option,
alignments: await AlignmentModel.find({
index: { $in: option.alignments.map(a => a.index) },
}).lean(),
};
}
});
return resolveChoice(background.ideals, {
options,
});
}
},
};

export default Background;
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,30 @@ import {
resolveChoice,
resolveContainsStringFilter,
resolveSpells,
SpellQuery,
} from './common.js';

const resolveEquipmentOption = async option => {
import { Class } from '../../models/class/types';
import { Option } from '../../models/common/types';

type Args = {
name?: string;
order_direction?: string;
};

const resolveEquipmentOption: any = async (option: Option) => {
if (option.option_type === 'counted_reference') {
return {
...option,
of: await EquipmentModel.findOne({ index: option.of.index }).lean(),
prerequisites: option.prerequisites?.map(async prereq => ({
...prereq,
proficiency: await ProficiencyModel.findOne({ index: prereq.proficiency.index }).lean(),
proficiency: await ProficiencyModel.findOne({ index: prereq.proficiency?.index }).lean(),
})),
};
}

if (option.option_type === 'choice') {
if (option.option_type === 'choice' && 'equipment_category' in option.choice.from) {
return {
...option,
choice: resolveChoice(option.choice, {
Expand All @@ -34,15 +43,17 @@ const resolveEquipmentOption = async option => {
};
}

return {
...option,
items: option.items.map(async item => await resolveEquipmentOption(item)),
};
if ('items' in option) {
return {
...option,
items: option.items.map(async item => await resolveEquipmentOption(item)),
};
}
};

const Class = {
proficiencies: async (klass, args) => {
const filters = [
proficiencies: async (klass: Class, args: Args) => {
const filters: any[] = [
{
index: { $in: klass.proficiencies.map(p => p.index) },
},
Expand All @@ -54,11 +65,11 @@ const Class = {

return await ProficiencyModel.find(coalesceFilters(filters)).lean();
},
saving_throws: async klass =>
saving_throws: async (klass: Class) =>
await AbilityScoreModel.find({
index: { $in: klass.saving_throws.map(st => st.index) },
}).lean(),
spellcasting: async klass =>
spellcasting: async (klass: Class) =>
klass.spellcasting
? {
...klass.spellcasting,
Expand All @@ -67,35 +78,36 @@ const Class = {
}).lean(),
}
: null,
spells: async (klass, args) =>
spells: async (klass: Class, args: SpellQuery) =>
resolveSpells(args, [{ classes: { $elemMatch: { index: klass.index } } }]),
starting_equipment: async klass => {
starting_equipment: async (klass: Class) => {
const starting_equipment = klass.starting_equipment;
const equipment = await EquipmentModel.find({
index: { $in: starting_equipment.map(se => se.equipment.index) },
index: { $in: starting_equipment?.map(se => se.equipment.index) },
}).lean();

return starting_equipment.map(se => ({
return starting_equipment?.map(se => ({
...se,
equipment: equipment.find(e => e.index === se.equipment.index),
}));
},
class_levels: async klass => await LevelModel.find({ 'class.index': klass.index }).lean(),
subclasses: async (klass, args) => {
const filters = [{ index: { $in: klass.subclasses.map(s => s.index) } }];
class_levels: async (klass: Class) =>
await LevelModel.find({ 'class.index': klass.index }).lean(),
subclasses: async (klass: Class, args: Args) => {
const filters: any[] = [{ index: { $in: klass.subclasses.map(s => s.index) } }];

if (args.name) {
filters.push(resolveContainsStringFilter(args.name));
}

return await SubclassModel.find(coalesceFilters(filters)).lean();
},
multi_classing: async klass => {
const multiclassingToReturn = {};
multi_classing: async (klass: Class) => {
const multiclassingToReturn: Record<any, any> = {};
const { multi_classing } = klass;

multiclassingToReturn.proficiencies = await ProficiencyModel.find({
index: { $in: multi_classing.proficiencies.map(prof => prof.index) },
index: { $in: multi_classing.proficiencies?.map(prof => prof.index) },
}).lean();

if (multi_classing.prerequisites) {
Expand All @@ -109,58 +121,83 @@ const Class = {
);
}

if (multi_classing.prerequisite_options) {
if (
multi_classing.prerequisite_options &&
'options' in multi_classing.prerequisite_options.from
) {
multiclassingToReturn.prerequisite_options = resolveChoice(
multi_classing.prerequisite_options,
{
options: multi_classing.prerequisite_options.from.options.map(async option => ({
...option,
ability_score: await AbilityScoreModel.findOne({
index: option.ability_score.index,
}).lean(),
})),
options: multi_classing.prerequisite_options.from.options.map(async option => {
if (option.option_type === 'ability_bonus') {
return {
...option,
ability_score: await AbilityScoreModel.findOne({
index: option.ability_score.index,
}).lean(),
};
}
}),
}
);
}

if (multi_classing.proficiency_choices) {
multiclassingToReturn.proficiency_choices = multi_classing.proficiency_choices.map(
async choice =>
resolveChoice(choice, {
options: choice.from.options.map(async option => ({
...option,
item: await ProficiencyModel.findOne({ index: option.item.index }).lean(),
})),
})
async choice => {
if ('options' in choice.from) {
return resolveChoice(choice, {
options: choice.from.options.map(async option => {
if ('item' in option) {
return {
...option,
item: await ProficiencyModel.findOne({ index: option.item.index }).lean(),
};
}
}),
});
}
}
);
}

return multiclassingToReturn;
},
proficiency_choices: async klass =>
klass.proficiency_choices.map(async choice =>
resolveChoice(choice, {
options: choice.from.options.map(async option =>
option.option_type === 'reference'
? {
proficiency_choices: async (klass: Class) =>
klass.proficiency_choices.map(async choice => {
if ('options' in choice.from) {
return resolveChoice(choice, {
options: choice.from.options.map(async option => {
if ('item' in option) {
return {
...option,
item: await ProficiencyModel.findOne({ index: option.item.index }).lean(),
}
: {
...option,
choice: resolveChoice(option.choice, {
options: option.choice.from.options.map(async o => ({
};
}

if ('choice' in option && 'options' in option.choice.from) {
const options = option.choice.from.options.map(async o => {
if ('item' in o) {
return {
...o,
item: await ProficiencyModel.findOne({ index: o.item.index }).lean(),
})),
};
}
});
return {
...option,
choice: resolveChoice(option.choice, {
options,
}),
}
),
})
),
starting_equipment_options: async klass =>
};
}
}),
});
}
}),
starting_equipment_options: async (klass: Class) =>
klass.starting_equipment_options.map(async se_option => {
const optionToReturn = { ...se_option };
const optionToReturn: Record<any, any> = { ...se_option };
const from = se_option.from;

if (from.option_set_type === 'equipment_category') {
Expand All @@ -171,10 +208,13 @@ const Class = {
}).lean(),
};
} else {
optionToReturn.from = {
...from,
options: from.options.map(async option => await resolveEquipmentOption(option)),
};
if ('options' in from) {
const options = from.options.map(async option => await resolveEquipmentOption(option));
optionToReturn.from = {
...from,
options,
};
}
}

return optionToReturn;
Expand Down
Loading