18 Commits

Author SHA1 Message Date
Tee
aa62e1b6ee Bump patch for doc update 2021-03-23 00:22:41 -04:00
Tee
4b4d4cb901 Add API configuration steps 2021-03-23 00:21:34 -04:00
Tee
aca7f28a93 Update version number 2021-03-22 22:45:29 -04:00
Tee
0bdd1f0def Update minor version 2021-03-22 22:45:05 -04:00
Tee
e0afb2932a Update card and set property docs 2021-03-22 22:43:29 -04:00
Tee
2d7b47efd4 Add deprication notice in README 2021-03-22 22:41:18 -04:00
Tee
f077348af4 Add deprication notices to Meta methods 2021-03-22 22:31:06 -04:00
Tee
21d94dd997 Refactor meta route retrieval and return types 2021-03-22 22:26:08 -04:00
Tee
c5d48dba11 Add set deprication noticess 2021-03-22 22:23:29 -04:00
Tee
4d442f2d81 Add card method deprication notices 2021-03-22 22:23:14 -04:00
Tee
ed55ddc434 Add v2 Migration guide 2021-03-22 22:22:53 -04:00
Tee
9d40a50d80 Install types/node dependency for environment variables 2021-03-22 00:39:43 -04:00
Tee
eedad4f043 Set API key header with environment variable 2021-03-22 00:39:23 -04:00
Tee
47861f3760 Update optional properties and formatting for Card 2021-03-22 00:39:05 -04:00
Tee
3624938ade Update optional properties for card interfaces 2021-03-22 00:38:39 -04:00
82ca4b6626 Merge pull request #20 from PokemonTCG/revert-19-v2-migration
Revert "Add v2 Migration"
2021-03-16 00:24:43 -04:00
76fa13fa12 Revert "Add v2 Migration" 2021-03-16 00:24:25 -04:00
3b3b65e7d0 Merge pull request #19 from acupoftee/v2-migration
Add v2 Migration
2021-03-16 00:22:27 -04:00
40 changed files with 1129 additions and 5951 deletions

View File

@ -1,2 +0,0 @@
node_modules
dist

View File

@ -1,19 +0,0 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"prettier"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"rules": {
"@typescript-eslint/no-empty-interface": 0,
"@typescript-eslint/no-empty-function": 0,
"no-console": 1
}
}

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
node_modules
dist
*.tgz
.idea

View File

@ -1,2 +0,0 @@
node_modules
dist

View File

@ -1,6 +0,0 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": true,
"singleQuote": true
}

157
MIGRATING.md Normal file
View File

