Skip to content

Commit

Permalink
feat(api): Add 2014 version to prepare for 2024 version (#636)
Browse files Browse the repository at this point in the history
* feat(models): All current models are switched to the `2014-` prefixed ones

* refactor(models): Move all current modesl under 2014 folder

* feat(routes): Add in 2014 routes and move controllers

* Now with working tests

* Setup graphql endpoints for 2014

* Allow for versioned schemas

* Swagger updates

* Add versioning readme
  • Loading branch information
bagelbits authored Jan 6, 2025
1 parent 5f5e7f3 commit b09c32a
Show file tree
Hide file tree
Showing 346 changed files with 3,922 additions and 1,789 deletions.
42 changes: 23 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,37 @@ Then back over here in the 5e-srd-api repo, in the file `docker-compose.yml`, yo
## Making API Requests

Make API requests by using the root address:
`http://localhost:3000/api/`
`http://localhost:3000/api/2014`

You should get a response with the available endpoints for the root:

```json
{
"ability-scores": "/api/ability-scores",
"classes": "/api/classes",
"conditions": "/api/conditions",
"damage-types": "/api/damage-types",
"equipment-categories": "/api/equipment-categories",
"equipment": "/api/equipment",
"features": "/api/features",
"languages": "/api/languages",
"magic-schools": "/api/magic-schools",
"monsters": "/api/monsters",
"proficiencies": "/api/proficiencies",
"races": "/api/races",
"skills": "/api/skills",
"spells": "/api/spells",
"subclasses": "/api/subclasses",
"subraces": "/api/subraces",
"traits": "/api/traits",
"weapon-properties": "/api/weapon-properties"
"ability-scores": "/api/2014/ability-scores",
"classes": "/api/2014/classes",
"conditions": "/api/2014/conditions",
"damage-types": "/api/2014/damage-types",
"equipment-categories": "/api/2014/equipment-categories",
"equipment": "/api/2014/equipment",
"features": "/api/2014/features",
"languages": "/api/2014/languages",
"magic-schools": "/api/2014/magic-schools",
"monsters": "/api/2014/monsters",
"proficiencies": "/api/2014/proficiencies",
"races": "/api/2014/races",
"skills": "/api/2014/skills",
"spells": "/api/2014/spells",
"subclasses": "/api/2014/subclasses",
"subraces": "/api/2014/subraces",
"traits": "/api/2014/traits",
"weapon-properties": "/api/2014/weapon-properties"
}
```

### Versioning

The API is versioned by release years of the SRD. Currently only `/api/2014` is available. The next version will be `/api/2024`.

## Working with a local image of 5e Database

If you are working on a feature which requires changes to both this repo, _and_ the 5e-database repo, it is useful to know how to connect the former to the latter for testing purposes. A simple process for doing so is as follows:
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3.8'

services:
db:
image: ghcr.io/5e-bits/5e-database:latest
Expand Down
1 change: 1 addition & 0 deletions jest.config.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const integrationConfig: Config.InitialOptions = {
displayName: 'Integration Tests',
testRegex: '\\.itest\\.(js|ts)$',
silent: true,
maxWorkers: '50%', // Use 50% of available CPUs
};

console.log('RUNNING INTEGRATION TESTS');
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"gen-postman": "npm run bundle-swagger && portman --cliOptionsFile portman-cli.json",
"test": "npm run test:unit && npm run test:integration:local",
"test:unit": "node --experimental-vm-modules node_modules/jest/bin/jest.js -c jest.config.unit.ts",
"test:integration": "node --experimental-vm-modules node_modules/jest/bin/jest.js -c jest.config.integration.ts --detectOpenHandles --forceExit",
"test:integration": "node --max-old-space-size=4096 --experimental-vm-modules node_modules/jest/bin/jest.js -c jest.config.integration.ts --detectOpenHandles --forceExit --runInBand",
"test:integration:local": "docker compose pull && docker compose build && docker compose run --use-aliases api npm run test:integration"
},
"dependencies": {
Expand Down
4 changes: 4 additions & 0 deletions src/controllers/api/2014/abilityScoreController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import AbilityScore from '../../../models/2014/abilityScore/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(AbilityScore);
4 changes: 4 additions & 0 deletions src/controllers/api/2014/alignmentController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Alignment from '../../../models/2014/alignment/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(Alignment);
4 changes: 4 additions & 0 deletions src/controllers/api/2014/backgroundController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Background from '../../../models/2014/background/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(Background);
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Request, Response, NextFunction } from 'express';

