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
42 changed files with 1089 additions and 6076 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
}
}

View File

@ -1,36 +0,0 @@
name: Build
on:
pull_request:
push:
branches:
- master
- dev
jobs:
test:
name: Pokemon TCG TypeScript Integration Tests
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v1
- name: 'Setup Node'
uses: actions/setup-node@v1
with:
node-version: 12
- name: 'Install dependencies'
run: 'npm ci'
- name: 'Format SDK'
run: 'npm run prettier'
- name: 'Lint SDK'
run: 'npm run lint'
- name: 'Test SDK'
run: 'npm run test'
- name: 'Build SDK'
run: 'npm run build'

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
}

View File

@ -1,6 +1,6 @@
# Migrating from v1 to v2
The functions and typings in V2 the SDK have been re-named to improve developer experience.
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
@ -22,12 +22,12 @@ the TypeScript interfaces can be used as intended, which is to simply describe t
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.
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.
to be compatible with V2 of the SDK.
## Card Functions
### `PokemonTCG.Card.all()` -> `PokemonTCG.getAllCards()`
@ -119,7 +119,7 @@ PokemonTCG.findSetsByQueries(paramsV2).then((sets: PokemonTCG.Set[]) => {
});
```
## Meta Functions
## Meta Functions
### `PokemonTCG.Meta.allTypes()` -> `PokemonTCG.getTypes()`
```typescript

239
README.md
View File