@ -0,0 +1,157 @@
# Migrating from v1 to v2
The functions and typings in V2 the SDK have been re-named to improve developer experience.
The guide will provide you with the steps to help you migrate your application.
## Type Changes
Interfaces are no longer prefixed with the letter `I`. **Interfaces in the TypeScript compile are used solely for type-checking purposes.**
Originally, `ICard` and `ISet` existed to be implemented with the `Card` and `Set` classes respectively. Because each function is now an independently exported function,
the TypeScript interfaces can be used as intended, which is to simply describe the shape of the data from the API:
`IQuery` was also changed to `Parameter` to complement the [new parameter syntax](https://docs.pokemontcg.io/#api_v2cards_list) in V2 of the API.
* `ICard` -> `Card`
* `ISet` -> `Set`
* `IAbility` -> `Ability`
* `IResistance` -> `Resistance`
* `IWeakness` -> `Weakness`
* `IAttack` -> `Attack`
* `IQuery` -> `Parameter`
## Function Changes
The API functions are no longer abstracted in classes. Instead, each function is an individual export which still returns
data of type `Card` or `Set` to reduce redundancy in the SDK. The function names were renamed to reveal intent as clearly as possible. This results
in code that is self documenting, and enforces a convention where the API functionality is described
thoroughly for developers.
There is no change in the function return types, nor underlying functionality. Functions will continue to return a generic promised based on the resource (i.e. `Promise<Card>`, `Promise<Set>`).
It is recommended to refactor the function names with the find-and-replace tool in your IDE or text editor in order for your project
to be compatible with V2 of the SDK.
## Card Functions
### `PokemonTCG.Card.all()` -> `PokemonTCG.getAllCards()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
PokemonTCG.Card.all();
// V2
PokemonTCG.getAllCards();
```
### `PokemonTCG.Card.find()` -> `PokemonTCG.findCardByID()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
PokemonTCG.Card.find('xy7-54').then((card: PokemonTCG.Card) => {
console.log(card.name) // Gardevoir
});
// V2
PokemonTCG.findCardByID('xy7-54').then((card: PokemonTCG.Card) => {
console.log(card.name) // Gardevoir
});
```
### `PokemonTCG.Card.where()` -> `PokemonTCG.findCardsByQueries()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
const paramsV1: PokemonTCG.IQuery[] = [{ name: 'name', value: 'Gardevoir' }];
PokemonTCG.Card.where(paramsV1).then((cards: PokemonTCG.Card[]) => {
console.log(card[0].name) // Gardevoir
});
// V2
const paramsV2: PokemonTCG.Parameter[] = { q: 'id:xy7-54' };
PokemonTCG.findCardsByQueries(paramsV2).then((cards: PokemonTCG.Card[]) => {
console.log(card[0].name) // Gardevoir
});
```
## Set Functions
### `PokemonTCG.Set.all()` -> `PokemonTCG.getAllSets()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
PokemonTCG.Set.all();
// V2
PokemonTCG.getAllSets();
```
### `PokemonTCG.Set.find()` -> `PokemonTCG.findSetByID()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
PokemonTCG.Set.find('base1').then((set: PokemonTCG.Set) => {
console.log(set.name) // Base
});
// V2
PokemonTCG.findSetByID('base1').then((set: PokemonTCG.Set) => {
console.log(set.name) // Base
});
```
### `PokemonTCG.Set.where()` -> `PokemonTCG.findSetsByQueries()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
const paramsV1: PokemonTCG.IQuery[] = [{ name: 'name', value:'Base' }];
PokemonTCG.Set.where(paramsV1).then((sets: PokemonTCG.Set[]) => {
console.log(sets[0].name) // Base
});
// V2
const paramsV2: PokemonTCG.Parameter[] = { q: 'name:Base' };
PokemonTCG.findSetsByQueries(paramsV2).then((sets: PokemonTCG.Set[]) => {
console.log(sets[0].name) // Base
});
```
## Meta Functions
### `PokemonTCG.Meta.allTypes()` -> `PokemonTCG.getTypes()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
PokemonTCG.Meta.getAllTypes();
// V2
PokemonTCG.getTypes();
```
### `PokemonTCG.Meta.allSupertypes()` -> `PokemonTCG.getSupertypes()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
PokemonTCG.Meta.allSupertypes();
// V2
PokemonTCG.getSupertypes();
```
### `PokemonTCG.Meta.allSubtypes()` -> `PokemonTCG.getSubtypes()`
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
// V1
PokemonTCG.Meta.allSubtypes();
// V2
PokemonTCG.getSubtypes();
```

View File

@ -2,6 +2,9 @@
This is the TypeScript SDK for the [Pokemon TCG API](https://pokemontcg.io).
# V2 Announcement
Version 1 of this SDK is officially depricated. Version 2 stable release this SDK is scheduled to be released on **Friday, April 3rd, 20201**. Version 1 will continue to receive support until then. **See the [migration guide](MIGRATING.md) for steps to update your app to use the latest supported version of the SDK**
## Installation
**npm**
@ -12,35 +15,40 @@ This is the TypeScript SDK for the [Pokemon TCG API](https://pokemontcg.io).
yarn add pokemon-tcg-sdk-typescript
It is recommended to use an API key for version 2 of the API. By default, requests are limited to 20,000/day. Requests are rate limited to 1000 requests a day, and a maximum of 30 per minute.
To use the SDK with an API key, create an account at https://dev.pokemontcg.io to grab an API key. Then set your API key to the environment variable POKEMONTCG_API_KEY in a .env file. Make sure to use this exact environment variable, otherwise the SDK will not be able to read the API key.
## Class Definitions
### Card
```typescript
ability: IAbility;
ancientTrait?: IAncientTrait;
artist: string;
attacks: IAttack[];
convertedRetreatCost: number;
evolvesFrom: string;
hp: string;
id: string;
imageUrl: string;
imageUrlHiRes: string;
name: string;
nationalPokedexNumber: number;
number: string;
rarity: string;
resistances: IResistance[];
retreatCost: string[];
series: string;
set: string;
setCode: string;
subtype: string;
supertype: string;
text: string[];
types: string[];
weaknesses: IWeakness[];
id: string;
name: string;
supertype: string;
subtypes: string[];
hp?: string;
types?: string[];
evolesFrom?: string;
evolvesTo?: string[];
rules?: string[];
ancientTrait?: IAncientTrait;
abilities?: IAbility[];
attacks?: IAttack[];
weaknesses?: IWeakness[];
resistances?: IResistance[];
retreatCost?: string[];
convertedRetreatCost?: number;
set: ISet;
number: string;
artist?: string;
rarity: string;
flavorText?: string;
nationalPokedexNumbers?: number[];
legalities: ILegality;
images: ICardImage;
tcgplayer?: ITCGPlayer;
```
### IAbility
@ -71,17 +79,16 @@ value: string;
### Set
```typescript
code: string;
expandedLegal: boolean;
logoUrl: string;
name: string;
ptcgoCode: string;
releaseDate: string;
series: string;
standardLegal: boolean;
symbolUrl: string;
totalCards: number;
updatedAt: string;
id: string;
images: ISetImage;
legalities: ILegality;
name: string;
printedTotal: number;
ptcgoCode: string;
releaseDate: string;
series: string;
total: number;
updatedAt: string;
```
### IQuery

86
coverage/client.test.ts Normal file
View File

@ -0,0 +1,86 @@
import * as chai from 'chai';
import { Client } from '../src/client';
import { IQuery } from '../src/interfaces/query';
const expect = chai.expect;
describe('Client', () => {
it('should get a single using the cards resource and query params' , () => {
const params: IQuery[] = [{
name: 'id',
value: 'xy7-54'
}];
Client.get('cards', params)
.then(response => {
expect(response).to.be.a('array');
expect(response[0].name).to.equal('Ampharos');
});
});
it('should get a default list of cards using the cards resource with no query params', () => {
Client.get('cards')
.then(response => {
expect(response).to.be.a('array');
expect(response.length).to.equal(250);
});
});
it('should get sets using the sets resource and query params', () => {
const params: IQuery[] = [{
name: 'name',
value: 'Base'
}];
Client.get('sets', params)
.then(response => {
expect(response).to.be.a('array');
expect(response[0]).to.be.a('object');
});
});
it('should get a single set using the sets resource and query params', () => {
const params: IQuery[] = [{
name: 'id',
value: 'base1'
}];
Client.get('sets', params)
.then(response => {
expect(response).to.be.a('array');
expect(response[0].name).to.equal('Base');
});
});
it('should get a default list of sets using the sets resource with no query params', () => {
Client.get('sets')
.then(response => {
expect(response).to.be.a('array');
expect(response[0]).to.be.a('object');
expect(response[0].id).to.equal('base1');
});
});
it('should get a list of types using the types resource', () => {
Client.get('types')
.then(response => {
expect(response).to.be.a('array');
expect(response[0]).to.be.a('string');
});
});
it('should get a list of supertypes using the supertypes resource', () => {
Client.get('supertypes')
.then(response => {
expect(response).to.be.a('array');
expect(response[0]).to.be.a('string');
});
});
it('should get a list of subtypes using the subtypes resource', () => {
Client.get('subtypes')
.then(response => {
expect(response).to.be.a('array');
expect(response[0]).to.be.a('string');
});
});
});

View File

@ -0,0 +1,38 @@
import * as chai from 'chai';
import { Card } from '../src/classes/card';
import { QueryBuilder } from '../src/queryBuilder';
import { IQuery } from '../src/interfaces/query';
const expect = chai.expect;
describe('QueryBuilder', () => {
it('should use find to get a single instance', () => {
QueryBuilder.find<Card>(Card, 'xy7-54')
.then(card => {
expect(card).to.be.a('object');
expect(card.name).to.equal('Gardevoir');
});
});
it('should use where to filter data', () => {
const params: IQuery[] = [
{
name: 'q',
value: 'name:Charizard set.id:base1'
}
];
QueryBuilder.where<Card>(Card, params)
.then(cards => {
expect(cards.length).to.equal(1);
expect(cards[0].id).to.equal('base1-4');
expect(cards[0].set.name).to.equal('Base');
});
});
it('should use all to get all cards', () => {
QueryBuilder.all<Card>(Card)
.then(cards => {
expect(cards.length).to.equal(250);
});
});
});

View File

@ -1,7 +0,0 @@
module.exports = {
"testRegex": '.*\\.test\\.ts$',
"transform": {
"^.+\\.(ts|tsx)$": "ts-jest"
},
"testTimeout": 30000
}

5896
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "pokemon-tcg-sdk-typescript",
"version": "2.0.0",
"version": "1.3.1",
"description": "Typescript SDK for the PokemonTCG API (https://pokemontcg.io)",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@ -11,10 +11,7 @@
"SDK"
],
"scripts": {
"format": "prettier --config .prettierrc.json 'src/**/*.ts' --write",
"lint": "eslint . --ext .ts",
"lint-and-fix": "eslint . --ext .ts --fix",
"test": "jest",
"test": "mocha --reporter spec --require ts-node/register 'coverage/**/*.test.ts'",
"build": "tsc"
},
"repository": {
@ -25,24 +22,19 @@
"Bradyn Glines (https://github.com/glinesbdev)",
"CptSpaceToaster (https://github.com/CptSpaceToaster)",
"Monbrey (https://github.com/Monbrey)",
"Jonathan Meyer (https://github.com/jonathan-meyer)",
"Elisabeth Diang (https://github.com/acupoftee)"
"Jonathan Meyer (https://github.com/jonathan-meyer)"
],
"license": "MIT",
"dependencies": {
"axios": "0.21.1"
"axios": "^0.19.0"
},
"devDependencies": {
"@types/jest": "26.0.20",
"@typescript-eslint/eslint-plugin": "4.17.0",
"@typescript-eslint/parser": "4.17.0",
"eslint": "7.22.0",
"eslint-config-prettier": "8.1.0",
"eslint-plugin-prettier": "3.3.1",
"jest": "26.6.3",
"prettier": "2.2.1",
"ts-jest": "26.5.3",
"ts-node": "4.1.0",
"@types/chai": "^4.1.1",
"@types/mocha": "^2.2.46",
"@types/node": "^14.14.35",
"chai": "^4.1.2",
"mocha": "^8.2.1",
"ts-node": "^4.1.0",
"typescript": "4.1.5"
}
}

77
src/classes/card.ts Normal file
View File

@ -0,0 +1,77 @@
import { IAbility } from "../interfaces/ability";
import { IAncientTrait } from "../interfaces/ancientTrait";
import { IAttack } from "../interfaces/attack";
import { ICard } from "../interfaces/card";
import { ICardImage } from "../interfaces/image";
import { ILegality } from "../interfaces/legality";
import { IQuery } from "../interfaces/query";
import { IResistance } from "../interfaces/resistance";
import { ISet } from "../interfaces/set";
import { ITCGPlayer } from "../interfaces/tcgplayer";
import { IWeakness } from "../interfaces/weakness";
import { QueryBuilder } from "../queryBuilder";
export class Card implements ICard {
id: string;
name: string;
supertype: string;
subtypes: string[];
hp?: string;
types?: string[];
evolesFrom?: string;
evolvesTo?: string[];
rules?: string[];
ancientTrait?: IAncientTrait;
abilities?: IAbility[];
attacks?: IAttack[];
weaknesses?: IWeakness[];
resistances?: IResistance[];
retreatCost?: string[];
convertedRetreatCost?: number;
set: ISet;
number: string;
artist?: string;
rarity: string;
flavorText?: string;
nationalPokedexNumbers?: number[];
legalities: ILegality;
images: ICardImage;
tcgplayer?: ITCGPlayer;
resource(): string {
return "cards";
}
/**
* @deprecated `Card.find` is renamed to `findCardById` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async find(id: string): Promise<Card> {
return QueryBuilder.find(this, id)
.then((response) => {
return response;
})
.catch((error) => Promise.reject(error));
}
/**
* @deprecated `Card.all` is renamed to `getAllCards` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async all(): Promise<Card[]> {
return QueryBuilder.all(this)
.then((response) => {
return response;
})
.catch((error) => Promise.reject(error));
}
/**
* @deprecated `Card.where` is renamed to `findCardsByQueries` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async where(params: IQuery[]): Promise<Card[]> {
return QueryBuilder.where(this, params)
.then((response) => {
return response;
})
.catch((error) => Promise.reject(error));
}
}

35
src/classes/meta.ts Normal file
View File

@ -0,0 +1,35 @@
import { Client } from '../client';
export class Meta {
/**
* @deprecated `allTypes` is renamed to `getAllTypes` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async allTypes(): Promise<string[]> {
const resposne = await Client.get('types');
return resposne;
}
/**
* @deprecated `allSubtypes` is renamed to `getAllSubtypes` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async allSubtypes(): Promise<string[]> {
const response = await Client.get('subtypes');
return response;
}
/**
* @deprecated `allSupertypes` is renamed to `getAllSupertypes` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async allSupertypes(): Promise<string[]> {
const response = await Client.get('supertypes');
return response;
}
/**
* @deprecated `allRarities` is renamed to `getAllRarities` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async allRarities(): Promise<string[]> {
const response = await Client.get('rarities');
return response;
}
}

55
src/classes/set.ts Normal file
View File

@ -0,0 +1,55 @@
import { ISet } from '../interfaces/set';
import { IQuery } from '../interfaces/query';
import { QueryBuilder } from '../queryBuilder';
import { ILegality } from '../interfaces/legality';
import { ISetImage } from '../interfaces/image';
export class Set implements ISet {
id: string;
images: ISetImage;
legalities: ILegality;
name: string;
printedTotal: number;
ptcgoCode: string;
releaseDate: string;
series: string;
total: number;
updatedAt: string;
resource(): string {
return 'sets';
}
/**
* @deprecated `Set.find` is renamed to `findSetById` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async find(id: string): Promise<Set> {
return QueryBuilder.find(this, id)
.then(response => {
return response;
})
.catch(error => Promise.reject(error));
}
/**
* @deprecated `Set.all` is renamed to `getAllSets` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async all(): Promise<Set[]> {
return QueryBuilder.all(this)
.then(response => {
return response;
})
.catch(error => Promise.reject(error));
}
/**
* @deprecated `Set.where` is renamed to `findSetsByQueries` in version 2. See the **[migration guide](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/blob/master/MIGRATING.md)** for more info.
*/
static async where(params: IQuery[]): Promise<Set[]> {
return QueryBuilder.where(this, params)
.then(response => {
return response;
})
.catch(error => Promise.reject(error));
}
}

View File

@ -1,71 +1,42 @@
import * as axios from 'axios';
import { Query } from './interfaces/query';
import { API_URL, API_VERSION } from './sdk';
import { IQuery } from './interfaces/query';
export class Client {
private readonly POKEMONTCG_API_BASE_URL: string =
'https://api.pokemontcg.io';
private readonly POKEMONTCG_API_VERSION: string = '2';
private readonly POKEMONTCG_API_URL: string = `${this.POKEMONTCG_API_BASE_URL}/v${this.POKEMONTCG_API_VERSION}`;
private readonly POKEMONTCG_API_KEY?: string =
process.env.POKEMONTCG_API_KEY;
static apiUrl: string = `${API_URL}/v${API_VERSION}`;
private static instance: Client;
static async get(resource: string, params?: IQuery[] | string): Promise<any> {
let url: string = `${this.apiUrl}/${resource}`;
const POKEMONTCG_API_KEY = process.env.POKEMONTCG_API_KEY;
const config: axios.AxiosRequestConfig = {
headers: {
'Content-Type': 'application/json'
}
};
private constructor() {}
if (POKEMONTCG_API_KEY) {
config.headers['X-Api-Key'] = POKEMONTCG_API_KEY;
}
public static getInstance(): Client {
if (!Client.instance) {
Client.instance = new Client();
}
if(typeof params === 'string') url += `/${params}`;
else url += `?${this.paramsToQuery(params)}`;
return Client.instance;
return axios.default.get<any>(url, config)
.then(response => {
return response.data[Object.keys(response.data)[0]];
})
.catch(error => Promise.reject(error));
}
private static paramsToQuery(params?: IQuery[]): string {
let query: string = '';
if (params) {
params.map((q: IQuery) => {
query += `${q.name}=${encodeURIComponent(q.value.toString())}`.concat('&');
});
}
async get<T>(resource: string, params?: Query[] | string): Promise<T> {
let url = `${this.POKEMONTCG_API_URL}/${resource}`;
const headers = {
'Content-Type': 'application/json',
};
if (this.POKEMONTCG_API_KEY) {
headers['X-Api-Key'] = this.POKEMONTCG_API_KEY;
}
const config: axios.AxiosRequestConfig = {
headers,
};
if (typeof params === 'string') {
if (
params.toLowerCase().includes('page') ||
params.toLowerCase().includes('order')
)
url += `?${params}`;
else url += `/${params}`;
} else if (params) url += `?q=${this.paramsToQuery(params)}`;
return axios.default
.get<T>(url, config)
.then((response) => {
return response.data[Object.keys(response.data)[0]];
})
.catch((error) => Promise.reject(error));
}
private paramsToQuery(params: Query[]): string {
let query = '';
const paramsLength: number = params.length;
params.map((q: Query, i: number) => {
if (paramsLength === i + 1) {
query += `${q.name}:${encodeURIComponent(q.value.toString())}`;
} else {
query += `${q.name}:${encodeURIComponent(
q.value.toString()
)}`.concat('&');
}
});
return query;
}
return query;
}
}

View File

@ -1,6 +0,0 @@
export enum Parameter {
Query = 'q',
Page = 'page',
PageSize = 'pageSize',
Order = 'orderBy',
}

View File

@ -1,25 +0,0 @@
export enum Rarity {
AmazingRare = 'Amazing Rare',
Common = 'Common',
Legend = 'LEGEND',
Promo = 'Promo',
Rare = 'Rare',
RareAce = 'Rare ACE',
RareBreak = 'Rare BREAK',
RareHolo = 'Rare Holo',
RareHoloEX = 'Rare Holo EX',
RareHoloGX = 'Rare Holo GX',
RareHoloLVX = 'Rare Holo LV.X',
RareHoloStar = 'Rare Holo Star',
RareHoloV = 'Rare Holo V',
RareHoloVMAX = 'Rare Holo VMAX',
RarePrime = 'Rare Prime',
RarePrimeStar = 'Rare Prism Star',
RareRainbow = 'Rare Rainbow',
RareSecret = 'Rare Secret',
RareShining = 'Rare Shining',
RareShiny = 'Rare Shiny',
RareShinyGX = 'Rare Shiny GX',
RareUltra = 'Rare Ultra',
Uncommon = 'Uncommon',
}

View File

@ -1,25 +0,0 @@
export enum Subtype {
Break = 'BREAK',
Baby = 'Baby',
Basic = 'Basic',
EX = 'EX',
GX = 'GX',
GoldenrodGameCorner = 'Goldenrod Game Corner',
Item = 'Item',
Legend = 'LEGEND',
LevelUp = 'Level-Up',
Mega = 'MEGA',
PokemonTool = 'Pokémon Tool',
PokemonToolF = 'Pokémon Tool F',
Restored = 'Restored',
RocketsSecretMachine = "Rocket's Secret Machine",
Special = 'Special',
Stadium = 'Stadium',
StageOne = 'Stage 1',
StageTwo = 'Stage 2',
Supporter = 'Supporter',
TagTeam = 'TAG TEAM',
TechnicalMachine = 'Technical Machine',
V = 'V',
VMax = 'VMAX',
}

View File

@ -1,5 +0,0 @@
export enum Supertype {
Energy = 'Energy',
Pokemon = 'Pokémon',
Trainer = 'Trainer',
}

View File

@ -1,13 +0,0 @@
export enum Type {
Colorless = 'Colorless',
Darkness = 'Darkness',
Dragon = 'Dragon',
Fairy = 'Fairy',
Fighting = 'Fighting',
Fire = 'Fire',
Grass = 'Grass',
Lightening = 'Lightning',
Metal = 'Metal',
Psychic = 'Psychic',
Water = 'Water',
}

View File

@ -1,5 +1,5 @@
export interface Ability {
name: string;
text: string;
type: string;
}
export interface IAbility {
name: string;
text: string;
type: string;
}

View File

@ -1,4 +1,4 @@
export interface AncientTrait {
name: string;
text: string;
}
export interface IAncientTrait {
name: string;
text: string;
}

View File

@ -1,7 +1,7 @@
export interface Attack {
convertedEnergyCost: number;
cost: string[];
damage: string;
name: string;
text: string;
}
export interface IAttack {
convertedEnergyCost: number;
cost: string[];
damage: string;
name: string;
text: string;
}

View File

@ -1,41 +1,37 @@
import { Ability } from './ability';
import { AncientTrait } from './ancientTrait';
import { Attack } from './attack';
import { Resistance, Weakness } from './stats';
import { CardImage } from './image';
import { ILegality } from './legality';
import { Set } from './set';
import { TCGPlayer } from './tcgplayer';
import { IAbility } from "../interfaces/ability";
import { IAncientTrait } from "./ancientTrait";
import { IAttack } from "../interfaces/attack";
import { IResistance } from "../interfaces/resistance";
import { IWeakness } from "../interfaces/weakness";
import { ICardImage } from "./image";
import { ILegality } from "./legality";
import { ISet } from "./set";
import { ITCGPlayer } from "./tcgplayer";
import { Type } from '../enums/type';
import { Supertype } from '../enums/supertype';
import { Subtype } from '../enums/subtype';
import { Rarity } from '../enums/rarity';
export interface Card {
id: string;
name: string;
supertype: Supertype;
subtypes: Subtype[];
hp?: string;
types?: Type[];
evolesFrom?: string;
evolvesTo?: string[];
rules?: string[];
ancientTrait?: AncientTrait;
abilities?: Ability[];
attacks?: Attack[];
weaknesses?: Weakness[];
resistances?: Resistance[];
retreatCost?: string[];
convertedRetreatCost?: number;
set: Set;
number: string;
artist?: string;
rarity: Rarity;
flavorText?: string;
nationalPokedexNumbers?: number[];
legalities: ILegality;
images: CardImage;
tcgplayer?: TCGPlayer;
export interface ICard {
id: string;
name: string;
supertype: string;
subtypes: string[];
hp?: string;
types?: string[];
evolesFrom?: string;
evolvesTo?: string[];
rules?: string[];
ancientTrait?: IAncientTrait;
abilities?: IAbility[];
attacks?: IAttack[];
weaknesses?: IWeakness[];
resistances?: IResistance[];
retreatCost?: string[];
convertedRetreatCost?: number;
set: ISet;
number: string;
artist?: string;
rarity: string;
flavorText?: string;
nationalPokedexNumbers?: number[];
legalities: ILegality;
images: ICardImage;
tcgplayer?: ITCGPlayer;
}

View File

@ -1,9 +1,9 @@
export interface SetImage {
symbol: string;
logo: string;
export interface ISetImage {
symbol: string;
logo: string;
}
export interface CardImage {
small: string;
large: string;
}
export interface ICardImage {
small: string;
large: string;
}

View File

@ -1,10 +1,10 @@
export enum Legality {
Legal = 'Legal',
Banned = 'Banned',
LEGAL = 'Legal',
BANNED = 'Banned',
}
export interface ILegality {
expanded?: Legality;
standard?: Legality;
unlimited?: Legality;
}
expanded: Legality | undefined
standard: Legality | undefined
unlimited: Legality | undefined
}

View File

@ -1,4 +1,4 @@
export interface Query {
name: string;
value: string | number;
}
export interface IQuery {
name: string;
value: string | number;
}

View File

@ -0,0 +1,4 @@
export interface IResistance {
type: string;
value: string;
}

View File

@ -1,15 +1,15 @@
import { SetImage } from './image';
import { ILegality } from './legality';
import { ISetImage } from "./image";
import { ILegality } from "./legality";
export interface Set {
id: string;
name: string;
series: string;
printedTotal: number;
total: number;
legalities: ILegality;
ptcgoCode: string;
releaseDate: string;
updatedAt: string;
images: SetImage;
}
export interface ISet {
id: string;
images: ISetImage;
legalities: ILegality;
name: string;
printedTotal: number;
ptcgoCode: string;
releaseDate: string;
series: string;
total: number;
updatedAt: string;
}

View File

@ -1,8 +0,0 @@
interface Stats {
type: string;
value: string;
}
export interface Resistance extends Stats {}
export interface Weakness extends Stats {}

View File

@ -1,17 +1,17 @@
export interface TCGPlayer {
url: string;
updatedAt: string;
prices: {
normal?: Price;
holofoil?: Price;
reverseHolofoil?: Price;
};
export interface ITCGPlayer {
url: string;
updatedAt: string;
prices: {
normal: IPrice | undefined;
holofoil: IPrice | undefined;
reverseHolofoil: IPrice | undefined;
}
}
export interface Price {
low: number | null;
mid: number | null;
high: number | null;
market: number | null;
directLow: number | null;
}
export interface IPrice {
low: number | null
mid: number | null
high: number | null
market: number | null
directLow: number | null
}

View File

@ -0,0 +1,4 @@
export interface IWeakness {
type: string;
value: string;
}

28
src/queryBuilder.ts Normal file
View File

@ -0,0 +1,28 @@
import { Client } from './client';
import { Card } from './classes/card';
import { Set } from './classes/set';
import { IQuery } from './interfaces/query';
export class QueryBuilder {
static all<T extends Card | Set>(type: {new (): T}): Promise<T[]> {
const t = new type();
const params: IQuery[] = [{
name: 'pageSize',
value: 250,
}];
return Client.get(t.resource(), params);
}
static find<T extends Card | Set>(type: {new (): T}, id: string): Promise<T> {
const t = new type();
return Client.get(t.resource(), id);
}
static where<T extends Card | Set>(type: {new (): T}, params: IQuery[]): Promise<T[]> {
const t = new type();
return Client.get(t.resource(), params);
}
}

View File

@ -1,17 +1,16 @@
// Constants
export const API_URL: string = 'https://api.pokemontcg.io';
export const API_VERSION: string = '2';
// Classes
export * from './classes/card';
export * from './classes/set';
export * from './classes/meta';
// Interfaces
export * from './interfaces/ability';
export * from './interfaces/attack';
export * from './interfaces/card';
export * from './interfaces/query';
export * from './interfaces/stats';
// Enums
export * from './enums/type';
export * from './enums/supertype';
export * from './enums/subtype';
export * from './enums/rarity';
export * from './enums/parameter';
// Services
export * from './services/cardService';
export * from './services/setService';
export * from './interfaces/resistance';
export * from './interfaces/weakness';

View File

@ -1,55 +0,0 @@
import { Query } from '../interfaces/query';
import { Card } from '../interfaces/card';
import { Type } from '../enums/type';
import { Supertype } from '../enums/supertype';
import { Subtype } from '../enums/subtype';
import { Rarity } from '../enums/rarity';
import { Client } from '../client';
export async function findCardByID(id: string): Promise<Card> {
const client: Client = Client.getInstance();
const response: Card = await client.get<Card>('cards', id);
return response;
}
export async function findCardsByQueries(params: Query[]): Promise<Card[]> {
const client: Client = Client.getInstance();
const response: Card[] = await client.get<Card[]>('cards', params);
return response;
}
export async function getAllCards(): Promise<Card[]> {
const param = 'pageSize:250';
const client: Client = Client.getInstance();
const response: Card[] = await client.get<Card[]>('cards', param);
return response;
}
export async function getTypes(): Promise<Type[]> {
const client: Client = Client.getInstance();
const response: Type[] = await client.get<Type[]>('types');
return response;
}
export async function getSupertypes(): Promise<Supertype[]> {
const client: Client = Client.getInstance();
const response: Supertype[] = await client.get<Supertype[]>('supertypes');
return response;
}
export async function getSubtypes(): Promise<Subtype[]> {
const client: Client = Client.getInstance();
const response: Subtype[] = await client.get<Subtype[]>('subtypes');
return response;
}
export async function getRarities(): Promise<Rarity[]> {
const client: Client = Client.getInstance();
const response: Rarity[] = await client.get<Rarity[]>('rarities');
return response;
}

View File

@ -1,23 +0,0 @@
import { Query } from '../interfaces/query';
import { Set } from '../interfaces/set';
import { Client } from '../client';
export async function findSetByID(id: string): Promise<Set> {
const client: Client = Client.getInstance();
const response: Set = await client.get<Set>('sets', id);
return response;
}
export async function findSetsByQueries(params: Query[]): Promise<Set[]> {
const client: Client = Client.getInstance();
const response: Set[] = await client.get<Set[]>('sets', params);
return response;
}
export async function getAllSets(): Promise<Set[]> {
const param = 'pageSize:250';
const client: Client = Client.getInstance();
const response: Set[] = await client.get<Set[]>('sets', param);
return response;
}

View File

@ -1,57 +0,0 @@
import { findCardByID, findCardsByQueries, getAllCards, getSupertypes, getSubtypes, getTypes, getRarities } from "../src/services/cardService";
import { Query } from "../src/interfaces/query";
import { Card } from "../src/interfaces/card";
import { Type } from '../src/enums/type';
import { Supertype } from '../src/enums/supertype';
import { Subtype } from '../src/enums/subtype';
import { Rarity } from '../src/enums/rarity';
describe('Card Service', () => {
it('should get a single card using query parameters', async () => {
const params: Query[] = [{
name: 'id',
value: 'xy7-54'
}]
const result: Card[] = await findCardsByQueries(params);
expect(result[0].name).toEqual('Gardevoir');
})
it('should get a single card using a card id', async () => {
const result: Card = await findCardByID('xy7-54');
expect(result.name).toEqual('Gardevoir');
})
it('should get a default list of cards using the cards resource with no query params', async () => {
const results: Card[] = await getAllCards();
expect(results).toHaveLength(250);
});
it('should get a list of card supertypes', async () => {
const expected: Supertype[] = Object.values(Supertype);
const result: Supertype[] = await getSupertypes();
expect(expected.sort()).toEqual(result.sort());
});
it('should get a list of card subtypes', async () => {
const expected: Subtype[] = Object.values(Subtype);
const result: Subtype[] = await getSubtypes();
expect(expected.sort()).toEqual(result.sort());
});
it('should get a list of card rarities', async () => {
const expected: Rarity[] = Object.values(Rarity);
const result: Rarity[] = await getRarities();
expect(expected.sort()).toEqual(result.sort());
});
it('should get a list of card types', async () => {
const expected: Type[] = Object.values(Type);
const result: Type[] = await getTypes();
expect(expected.sort()).toEqual(result.sort());
});
})

View File

@ -1,25 +0,0 @@
import { findSetByID, findSetsByQueries, getAllSets } from '../src/services/setService';
import { Query } from "../src/interfaces/query";
import { Set } from "../src/interfaces/set";
describe('Set Service', () => {
it('should get a single set using query parameters', async () => {
const params: Query[] = [{
name: 'name',
value: 'Base'
}];
const result: Set[] = await findSetsByQueries(params);
expect(result[0].name).toEqual('Base');
})
it('should get a single set using a set id', async () => {
const result: Set = await findSetByID('base1');
expect(result.name).toEqual('Base');
})
it('should get a default list of sets using the sets resource with no query params', async () => {
const results: Set[] = await getAllSets();
expect(results.length).toBeLessThanOrEqual(250);
});
})

View File

@ -13,6 +13,6 @@
],
"exclude": [
"node_modules",
"test"
"coverage"
]
}