import { ResourceList, escapeRegExp } from '../../util/index.js';

import Class from '../../models/class/index.js';
import Feature from '../../models/feature/index.js';
import Level from '../../models/level/index.js';
import Proficiency from '../../models/proficiency/index.js';
import SimpleController from '../simpleController.js';
import Spell from '../../models/spell/index.js';
import Subclass from '../../models/subclass/index.js';
import { ResourceList, escapeRegExp } from '../../../util/index.js';

import Class from '../../../models/2014/class/index.js';
import Feature from '../../../models/2014/feature/index.js';
import Level from '../../../models/2014/level/index.js';
import Proficiency from '../../../models/2014/proficiency/index.js';
import SimpleController from '../../simpleController.js';
import Spell from '../../../models/2014/spell/index.js';
import Subclass from '../../../models/2014/subclass/index.js';

const simpleController = new SimpleController(Class);
interface ShowLevelsForClassQuery {
Expand Down
4 changes: 4 additions & 0 deletions src/controllers/api/2014/conditionController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Condition from '../../../models/2014/condition/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(Condition);
4 changes: 4 additions & 0 deletions src/controllers/api/2014/damageTypeController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import DamageType from '../../../models/2014/damageType/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(DamageType);
4 changes: 4 additions & 0 deletions src/controllers/api/2014/equipmentCategoryController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import EquipmentCategory from '../../../models/2014/equipmentCategory/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(EquipmentCategory);
4 changes: 4 additions & 0 deletions src/controllers/api/2014/equipmentController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Equipment from '../../../models/2014/equipment/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(Equipment);
4 changes: 4 additions & 0 deletions src/controllers/api/2014/featController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Feat from '../../../models/2014/feat/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(Feat);
4 changes: 4 additions & 0 deletions src/controllers/api/2014/featureController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Feature from '../../../models/2014/feature/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(Feature);
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextFunction, Request, Response } from 'express';

import { GetObjectCommand } from '@aws-sdk/client-s3';
import { awsS3Client } from '../../util/index.js';
import { awsS3Client } from '../../../util/index.js';