@ -1,163 +1,166 @@
# Pokémon TCG TypeScript SDK
# Pokemon TCG SDK TypeScript
*Now supporting Version 2 of the Pokémon TCG API! Please refer to the [V1 to V2 Migration](https://docs.pokemontcg.io/#documentationmigration) section of the
official API docs for more information.*
This is the TypeScript SDK for the [Pokemon TCG API](https://pokemontcg.io).
***See the [migration guide](MIGRATING.md) for steps to update your app to use the latest supported version of the SDK***
[![pokemontcg-developers on discord](https://img.shields.io/badge/discord-pokemontcg--developers-738bd7.svg)](https://discord.gg/dpsTCvg)
![pokemon-tcg-sdk-typescript build status](https://github.com/acupoftee/pokemon-tcg-sdk-typescript/actions/workflows/sdk_test.yaml/badge.svg
)
This is the TypeScript SDK for the [Pokémon Trading Card Game API](https://docs.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**
npm install pokemon-tcg-sdk-typescript
npm install --save pokemon-tcg-sdk-typescript
**yarn**
yarn add pokemon-tcg-sdk-typescript
# Configuration
The SDK works out of the box! Simply import the SDK, and you're ready to go:
```typescript
import { PokemonTCG } from '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.
PokemonTCG.findCardByID('xy7-54').then((card: PokemonTCG.Card) => {
console.log(card.name) // Gardevoir
})
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
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;
```
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.
### IAbility
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.**
# Usage
All function calls return generic promises like `Promise<T>` or `Promise<T[]>`
## Card Methods
* [findCardByID()](#findcardbyid)
* [findCardsByQueries()](#findcardbyqueries)
* [getAllCards()](#getallcards)
* [getTypes()](#gettypes)
* [getSupertypes()](#getsupertypes)
* [getSubtypes()](#getsubtypes)
* [getRarities()](#getrarities)
## Set Methods
* [findSetByID()](#findsetbyid)
* [findSetsByQueries()](#findsetbyqueries)
* [getAllSets()](#getallsets)
### findCardByID()
Returns a single Pokémon card given an ID.
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
PokemonTCG.findCardByID('xy7-54').then((card: PokemonTCG.Card) => {
console.log(card.name) // Gardevoir
});
name: string;
text: string;
type: string;
```
### findCardByQueries()
Returns an array of cards filtered through a search query.
### IAttack
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
const params: PokemonTCG.Query[] = { q: 'id:xy7-54' };
PokemonTCG.findCardsByQueries(params).then((cards: PokemonTCG.Card[]) => {
console.log(card[0].name) // Gardevoir
});
```
### getAllCards()
Returns all Pokémon cards available through recursive pagination.
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
PokemonTCG.getAllCards();
cost: string[];
name: string;
text: string;
damage: string;
convertedEnergyCost: string;
```
### getTypes()
Returns all Energy Types
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
### IResistance, IWeakness
PokemonTCG.getTypes();
```typescript
type: string;
value: string;
```
### getSupertypes()
Returns all Super Types
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
### Set
PokemonTCG.getSupertypes();
```typescript
id: string;
images: ISetImage;
legalities: ILegality;
name: string;
printedTotal: number;
ptcgoCode: string;
releaseDate: string;
series: string;
total: number;
updatedAt: string;
```
### getSubtypes()
Returns all Sub Types
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
### IQuery
PokemonTCG.getSubtypes();
```typescript
{ name: string, value: string | number }
```
### getRarities()
Returns all card Rarities
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
## Method Definitions
PokemonTCG.getRarities();
```
### findSetByID()
Returns a single Pokémon card given an ID.
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
Card.find(id: string): Promise<Card>
Card.where(params: IQuery[]): Promise<Card[]>
Card.all(): Promise<Card[]>
PokemonTCG.findSetByID('base1').then((set: PokemonTCG.Set) => {
console.log(set.name) // Base
});
Set.find(id: string): Promise<Set>
Set.where(params: IQuery[]): Promise<Set[]>
Set.all(): Promise<Set[]>
Meta.allTypes(): Promise<string[]>
Meta.allSubtypes(): Promise<string[]>
Meta.allSupertypes(): Promise<string[]>
```
### findSetByQueries()
Returns an array of cards filtered through a search query.
## Usage
All of the calls return generic promises like `Promise<T>` or `Promise<T[]>`. The type is determined from the class making the call. The examples here are using the `Card` class but the usage for the other classes are the same.
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript'
const params: PokemonTCG.Query[] = { q: 'name:Base' };
PokemonTCG.Card.find('xy1')
.then(card => {
// do stuff with the card
})
.catch(error => {
// do something with the error
});
PokemonTCG.findSetsByQueries(params).then((sets: PokemonTCG.Set[]) => {
console.log(sets[0].name) // Base
});
```
### getAllSets()
Returns all Pokémon sets available through recursive pagination.
```typescript
import { PokemonTCG } from 'pokemon-tcg-sdk-typescript';
let params: PokemonTCG.IQuery[] = [{ name: 'name', value: 'Charizard' }];
PokemonTCG.Card.where(params)
.then(cards => {
// do stuff with the cards
})
.catch(error => {
// do something with the error
});
PokemonTCG.getAllSets();
PokemonTCG.Card.all()
.then(cards => {
// do stuff with the cards
})
.catch(error => {
// do something with the error
});
```
## Contributing
Contributions are welcome! If you want to contribute, feel free to fork the repository, open and issue, then submit a pull request.
ESLint and Prettier are used to enforce a consistent coding style.
* 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`
### Setup
Raring to code your heart out? Awesome! Here's how to get started:
1. Open and issue with a bug or feature. Ensure the change is not already being worked on.
2. Fork and clone the repository from the `master` branch.
3. Create a feature branch.
4. Run `npm ci` to install exact versions specified in the `package-lock.json`.
5. Code your heart out!
6. Run `npm run test` to run ESLint and Jest tests.
7. (OPTIONAL) Test your changes in a project of yours:
1. Create a link with `npm` or `yarn` (depending on what tool you installed this SDK with)
2. In your project that uses the SDK, install the linked package with `yarn/npm link pokemon-tcg-sdk-typescript`
3. Verify the SDK behaves as expected, and your changes took effect
8. Submit a [pull request](https://github.com/PokemonTCG/pokemon-tcg-sdk-typescript/compare)! 🎉

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": 300000
}

5898
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.1.0-beta.1",
"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": {
"prettier": "prettier --config .prettierrc.json 'src/**/*.ts' --write",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"test": "npm run lint && jest",
"build": "npm run lint:fix && tsc"
"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,64 +1,42 @@
import * as axios from 'axios';
import { Parameter } from './interfaces/parameter';
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?: Parameter | 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') {
url += `/${params}`;
} else if (params) {
url += `?${this.stringify(params)}`;
}
return axios.default
.get<T>(url, config)
.then((response) => {
return response.data[Object.keys(response.data)[0]];
})
.catch((error) => Promise.reject(error));
}
private stringify(params: Parameter): string {
const queryString = Object.keys(params)
.map(
(key: string) =>
`${encodeURIComponent(key)}=${encodeURIComponent(
params[key]
)}`
)
.join('&');
return queryString;
}
return query;
}
}

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,27 +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',
RapidStrike = 'Rapid Strike',
SingleStrike = 'Single Strike'
}

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,6 +0,0 @@
export interface Parameter {
q?: string;
orderBy?: string;
page?: number;
pageSize?: number;
}

4
src/interfaces/query.ts Normal file
View File

@ -0,0 +1,4 @@
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,20 +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/parameter';
export * from './interfaces/stats';
export * from './interfaces/set';
export * from './interfaces/image';
export * from './interfaces/tcgplayer';
export * from './interfaces/legality';
// Enums
export * from './enums/type';
export * from './enums/supertype';
export * from './enums/subtype';
export * from './enums/rarity';
// Services
export * from './services/cardService';
export * from './services/setService';
export * from './interfaces/query';
export * from './interfaces/resistance';
export * from './interfaces/weakness';

View File

@ -1,66 +0,0 @@
import { Parameter } from '../interfaces/parameter';
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';
async function paginateAllCards(pageNumber: number, params?: Parameter): Promise<Card[]> {
let currentPage = pageNumber;
const client: Client = Client.getInstance();
const response: Card[] = await client.get<Card[]>('cards', { pageSize: 250, page: currentPage, ...params });
if (response.length === 0) {
return response;
} else {
currentPage++;
return response.concat(await paginateAllCards(currentPage));
}
}
export async function getAllCards(params?: Parameter): Promise<Card[]> {
const startingPage = 1;
const response: Card[] = await paginateAllCards(startingPage, params);
return response;
}
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: Parameter): Promise<Card[]> {
const client: Client = Client.getInstance();
const response: Card[] = await client.get<Card[]>('cards', params);
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 { Parameter } from '../interfaces/parameter';
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: Parameter): 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 params: Parameter = { pageSize: 250 };
const client: Client = Client.getInstance();
const response: Set[] = await client.get<Set[]>('sets', params);
return response;
}

View File

@ -1,55 +0,0 @@
import { findCardByID, findCardsByQueries, getSupertypes, getSubtypes, getTypes, getRarities } from "../src/services/cardService";
import { Parameter } from "../src/interfaces/parameter";
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: Parameter = { q: 'id: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 maximum of 250 cards given a page number by default', async () => {
const totalCards = 250
const results: Card[] = await findCardsByQueries({ page: 1});
expect(results).toHaveLength(totalCards);
});
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,22 +0,0 @@
import { findSetByID, findSetsByQueries, getAllSets } from '../src/services/setService';
import { Parameter } from "../src/interfaces/parameter";
import { Set } from "../src/interfaces/set";
describe('Set Service', () => {
it('should get a single set using query parameters', async () => {
const params: Parameter = { q: 'name: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"
]
}