36 Commits

Author SHA1 Message Date
e061d81e19 Update package.json 2025-01-20 17:09:54 +00:00
0cbb20fdf2 Update package.json 2025-01-20 14:35:23 +00:00
6a08d3a61a Update package.json 2025-01-20 13:28:56 +00:00
73328a1df2 Update package.json 2025-01-20 11:24:46 +00:00
25b4c2f5d1 Update package.json 2025-01-20 11:03:12 +00:00
Tee
5f2de997ea Bump version number 2021-12-16 20:53:39 -05:00
Tee
befb72bde6 Update contribution instructions 2021-12-16 20:52:46 -05:00
Tee
6cd9eab51b add regulationMark property to card interface 2021-12-16 20:51:59 -05:00
Tee
c4967fb899 Add name and github link to contrubition section 2021-12-16 20:51:11 -05:00
Tee
7ff5d7863d Update version 2021-08-26 22:26:31 -04:00
Tee
f93dbe2fb6 Add missing set import 2021-08-26 21:20:27 -04:00
Tee
9b95435d9e Add new release date and extra contribution steps 2021-08-26 21:20:04 -04:00
Tee
b554a5f5d8 Merge pull request #26 from CptSpaceToaster/add-cardmarket-properties
Add some cardmarket properties
2021-08-10 10:01:58 -04:00
a0b055f6e7 Add some cardmarket properties
Most of these are nullable
2021-08-05 22:56:46 -04:00
ee12437d1a Merge pull request #23 from CptSpaceToaster/main
Add `1stEditionNormal` and `1stEditionHoloFoil` properties in TCGPlayer interface
2021-04-01 21:47:03 -04:00
380d2e7c97 Add missing properties, but their names are weird
They're like this in the JSON :(
2021-03-26 12:36:18 -04:00
Tee
5b5d076e52 Bump patch version 2021-03-24 22:52:56 -04:00
Tee
5d45d75720 fix evolvesFrom typo 2021-03-24 22:52:27 -04:00
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
41 changed files with 1177 additions and 5964 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();
```

106
README.md
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, September 17th, 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,41 @@ 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;
cardmarket?: ICardmarket;
```
### IAbility
@ -71,17 +80,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
@ -140,17 +148,19 @@ PokemonTCG.Card.all()
```
## Contributing
* Fork it (click the Fork button at the top of the page)
* Create your feature branch (git checkout -b my-new-feature)
* Make some changes and fix some bugs!
* Run the tests `npm run-script test`
* Test your changes in a project of yours:
* Create a link with [npm](https://docs.npmjs.com/cli/link.html) or [yarn](https://yarnpkg.com/lang/en/docs/cli/link/) (depending on what tool you installed this SDK with)
* In your project that **uses** the SDK, install the linked package with `yarn/npm link pokemon-tcg-sdk-typescript`
* Verify the SDK behaves as expected, and your changes took effect
* Commit your changes (git commit -am 'Add some feature')
* Push to the branch (git push origin my-new-feature)
* Create a new Pull Request
* Open an issue
* Describe what the SDK is missing and what changes you'd like to see implemented
* **Ask clarifying questions**
* Fork it (click the Fork button at the top of the page)
* Create your feature branch (git checkout -b my-new-feature)
* Make some changes and fix some bugs!
* Run the tests `npm run-script test`
* Test your changes in a project of yours:
* Create a link with [npm](https://docs.npmjs.com/cli/link.html) or [yarn](https://yarnpkg.com/lang/en/docs/cli/link/) (depending on what tool you installed this SDK with)
* In your project that **uses** the SDK, install the linked package with `yarn/npm link pokemon-tcg-sdk-typescript`
* Verify the SDK behaves as expected, and your changes took effect
* Commit your changes (git commit -am 'Add some feature')
* Push to the branch (git push origin my-new-feature)
* Create a new Pull Request to `master`
## TODO
* Add more testing?

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.4",
"description": "Typescript SDK for the PokemonTCG API (https://pokemontcg.io)",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@ -11,38 +11,32 @@
"SDK"
],
"scripts": {
"format": "prettier --config .prettierrc.json 'src/**/*.ts' --write",
"lint": "eslint . --ext .ts",
"lint-and-fix": "eslint . --ext .ts --fix",
"test": "jest",
"prepare": "npm run build",
"test": "mocha --reporter spec --require ts-node/register 'coverage/**/*.test.ts'",
"build": "tsc"
},
"repository": {
"type": "git",
"url": "https://github.com/PokemonTCG/pokemon-tcg-sdk-typescript"
"url": "https://gitea.sebar.dev/gitea_admin/pokemon-tcg-sdk-typescript.git"
},
"contributors": [
"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)"
"Tee Diang (https://github.com/acupoftee"
],
"license": "MIT",
"dependencies": {
"axios": "0.21.1"
"axios": "^1.7.9"
},
"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"
}
}

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

@ -0,0 +1,80 @@
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 { ICardmarket } from "../interfaces/cardmarket";
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;
regulationMark?: string;
images: ICardImage;
tcgplayer?: ITCGPlayer;
cardmarket?: ICardmarket;
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,40 @@
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 { ICardmarket } from "./cardmarket";
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[];
evolvesFrom?: 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;
regulationMark?: string;
images: ICardImage;
tcgplayer?: ITCGPlayer;
cardmarket?: ICardmarket;
}

View File

@ -0,0 +1,21 @@
export interface ICardmarket {
url: string;
updatedAt: string;
prices: {
averageSellPrice: number | null
lowPrice: number | null
trendPrice: number | null
germanProLow: number | null
suggestedPrice: number | null
reverseHoloSell: number | null
reverseHoloLow: number | null
reverseHoloTrend: number | null
lowPriceExPlus: number | null
avg1: number | null
avg7: number | null
avg30: number | null
reverseHoloAvg1: number | null
reverseHoloAvg7: number | null
reverseHoloAvg30: number | null
}
}

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,19 @@
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;
'1stEditionNormal': IPrice | undefined;
'1stEditionHolofoil': 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,17 @@
// 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/set';
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"
]
}