const show = async (req: Request, res: Response, next: NextFunction) => {
try {
Expand Down
4 changes: 4 additions & 0 deletions src/controllers/api/2014/languageController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Language from '../../../models/2014/language/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(Language);
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from 'express';

import { ResourceList, escapeRegExp, redisClient } from '../../util/index.js';
import MagicItem from '../../models/magicItem/index.js';
import { ResourceList, escapeRegExp, redisClient } from '../../../util/index.js';
import MagicItem from '../../../models/2014/magicItem/index.js';

interface IndexQuery {
name?: { $regex: RegExp };
Expand Down
4 changes: 4 additions & 0 deletions src/controllers/api/2014/magicSchoolController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import MagicSchool from '../../../models/2014/magicSchool/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(MagicSchool);
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Request, Response, NextFunction } from 'express';

import { ResourceList, escapeRegExp, redisClient } from '../../util/index.js';
import { ResourceList, escapeRegExp, redisClient } from '../../../util/index.js';

import Monster from '../../models/monster/index.js';
import Monster from '../../../models/2014/monster/index.js';

interface IndexQuery {
name?: { $regex: RegExp };
Expand All @@ -22,7 +22,7 @@ export const index = async (req: Request, res: Response, next: NextFunction) =>

const challengeRating = req.query.challenge_rating as string[];
searchQueries.challenge_rating = {
$in: challengeRating.map(Number).filter(item => !isNaN(item)),
$in: challengeRating.map(Number).filter((item) => !isNaN(item)),
};
}

Expand Down
4 changes: 4 additions & 0 deletions src/controllers/api/2014/proficiencyController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Proficiency from '../../../models/2014/proficiency/index.js';
import SimpleController from '../../simpleController.js';

export default new SimpleController(Proficiency);
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Request, Response, NextFunction } from 'express';

import Proficiency from '../../models/proficiency/index.js';
import Race from '../../models/race/index.js';
import { ResourceList } from '../../util/data.js';
import SimpleController from '../simpleController.js';
import Subrace from '../../models/subrace/index.js';
import Trait from '../../models/trait/index.js';
import Proficiency from '../../../models/2014/proficiency/index.js';
import Race from '../../../models/2014/race/index.js';
import { ResourceList } from '../../../util/data.js';
import SimpleController from '../../simpleController.js';
import Subrace from '../../../models/2014/subrace/index.js';
import Trait from '../../../models/2014/trait/index.js';

const simpleController = new SimpleController(Race);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from 'express';
import { ResourceList, escapeRegExp, redisClient } from '../../util/index.js';
import { ResourceList, escapeRegExp, redisClient } from '../../../util/index.js';

import Rule from '../../models/rule/index.js';
import Rule from '../../../models/2014/rule/index.js';

interface IndexQuery {
name?: { $regex: RegExp };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from 'express';
import { ResourceList, escapeRegExp, redisClient } from '../../util/index.js';
import { ResourceList, escapeRegExp, redisClient } from '../../../util/index.js';

import RuleSection from '../../models/ruleSection/index.js';
import RuleSection from '../../../models/2014/ruleSection/index.js';
interface IndexQuery {
name?: { $regex: RegExp };
desc?: { $regex: RegExp };
Expand Down
4 changes: 4 additions & 0 deletions src/controllers/api/2014/skillController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import SimpleController from '../../simpleController.js';
import Skill from '../../../models/2014/skill/index.js';

export default new SimpleController(Skill);
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Request, Response, NextFunction } from 'express';
import { ResourceList, escapeRegExp, redisClient } from '../../util/index.js';
import { ResourceList, escapeRegExp, redisClient } from '../../../util/index.js';

interface IndexQuery {
name?: { $regex: RegExp };
level?: { $in: string[] };
'school.name'?: { $in: RegExp[] };
}

import Spell from '../../models/spell/index.js';
import Spell from '../../../models/2014/spell/index.js';

export const index = async (req: Request, res: Response, next: NextFunction) => {
try {
Expand All @@ -23,7 +23,7 @@ export const index = async (req: Request, res: Response, next: NextFunction) =>
if (req.query.school !== undefined) {
let schoolRegex;
if (Array.isArray(req.query.school)) {
schoolRegex = req.query.school.map(c => new RegExp(escapeRegExp(c as string), 'i'));
schoolRegex = req.query.school.map((c) => new RegExp(escapeRegExp(c as string), 'i'));
} else {
schoolRegex = [new RegExp(escapeRegExp(req.query.school as string), 'i')];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Request, Response, NextFunction } from 'express';
import Feature from '../../models/feature/index.js';
import Level from '../../models/level/index.js';
import { ResourceList } from '../../util/data.js';
import SimpleController from '../simpleController.js';
import Subclass from '../../models/subclass/index.js';
import Feature from '../../../models/2014/feature/index.js';
import Level from '../../../models/2014/level/index.js';
import { ResourceList } from '../../../util/data.js';
import SimpleController from '../../simpleController.js';
import Subclass from '../../../models/2014/subclass/index.js';

const simpleController = new SimpleController(Subclass);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Request, Response, NextFunction } from 'express';
import Proficiency from '../../models/proficiency/index.js';
import { ResourceList } from '../../util/data.js';
import SimpleController from '../simpleController.js';
import Subrace from '../../models/subrace/index.js';
import Trait from '../../models/trait/index.js';
import Proficiency from '../../../models/2014/proficiency/index.js';
import { ResourceList } from '../../../util/data.js';
import SimpleController from '../../simpleController.js';
import Subrace from '../../../models/2014/subrace/index.js';
import Trait from '../../../models/2014/trait/index.js';

const simpleController = new SimpleController(Subrace);

Expand Down
4 changes: 4 additions & 0 deletions src/controllers/api/2014/traitController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import SimpleController from '../../simpleController.js';
import Trait from '../../../models/2014/trait/index.js';

export default new SimpleController(Trait);
4 changes: 4 additions & 0 deletions src/controllers/api/2014/weaponPropertyController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import SimpleController from '../../simpleController.js';
import WeaponProperty from '../../../models/2014/weaponProperty/index.js';

export default new SimpleController(WeaponProperty);
4 changes: 0 additions & 4 deletions src/controllers/api/abilityScoreController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/alignmentController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/backgroundController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/conditionController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/damageTypeController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/equipmentCategoryController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/equipmentController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/featController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/featureController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/languageController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/magicSchoolController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/proficiencyController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/skillController.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/controllers/api/traitController.ts

This file was deleted.

Loading

0 comments on commit b09c32a

Please sign in to comment.