From 55fd2daaf7ef1ee138ec664f7fc6205f55ee34f8 Mon Sep 17 00:00:00 2001 From: Jeroen Claassens Date: Thu, 8 Jul 2021 00:42:25 +0200 Subject: [PATCH] feat: lots stuff or something - Fully implemented films - Fixed enums for people, planets, species, starships - Removed films enum as it is covered by class-validator - Added GraphQLLong scalar - Fixed various entries in the dataset because the swapi data is crap - Updated playgrounds default tabs data - Fixed various numbers that should be Float, not Int in GraphQL - Updated GraphQLSet filter method to filter out the predicate value --- package.json | 1 + src/arguments/FilmsArgs.ts | 3 - src/arguments/PersonArgs.ts | 2 +- src/arguments/PlanetArgs.ts | 2 +- src/arguments/SpeciesArgs.ts | 2 +- src/arguments/StarshipArgs.ts | 2 +- src/assets/people.ts | 18 ++-- src/assets/planets.ts | 174 ++++++++++++++++---------------- src/assets/species.ts | 2 +- src/assets/starships.ts | 70 ++++++------- src/assets/vehicles.ts | 26 ++--- src/defaultPlaygroundTabs.ts | 160 +++++++++++++++++++++-------- src/scalars/GraphQLLong.ts | 41 ++++++++ src/server.ts | 23 ++--- src/services/FilmService.ts | 91 +++++++++++++++-- src/services/PersonService.ts | 4 +- src/services/PlanetService.ts | 4 +- src/services/SpeciesService.ts | 4 +- src/services/StarshipService.ts | 10 +- src/services/VehicleService.ts | 2 +- src/structures/Planet.ts | 7 +- src/structures/Species.ts | 3 +- src/structures/Starship.ts | 11 +- src/structures/Vehicle.ts | 10 +- src/tsconfig.json | 1 + src/utils/GraphQLSet.ts | 24 ++++- src/utils/star-wars.d.ts | 6 +- 27 files changed, 460 insertions(+), 243 deletions(-) create mode 100644 src/scalars/GraphQLLong.ts diff --git a/package.json b/package.json index 0e29979..1a29dd1 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "#assets/*": "./generated/api/assets/*.js", "#jsonAssets/*": "./generated/api/assets/*", "#resolvers/*": "./generated/api/resolvers/*.js", + "#scalars/*": "./generated/api/scalars/*.js", "#services/*": "./generated/api/services/*.js", "#structures/*": "./generated/api/structures/*.js", "#utils/*": "./generated/api/utils/*.js", diff --git a/src/arguments/FilmsArgs.ts b/src/arguments/FilmsArgs.ts index 70d4992..c7271b1 100644 --- a/src/arguments/FilmsArgs.ts +++ b/src/arguments/FilmsArgs.ts @@ -1,9 +1,6 @@ -import filmData from '#assets/films'; import { IsIn, IsNumber } from 'class-validator'; import { ArgsType, Field, Int } from 'type-graphql'; -export const films = filmData.enumObject(); - @ArgsType() export default class FilmArgs { @Field(() => Int, { description: 'The film to look up, referenced by episode number' }) diff --git a/src/arguments/PersonArgs.ts b/src/arguments/PersonArgs.ts index 57447f8..b4f6a05 100644 --- a/src/arguments/PersonArgs.ts +++ b/src/arguments/PersonArgs.ts @@ -6,7 +6,7 @@ export const people = personData.enumObject(); @ArgsType() export default class PersonArgs { - @Field(() => String, { description: 'The person to look up' }) + @Field(() => people, { description: 'The person to look up' }) @IsString() public person!: string; } diff --git a/src/arguments/PlanetArgs.ts b/src/arguments/PlanetArgs.ts index b6436cd..265a9f6 100644 --- a/src/arguments/PlanetArgs.ts +++ b/src/arguments/PlanetArgs.ts @@ -6,7 +6,7 @@ export const planets = planetData.enumObject(); @ArgsType() export default class PlanetArgs { - @Field(() => String, { description: 'The planet to look up' }) + @Field(() => planets, { description: 'The planet to look up' }) @IsString() public planet!: string; } diff --git a/src/arguments/SpeciesArgs.ts b/src/arguments/SpeciesArgs.ts index d239ea3..4b25f4d 100644 --- a/src/arguments/SpeciesArgs.ts +++ b/src/arguments/SpeciesArgs.ts @@ -6,7 +6,7 @@ export const species = speciesData.enumObject(); @ArgsType() export default class SpeciesArgs { - @Field(() => String, { description: 'The species to look up' }) + @Field(() => species, { description: 'The species to look up' }) @IsString() public species!: string; } diff --git a/src/arguments/StarshipArgs.ts b/src/arguments/StarshipArgs.ts index 72e0294..da22de9 100644 --- a/src/arguments/StarshipArgs.ts +++ b/src/arguments/StarshipArgs.ts @@ -6,7 +6,7 @@ export const starships = starshipsData.enumObject(); @ArgsType() export default class StarshipArgs { - @Field(() => String, { description: 'The starship to look up' }) + @Field(() => starships, { description: 'The starship to look up' }) @IsString() public starship!: string; } diff --git a/src/assets/people.ts b/src/assets/people.ts index 353f6b6..b11ee5e 100644 --- a/src/assets/people.ts +++ b/src/assets/people.ts @@ -283,7 +283,7 @@ export default new GraphQLCollection([ hairColors: null, height: 175, homeworld: 'Nal Hutta', - mass: NaN, + mass: 1358, name: 'Jabba Desilijic Tiure', skinColors: ['green-tan', 'brown'], species: ['hutt'], @@ -598,7 +598,7 @@ export default new GraphQLCollection([ } ], [ - 'padm├®amidala', + 'padmeamidala', { birthYear: '46BBY', eyeColors: ['brown'], @@ -608,7 +608,7 @@ export default new GraphQLCollection([ height: 185, homeworld: 'Naboo', mass: 45, - name: 'Padm├® Amidala', + name: 'Padmé Amidala', skinColors: ['light'], species: [], starships: ['naboofighter', 'htypenubianyacht', 'naboostarskiff'], @@ -670,7 +670,7 @@ export default new GraphQLCollection([ } ], [ - 'ricoli├®', + 'ricolie', { birthYear: 'unknown', eyeColors: ['blue'], @@ -680,7 +680,7 @@ export default new GraphQLCollection([ height: 183, homeworld: 'Naboo', mass: null, - name: 'Ric Oli├®', + name: 'Ric Olié', skinColors: ['fair'], species: [], starships: ['nabooroyalstarship'], @@ -1066,7 +1066,7 @@ export default new GraphQLCollection([ } ], [ - 'cord├®', + 'corde', { birthYear: 'unknown', eyeColors: ['brown'], @@ -1076,7 +1076,7 @@ export default new GraphQLCollection([ height: 157, homeworld: 'Naboo', mass: null, - name: 'Cord├®', + name: 'Cordé', skinColors: ['light'], species: [], starships: [], @@ -1156,7 +1156,7 @@ export default new GraphQLCollection([ } ], [ - 'dorm├®', + 'dorme', { birthYear: 'unknown', eyeColors: ['brown'], @@ -1166,7 +1166,7 @@ export default new GraphQLCollection([ height: 165, homeworld: 'Naboo', mass: null, - name: 'Dorm├®', + name: 'Dormé', skinColors: ['light'], species: ['human'], starships: [], diff --git a/src/assets/planets.ts b/src/assets/planets.ts index 006a2c7..fca0228 100644 --- a/src/assets/planets.ts +++ b/src/assets/planets.ts @@ -9,10 +9,10 @@ export default new GraphQLCollection([ climate: ['arid'], diameter: 10465, films: [4, 6, 1, 2, 3], - gravity: '1 standard', + gravity: 1, name: 'Tatooine', orbitalPeriod: '304', - population: '200000', + population: 200000, residents: [ 'lukeskywalker', 'c3po', @@ -36,10 +36,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 12500, films: [4, 3], - gravity: '1 standard', + gravity: 1, name: 'Alderaan', orbitalPeriod: '364', - population: '2000000000', + population: 2000000000, residents: ['leiaorgana', 'bailprestororgana', 'raymusantilles'], rotationPeriod: '24', surfaceWater: '40', @@ -52,10 +52,10 @@ export default new GraphQLCollection([ climate: ['temperate', 'tropical'], diameter: 10200, films: [4], - gravity: '1 standard', + gravity: 1, name: 'Yavin IV', orbitalPeriod: '4818', - population: '1000', + population: 1000, residents: [], rotationPeriod: '24', surfaceWater: '8', @@ -68,7 +68,7 @@ export default new GraphQLCollection([ climate: ['frozen'], diameter: 7200, films: [5], - gravity: '1.1 standard', + gravity: 1.1, name: 'Hoth', orbitalPeriod: '549', population: null, @@ -100,10 +100,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 118000, films: [5], - gravity: '1.5 (surface), 1 standard (Cloud City)', + gravity: 1, name: 'Bespin', orbitalPeriod: '5110', - population: '6000000', + population: 6000000, residents: ['lobot'], rotationPeriod: '12', surfaceWater: '0', @@ -116,10 +116,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 4900, films: [6], - gravity: '0.85 standard', + gravity: 0.85, name: 'Endor', orbitalPeriod: '402', - population: '30000000', + population: 30000000, residents: ['wicketsystriwarrick'], rotationPeriod: '18', surfaceWater: '8', @@ -132,10 +132,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 12120, films: [6, 1, 2, 3], - gravity: '1 standard', + gravity: 1, name: 'Naboo', orbitalPeriod: '312', - population: '4500000000', + population: 4500000000, residents: [ 'r2d2', 'palpatine', @@ -160,10 +160,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 12240, films: [6, 1, 2, 3], - gravity: '1 standard', + gravity: 1, name: 'Coruscant', orbitalPeriod: '368', - population: '1000000000000', + population: 1000000000000, residents: ['finisvalorum', 'adigallia', 'jocastanu'], rotationPeriod: '24', surfaceWater: null, @@ -176,10 +176,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 19720, films: [2], - gravity: '1 standard', + gravity: 1, name: 'Kamino', orbitalPeriod: '463', - population: '1000000000', + population: 1000000000, residents: ['bobafett', 'lamasu', 'taunwe'], rotationPeriod: '27', surfaceWater: '100', @@ -192,10 +192,10 @@ export default new GraphQLCollection([ climate: ['temperate', 'arid'], diameter: 11370, films: [2], - gravity: '0.9 standard', + gravity: 0.9, name: 'Geonosis', orbitalPeriod: '256', - population: '100000000000', + population: 100000000000, residents: ['pogglethelesser'], rotationPeriod: '30', surfaceWater: '5', @@ -208,10 +208,10 @@ export default new GraphQLCollection([ climate: ['temperate', 'arid', 'windy'], diameter: 12900, films: [3], - gravity: '1 standard', + gravity: 1, name: 'Utapau', orbitalPeriod: '351', - population: '95000000', + population: 95000000, residents: ['tionmedon'], rotationPeriod: '27', surfaceWater: '0.9', @@ -224,10 +224,10 @@ export default new GraphQLCollection([ climate: ['hot'], diameter: 4200, films: [3], - gravity: '1 standard', + gravity: 1, name: 'Mustafar', orbitalPeriod: '412', - population: '20000', + population: 20000, residents: [], rotationPeriod: '36', surfaceWater: '0', @@ -240,10 +240,10 @@ export default new GraphQLCollection([ climate: ['tropical'], diameter: 12765, films: [3], - gravity: '1 standard', + gravity: 1, name: 'Kashyyyk', orbitalPeriod: '381', - population: '45000000', + population: 45000000, residents: ['chewbacca', 'tarfful'], rotationPeriod: '26', surfaceWater: '60', @@ -256,10 +256,10 @@ export default new GraphQLCollection([ climate: ['artificial temperate '], diameter: 0, films: [3], - gravity: '0.56 standard', + gravity: 0.56, name: 'Polis Massa', orbitalPeriod: '590', - population: '1000000', + population: 1000000, residents: [], rotationPeriod: '24', surfaceWater: '0', @@ -272,10 +272,10 @@ export default new GraphQLCollection([ climate: ['frigid'], diameter: 10088, films: [3], - gravity: '1 standard', + gravity: 1, name: 'Mygeeto', orbitalPeriod: '167', - population: '19000000', + population: 19000000, residents: [], rotationPeriod: '12', surfaceWater: null, @@ -288,10 +288,10 @@ export default new GraphQLCollection([ climate: ['hot', 'humid'], diameter: 9100, films: [3], - gravity: '0.75 standard', + gravity: 0.75, name: 'Felucia', orbitalPeriod: '231', - population: '8500000', + population: 8500000, residents: [], rotationPeriod: '34', surfaceWater: null, @@ -304,10 +304,10 @@ export default new GraphQLCollection([ climate: ['temperate', 'moist'], diameter: 0, films: [3], - gravity: '1 standard', + gravity: 1, name: 'Cato Neimoidia', orbitalPeriod: '278', - population: '10000000', + population: 10000000, residents: ['nutegunray'], rotationPeriod: '25', surfaceWater: null, @@ -323,7 +323,7 @@ export default new GraphQLCollection([ gravity: null, name: 'Saleucami', orbitalPeriod: '392', - population: '1400000000', + population: 1400000000, residents: [], rotationPeriod: '26', surfaceWater: null, @@ -336,7 +336,7 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 0, films: [], - gravity: '1 standard', + gravity: 1, name: 'Stewjon', orbitalPeriod: null, population: null, @@ -352,10 +352,10 @@ export default new GraphQLCollection([ climate: ['polluted'], diameter: 13490, films: [], - gravity: '1 standard', + gravity: 1, name: 'Eriadu', orbitalPeriod: '360', - population: '22000000000', + population: 22000000000, residents: ['wilhufftarkin'], rotationPeriod: '24', surfaceWater: null, @@ -368,10 +368,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 11000, films: [], - gravity: '1 standard', + gravity: 1, name: 'Corellia', orbitalPeriod: '329', - population: '3000000000', + population: 3000000000, residents: ['hansolo', 'wedgeantilles'], rotationPeriod: '25', surfaceWater: '70', @@ -384,10 +384,10 @@ export default new GraphQLCollection([ climate: ['hot'], diameter: 7549, films: [], - gravity: '1 standard', + gravity: 1, name: 'Rodia', orbitalPeriod: '305', - population: '1300000000', + population: 1300000000, residents: ['greedo'], rotationPeriod: '29', surfaceWater: '60', @@ -400,10 +400,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 12150, films: [], - gravity: '1 standard', + gravity: 1, name: 'Nal Hutta', orbitalPeriod: '413', - population: '7000000000', + population: 7000000000, residents: ['jabbadesilijictiure'], rotationPeriod: '87', surfaceWater: null, @@ -416,10 +416,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 9830, films: [], - gravity: '1 standard', + gravity: 1, name: 'Dantooine', orbitalPeriod: '378', - population: '1000', + population: 1000, residents: [], rotationPeriod: '25', surfaceWater: null, @@ -435,7 +435,7 @@ export default new GraphQLCollection([ gravity: null, name: 'Bestine IV', orbitalPeriod: '680', - population: '62000000', + population: 62000000, residents: ['jektonoporkins'], rotationPeriod: '26', surfaceWater: '98', @@ -448,10 +448,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 14050, films: [5], - gravity: '1 standard', + gravity: 1, name: 'Ord Mantell', orbitalPeriod: '334', - population: '4000000000', + population: 4000000000, residents: [], rotationPeriod: '26', surfaceWater: '10', @@ -464,10 +464,10 @@ export default new GraphQLCollection([ climate: ['arid'], diameter: 0, films: [], - gravity: '0.62 standard', + gravity: 0.62, name: 'Trandosha', orbitalPeriod: '371', - population: '42000000', + population: 42000000, residents: ['bossk'], rotationPeriod: '25', surfaceWater: null, @@ -480,10 +480,10 @@ export default new GraphQLCollection([ climate: ['arid'], diameter: 0, films: [], - gravity: '1 standard', + gravity: 1, name: 'Socorro', orbitalPeriod: '326', - population: '300000000', + population: 300000000, residents: ['landocalrissian'], rotationPeriod: '20', surfaceWater: null, @@ -496,10 +496,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 11030, films: [], - gravity: '1', + gravity: 1, name: 'Mon Cala', orbitalPeriod: '398', - population: '27000000000', + population: 27000000000, residents: ['ackbar'], rotationPeriod: '21', surfaceWater: '100', @@ -512,10 +512,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 13500, films: [], - gravity: '1', + gravity: 1, name: 'Chandrila', orbitalPeriod: '368', - population: '1200000000', + population: 1200000000, residents: ['monmothma'], rotationPeriod: '20', surfaceWater: '40', @@ -528,10 +528,10 @@ export default new GraphQLCollection([ climate: ['superheated'], diameter: 12780, films: [], - gravity: '1', + gravity: 1, name: 'Sullust', orbitalPeriod: '263', - population: '18500000000', + population: 18500000000, residents: ['niennunb'], rotationPeriod: '20', surfaceWater: '5', @@ -544,10 +544,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 7900, films: [], - gravity: '1', + gravity: 1, name: 'Toydaria', orbitalPeriod: '184', - population: '11000000', + population: 11000000, residents: ['watto'], rotationPeriod: '21', surfaceWater: null, @@ -560,10 +560,10 @@ export default new GraphQLCollection([ climate: ['arid', 'temperate', 'tropical'], diameter: 18880, films: [], - gravity: '1.56', + gravity: 1.56, name: 'Malastare', orbitalPeriod: '201', - population: '2000000000', + population: 2000000000, residents: ['sebulba'], rotationPeriod: '26', surfaceWater: null, @@ -576,10 +576,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 10480, films: [], - gravity: '0.9', + gravity: 0.9, name: 'Dathomir', orbitalPeriod: '491', - population: '5200', + population: 5200, residents: ['darthmaul'], rotationPeriod: '24', surfaceWater: null, @@ -592,10 +592,10 @@ export default new GraphQLCollection([ climate: ['temperate', 'arid', 'subartic'], diameter: 10600, films: [], - gravity: '1', + gravity: 1, name: 'Ryloth', orbitalPeriod: '305', - population: '1500000000', + population: 1500000000, residents: ['bibfortuna', 'aylasecura'], rotationPeriod: '30', surfaceWater: '5', @@ -624,10 +624,10 @@ export default new GraphQLCollection([ climate: ['temperate', 'artic'], diameter: 14900, films: [], - gravity: '1', + gravity: 1, name: 'Vulpter', orbitalPeriod: '391', - population: '421000000', + population: 421000000, residents: ['dudbolt'], rotationPeriod: '22', surfaceWater: null, @@ -659,7 +659,7 @@ export default new GraphQLCollection([ gravity: null, name: 'Tund', orbitalPeriod: '1770', - population: '0', + population: 0, residents: ['benquadinaros'], rotationPeriod: '48', surfaceWater: null, @@ -672,10 +672,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 10120, films: [], - gravity: '0.98', + gravity: 0.98, name: 'Haruun Kal', orbitalPeriod: '383', - population: '705300', + population: 705300, residents: ['macewindu'], rotationPeriod: '25', surfaceWater: null, @@ -688,10 +688,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: null, films: [], - gravity: '1', + gravity: 1, name: 'Cerea', orbitalPeriod: '386', - population: '450000000', + population: 450000000, residents: ['kiadimundi'], rotationPeriod: '27', surfaceWater: '20', @@ -704,10 +704,10 @@ export default new GraphQLCollection([ climate: ['tropical', 'temperate'], diameter: 15600, films: [], - gravity: '1', + gravity: 1, name: 'Glee Anselm', orbitalPeriod: '206', - population: '500000000', + population: 500000000, residents: ['kitfisto'], rotationPeriod: '33', surfaceWater: '80', @@ -752,7 +752,7 @@ export default new GraphQLCollection([ climate: ['arid', 'rocky', 'windy'], diameter: null, films: [], - gravity: '1', + gravity: 1, name: 'Iktotch', orbitalPeriod: '481', population: null, @@ -784,7 +784,7 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 13400, films: [], - gravity: '1', + gravity: 1, name: 'Dorin', orbitalPeriod: '409', population: null, @@ -800,10 +800,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: null, films: [], - gravity: '1', + gravity: 1, name: 'Champala', orbitalPeriod: '318', - population: '3500000000', + population: 3500000000, residents: ['masamedda'], rotationPeriod: '27', surfaceWater: null, @@ -883,7 +883,7 @@ export default new GraphQLCollection([ gravity: null, name: 'Ojom', orbitalPeriod: null, - population: '500000000', + population: 500000000, residents: ['dexterjettster'], rotationPeriod: null, surfaceWater: '100', @@ -896,10 +896,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: null, films: [], - gravity: '1', + gravity: 1, name: 'Skako', orbitalPeriod: '384', - population: '500000000000', + population: 500000000000, residents: ['wattambor'], rotationPeriod: '27', surfaceWater: null, @@ -912,10 +912,10 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: 13800, films: [], - gravity: '1', + gravity: 1, name: 'Muunilinst', orbitalPeriod: '412', - population: '5000000000', + population: 5000000000, residents: ['sanhill'], rotationPeriod: '28', surfaceWater: '25', @@ -928,7 +928,7 @@ export default new GraphQLCollection([ climate: ['temperate'], diameter: null, films: [], - gravity: '1', + gravity: 1, name: 'Shili', orbitalPeriod: null, population: null, @@ -944,10 +944,10 @@ export default new GraphQLCollection([ climate: ['arid', 'temperate', 'tropical'], diameter: 13850, films: [], - gravity: '1', + gravity: 1, name: 'Kalee', orbitalPeriod: '378', - population: '4000000000', + population: 4000000000, residents: ['grievous'], rotationPeriod: '23', surfaceWater: null, diff --git a/src/assets/species.ts b/src/assets/species.ts index 698b188..db52010 100644 --- a/src/assets/species.ts +++ b/src/assets/species.ts @@ -16,7 +16,7 @@ export default new GraphQLCollection([ homeworld: 'Coruscant', language: 'Galactic Basic', name: 'Human', - people: ['dorm├®', 'dooku', 'bailprestororgana', 'jocastanu'], + people: ['dorme', 'dooku', 'bailprestororgana', 'jocastanu'], skinColors: ['caucasian', 'black', 'asian', 'hispanic'] } ], diff --git a/src/assets/starships.ts b/src/assets/starships.ts index 1194620..f8c234b 100644 --- a/src/assets/starships.ts +++ b/src/assets/starships.ts @@ -9,7 +9,7 @@ export default new GraphQLCollection([ cargoCapacity: 3000000, consumables: '1 year', costInCredits: 3500000, - crew: '30-165', + crew: 165, films: [4, 6, 3], hyperdriveRating: 2, length: 150, @@ -29,7 +29,7 @@ export default new GraphQLCollection([ cargoCapacity: 36000000, consumables: '2 years', costInCredits: 150000000, - crew: '47,060', + crew: 47060, films: [4, 5, 6], hyperdriveRating: 2, length: 1600, @@ -49,7 +49,7 @@ export default new GraphQLCollection([ cargoCapacity: 180000, consumables: '1 month', costInCredits: 240000, - crew: '5', + crew: 5, films: [4], hyperdriveRating: 1, length: 38, @@ -69,7 +69,7 @@ export default new GraphQLCollection([ cargoCapacity: 1000000000000, consumables: '3 years', costInCredits: 1000000000000, - crew: '342,953', + crew: 342953, films: [4], hyperdriveRating: 4, length: 120000, @@ -89,7 +89,7 @@ export default new GraphQLCollection([ cargoCapacity: 100000, consumables: '2 months', costInCredits: 100000, - crew: '4', + crew: 4, films: [4, 5, 6], hyperdriveRating: 0.5, length: 34.37, @@ -109,7 +109,7 @@ export default new GraphQLCollection([ cargoCapacity: 110, consumables: '1 week', costInCredits: 134999, - crew: '2', + crew: 2, films: [4, 5, 6], hyperdriveRating: 1, length: 14, @@ -129,7 +129,7 @@ export default new GraphQLCollection([ cargoCapacity: 110, consumables: '1 week', costInCredits: 149999, - crew: '1', + crew: 1, films: [4, 5, 6], hyperdriveRating: 1, length: 12.5, @@ -149,7 +149,7 @@ export default new GraphQLCollection([ cargoCapacity: 150, consumables: '5 days', costInCredits: null, - crew: '1', + crew: 1, films: [4], hyperdriveRating: 1, length: 9.2, @@ -169,7 +169,7 @@ export default new GraphQLCollection([ cargoCapacity: 250000000, consumables: '6 years', costInCredits: 1143350000, - crew: '279,144', + crew: 279144, films: [5, 6], hyperdriveRating: 2, length: 19000, @@ -189,7 +189,7 @@ export default new GraphQLCollection([ cargoCapacity: 19000000, consumables: '6 months', costInCredits: null, - crew: '6', + crew: 6, films: [5, 6], hyperdriveRating: 4, length: 90, @@ -209,7 +209,7 @@ export default new GraphQLCollection([ cargoCapacity: 70000, consumables: '1 month', costInCredits: null, - crew: '1', + crew: 1, films: [5, 2], hyperdriveRating: 3, length: 21.5, @@ -229,7 +229,7 @@ export default new GraphQLCollection([ cargoCapacity: 80000, consumables: '2 months', costInCredits: 240000, - crew: '6', + crew: 6, films: [5, 6], hyperdriveRating: 1, length: 20, @@ -249,7 +249,7 @@ export default new GraphQLCollection([ cargoCapacity: 6000000, consumables: '2 years', costInCredits: 8500000, - crew: '854', + crew: 854, films: [5, 6], hyperdriveRating: 2, length: 300, @@ -269,7 +269,7 @@ export default new GraphQLCollection([ cargoCapacity: null, consumables: '2 years', costInCredits: 104000000, - crew: '5400', + crew: 5400, films: [6], hyperdriveRating: 1, length: 1200, @@ -289,7 +289,7 @@ export default new GraphQLCollection([ cargoCapacity: 40, consumables: '1 week', costInCredits: 175000, - crew: '1', + crew: 1, films: [6], hyperdriveRating: 1, length: 9.6, @@ -309,7 +309,7 @@ export default new GraphQLCollection([ cargoCapacity: 45, consumables: '1 week', costInCredits: 220000, - crew: '1', + crew: 1, films: [6], hyperdriveRating: 2, length: 16.9, @@ -329,7 +329,7 @@ export default new GraphQLCollection([ cargoCapacity: null, consumables: null, costInCredits: null, - crew: '9', + crew: 9, films: [1], hyperdriveRating: 2, length: 115, @@ -349,7 +349,7 @@ export default new GraphQLCollection([ cargoCapacity: 4000000000, consumables: '500 days', costInCredits: null, - crew: '175', + crew: 175, films: [1, 2, 3], hyperdriveRating: 2, length: 3170, @@ -369,7 +369,7 @@ export default new GraphQLCollection([ cargoCapacity: 65, consumables: '7 days', costInCredits: 200000, - crew: '1', + crew: 1, films: [1, 2], hyperdriveRating: 1, length: 11, @@ -389,7 +389,7 @@ export default new GraphQLCollection([ cargoCapacity: null, consumables: null, costInCredits: null, - crew: '8', + crew: 8, films: [1], hyperdriveRating: 1.8, length: 76, @@ -409,7 +409,7 @@ export default new GraphQLCollection([ cargoCapacity: 2500000, consumables: '30 days', costInCredits: 55000000, - crew: '1', + crew: 1, films: [1], hyperdriveRating: 1.5, length: 26.5, @@ -429,7 +429,7 @@ export default new GraphQLCollection([ cargoCapacity: null, consumables: '1 year', costInCredits: 2000000, - crew: '5', + crew: 5, films: [2], hyperdriveRating: 0.7, length: 39, @@ -469,7 +469,7 @@ export default new GraphQLCollection([ cargoCapacity: 60, consumables: '7 days', costInCredits: 180000, - crew: '1', + crew: 1, films: [2, 3], hyperdriveRating: 1, length: 8, @@ -489,7 +489,7 @@ export default new GraphQLCollection([ cargoCapacity: null, consumables: null, costInCredits: null, - crew: '4', + crew: 4, films: [2], hyperdriveRating: 0.9, length: 47.9, @@ -509,7 +509,7 @@ export default new GraphQLCollection([ cargoCapacity: 11250000, consumables: '2 years', costInCredits: null, - crew: '700', + crew: 700, films: [2], hyperdriveRating: 0.6, length: 752, @@ -529,7 +529,7 @@ export default new GraphQLCollection([ cargoCapacity: 240, consumables: '7 days', costInCredits: 35700, - crew: '3', + crew: 3, films: [2], hyperdriveRating: 1.5, length: 15.2, @@ -549,7 +549,7 @@ export default new GraphQLCollection([ cargoCapacity: 50000000, consumables: '4 years', costInCredits: 125000000, - crew: '600', + crew: 600, films: [3], hyperdriveRating: 1.5, length: 1088, @@ -569,7 +569,7 @@ export default new GraphQLCollection([ cargoCapacity: 50000, consumables: '56 days', costInCredits: 1000000, - crew: '5', + crew: 5, films: [3], hyperdriveRating: 1, length: 18.5, @@ -589,7 +589,7 @@ export default new GraphQLCollection([ cargoCapacity: 20000000, consumables: '2 years', costInCredits: 59000000, - crew: '7400', + crew: 7400, films: [3], hyperdriveRating: 1, length: 1137, @@ -609,7 +609,7 @@ export default new GraphQLCollection([ cargoCapacity: null, consumables: null, costInCredits: null, - crew: '3', + crew: 3, films: [3], hyperdriveRating: 0.5, length: 29.2, @@ -629,7 +629,7 @@ export default new GraphQLCollection([ cargoCapacity: 60, consumables: '2 days', costInCredits: 320000, - crew: '1', + crew: 1, films: [3], hyperdriveRating: 1, length: 5.47, @@ -649,7 +649,7 @@ export default new GraphQLCollection([ cargoCapacity: 110, consumables: '5 days', costInCredits: 155000, - crew: '3', + crew: 3, films: [3], hyperdriveRating: 1, length: 14.5, @@ -669,7 +669,7 @@ export default new GraphQLCollection([ cargoCapacity: 40000000, consumables: '2 years', costInCredits: 57000000, - crew: '200', + crew: 200, films: [3], hyperdriveRating: 1, length: 825, @@ -689,7 +689,7 @@ export default new GraphQLCollection([ cargoCapacity: 140, consumables: '7 days', costInCredits: 168000, - crew: '1', + crew: 1, films: [3], hyperdriveRating: 6, length: 6.71, @@ -709,7 +709,7 @@ export default new GraphQLCollection([ cargoCapacity: 60, consumables: '15 hours', costInCredits: 102500, - crew: '1', + crew: 1, films: [3], hyperdriveRating: 1, length: 7.9, diff --git a/src/assets/vehicles.ts b/src/assets/vehicles.ts index 290d688..6de9d9e 100644 --- a/src/assets/vehicles.ts +++ b/src/assets/vehicles.ts @@ -79,7 +79,7 @@ export default new GraphQLCollection([ 'snowspeeder', { cargoCapacity: 10, - consumables: 'none', + consumables: null, costInCredits: null, crew: 2, films: [5], @@ -96,7 +96,7 @@ export default new GraphQLCollection([ [ 'tiebomber', { - cargoCapacity: NaN, + cargoCapacity: null, consumables: '2 days', costInCredits: null, crew: 1, @@ -133,7 +133,7 @@ export default new GraphQLCollection([ 'atst', { cargoCapacity: 200, - consumables: 'none', + consumables: null, costInCredits: null, crew: 2, films: [5, 6], @@ -241,7 +241,7 @@ export default new GraphQLCollection([ 'vulturedroid', { cargoCapacity: 0, - consumables: 'none', + consumables: null, costInCredits: null, crew: 0, films: [1, 3], @@ -294,8 +294,8 @@ export default new GraphQLCollection([ [ 'singletrooperaerialplatform', { - cargoCapacity: NaN, - consumables: 'none', + cargoCapacity: null, + consumables: null, costInCredits: 2500, crew: 1, films: [1], @@ -367,7 +367,7 @@ export default new GraphQLCollection([ 'zephyrgswoopbike', { cargoCapacity: 200, - consumables: 'none', + consumables: null, costInCredits: 5750, crew: 1, films: [2], @@ -547,7 +547,7 @@ export default new GraphQLCollection([ 'tsmeu6personalwheelbike', { cargoCapacity: 10, - consumables: 'none', + consumables: null, costInCredits: 15000, crew: 1, films: [3], @@ -583,7 +583,7 @@ export default new GraphQLCollection([ 'droidtrifighter', { cargoCapacity: 0, - consumables: 'none', + consumables: null, costInCredits: 20000, crew: 1, films: [3], @@ -619,7 +619,7 @@ export default new GraphQLCollection([ 'raddaughgnaspfluttercraft', { cargoCapacity: 20, - consumables: 'none', + consumables: null, costInCredits: 14750, crew: 2, films: [3], @@ -654,8 +654,8 @@ export default new GraphQLCollection([ [ 'corporatealliancetankdroid', { - cargoCapacity: NaN, - consumables: 'none', + cargoCapacity: null, + consumables: null, costInCredits: 49000, crew: 0, films: [3], @@ -673,7 +673,7 @@ export default new GraphQLCollection([ 'droidgunship', { cargoCapacity: 0, - consumables: 'none', + consumables: null, costInCredits: 60000, crew: 0, films: [3], diff --git a/src/defaultPlaygroundTabs.ts b/src/defaultPlaygroundTabs.ts index be8e14b..9d88ca2 100644 --- a/src/defaultPlaygroundTabs.ts +++ b/src/defaultPlaygroundTabs.ts @@ -1,81 +1,153 @@ import type { MiddlewareOptions } from '@apollographql/graphql-playground-html'; const isDev = process.platform === 'win32' || process.platform === 'darwin'; +const endpoint = isDev ? `http://localhost:${process.env.PORT || 8293}` : 'https://swapi.skyra.pw/'; const defaultTabs: NonNullable = [ { - name: 'Person Details simple', - endpoint: isDev ? `http://localhost:${process.env.PORT || 8293}` : 'https://swapi.skyra.pw/', + name: 'Full Film Details', + endpoint, query: [ '{', - '\tgetPerson(person: lukeskywalker) {', - '\t\tbirthYear', - '\t\teyeColor', - '\t\tfilms { name }', - '\t\tgender', - '\t\thairColor', - '\t\theight', - '\t\thomeworld', - '\t\tmass', - '\t\tname', - '\t\tskinColor', - '\t\tspecies { name }', - '\t\tstarships { name }', - '\t\tvehciles { name }', + '\tgetFilm(film: 4) {', + '\t\tdirector', + '\t\tcharacters {', + '\t\t\tbirthYear', + '\t\t\teyeColors', + '\t\t\tgender', + '\t\t\thairColors', + '\t\t\theight', + '\t\t\tmass', + '\t\t\tname', + '\t\t\tskinColors', + '\t\t}', + '\t\tplanets {', + '\t\t\tclimates', + '\t\t\tdiameter', + '\t\t\tgravity', + '\t\t\tname', + '\t\t\torbitalPeriod', + '\t\t\tpopulation', + '\t\t\trotationPeriod', + '\t\t\tsurfaceWater', + '\t\t\tterrains', + '\t\t}', + '\t\tspecies {', + '\t\t\taverageHeight', + '\t\t\taverageLifespan', + '\t\t\tclassification', + '\t\t\tdesignation', + '\t\t\teyeColors', + '\t\t\thairColors', + '\t\t\tlanguage', + '\t\t\tname', + '\t\t\tskinColors', + '\t\t}', + '\t\tstarships {', + '\t\t\tcargoCapacity', + '\t\t\tconsumables', + '\t\t\tcostInCredits', + '\t\t\tcrew', + '\t\t\thyperdriveRating', + '\t\t\tlength', + '\t\t\tmanufacturers', + '\t\t\tmaxAtmospheringSpeed', + '\t\t\tMGLT', + '\t\t\tmodel', + '\t\t\tname', + '\t\t\tpassengers', + '\t\t\tstarshipClass', + '\t\t}', + '\t\tvehicles {', + '\t\t\tcargoCapacity', + '\t\t\tconsumables', + '\t\t\tcostInCredits', + '\t\t\tcrew', + '\t\t\tlength', + '\t\t\tmanufacturers', + '\t\t\tmaxAtmospheringSpeed', + '\t\t\tmodel', + '\t\t\tname', + '\t\t\tpassengers', + '\t\t\tvehicleClass', + '\t\t}', '\t}', - '}' + '}', + '' ].join('\n') }, { name: 'Person Details with variables', - endpoint: isDev ? `http://localhost:${process.env.PORT || 8293}` : 'https://swapi.skyra.pw/', + endpoint, variables: ['{', '\t"person": "lukeskywalker"', '}'].join('\n'), query: [ - 'query($person: People!) {', + 'query($person: StarWarsPeople!) {', '\tgetPerson(person: $person) {', '\t\tbirthYear', - '\t\teyeColor', - '\t\tfilms { name }', + '\t\teyeColors', + '\t\tfilms {', + '\t\t\ttitle', + '\t\t}', '\t\tgender', - '\t\thairColor', + '\t\thairColors', '\t\theight', - '\t\thomeworld', + '\t\thomeworld {', + '\t\t\tname', + '\t\t}', '\t\tmass', '\t\tname', - '\t\tskinColor', - '\t\tspecies { name }', - '\t\tstarships { name }', - '\t\tvehciles { name }', + '\t\tskinColors', + '\t\tspecies {', + '\t\t\tname', + '\t\t}', + '\t\tstarships {', + '\t\t\tname', + '\t\t}', + '\t\tvehicles {', + '\t\t\tname', + '\t\t}', '\t}', - '}' + '}', + '' ].join('\n') }, { name: 'Person with fragments and variables', - endpoint: isDev ? `http://localhost:${process.env.PORT || 8293}` : 'https://swapi.skyra.pw/', + endpoint, variables: ['{', '\t"person": "lukeskywalker"', '}'].join('\n'), query: [ - 'fragment data on People {', - '\t\tbirthYear', - '\t\teyeColor', - '\t\tfilms { name }', - '\t\tgender', - '\t\thairColor', - '\t\theight', - '\t\thomeworld', - '\t\tmass', + 'fragment data on Person {', + '\tbirthYear', + '\teyeColors', + '\tfilms {', + '\t\ttitle', + '\t}', + '\tgender', + '\thairColors', + '\theight', + '\thomeworld {', + '\t\tname', + '\t}', + '\tmass', + '\tname', + '\tskinColors', + '\tspecies {', + '\t\tname', + '\t}', + '\tstarships {', + '\t\tname', + '\t}', + '\tvehicles {', '\t\tname', - '\t\tskinColor', - '\t\tspecies { name }', - '\t\tstarships { name }', - '\t\tvehciles { name }', + '\t}', '}', '', - 'query($person: People!) {', + 'query($person: StarWarsPeople!) {', '\tgetPerson(person: $person) {', '\t\t...data', '\t}', - '}' + '}', + '' ].join('\n') } ]; diff --git a/src/scalars/GraphQLLong.ts b/src/scalars/GraphQLLong.ts new file mode 100644 index 0000000..914f62e --- /dev/null +++ b/src/scalars/GraphQLLong.ts @@ -0,0 +1,41 @@ +import { GraphQLScalarType, Kind, ValueNode } from 'graphql'; + +const MAX_LONG = Number.MAX_SAFE_INTEGER; + +const MIN_LONG = Number.MIN_SAFE_INTEGER; + +function coerceLong(value: unknown): number { + if (value === '') { + throw new TypeError('Long cannot represent non 52-bit signed integer value: (empty string)'); + } + + const num = Number(value); + + if (num === Infinity || (num <= MAX_LONG && num >= MIN_LONG)) { + if (num < 0) { + return Math.ceil(num); + } + return Math.floor(num); + } + + throw new TypeError(`Long cannot represent non 52-bit signed integer value: ${String(value)}`); +} + +function parseLiteral(ast: ValueNode) { + if (ast.kind === Kind.INT) { + const num = parseInt(ast.value, 10); + if (num <= MAX_LONG && num >= MIN_LONG) { + return num; + } + } + + return null; +} + +export default new GraphQLScalarType({ + name: 'Long', + description: 'A 52-bit integer', + serialize: coerceLong, + parseValue: coerceLong, + parseLiteral +}); diff --git a/src/server.ts b/src/server.ts index a145fb0..3b99771 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,10 +1,14 @@ -import { films } from '#arguments/FilmsArgs'; import { people } from '#arguments/PersonArgs'; import { planets } from '#arguments/PlanetArgs'; import { species } from '#arguments/SpeciesArgs'; import { starships } from '#arguments/StarshipArgs'; import { vehicles } from '#arguments/VehicleArgs'; import FilmResolver from '#resolvers/FilmResolver'; +import PersonResolver from '#resolvers/PersonResolver'; +import PlanetResolver from '#resolvers/PlanetResolver'; +import SpeciesResolver from '#resolvers/SpeciesResolver'; +import StarshipResolver from '#resolvers/StarshipResolver'; +import VehicleResolver from '#resolvers/VehicleResolver'; import tabs from '#root/defaultPlaygroundTabs'; import { ApolloServer } from 'apollo-server-koa'; import type { GraphQLSchema } from 'graphql'; @@ -12,38 +16,33 @@ import Koa from 'koa'; import { buildSchemaSync, registerEnumType } from 'type-graphql'; export const buildGqlSchema = (): GraphQLSchema => { - registerEnumType(films, { - name: 'Films', - description: 'The Star Wars films' - }); - registerEnumType(people, { - name: 'People', + name: 'StarWarsPeople', description: 'The people in Star Wars' }); registerEnumType(planets, { - name: 'Planets', + name: 'StarWarsPlanets', description: 'The planets in Star War' }); registerEnumType(species, { - name: 'Species', + name: 'StarWarsSpecies', description: 'The species in Star Wars' }); registerEnumType(starships, { - name: 'Starships', + name: 'StarWarsStarships', description: 'The starships in Star Wars' }); registerEnumType(vehicles, { - name: 'Vehicles', + name: 'StarWarsVehicles', description: 'The vehicles in Star Wars' }); return buildSchemaSync({ - resolvers: [FilmResolver], + resolvers: [FilmResolver, PersonResolver, PlanetResolver, SpeciesResolver, StarshipResolver, VehicleResolver], dateScalarMode: 'isoDate' }); }; diff --git a/src/services/FilmService.ts b/src/services/FilmService.ts index 6e9db6b..24c04c8 100644 --- a/src/services/FilmService.ts +++ b/src/services/FilmService.ts @@ -1,7 +1,17 @@ import FilmArgs from '#arguments/FilmsArgs'; import FuzzyFilmArgs from '#arguments/FuzzyArgs/FuzzyFilmArgs'; import films from '#assets/films'; +import PersonService from '#services/PersonService'; +import PlanetService from '#services/PlanetService'; +import SpeciesService from '#services/SpeciesService'; +import StarshipService from '#services/StarshipService'; +import VehicleService from '#services/VehicleService'; import Film from '#structures/Film'; +import type Person from '#structures/Person'; +import type Planet from '#structures/Planet'; +import type Species from '#structures/Species'; +import type Starship from '#structures/Starship'; +import type Vehicle from '#structures/Vehicle'; import { addPropertyToClass } from '#utils/addPropertyToClass'; import FuzzySearch from '#utils/FuzzySearch'; import type GraphQLSet from '#utils/GraphQLSet'; @@ -11,26 +21,91 @@ import type Fuse from 'fuse.js'; import { Args } from 'type-graphql'; export default class FilmService { + private personService: PersonService; + private planetService: PlanetService; + private speciesService: SpeciesService; + private starshipService: StarshipService; + private vehicleService: VehicleService; + + public constructor() { + this.personService = new PersonService(); + this.planetService = new PlanetService(); + this.speciesService = new SpeciesService(); + this.starshipService = new StarshipService(); + this.vehicleService = new VehicleService(); + } + public getByEpisodeNumber(@Args(() => FilmArgs) { film }: FilmArgs): StarWarsApi.Film | undefined { return films.get(film); } - // TODO: add parameter to prevent deep-nesting - // TODO: ensure requestedFields supports deep-nesting - public mapFilmDataToFilmGraphQL(data: StarWarsApi.Film, requestedFields: GraphQLSet): Film { + public mapFilmDataToFilmGraphQL(data: StarWarsApi.Film, requestedFields: GraphQLSet, isReferencedCall = false): Film { const film = new Film(); - addPropertyToClass(film, 'characters', data.characters, requestedFields); // TODO: map to actual GraphQL Class + const characters: Person[] = []; + const planets: Planet[] = []; + const species: Species[] = []; + const starships: Starship[] = []; + const vehicles: Vehicle[] = []; + + if (!isReferencedCall) { + if (requestedFields.has('characters')) { + const characterFields = requestedFields.filterStartsWith>('characters.'); + + for (const character of data.characters) { + const personData = this.personService.getByPersonName({ person: character })!; + characters.push(this.personService.mapPersonDataToPersonGraphQL(personData, characterFields, true)); + } + } + + if (requestedFields.has('planets')) { + const planetFields = requestedFields.filterStartsWith>('planets.'); + + for (const planet of data.planets) { + const planetData = this.planetService.getByPlanetName({ planet })!; + planets.push(this.planetService.mapPlanetDataToPlanetGraphQL(planetData, planetFields, true)); + } + } + + if (requestedFields.has('species')) { + const speciesFields = requestedFields.filterStartsWith>('species.'); + + for (const filmSpecies of data.species) { + const speciesData = this.speciesService.getBySpeciesName({ species: filmSpecies })!; + species.push(this.speciesService.mapSpeciesDataToSpeciesGraphQL(speciesData, speciesFields, true)); + } + } + + if (requestedFields.has('starships')) { + const starshipFields = requestedFields.filterStartsWith>('starships.'); + + for (const starship of data.starships) { + const starshipData = this.starshipService.getByStarshipName({ starship })!; + starships.push(this.starshipService.mapStarshipDataToStarshipGraphQL(starshipData, starshipFields, true)); + } + } + + if (requestedFields.has('vehicles')) { + const vehicleFields = requestedFields.filterStartsWith>('vehicles.'); + + for (const vehicle of data.vehicles) { + const vehicleData = this.vehicleService.getByVehicleName({ vehicle })!; + vehicles.push(this.vehicleService.mapVehicleDataToVehicleGraphQL(vehicleData, vehicleFields, true)); + } + } + } + + addPropertyToClass(film, 'characters', characters, requestedFields); addPropertyToClass(film, 'director', data.director, requestedFields); addPropertyToClass(film, 'episodeId', data.episodeId, requestedFields); addPropertyToClass(film, 'openingCrawl', data.openingCrawl, requestedFields); - addPropertyToClass(film, 'planets', data.planets, requestedFields); // TODO: map to actual GraphQL Class + addPropertyToClass(film, 'planets', planets, requestedFields); addPropertyToClass(film, 'producers', data.producers, requestedFields); addPropertyToClass(film, 'releaseDate', new Date(data.releaseDate), requestedFields); - addPropertyToClass(film, 'species', data.species, requestedFields); // TODO: map to actual GraphQL Class - addPropertyToClass(film, 'starships', data.starships, requestedFields); // TODO: map to actual GraphQL Class + addPropertyToClass(film, 'species', species, requestedFields); + addPropertyToClass(film, 'starships', starships, requestedFields); addPropertyToClass(film, 'title', data.title, requestedFields); - addPropertyToClass(film, 'vehicles', data.vehicles, requestedFields); // TODO: map to actual GraphQL Class + addPropertyToClass(film, 'vehicles', vehicles, requestedFields); return film; } diff --git a/src/services/PersonService.ts b/src/services/PersonService.ts index 4de191c..c14ca46 100644 --- a/src/services/PersonService.ts +++ b/src/services/PersonService.ts @@ -17,13 +17,13 @@ export default class PersonService { // TODO: add parameter to prevent deep-nesting // TODO: ensure requestedFields supports deep-nesting - public mapPersonDataToPersonGraphQL(data: StarWarsApi.Person, requestedFields: GraphQLSet): Person { + public mapPersonDataToPersonGraphQL(data: StarWarsApi.Person, requestedFields: GraphQLSet, _isReferencedCall = false): Person { // const film = new Film(); const person = new Person(); addPropertyToClass(person, 'birthYear', data.birthYear, requestedFields); addPropertyToClass(person, 'eyeColors', data.eyeColors, requestedFields); - addPropertyToClass(person, 'films', data.films, requestedFields); // TODO: map to actual GraphQL Class + // addPropertyToClass(person, 'films', data.films, requestedFields); // TODO: map to actual GraphQL Class addPropertyToClass(person, 'gender', data.gender, requestedFields); addPropertyToClass(person, 'hairColors', data.hairColors, requestedFields); addPropertyToClass(person, 'height', data.height, requestedFields); diff --git a/src/services/PlanetService.ts b/src/services/PlanetService.ts index 56165f5..05e966e 100644 --- a/src/services/PlanetService.ts +++ b/src/services/PlanetService.ts @@ -17,12 +17,12 @@ export default class PlanetService { // TODO: add parameter to prevent deep-nesting // TODO: ensure requestedFields supports deep-nesting - public mapPlanetDataToPlanetGraphQL(data: StarWarsApi.Planet, requestedFields: GraphQLSet): Planet { + public mapPlanetDataToPlanetGraphQL(data: StarWarsApi.Planet, requestedFields: GraphQLSet, _isReferencedCall = false): Planet { const planet = new Planet(); addPropertyToClass(planet, 'climates', data.climate, requestedFields); addPropertyToClass(planet, 'diameter', data.diameter, requestedFields); - addPropertyToClass(planet, 'films', data.films, requestedFields); // TODO: map to actual GraphQL Class + // addPropertyToClass(planet, 'films', data.films, requestedFields); // TODO: map to actual GraphQL Class addPropertyToClass(planet, 'gravity', data.gravity, requestedFields); addPropertyToClass(planet, 'name', data.name, requestedFields); addPropertyToClass(planet, 'orbitalPeriod', data.orbitalPeriod, requestedFields); diff --git a/src/services/SpeciesService.ts b/src/services/SpeciesService.ts index 94de850..39d1d36 100644 --- a/src/services/SpeciesService.ts +++ b/src/services/SpeciesService.ts @@ -17,7 +17,7 @@ export default class SpeciesService { // TODO: add parameter to prevent deep-nesting // TODO: ensure requestedFields supports deep-nesting - public mapSpeciesDataToSpeciesGraphQL(data: StarWarsApi.Species, requestedFields: GraphQLSet): Species { + public mapSpeciesDataToSpeciesGraphQL(data: StarWarsApi.Species, requestedFields: GraphQLSet, _isReferencedCall = false): Species { const species = new Species(); addPropertyToClass(species, 'averageHeight', data.averageHeight, requestedFields); @@ -25,7 +25,7 @@ export default class SpeciesService { addPropertyToClass(species, 'classification', data.classification, requestedFields); addPropertyToClass(species, 'designation', data.designation, requestedFields); addPropertyToClass(species, 'eyeColors', data.eyeColors, requestedFields); - addPropertyToClass(species, 'films', data.films, requestedFields); // TODO: map to actual GraphQL Class + // addPropertyToClass(species, 'films', data.films, requestedFields); // TODO: map to actual GraphQL Class addPropertyToClass(species, 'hairColors', data.hairColors, requestedFields); addPropertyToClass(species, 'homeworld', data.homeworld, requestedFields); // TODO: map to actual GraphQL Class addPropertyToClass(species, 'language', data.language, requestedFields); diff --git a/src/services/StarshipService.ts b/src/services/StarshipService.ts index 4dd6f3d..eb0c849 100644 --- a/src/services/StarshipService.ts +++ b/src/services/StarshipService.ts @@ -10,21 +10,25 @@ import Util from '#utils/util'; import type Fuse from 'fuse.js'; import { Args } from 'type-graphql'; -export default class SpeciesService { +export default class StarshipService { public getByStarshipName(@Args(() => StarshipArgs) { starship }: StarshipArgs): StarWarsApi.Starship | undefined { return starships.get(starship); } // TODO: add parameter to prevent deep-nesting // TODO: ensure requestedFields supports deep-nesting - public mapStarshipDataToStarshipGraphQL(data: StarWarsApi.Starship, requestedFields: GraphQLSet): Starship { + public mapStarshipDataToStarshipGraphQL( + data: StarWarsApi.Starship, + requestedFields: GraphQLSet, + _isReferencedCall = false + ): Starship { const starship = new Starship(); addPropertyToClass(starship, 'cargoCapacity', data.cargoCapacity, requestedFields); addPropertyToClass(starship, 'consumables', data.consumables, requestedFields); addPropertyToClass(starship, 'costInCredits', data.costInCredits, requestedFields); addPropertyToClass(starship, 'crew', data.crew, requestedFields); - addPropertyToClass(starship, 'films', data.films, requestedFields); // TODO: map to actual GraphQL Class + // addPropertyToClass(starship, 'films', data.films, requestedFields); // TODO: map to actual GraphQL Class addPropertyToClass(starship, 'hyperdriveRating', data.hyperdriveRating, requestedFields); addPropertyToClass(starship, 'length', data.length, requestedFields); addPropertyToClass(starship, 'manufacturers', data.manufacturers, requestedFields); diff --git a/src/services/VehicleService.ts b/src/services/VehicleService.ts index bc07762..c9e2d28 100644 --- a/src/services/VehicleService.ts +++ b/src/services/VehicleService.ts @@ -17,7 +17,7 @@ export default class VehicleService { // TODO: add parameter to prevent deep-nesting // TODO: ensure requestedFields supports deep-nesting - public mapVehicleDataToVehicleGraphQL(data: StarWarsApi.Vehicle, requestedFields: GraphQLSet): Vehicle { + public mapVehicleDataToVehicleGraphQL(data: StarWarsApi.Vehicle, requestedFields: GraphQLSet, _isReferencedCall = false): Vehicle { const vehicle = new Vehicle(); addPropertyToClass(vehicle, 'cargoCapacity', data.cargoCapacity, requestedFields); diff --git a/src/structures/Planet.ts b/src/structures/Planet.ts index 1475b1b..53d5b20 100644 --- a/src/structures/Planet.ts +++ b/src/structures/Planet.ts @@ -1,6 +1,7 @@ +import GraphQLLong from '#scalars/GraphQLLong'; import Film from '#structures/Film'; import Person from '#structures/Person'; -import { Field, Int, ObjectType } from 'type-graphql'; +import { Field, Float, Int, ObjectType } from 'type-graphql'; @ObjectType({ description: 'A planet that appeared in Star Wars' }) export default class Planet { @@ -13,7 +14,7 @@ export default class Planet { @Field(() => [Film], { description: 'The films in which this planet was featured' }) public films!: Film[]; - @Field(() => Int, { + @Field(() => Float, { nullable: true, description: 'A number denoting the gravity of this planet, were "1" is standard gravity, "2" is twice standard gravity and "0.5" is half standard gravity. This is null for planets for which the gravity is unknown.' @@ -30,7 +31,7 @@ export default class Planet { }) public orbitalPeriod?: number | null; - @Field(() => Int, { + @Field(() => GraphQLLong, { nullable: true, description: 'The average population of sentient beings inhabiting this planet. Null if population is unknown.' }) diff --git a/src/structures/Species.ts b/src/structures/Species.ts index dbe8771..2f0986e 100644 --- a/src/structures/Species.ts +++ b/src/structures/Species.ts @@ -1,3 +1,4 @@ +import GraphQLLong from '#scalars/GraphQLLong'; import Film from '#structures/Film'; import Person from '#structures/Person'; import Planet from '#structures/Planet'; @@ -8,7 +9,7 @@ export default class Species { @Field(() => Int, { nullable: true, description: 'The average heigh of this species, if specified' }) public averageHeight?: number | null; - @Field(() => Int, { nullable: true, description: 'The average lifespan of this species, if specified' }) + @Field(() => GraphQLLong, { nullable: true, description: 'The average lifespan of this species, if specified' }) public averageLifespan?: number | null; @Field(() => String, { nullable: true, description: 'The classification of this species, such as "mammal" or "reptile"' }) diff --git a/src/structures/Starship.ts b/src/structures/Starship.ts index 25ff6d2..0e2373e 100644 --- a/src/structures/Starship.ts +++ b/src/structures/Starship.ts @@ -1,10 +1,11 @@ +import GraphQLLong from '#scalars/GraphQLLong'; import Film from '#structures/Film'; import Person from '#structures/Person'; -import { Field, Int, ObjectType } from 'type-graphql'; +import { Field, Float, Int, ObjectType } from 'type-graphql'; @ObjectType({ description: 'A starship that appears in Star Wars' }) export default class Starship { - @Field(() => Int, { nullable: true, description: 'The maximum cargo capacity of this starship in kilograms' }) + @Field(() => GraphQLLong, { nullable: true, description: 'The maximum cargo capacity of this starship in kilograms' }) public cargoCapacity?: number | null; @Field(() => String, { @@ -13,7 +14,7 @@ export default class Starship { }) public consumables?: string | null; - @Field(() => Int, { nullable: true, description: 'The cost of this starship, new, in galactic credits' }) + @Field(() => GraphQLLong, { nullable: true, description: 'The cost of this starship, new, in galactic credits' }) public costInCredits?: number | null; @Field(() => Int, { nullable: true, description: 'The number of personnel needed to run or pilot this starship' }) @@ -22,10 +23,10 @@ export default class Starship { @Field(() => [Film], { description: 'The films this starship appeared in' }) public films!: Film[]; - @Field(() => Int, { nullable: true, description: 'The class of hyperdrive this starship has' }) + @Field(() => Float, { nullable: true, description: 'The class of hyperdrive this starship has' }) public hyperdriveRating?: number | null; - @Field(() => Int, { description: 'The length of this starship in meters' }) + @Field(() => Float, { description: 'The length of this starship in meters' }) public length!: number; @Field(() => [String], { description: 'An array of manufacturers of this starship' }) diff --git a/src/structures/Vehicle.ts b/src/structures/Vehicle.ts index 0405a35..c5c0ec5 100644 --- a/src/structures/Vehicle.ts +++ b/src/structures/Vehicle.ts @@ -1,5 +1,5 @@ import Person from '#structures/Person'; -import { Field, Int, ObjectType } from 'type-graphql'; +import { Field, Float, Int, ObjectType } from 'type-graphql'; @ObjectType({ description: 'A vehicle that appeared in Star Wars' }) export default class Vehicle { @@ -7,9 +7,11 @@ export default class Vehicle { public cargoCapacity!: number; @Field(() => String, { - description: 'The maximum length of time that this vehicle can provide consumables for its entire crew without having to resupply' + nullable: true, + description: + 'The maximum length of time that this vehicle can provide consumables for its entire crew without having to resupply. Null if unknown or unspecified.' }) - public consumables?: string; + public consumables?: string | null; @Field(() => Int, { nullable: true, description: 'The cost of this vehicle, new, in galactic credits' }) public costInCredits?: number | null; @@ -17,7 +19,7 @@ export default class Vehicle { @Field(() => Int, { description: 'The number of personnel needed to run or pilot this vehicle' }) public crew!: number; - @Field(() => Int, { nullable: true, description: 'The length of this vehicle in meters' }) + @Field(() => Float, { nullable: true, description: 'The length of this vehicle in meters' }) public length?: number | null; @Field(() => [String], { nullable: true, description: 'An array of manufacturers of this vehicle' }) diff --git a/src/tsconfig.json b/src/tsconfig.json index 0d3209d..76f7db1 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -10,6 +10,7 @@ "#jsonAssets/*.json": ["./assets/*.json"], "#dexdata/*": ["./assets/pokedex-data/*"], "#resolvers/*": ["./resolvers/*"], + "#scalars/*": ["./scalars/*"], "#services/*": ["./services/*"], "#structures/*": ["./structures/*"], "#utils/*": ["./utils/*"], diff --git a/src/utils/GraphQLSet.ts b/src/utils/GraphQLSet.ts index fc9d34f..9759e48 100644 --- a/src/utils/GraphQLSet.ts +++ b/src/utils/GraphQLSet.ts @@ -26,7 +26,7 @@ export default class GraphQLSet extends Set { * @param fn The function to test with (should return boolean) * @param [thisArg] Value to use as `this` when executing function * @returns {GraphQLSet} - * @example graphqlset.filter((v) => v.startsWith('parentKey')); + * @example graphqlSet.filter((v) => v.startsWith('parentKey')); */ public filter(fn: (value: V, set: this) => boolean): this; public filter(fn: (value: V, set: this) => boolean): R; @@ -43,5 +43,27 @@ export default class GraphQLSet extends Set { return results; } + /** + * Similar to {@link GraphQLSet.filter}, but instead of receiving a predicate callback, + * this instead receives a string that will be checked through a `.startsWith` call. + * If the value starts with the given {@link checkString} then that {@link checkString} + * is removed from the start of the value and the remaining value is added to the result. + * + * @param checkString The string that will be used in the `.startsWith` check + * @returns {GraphQLSet} + * @example graphqlSet.filter('parentKey.'); + */ + public filterStartsWith>(checkString: string): R { + const results = new this.constructor[Symbol.species]() as R; + + for (const val of this) { + if (typeof val === 'string' && val.startsWith(checkString)) { + results.add(val.replace(checkString, '') as unknown as V); + } + } + + return results; + } + public static readonly default: typeof GraphQLSet = GraphQLSet; } diff --git a/src/utils/star-wars.d.ts b/src/utils/star-wars.d.ts index 786a40e..fd6cb17 100644 --- a/src/utils/star-wars.d.ts +++ b/src/utils/star-wars.d.ts @@ -33,10 +33,10 @@ declare namespace StarWarsApi { climate: string[] | null; diameter: number | null; films: number[]; - gravity: string | null; + gravity: number | null; name: string; orbitalPeriod: string | null; - population: string | null; + population: number | null; residents: string[]; rotationPeriod: string | null; surfaceWater: string | null; @@ -62,7 +62,7 @@ declare namespace StarWarsApi { cargoCapacity: number | null; consumables: string | null; costInCredits: number | null; - crew: string | null; + crew: number | null; films: number[]; hyperdriveRating: number | null; length: number;