mirror of
https://github.com/tcgdex/javascript-sdk.git
synced 2025-07-13 02:25:10 +00:00
Compare commits
15 Commits
v2.5.1
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
3f865e1895 | |||
f5dd4cb88c | |||
9b9ff2f028 | |||
ce64a95f4e | |||
460f101026 | |||
b3ba7820a3
|
|||
1f3aae5401 | |||
e501faa823 | |||
e08fd98269 | |||
54a4b729b3 | |||
26af3b0779 | |||
bf54ab3809 | |||
f2621890e1 | |||
4364da480f | |||
0cc8577fe0 |
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -14,18 +14,20 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Follow current releases https://nodejs.org/en/about/releases/
|
||||
node-version: [14.x, 16.x, 18.x, 19.x]
|
||||
# Follow current releases https://github.com/nodejs/release#release-schedule
|
||||
node-version: [18.x, 20.x, 21.x, 22.x]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
@ -37,7 +39,7 @@ jobs:
|
||||
run: npm run test
|
||||
|
||||
- name: Upload Coverage
|
||||
if: matrix.node-version == '16.x'
|
||||
if: matrix.node-version == '22.x'
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
# Comma-separated list of files to upload
|
||||
|
2
.github/workflows/code-quality.yml
vendored
2
.github/workflows/code-quality.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup NodeJS
|
||||
uses: actions/setup-node@v3
|
||||
|
27
.github/workflows/publish.yml
vendored
27
.github/workflows/publish.yml
vendored
@ -1,19 +1,22 @@
|
||||
name: publish
|
||||
name: Publish the Package
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+*'
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup NodeJS
|
||||
- name: Setup Publishing to NPMJS
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18.x'
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies
|
||||
@ -22,7 +25,17 @@ jobs:
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Publish
|
||||
- name: Publish on NPM
|
||||
run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Setup Publishing to Github Packages
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
registry-url: 'https://npm.pkg.github.com'
|
||||
|
||||
- name: Publish on Github
|
||||
run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.REPO_TOKEN }}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<img src="https://img.shields.io/github/stars/tcgdex/javascript-sdk?style=flat-square" alt="Github stars">
|
||||
</a>
|
||||
<a href="https://github.com/tcgdex/javascript-sdk/actions/workflows/build.yml">
|
||||
<img src="https://img.shields.io/github/workflow/status/tcgdex/javascript-sdk/Build%20&%20Test?style=flat-square" alt="the TCGdex JAvascript SDK is released under the MIT license." />
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/tcgdex/javascript-sdk/build.yml?style=flat-square" alt="the TCGdex JAvascript SDK is released under the MIT license." />
|
||||
</a>
|
||||
<a href="https://discord.gg/NehYTAhsZE">
|
||||
<img src="https://img.shields.io/discord/857231041261076491?color=%235865F2&label=Discord&style=flat-square" alt="Discord Link">
|
||||
|
@ -1,5 +1,7 @@
|
||||
const TCGdex = require("../src/tcgdex").default
|
||||
const fetch = require('node-fetch')
|
||||
/// <reference types="jest" />
|
||||
|
||||
const { default: TCGdex, Query } = require("../src/tcgdex")
|
||||
import fetch from 'node-fetch'
|
||||
|
||||
const fakeFetch = (response, status = 200) => jest.fn(() =>
|
||||
Promise.resolve({
|
||||
@ -8,59 +10,141 @@ const fakeFetch = (response, status = 200) => jest.fn(() =>
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
|
||||
test('Basic test', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fakeFetch({ok: true})
|
||||
TCGdex.fetch = fakeFetch({ ok: true })
|
||||
const res = await tcgdex.fetch('cards', 'basic-test')
|
||||
expect(res).toEqual({ok: true})
|
||||
expect(res).toEqual({ ok: true })
|
||||
expect(TCGdex.fetch).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('Cache test', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fakeFetch({ok: 'a'})
|
||||
const res1 = await tcgdex.fetch('cards', 'cache-test')
|
||||
expect(res1).toEqual({ok: 'a'})
|
||||
TCGdex.fetch = fakeFetch({ok: 'b'})
|
||||
const res2 = await tcgdex.fetch('cards', 'cache-test')
|
||||
expect(res2).toEqual({ok: 'a'})
|
||||
})
|
||||
|
||||
test('endpoint errors', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fakeFetch({ok: 'a'})
|
||||
TCGdex.fetch = fakeFetch({ ok: 'a' })
|
||||
await expect(tcgdex.fetch('non existing endpoint')).rejects.toThrow()
|
||||
await expect(tcgdex.fetch()).rejects.toThrow()
|
||||
})
|
||||
|
||||
test('404 test', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fakeFetch(undefined, 404)
|
||||
expect(
|
||||
await tcgdex.fetch('cards', '404-test')
|
||||
).not.toBeDefined()
|
||||
})
|
||||
|
||||
test('test real endpoints', async () => {
|
||||
test(`404 error`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
const endpoints = [
|
||||
{endpoint: 'fetchCard', params: ['swsh1-1']},
|
||||
{endpoint: 'fetchCard', params: ['1', 'Sword & Shield']},
|
||||
{endpoint: 'fetchCards', params: ['swsh1']},
|
||||
{endpoint: 'fetchCards', params: []},
|
||||
{endpoint: 'fetchSet', params: ['swsh1']},
|
||||
{endpoint: 'fetchSets', params: ['swsh']},
|
||||
{endpoint: 'fetchSets', params: []},
|
||||
{endpoint: 'fetchSeries', params: []},
|
||||
{endpoint: 'fetchSerie', params: ['swsh']},
|
||||
]
|
||||
|
||||
for await (const item of endpoints) {
|
||||
expect(
|
||||
await tcgdex[item.endpoint](...item.params)
|
||||
).toBeDefined()
|
||||
}
|
||||
expect(
|
||||
await tcgdex.card.get('404-error')
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
test(`test getting full set from list`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect(
|
||||
await (await tcgdex.set.list())[0].getSet()
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
test(`test getting full serie from list`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect(
|
||||
await (await tcgdex.serie.list())[0].getSerie()
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
test(`test getting full card from list`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect(
|
||||
await (await tcgdex.card.list())[0].getCard()
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
|
||||
test(`test get set from card`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect(
|
||||
await (await tcgdex.card.get('swsh1-136')).getSet()
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
test(`test get serie from set`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect(
|
||||
await (await tcgdex.set.get('swsh1')).getSerie()
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
test(`advanced query system`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect(
|
||||
(await tcgdex.card.list(
|
||||
Query.create()
|
||||
.equal('name', 'Pikachu')
|
||||
.greaterOrEqualThan('hp', 60)
|
||||
.lesserThan('hp', 70)
|
||||
.contains('localId', '5')
|
||||
.not.contains('localId', 'tg')
|
||||
.not.equal('id', 'cel25-5')
|
||||
.sort('localId', 'ASC')
|
||||
.paginate(3, 2)
|
||||
)).length
|
||||
).toBe(2)
|
||||
})
|
||||
|
||||
const endpoints = [
|
||||
{ endpoint: 'card', params: ['swsh1-136'] },
|
||||
{ endpoint: 'set', params: ['swsh1'] },
|
||||
{ endpoint: 'serie', params: ['swsh'] },
|
||||
{ endpoint: 'type', params: ['fire'] },
|
||||
{ endpoint: 'retreat', params: ['1'] },
|
||||
{ endpoint: 'rarity', params: ['common'] },
|
||||
{ endpoint: 'illustrator', params: [''] },
|
||||
{ endpoint: 'hp', params: ['30'] },
|
||||
{ endpoint: 'categorie', params: ['pokemon'] },
|
||||
{ endpoint: 'dexID', params: ['1'] },
|
||||
{ endpoint: 'energyType', params: ['normal'] },
|
||||
{ endpoint: 'regulationMark', params: ['f'] },
|
||||
{ endpoint: 'stage', params: ['basic'] },
|
||||
{ endpoint: 'suffixe', params: ['ex'] },
|
||||
{ endpoint: 'trainerType', params: ['item'] },
|
||||
{ endpoint: 'variant', params: ['normal'] },
|
||||
]
|
||||
|
||||
for (const endpoint of endpoints) {
|
||||
test(`test real ${endpoint.endpoint} endpoint list`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect(
|
||||
await (tcgdex[endpoint.endpoint]).list()
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
test(`test real ${endpoint.endpoint} endpoint item`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect(
|
||||
await (tcgdex[endpoint.endpoint]).get(endpoint.params[0])
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
test(`random card/set/serie`, async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
|
||||
expect((await tcgdex.random.card())).toBeTruthy()
|
||||
expect((await tcgdex.random.set())).toBeTruthy()
|
||||
expect((await tcgdex.random.serie())).toBeTruthy()
|
||||
})
|
||||
|
66
__tests__/deprecated.test.js
Normal file
66
__tests__/deprecated.test.js
Normal file
@ -0,0 +1,66 @@
|
||||
const TCGdex = require("../src/tcgdex").default
|
||||
const fetch = require('node-fetch')
|
||||
|
||||
const fakeFetch = (response, status = 200) => jest.fn(() =>
|
||||
Promise.resolve({
|
||||
status: status,
|
||||
json: () => Promise.resolve(response),
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
|
||||
test('Basic test', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fakeFetch({ok: true})
|
||||
const res = await tcgdex.fetch('cards', 'basic-test')
|
||||
expect(res).toEqual({ok: true})
|
||||
expect(TCGdex.fetch).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('Cache test', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fakeFetch({ok: 'a'})
|
||||
const res1 = await tcgdex.fetch('cards', 'cache-test')
|
||||
expect(res1).toEqual({ok: 'a'})
|
||||
TCGdex.fetch = fakeFetch({ok: 'b'})
|
||||
const res2 = await tcgdex.fetch('cards', 'cache-test')
|
||||
expect(res2).toEqual({ok: 'a'})
|
||||
})
|
||||
|
||||
test('endpoint errors', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fakeFetch({ok: 'a'})
|
||||
await expect(tcgdex.fetch('non existing endpoint')).rejects.toThrow()
|
||||
await expect(tcgdex.fetch()).rejects.toThrow()
|
||||
})
|
||||
|
||||
test('404 test', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fakeFetch(undefined, 404)
|
||||
expect(
|
||||
await tcgdex.fetch('cards', '404-test')
|
||||
).not.toBeDefined()
|
||||
})
|
||||
|
||||
test('test real endpoints', async () => {
|
||||
const tcgdex = new TCGdex('en')
|
||||
TCGdex.fetch = fetch
|
||||
const endpoints = [
|
||||
{endpoint: 'fetchCard', params: ['swsh1-1']},
|
||||
{endpoint: 'fetchCard', params: ['1', 'Sword & Shield']},
|
||||
{endpoint: 'fetchCards', params: ['swsh1']},
|
||||
{endpoint: 'fetchCards', params: []},
|
||||
{endpoint: 'fetchSet', params: ['swsh1']},
|
||||
{endpoint: 'fetchSets', params: ['swsh']},
|
||||
{endpoint: 'fetchSets', params: []},
|
||||
{endpoint: 'fetchSeries', params: []},
|
||||
{endpoint: 'fetchSerie', params: ['swsh']},
|
||||
]
|
||||
|
||||
for await (const item of endpoints) {
|
||||
expect(
|
||||
await tcgdex[item.endpoint](...item.params)
|
||||
).toBeDefined()
|
||||
}
|
||||
})
|
403
package-lock.json
generated
403
package-lock.json
generated
@ -1,16 +1,18 @@
|
||||
{
|
||||
"name": "@tcgdex/sdk",
|
||||
"version": "2.5.0",
|
||||
"version": "2.6.0-beta.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@tcgdex/sdk",
|
||||
"version": "2.5.0",
|
||||
"version": "2.6.0-beta.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"isomorphic-unfetch": "^3",
|
||||
"unfetch": "^4"
|
||||
"@cachex/memory": "^1.0.0",
|
||||
"@cachex/web-storage": "^1.0.1",
|
||||
"@dzeio/object-util": "^1",
|
||||
"isomorphic-unfetch": "^3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7",
|
||||
@ -1723,6 +1725,30 @@
|
||||
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@cachex/core": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cachex/core/-/core-1.0.0.tgz",
|
||||
"integrity": "sha512-JZMGqh2mEAB1JqX2A7yMk6FwGMEoGTjw/Hn5UcqWXUq/Etl2cl8Z6xFUraAN9bv7wX3tTwWol/mh5Ej34to8ng==",
|
||||
"dependencies": {
|
||||
"@dzeio/object-util": "^1.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@cachex/memory": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cachex/memory/-/memory-1.0.0.tgz",
|
||||
"integrity": "sha512-x/oLaj9ZbwCd4Z+3CA20kPd0mRchNFYt2VMz7vlCczWrhX5Lk1b6Z9xUFWMHpjEb2x1G9K194R+vC5qyj4QslQ==",
|
||||
"dependencies": {
|
||||
"@cachex/core": "^1"
|
||||
}
|
||||
},
|
||||
"node_modules/@cachex/web-storage": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@cachex/web-storage/-/web-storage-1.0.1.tgz",
|
||||
"integrity": "sha512-E8Xa9qDZgNgr+lcj3eixowg7PH2CVZbp3huuoc5xVVTtwYrZi5YqbHBG12yG3r6C6Fts/2Yoq6cbVBSm6c8VRA==",
|
||||
"dependencies": {
|
||||
"@cachex/core": "^1"
|
||||
}
|
||||
},
|
||||
"node_modules/@dzeio/config": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@dzeio/config/-/config-1.1.12.tgz",
|
||||
@ -1750,16 +1776,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@dzeio/object-util": {
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@dzeio/object-util/-/object-util-1.4.5.tgz",
|
||||
"integrity": "sha512-V04GE77lipF2qnzMuA+T3blyPVo+ABKQLrmEteerXecA7G+TCisyQKIVMewFvF9qNsJ1LOVTckWW9wnRPyAwoQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@dzeio/object-util/-/object-util-1.8.3.tgz",
|
||||
"integrity": "sha512-/d0ezut7EGrEKedcD8K2Jb2NAMSFfhxNj4rpUBlGzmmakJjJCXAgXvSDLjUwYrgHuabxbxlAn90Wo727MCzWLA=="
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
|
||||
"integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz",
|
||||
"integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
@ -1780,9 +1804,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
||||
"version": "13.19.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz",
|
||||
"integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==",
|
||||
"version": "13.20.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
|
||||
"integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"type-fest": "^0.20.2"
|
||||
@ -1806,6 +1830,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz",
|
||||
"integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||
@ -2768,10 +2801,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.11.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
|
||||
"integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
|
||||
"dev": true
|
||||
"version": "20.12.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz",
|
||||
"integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-fetch": {
|
||||
"version": "2.6.2",
|
||||
@ -2883,14 +2919,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "5.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.1.tgz",
|
||||
"integrity": "sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.1.tgz",
|
||||
"integrity": "sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.48.1",
|
||||
"@typescript-eslint/types": "5.48.1",
|
||||
"@typescript-eslint/typescript-estree": "5.48.1",
|
||||
"@typescript-eslint/scope-manager": "5.54.1",
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/typescript-estree": "5.54.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@ -2909,6 +2945,113 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz",
|
||||
"integrity": "sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/visitor-keys": "5.54.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz",
|
||||
"integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz",
|
||||
"integrity": "sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/visitor-keys": "5.54.1",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"semver": "^7.3.7",
|
||||
"tsutils": "^3.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz",
|
||||
"integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/semver": {
|
||||
"version": "7.3.8",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
|
||||
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "5.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz",
|
||||
@ -3112,9 +3255,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.8.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
|
||||
"integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
|
||||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
|
||||
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@ -3942,12 +4085,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz",
|
||||
"integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz",
|
||||
"integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint/eslintrc": "^1.4.1",
|
||||
"@eslint/eslintrc": "^2.0.0",
|
||||
"@eslint/js": "8.35.0",
|
||||
"@humanwhocodes/config-array": "^0.11.8",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
@ -3961,7 +4105,7 @@
|
||||
"eslint-utils": "^3.0.0",
|
||||
"eslint-visitor-keys": "^3.3.0",
|
||||
"espree": "^9.4.0",
|
||||
"esquery": "^1.4.0",
|
||||
"esquery": "^1.4.2",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"file-entry-cache": "^6.0.1",
|
||||
@ -4208,9 +4352,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esquery": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
|
||||
"integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz",
|
||||
"integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"estraverse": "^5.1.0"
|
||||
@ -7545,9 +7689,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz",
|
||||
"integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==",
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
||||
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@ -8889,6 +9033,12 @@
|
||||
"typpy": "^2.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/unfetch": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz",
|
||||
@ -10377,6 +10527,30 @@
|
||||
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
|
||||
"dev": true
|
||||
},
|
||||
"@cachex/core": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cachex/core/-/core-1.0.0.tgz",
|
||||
"integrity": "sha512-JZMGqh2mEAB1JqX2A7yMk6FwGMEoGTjw/Hn5UcqWXUq/Etl2cl8Z6xFUraAN9bv7wX3tTwWol/mh5Ej34to8ng==",
|
||||
"requires": {
|
||||
"@dzeio/object-util": "^1.8.3"
|
||||
}
|
||||
},
|
||||
"@cachex/memory": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cachex/memory/-/memory-1.0.0.tgz",
|
||||
"integrity": "sha512-x/oLaj9ZbwCd4Z+3CA20kPd0mRchNFYt2VMz7vlCczWrhX5Lk1b6Z9xUFWMHpjEb2x1G9K194R+vC5qyj4QslQ==",
|
||||
"requires": {
|
||||
"@cachex/core": "^1"
|
||||
}
|
||||
},
|
||||
"@cachex/web-storage": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@cachex/web-storage/-/web-storage-1.0.1.tgz",
|
||||
"integrity": "sha512-E8Xa9qDZgNgr+lcj3eixowg7PH2CVZbp3huuoc5xVVTtwYrZi5YqbHBG12yG3r6C6Fts/2Yoq6cbVBSm6c8VRA==",
|
||||
"requires": {
|
||||
"@cachex/core": "^1"
|
||||
}
|
||||
},
|
||||
"@dzeio/config": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@dzeio/config/-/config-1.1.12.tgz",
|
||||
@ -10387,16 +10561,14 @@
|
||||
}
|
||||
},
|
||||
"@dzeio/object-util": {
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@dzeio/object-util/-/object-util-1.4.5.tgz",
|
||||
"integrity": "sha512-V04GE77lipF2qnzMuA+T3blyPVo+ABKQLrmEteerXecA7G+TCisyQKIVMewFvF9qNsJ1LOVTckWW9wnRPyAwoQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@dzeio/object-util/-/object-util-1.8.3.tgz",
|
||||
"integrity": "sha512-/d0ezut7EGrEKedcD8K2Jb2NAMSFfhxNj4rpUBlGzmmakJjJCXAgXvSDLjUwYrgHuabxbxlAn90Wo727MCzWLA=="
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
|
||||
"integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz",
|
||||
"integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.4",
|
||||
@ -10411,9 +10583,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"globals": {
|
||||
"version": "13.19.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz",
|
||||
"integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==",
|
||||
"version": "13.20.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
|
||||
"integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-fest": "^0.20.2"
|
||||
@ -10427,6 +10599,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@eslint/js": {
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz",
|
||||
"integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==",
|
||||
"dev": true
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||
@ -11183,10 +11361,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.11.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
|
||||
"integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
|
||||
"dev": true
|
||||
"version": "20.12.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz",
|
||||
"integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"@types/node-fetch": {
|
||||
"version": "2.6.2",
|
||||
@ -11275,15 +11456,82 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "5.48.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.1.tgz",
|
||||
"integrity": "sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==",
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.1.tgz",
|
||||
"integrity": "sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "5.48.1",
|
||||
"@typescript-eslint/types": "5.48.1",
|
||||
"@typescript-eslint/typescript-estree": "5.48.1",
|
||||
"@typescript-eslint/scope-manager": "5.54.1",
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/typescript-estree": "5.54.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz",
|
||||
"integrity": "sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/visitor-keys": "5.54.1"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz",
|
||||
"integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz",
|
||||
"integrity": "sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"@typescript-eslint/visitor-keys": "5.54.1",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"semver": "^7.3.7",
|
||||
"tsutils": "^3.21.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "5.54.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz",
|
||||
"integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.54.1",
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.8",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
|
||||
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
@ -11417,9 +11665,9 @@
|
||||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "8.8.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
|
||||
"integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
|
||||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
|
||||
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-jsx": {
|
||||
@ -12030,12 +12278,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"eslint": {
|
||||
"version": "8.31.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz",
|
||||
"integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==",
|
||||
"version": "8.35.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz",
|
||||
"integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint/eslintrc": "^1.4.1",
|
||||
"@eslint/eslintrc": "^2.0.0",
|
||||
"@eslint/js": "8.35.0",
|
||||
"@humanwhocodes/config-array": "^0.11.8",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
@ -12049,7 +12298,7 @@
|
||||
"eslint-utils": "^3.0.0",
|
||||
"eslint-visitor-keys": "^3.3.0",
|
||||
"espree": "^9.4.0",
|
||||
"esquery": "^1.4.0",
|
||||
"esquery": "^1.4.2",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"file-entry-cache": "^6.0.1",
|
||||
@ -12215,9 +12464,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"esquery": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
|
||||
"integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz",
|
||||
"integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"estraverse": "^5.1.0"
|
||||
@ -14746,9 +14995,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz",
|
||||
"integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==",
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
||||
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
|
||||
"dev": true
|
||||
},
|
||||
"queue-microtask": {
|
||||
@ -15647,6 +15896,12 @@
|
||||
"typpy": "^2.3.4"
|
||||
}
|
||||
},
|
||||
"undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"unfetch": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz",
|
||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tcgdex/sdk",
|
||||
"version": "2.5.1",
|
||||
"version": "2.6.0-beta.4",
|
||||
"main": "./dist/tcgdex.node.js",
|
||||
"module": "./dist/tcgdex.node.mjs",
|
||||
"types": "./dist/tcgdex.node.d.ts",
|
||||
@ -53,12 +53,14 @@
|
||||
"node": ">=12"
|
||||
},
|
||||
"dependencies": {
|
||||
"isomorphic-unfetch": "^3",
|
||||
"unfetch": "^4"
|
||||
"@cachex/memory": "^1",
|
||||
"@cachex/web-storage": "^1",
|
||||
"@dzeio/object-util": "^1",
|
||||
"isomorphic-unfetch": "^3"
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "node scripts/export-version-number.js",
|
||||
"build": "tsup ./src/tcgdex.node.ts --format cjs,esm --dts --clean && tsup ./src/tcgdex.browser.ts --format iife --global-name TCGdex --sourcemap",
|
||||
"build": "rm -rf dist && tsup ./src/tcgdex.node.ts --format cjs,esm --dts --clean && tsup ./src/tcgdex.browser.ts --format iife --global-name TCGdex --sourcemap",
|
||||
"prepublishOnly": "npm run build",
|
||||
"lint": "eslint",
|
||||
"test": "jest --coverage"
|
||||
|
88
src/Query.ts
Normal file
88
src/Query.ts
Normal file
@ -0,0 +1,88 @@
|
||||
export default class Query {
|
||||
public params: Array<{ key: string, value: string | number | boolean }> = []
|
||||
|
||||
public not: {
|
||||
equal: (key: string, value: string) => Query
|
||||
contains: (key: string, value: string) => Query
|
||||
includes: (key: string, value: string) => Query
|
||||
like: (key: string, value: string) => Query
|
||||
isNull: (key: string) => Query
|
||||
} = {
|
||||
equal: (key: string, value: string) => {
|
||||
this.params.push({ key: key, value: `neq:${value}` })
|
||||
return this
|
||||
},
|
||||
contains: (key: string, value: string) => {
|
||||
this.params.push({ key: key, value: `not:${value}` })
|
||||
return this
|
||||
},
|
||||
includes: (key: string, value: string) => this.not.contains(key, value),
|
||||
like: (key: string, value: string) => this.not.contains(key, value),
|
||||
isNull: (key: string) => {
|
||||
this.params.push({ key: key, value: 'notnull:' })
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
public static create(): Query {
|
||||
return new Query()
|
||||
}
|
||||
|
||||
public includes(key: string, value: string): this {
|
||||
return this.contains(key, value)
|
||||
}
|
||||
|
||||
public like(key: string, value: string): this {
|
||||
return this.contains(key, value)
|
||||
}
|
||||
|
||||
public contains(key: string, value: string): this {
|
||||
this.params.push({ key: key, value: value })
|
||||
return this
|
||||
}
|
||||
|
||||
public equal(key: string, value: string): this {
|
||||
this.params.push({ key: key, value: `eq:${value}` })
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
public sort(key: string, order: 'ASC' | 'DESC'): this {
|
||||
this.params.push({ key: 'sort:field', value: key })
|
||||
this.params.push({ key: 'sort:order', value: order })
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
public greaterOrEqualThan(key: string, value: number) {
|
||||
this.params.push({ key: key, value: `gte:${value}` })
|
||||
return this
|
||||
}
|
||||
|
||||
public lesserOrEqualThan(key: string, value: number) {
|
||||
this.params.push({ key: key, value: `lte:${value}` })
|
||||
return this
|
||||
}
|
||||
|
||||
public greaterThan(key: string, value: number) {
|
||||
this.params.push({ key: key, value: `gt:${value}` })
|
||||
return this
|
||||
}
|
||||
|
||||
public lesserThan(key: string, value: number) {
|
||||
this.params.push({ key: key, value: `lt:${value}` })
|
||||
return this
|
||||
}
|
||||
|
||||
public isNull(key: string) {
|
||||
this.params.push({ key: key, value: 'null:' })
|
||||
return this
|
||||
}
|
||||
|
||||
public paginate(page: number, itemsPerPage: number): this {
|
||||
this.params.push({ key: 'pagination:page', value: page })
|
||||
this.params.push({ key: 'pagination:itemsPerPage', value: itemsPerPage })
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import TCGdex from './tcgdex'
|
||||
import { version } from './version'
|
||||
|
||||
export default class Request {
|
||||
|
||||
// 1 hour of TTL by default
|
||||
public static ttl = 1000 * 60 * 60
|
||||
|
||||
private static cache: Record<string, {response: any, time: number}> = {}
|
||||
|
||||
public static async fetch<T>(url: string): Promise<T | undefined> {
|
||||
let request = this.cache[url]
|
||||
const now = new Date().getTime()
|
||||
if (!request || now - request.time > this.ttl) {
|
||||
const unfetch = TCGdex.fetch
|
||||
const resp = await unfetch(url, {
|
||||
headers: {
|
||||
'user-agent': `@tcgdex/javascript-sdk/${version}`
|
||||
}
|
||||
})
|
||||
if (resp.status !== 200) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
this.cache[url] = { response: await resp.json(), time: now }
|
||||
request = this.cache[url]
|
||||
}
|
||||
return request.response
|
||||
}
|
||||
|
||||
}
|
26
src/endpoints/Endpoint.ts
Normal file
26
src/endpoints/Endpoint.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import type { Endpoints } from '../interfaces'
|
||||
import Model from '../models/Model'
|
||||
import type Query from '../Query'
|
||||
import type TCGdex from '../tcgdex'
|
||||
|
||||
export default class Endpoint<Item extends Model, List extends Model> {
|
||||
public constructor(
|
||||
protected readonly tcgdex: TCGdex,
|
||||
protected readonly itemModel: new (sdk: TCGdex) => Item,
|
||||
protected readonly listModel: new (sdk: TCGdex) => List,
|
||||
protected readonly endpoint: Endpoints
|
||||
) { }
|
||||
|
||||
public async get(id: string | number): Promise<Item | null> {
|
||||
const res = await this.tcgdex.fetch(this.endpoint as 'cards', id as string)
|
||||
if (!res) {
|
||||
return null
|
||||
}
|
||||
return Model.build(new this.itemModel(this.tcgdex), res)
|
||||
}
|
||||
|
||||
public async list(query?: Query): Promise<Array<List>> {
|
||||
const res = await this.tcgdex.fetchWithQuery([this.endpoint], query?.params)
|
||||
return (res as Array<object> ?? []).map((it) => Model.build(new this.listModel(this.tcgdex), it))
|
||||
}
|
||||
}
|
24
src/endpoints/SimpleEndpoint.ts
Normal file
24
src/endpoints/SimpleEndpoint.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import type { Endpoints } from '../interfaces'
|
||||
import Model from '../models/Model'
|
||||
import type Query from '../Query'
|
||||
import type TCGdex from '../tcgdex'
|
||||
|
||||
export default class SimpleEndpoint<Item extends Model, List extends string | number> {
|
||||
public constructor(
|
||||
protected readonly tcgdex: TCGdex,
|
||||
protected readonly itemModel: new (sdk: TCGdex) => Item,
|
||||
protected readonly endpoint: Endpoints
|
||||
) {}
|
||||
|
||||
public async get(id: string | number): Promise<Item | null> {
|
||||
const res = await this.tcgdex.fetch(this.endpoint as 'cards', id as string)
|
||||
if (!res) {
|
||||
return null
|
||||
}
|
||||
return Model.build(new this.itemModel(this.tcgdex), res)
|
||||
}
|
||||
|
||||
public async list(query?: Query): Promise<Array<List>> {
|
||||
return await this.tcgdex.fetchWithQuery([this.endpoint], query?.params) ?? []
|
||||
}
|
||||
}
|
9
src/interfaces.ts → src/interfaces.d.ts
vendored
9
src/interfaces.ts → src/interfaces.d.ts
vendored
@ -310,3 +310,12 @@ export interface StringEndpoint {
|
||||
name: string
|
||||
cards: Array<CardResume>
|
||||
}
|
||||
|
||||
export type Quality = 'low' | 'high'
|
||||
|
||||
export type Extension = 'jpg' | 'webp' | 'png'
|
||||
|
||||
export type Endpoints = 'cards' | 'categories' | 'dex-ids' | 'energy-types' |
|
||||
'hp' | 'illustrators' | 'rarities' | 'regulation-marks' |
|
||||
'retreats' | 'series' | 'sets' | 'stages' | 'suffixes' |
|
||||
'trainer-types' | 'types' | 'variants' | 'random'
|
198
src/models/Card.ts
Normal file
198
src/models/Card.ts
Normal file
@ -0,0 +1,198 @@
|
||||
import CardResume from './CardResume'
|
||||
import type { Variants } from './Other'
|
||||
import type TCGdexSet from './Set'
|
||||
import type SetResume from './SetResume'
|
||||
|
||||
// TODO: sort elements by alphabetical order
|
||||
export default class Card extends CardResume {
|
||||
/**
|
||||
* Card illustrator
|
||||
*/
|
||||
public illustrator?: string
|
||||
|
||||
/**
|
||||
* Card Rarity
|
||||
*
|
||||
* - None https://www.tcgdex.net/database/sm/smp/SM01
|
||||
* - Common https://www.tcgdex.net/database/xy/xy9/1
|
||||
* - Uncommon https://www.tcgdex.net/database/xy/xy9/2
|
||||
* - Rare https://www.tcgdex.net/database/xy/xy9/3
|
||||
* - Ultra Rare
|
||||
* - Secret Rare
|
||||
*/
|
||||
public rarity!: string
|
||||
|
||||
/**
|
||||
* Card Category
|
||||
*
|
||||
* - Pokemon
|
||||
* - Trainer
|
||||
* - Energy
|
||||
*/
|
||||
public category!: string
|
||||
|
||||
/**
|
||||
* Card Variants (Override Set Variants)
|
||||
*/
|
||||
public variants?: Variants
|
||||
|
||||
/**
|
||||
* Card Set
|
||||
*/
|
||||
public set!: SetResume
|
||||
|
||||
/**
|
||||
* Pokemon only elements
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pokemon Pokedex ID
|
||||
*/
|
||||
public dexId?: Array<number>
|
||||
|
||||
/**
|
||||
* Pokemon HP
|
||||
*/
|
||||
public hp?: number
|
||||
|
||||
/**
|
||||
* Pokemon Types
|
||||
* ex for multiple https://www.tcgdex.net/database/ex/ex13/17
|
||||
*/
|
||||
public types?: Array<string>
|
||||
|
||||
/**
|
||||
* Pokemon Sub Evolution
|
||||
*/
|
||||
public evolveFrom?: string
|
||||
|
||||
/**
|
||||
* Pokemon Weight
|
||||
*/
|
||||
public weight?: string
|
||||
|
||||
/**
|
||||
* Pokemon Description
|
||||
*/
|
||||
public description?: string
|
||||
|
||||
/**
|
||||
* Level of the Pokemon
|
||||
*
|
||||
* NOTE: can be equal to 'X' when the pokemon is a LEVEL-UP one
|
||||
*/
|
||||
public level?: number | string
|
||||
|
||||
/**
|
||||
* Pokemon Stage
|
||||
*
|
||||
* - Basic https://www.tcgdex.net/database/xy/xy9/1
|
||||
* - BREAK https://www.tcgdex.net/database/xy/xy9/18
|
||||
* - LEVEL-UP https://www.tcgdex.net/database/dp/dp1/121
|
||||
* - MEGA https://www.tcgdex.net/database/xy/xy1/2
|
||||
* - RESTORED https://www.tcgdex.net/database/bw/bw5/53
|
||||
* - Stage1 https://www.tcgdex.net/database/xy/xy9/2
|
||||
* - Stage2 https://www.tcgdex.net/database/xy/xy9/3
|
||||
* - VMAX https://www.tcgdex.net/database/swsh/swsh1/50
|
||||
*/
|
||||
public stage?: string
|
||||
|
||||
/**
|
||||
* Card Suffix
|
||||
*
|
||||
* - EX https://www.tcgdex.net/database/ex/ex2/94
|
||||
* - GX https://www.tcgdex.net/database/sm/sm12/4
|
||||
* - V https://www.tcgdex.net/database/swsh/swsh1/1
|
||||
* - Legend https://www.tcgdex.net/database/hgss/hgss1/114
|
||||
* - Prime https://www.tcgdex.net/database/hgss/hgss2/85
|
||||
* - SP https://www.tcgdex.net/database/pl/pl1/7
|
||||
* - TAG TEAM-GX https://www.tcgdex.net/database/sm/sm12/226
|
||||
*/
|
||||
public suffix?: string
|
||||
|
||||
/**
|
||||
* Pokemon Held Item
|
||||
*
|
||||
* ex https://www.tcgdex.net/database/dp/dp2/75
|
||||
*/
|
||||
public item?: {
|
||||
name: string
|
||||
effect: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Pokemon Abilities
|
||||
*
|
||||
* multi abilities ex https://www.tcgdex.net/database/ex/ex15/10
|
||||
*/
|
||||
public abilities?: Array<{
|
||||
type: string
|
||||
name: string
|
||||
effect: string
|
||||
}>
|
||||
|
||||
/**
|
||||
* Pokemon Attacks
|
||||
*/
|
||||
public attacks?: Array<{
|
||||
cost?: Array<string>
|
||||
name: string
|
||||
effect?: string
|
||||
damage?: string | number
|
||||
}>
|
||||
|
||||
/**
|
||||
* Pokemon Weaknesses
|
||||
*/
|
||||
public weaknesses?: Array<{
|
||||
type: string
|
||||
value?: string
|
||||
}>
|
||||
|
||||
public resistances?: Array<{
|
||||
type: string
|
||||
value?: string
|
||||
}>
|
||||
|
||||
public retreat?: number
|
||||
|
||||
// Trainer/Energy
|
||||
public effect?: string
|
||||
|
||||
// Trainer Only
|
||||
public trainerType?: string
|
||||
|
||||
// Energy Only
|
||||
public energyType?: string
|
||||
|
||||
/**
|
||||
* Define the rotation mark on cards >= Sword & Shield
|
||||
*/
|
||||
public regulationMark?: string
|
||||
|
||||
/**
|
||||
* Card ability to be played in official tournaments
|
||||
*
|
||||
* Note: all cards are avaialable to play in unlimited tournaments
|
||||
*/
|
||||
public legal!: {
|
||||
|
||||
/**
|
||||
* Ability to play in standard tournaments
|
||||
*/
|
||||
standard: boolean
|
||||
|
||||
/**
|
||||
* Ability to play in expanded tournaments
|
||||
*/
|
||||
expanded: boolean
|
||||
}
|
||||
|
||||
public override async getCard(): Promise<Card> {
|
||||
return this
|
||||
}
|
||||
|
||||
public async getSet(): Promise<TCGdexSet> {
|
||||
return (await this.sdk.set.get(this.set.id))!
|
||||
}
|
||||
}
|
47
src/models/CardResume.ts
Normal file
47
src/models/CardResume.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import type { Extension, Quality } from '../interfaces'
|
||||
import type Card from './Card'
|
||||
import Model from './Model'
|
||||
|
||||
export default class CardResume extends Model {
|
||||
/**
|
||||
* Globally unique card ID based on the set ID and the cards ID within the set
|
||||
*/
|
||||
public id!: string
|
||||
|
||||
/**
|
||||
* Card image url without the extension and quality
|
||||
*
|
||||
* @see {@link getImageURL}
|
||||
*/
|
||||
public image?: string
|
||||
|
||||
/**
|
||||
* ID indexing this card within its set, usually just its number
|
||||
*/
|
||||
public localId!: string
|
||||
|
||||
/**
|
||||
* Card Name (Including the suffix if next to card name)
|
||||
*/
|
||||
public name!: string
|
||||
|
||||
/**
|
||||
* the the Card Image full URL
|
||||
*
|
||||
* @param {Quality} quality the quality you want your image to be in
|
||||
* @param {Extension} extension extension you want you image to be
|
||||
* @return the full card URL
|
||||
*/
|
||||
public getImageURL(quality: Quality = 'high', extension: Extension = 'png'): string {
|
||||
return `${this.image}/${quality}.${extension}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full Card
|
||||
*
|
||||
* @return the full card if available
|
||||
*/
|
||||
public async getCard(): Promise<Card> {
|
||||
return (await this.sdk.card.get(this.id))!
|
||||
}
|
||||
}
|
28
src/models/Model.ts
Normal file
28
src/models/Model.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { objectLoop } from '@dzeio/object-util'
|
||||
import type TCGdex from '../tcgdex'
|
||||
|
||||
export default abstract class Model {
|
||||
|
||||
public constructor(
|
||||
protected readonly sdk: TCGdex
|
||||
) { }
|
||||
|
||||
/**
|
||||
* build a model depending on the data given
|
||||
* @param model the model to build
|
||||
* @param data the data to fill it with
|
||||
*/
|
||||
public static build<T extends Model>(model: T, data?: object): T {
|
||||
if (!data) {
|
||||
throw new Error('data is necessary.')
|
||||
}
|
||||
model.fill(data)
|
||||
return model
|
||||
}
|
||||
|
||||
protected fill(obj: object) {
|
||||
objectLoop(obj, (value, key) => {
|
||||
(this as object)[key] = value
|
||||
})
|
||||
}
|
||||
}
|
6
src/models/Other.d.ts
vendored
Normal file
6
src/models/Other.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export interface Variants {
|
||||
normal?: boolean
|
||||
reverse?: boolean
|
||||
holo?: boolean
|
||||
firstEdition?: boolean
|
||||
}
|
21
src/models/Serie.ts
Normal file
21
src/models/Serie.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { objectLoop } from '@dzeio/object-util'
|
||||
import Model from './Model'
|
||||
import SerieResume from './SerieResume'
|
||||
import SetResume from './SetResume'
|
||||
|
||||
export default class Serie extends SerieResume {
|
||||
public sets!: Array<SetResume>
|
||||
|
||||
protected fill(obj: object): void {
|
||||
objectLoop(obj, (value, key) => {
|
||||
switch (key) {
|
||||
case 'sets':
|
||||
this.sets = (value as Array<any>).map((it) => Model.build(new SetResume(this.sdk), it))
|
||||
break
|
||||
default:
|
||||
this[key] = value
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
24
src/models/SerieResume.ts
Normal file
24
src/models/SerieResume.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import type { Extension } from '../interfaces'
|
||||
import Model from './Model'
|
||||
import type Serie from './Serie'
|
||||
|
||||
export default class SerieResume extends Model {
|
||||
public id!: string
|
||||
public name!: string
|
||||
public logo?: string
|
||||
|
||||
/**
|
||||
* the the Card Image full URL
|
||||
*
|
||||
* @param {Quality} quality the quality you want your image to be in
|
||||
* @param {Extension} extension extension you want you image to be
|
||||
* @return the full card URL
|
||||
*/
|
||||
public getImageURL(extension: Extension = 'png'): string {
|
||||
return `${this.logo}.${extension}`
|
||||
}
|
||||
|
||||
public async getSerie(): Promise<Serie> {
|
||||
return (await this.sdk.serie.get(this.id))!
|
||||
}
|
||||
}
|
89
src/models/Set.ts
Normal file
89
src/models/Set.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import { objectLoop } from '@dzeio/object-util'
|
||||
import CardResume from './CardResume'
|
||||
import Model from './Model'
|
||||
import type { Variants } from './Other'
|
||||
import type SerieResume from './SerieResume'
|
||||
|
||||
// biome-ignore lint/suspicious/noShadowRestrictedNames: <explanation>
|
||||
export default class Set extends Model {
|
||||
public id!: string
|
||||
public name!: string
|
||||
public logo?: string
|
||||
public symbol?: string
|
||||
public serie!: SerieResume
|
||||
public tcgOnline?: string
|
||||
public variants?: Variants
|
||||
|
||||
public releaseDate!: string
|
||||
|
||||
/**
|
||||
* Designate if the set is usable in tournaments
|
||||
*
|
||||
* Note: this is specific to the set and if a
|
||||
* card is banned from the set it will still be true
|
||||
*/
|
||||
public legal!: {
|
||||
|
||||
/**
|
||||
* Ability to play in standard tournaments
|
||||
*/
|
||||
standard: boolean
|
||||
|
||||
/**
|
||||
* Ability to play in expanded tournaments
|
||||
*/
|
||||
expanded: boolean
|
||||
}
|
||||
|
||||
public cardCount!: {
|
||||
|
||||
/**
|
||||
* total of number of cards
|
||||
*/
|
||||
total: number
|
||||
|
||||
/**
|
||||
* number of cards officialy (on the bottom of each cards)
|
||||
*/
|
||||
official: number
|
||||
|
||||
/**
|
||||
* number of cards having a normal version
|
||||
*/
|
||||
normal: number
|
||||
|
||||
/**
|
||||
* number of cards having an reverse version
|
||||
*/
|
||||
reverse: number
|
||||
|
||||
/**
|
||||
* number of cards having an holo version
|
||||
*/
|
||||
holo: number
|
||||
|
||||
/**
|
||||
* Number of possible cards
|
||||
*/
|
||||
firstEd?: number
|
||||
}
|
||||
|
||||
public cards!: Array<CardResume>
|
||||
|
||||
public async getSerie() {
|
||||
return this.sdk.serie.get(this.serie.id)
|
||||
}
|
||||
|
||||
protected fill(obj: object): void {
|
||||
objectLoop(obj, (value, key) => {
|
||||
switch (key) {
|
||||
case 'cards':
|
||||
this.cards = (value as Array<any>).map((it) => Model.build(new CardResume(this.sdk), it))
|
||||
break
|
||||
default:
|
||||
this[key] = value
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
25
src/models/SetResume.ts
Normal file
25
src/models/SetResume.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import Model from './Model'
|
||||
import type TCGdexSet from './Set'
|
||||
|
||||
export default class SetResume extends Model {
|
||||
public id!: string
|
||||
public name!: string
|
||||
public logo?: string
|
||||
public symbol?: string
|
||||
public cardCount!: {
|
||||
|
||||
/**
|
||||
* total of number of cards
|
||||
*/
|
||||
total: number
|
||||
|
||||
/**
|
||||
* number of cards officialy (on the bottom of each cards)
|
||||
*/
|
||||
official: number
|
||||
}
|
||||
|
||||
public async getSet(): Promise<TCGdexSet> {
|
||||
return (await this.sdk.set.get(this.id))!
|
||||
}
|
||||
}
|
21
src/models/StringEndpoint.ts
Normal file
21
src/models/StringEndpoint.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { objectLoop } from '@dzeio/object-util'
|
||||
import CardResume from './CardResume'
|
||||
import Model from './Model'
|
||||
|
||||
export default class StringEndpoint extends Model {
|
||||
public name!: string
|
||||
public cards!: Array<CardResume>
|
||||
|
||||
protected fill(obj: object): void {
|
||||
objectLoop(obj, (value, key) => {
|
||||
switch (key) {
|
||||
case 'cards':
|
||||
this.cards = (value as Array<any>).map((it) => Model.build(new CardResume(this.sdk), it))
|
||||
break
|
||||
default:
|
||||
this[key] = value
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import unfetch from 'unfetch'
|
||||
import TCGdex from './tcgdex'
|
||||
|
||||
TCGdex.fetch = window.fetch ?? unfetch as any
|
||||
TCGdex.fetch = window.fetch
|
||||
|
||||
export default TCGdex
|
||||
|
261
src/tcgdex.ts
261
src/tcgdex.ts
@ -1,24 +1,161 @@
|
||||
import RequestWrapper from './Request'
|
||||
import { Serie, Set, Card, CardResume, SerieList, SetList, SupportedLanguages, StringEndpoint } from './interfaces'
|
||||
type Endpoint = 'cards' | 'categories' | 'dex-ids' | 'energy-types' | 'hp' | 'illustrators' | 'rarities' | 'regulation-marks' | 'retreats' | 'series' | 'sets' | 'stages' | 'suffixes' | 'trainer-types' | 'types' | 'variants'
|
||||
import type CacheInterface from '@cachex/core'
|
||||
import LocalStorageCache from '@cachex/web-storage'
|
||||
import MemoryCache from '@cachex/memory'
|
||||
import Query from './Query'
|
||||
import Endpoint from './endpoints/Endpoint'
|
||||
import SimpleEndpoint from './endpoints/SimpleEndpoint'
|
||||
import type {
|
||||
Card,
|
||||
CardResume,
|
||||
Endpoints,
|
||||
Serie,
|
||||
SerieList,
|
||||
SetList,
|
||||
StringEndpoint,
|
||||
SupportedLanguages,
|
||||
Set as TCGdexSet
|
||||
} from './interfaces'
|
||||
import CardModel from './models/Card'
|
||||
import CardResumeModel from './models/CardResume'
|
||||
import Model from './models/Model'
|
||||
import SerieModel from './models/Serie'
|
||||
import SerieResume from './models/SerieResume'
|
||||
import SetModel from './models/Set'
|
||||
import SetResumeModel from './models/SetResume'
|
||||
import StringEndpointModel from './models/StringEndpoint'
|
||||
import { ENDPOINTS, detectContext } from './utils'
|
||||
import { version } from './version'
|
||||
|
||||
const ENDPOINTS: Array<Endpoint> = ['cards', 'categories', 'dex-ids', 'energy-types', 'hp', 'illustrators', 'rarities', 'regulation-marks', 'retreats', 'series', 'sets', 'stages', 'suffixes', 'trainer-types', 'types', 'variants']
|
||||
const BASE_URL = 'https://api.tcgdex.net/v2'
|
||||
export default class TCGdex {
|
||||
|
||||
public static fetch: typeof fetch
|
||||
/**
|
||||
* How the remote data is going to be fetched
|
||||
*/
|
||||
public static fetch: typeof fetch = fetch
|
||||
|
||||
/**
|
||||
* @deprecated to change the lang use `this.lang`
|
||||
* @deprecated to change the lang use {@link TCGdex.getLang} and {@link TCGdex.setLang}
|
||||
*/
|
||||
public static defaultLang: SupportedLanguages = 'en'
|
||||
|
||||
public constructor(public lang?: SupportedLanguages) {}
|
||||
/**
|
||||
* the previously hidden caching system used by TCGdex to not kill the API
|
||||
*/
|
||||
public cache: CacheInterface =
|
||||
detectContext() === 'browser' ? new LocalStorageCache('tcgdex-cache') : new MemoryCache()
|
||||
|
||||
/**
|
||||
* the default cache TTL, only subsequent requests will have their ttl changed
|
||||
*/
|
||||
public cacheTTL = 60 * 60
|
||||
|
||||
// random card/set/serie endpoints
|
||||
public readonly random = {
|
||||
card: async (): Promise<CardModel> => {
|
||||
const res = await this.fetch('random', 'card')
|
||||
return Model.build(new CardModel(this), res)
|
||||
},
|
||||
set: async (): Promise<SetModel> => {
|
||||
const res = await this.fetch('random', 'set')
|
||||
return Model.build(new SetModel(this), res)
|
||||
},
|
||||
serie: async (): Promise<SerieModel> => {
|
||||
const res = await this.fetch('random', 'serie')
|
||||
return Model.build(new SerieModel(this), res)
|
||||
}
|
||||
}
|
||||
|
||||
public readonly card = new Endpoint(this, CardModel, CardResumeModel, 'cards')
|
||||
public readonly set = new Endpoint(this, SetModel, SetResumeModel, 'sets')
|
||||
public readonly serie = new Endpoint(this, SerieModel, SerieResume, 'series')
|
||||
|
||||
public readonly type = new SimpleEndpoint(this, StringEndpointModel, 'types')
|
||||
public readonly retreat = new SimpleEndpoint(this, StringEndpointModel, 'retreats')
|
||||
public readonly rarity = new SimpleEndpoint(this, StringEndpointModel, 'rarities')
|
||||
public readonly illustrator = new SimpleEndpoint(this, StringEndpointModel, 'illustrators')
|
||||
public readonly hp = new SimpleEndpoint(this, StringEndpointModel, 'hp')
|
||||
public readonly categorie = new SimpleEndpoint(this, StringEndpointModel, 'categories')
|
||||
public readonly dexID = new SimpleEndpoint(this, StringEndpointModel, 'dex-ids')
|
||||
public readonly energyType = new SimpleEndpoint(this, StringEndpointModel, 'energy-types')
|
||||
public readonly regulationMark = new SimpleEndpoint(this, StringEndpointModel, 'regulation-marks')
|
||||
public readonly stage = new SimpleEndpoint(this, StringEndpointModel, 'stages')
|
||||
public readonly suffixe = new SimpleEndpoint(this, StringEndpointModel, 'suffixes')
|
||||
public readonly trainerType = new SimpleEndpoint(this, StringEndpointModel, 'trainer-types')
|
||||
public readonly variant = new SimpleEndpoint(this, StringEndpointModel, 'variants')
|
||||
|
||||
private lang: SupportedLanguages = 'en'
|
||||
private endpointURL = 'https://api.tcgdex.net/v2'
|
||||
|
||||
public constructor(lang: SupportedLanguages = 'en') {
|
||||
this.setLang(lang)
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use the constructor parameter or {@link TCGdex.setLang} when in an instance
|
||||
*/
|
||||
public static setDefaultLang(lang: SupportedLanguages) {
|
||||
TCGdex.defaultLang = lang
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link TCGdex.setLang} when in an instance
|
||||
*/
|
||||
public static getDefaultLang(): SupportedLanguages {
|
||||
return TCGdex.defaultLang
|
||||
}
|
||||
|
||||
/**
|
||||
* the endpoint URL
|
||||
* ex: `https://api.tcgdex.net/v2`
|
||||
* @param endpoint the url
|
||||
*/
|
||||
public setEndpoint(endpoint: string) {
|
||||
this.endpointURL = endpoint
|
||||
}
|
||||
public getEndpoint(): string {
|
||||
return this.endpointURL
|
||||
}
|
||||
|
||||
/**
|
||||
* set the current cache methodology
|
||||
* @param cache the cache to use
|
||||
*/
|
||||
public setCache(cache: CacheInterface) {
|
||||
this.cache = cache
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current cache methodology
|
||||
* @param cache the cache to use
|
||||
*/
|
||||
public getCache(): CacheInterface {
|
||||
return this.cache
|
||||
}
|
||||
|
||||
/**
|
||||
* the endpoint URL
|
||||
* ex: `https://api.tcgdex.net/v2`
|
||||
* @param endpoint the url
|
||||
*/
|
||||
public setCacheTTL(seconds: number) {
|
||||
this.cacheTTL = seconds
|
||||
}
|
||||
/**
|
||||
* get the current useed cache ttl in seconds
|
||||
* @returns the cache ttl in seconds
|
||||
*/
|
||||
public getCacheTTL(): number {
|
||||
return this.cacheTTL
|
||||
}
|
||||
|
||||
public getLang(): SupportedLanguages {
|
||||
return this.lang ?? TCGdex.defaultLang ?? 'en'
|
||||
}
|
||||
|
||||
public setLang(lang: SupportedLanguages) {
|
||||
this.lang = lang
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to easily fetch a card using both it's global id and it's local ID
|
||||
* @param id the card global/local ID
|
||||
@ -47,7 +184,7 @@ export default class TCGdex {
|
||||
/**
|
||||
* @deprecated use `this.fetch('sets', set)`
|
||||
*/
|
||||
public async fetchSet(set: string): Promise<Set | undefined> {
|
||||
public async fetchSet(set: string): Promise<TCGdexSet | undefined> {
|
||||
return this.fetch('sets', set)
|
||||
}
|
||||
|
||||
@ -104,7 +241,14 @@ export default class TCGdex {
|
||||
* @param endpoint_0 'sets'
|
||||
* @param endpoint_1 {string} the set name or ID
|
||||
*/
|
||||
public async fetch(...endpoint: ['sets', string]): Promise<Set | undefined>
|
||||
public async fetch(...endpoint: ['sets', string]): Promise<TCGdexSet | undefined>
|
||||
|
||||
/**
|
||||
* Fetch a random element
|
||||
* @param endpoint_0 'random'
|
||||
* @param endpoint_1 {'set' | 'card' | 'serie'} the type of random element you want to get
|
||||
*/
|
||||
public async fetch(...endpoint: ['random', 'set' | 'card' | 'serie']): Promise<Card | TCGdexSet | Serie | undefined>
|
||||
|
||||
/**
|
||||
* Fetch every sets
|
||||
@ -148,7 +292,7 @@ export default class TCGdex {
|
||||
* @param endpoint_1 {string} (Optionnal) some details to go from the index file to the item file (mostly the ID/name)
|
||||
* @param endpoint_2 {string} (Optionnal) only for sets the card local ID to fetch the card through the set
|
||||
*/
|
||||
public async fetch(...endpoint: Array<Endpoint | string>): Promise<any | undefined> {
|
||||
public async fetch<T = object>(...endpoint: Array<Endpoints | string>): Promise<T | undefined> {
|
||||
if (endpoint.length === 0) {
|
||||
throw new Error('endpoint to fetch is empty!')
|
||||
}
|
||||
@ -157,29 +301,104 @@ export default class TCGdex {
|
||||
if (!ENDPOINTS.includes(baseEndpoint)) {
|
||||
throw new Error(`unknown endpoint to fetch! (${baseEndpoint})`)
|
||||
}
|
||||
return this.makeRequest(baseEndpoint, ...endpoint)
|
||||
return this.actualFetch<T>(this.getFullURL([baseEndpoint, ...endpoint]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to make the request and normalize the whole path
|
||||
* @param endpoint the endpoint to fetch
|
||||
* @param query the query
|
||||
*/
|
||||
private makeRequest<T = any>(...url: Array<string | number>) {
|
||||
public async fetchWithQuery<T = object>(
|
||||
endpoint: [Endpoints, ...Array<string>],
|
||||
query?: Array<{ key: string, value: string | number | boolean }>
|
||||
): Promise<T | undefined> {
|
||||
if (endpoint.length === 0) {
|
||||
throw new Error('endpoint to fetch is empty!')
|
||||
}
|
||||
const baseEndpoint = endpoint[0].toLowerCase() as Endpoints
|
||||
if (!ENDPOINTS.includes(baseEndpoint)) {
|
||||
throw new Error(`unknown endpoint to fetch! (${baseEndpoint})`)
|
||||
}
|
||||
return this.actualFetch<T>(this.getFullURL(endpoint, query))
|
||||
}
|
||||
|
||||
/**
|
||||
* format the final URL
|
||||
*/
|
||||
private getFullURL(
|
||||
url: Array<string | number>,
|
||||
searchParams?: Array<{ key: string, value: string | number | boolean }>
|
||||
): string {
|
||||
// Normalize path
|
||||
const path = url.map((subPath) => encodeURI(
|
||||
subPath
|
||||
let path = url.map(this.encode).join('/')
|
||||
|
||||
// handle the Search Params
|
||||
if (searchParams) {
|
||||
path += '?' + searchParams.map((it) => `${this.encode(it.key)}=${this.encode(it.value)}`).join('&')
|
||||
}
|
||||
|
||||
// return with the endpoint and all the shit
|
||||
return `${this.getEndpoint()}/${this.getLang()}/${path}`
|
||||
}
|
||||
|
||||
private async actualFetch<T = object>(path: string): Promise<T | undefined> {
|
||||
// get and return the cached value if available
|
||||
const cached = this.cache.get(path)
|
||||
if (cached) {
|
||||
return cached as T
|
||||
}
|
||||
|
||||
// the actual Fetch :D
|
||||
const resp = await TCGdex.fetch(path, {
|
||||
headers: {
|
||||
'user-agent': `@tcgdex/javascript-sdk/${version}`
|
||||
}
|
||||
})
|
||||
|
||||
// throw if a server-side error is occured
|
||||
if (resp.status >= 500) {
|
||||
try {
|
||||
const json = JSON.stringify(await resp.json())
|
||||
throw new Error(json)
|
||||
} catch {
|
||||
throw new Error('TCGdex Server responded with an invalid error :(')
|
||||
}
|
||||
}
|
||||
|
||||
// response is not valid :O
|
||||
if (resp.status !== 200) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
// parse, put to cache and return
|
||||
const json = await resp.json()
|
||||
this.cache.set(path, json, this.cacheTTL)
|
||||
return json as T
|
||||
}
|
||||
|
||||
/**
|
||||
* encode a string to be used in an url
|
||||
* @param str the string to encode to URL
|
||||
* @returns the encoded string
|
||||
*/
|
||||
private encode(str: string | number | boolean): string {
|
||||
return encodeURI(
|
||||
str
|
||||
// Transform numbers to string
|
||||
.toString()
|
||||
// replace this special character with an escaped one
|
||||
.replace('?', '%3F')
|
||||
// normalize the string
|
||||
.normalize('NFC')
|
||||
// remove some special chars by nothing
|
||||
// remove some special chars
|
||||
// eslint-disable-next-line no-misleading-character-class
|
||||
.replace(/["'\u0300-\u036f]/gu, '')
|
||||
)).join('/')
|
||||
return RequestWrapper.fetch<T>(`${BASE_URL}/${this.getLang()}/${path}`)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export * from './interfaces'
|
||||
|
||||
export * from './models/Card'
|
||||
export {
|
||||
Query
|
||||
}
|
||||
|
20
src/utils.ts
Normal file
20
src/utils.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import type { Endpoints } from './interfaces'
|
||||
|
||||
/**
|
||||
* detect the current running context ofthe program
|
||||
*/
|
||||
export function detectContext(): 'browser' | 'server' {
|
||||
try {
|
||||
const isBrowser = !!window
|
||||
return isBrowser ? 'browser' : 'server'
|
||||
} catch {
|
||||
return 'server'
|
||||
}
|
||||
}
|
||||
|
||||
export const ENDPOINTS: Array<Endpoints> = [
|
||||
'cards', 'categories', 'dex-ids', 'energy-types',
|
||||
'hp', 'illustrators', 'rarities', 'regulation-marks',
|
||||
'retreats', 'series', 'sets', 'stages', 'suffixes',
|
||||
'trainer-types', 'types', 'variants', 'random'
|
||||
] as const
|
@ -1,8 +1,10 @@
|
||||
{
|
||||
"extends": "./node_modules/@dzeio/config/tsconfig.base",
|
||||
"include": ["./src/tcgdex.node.ts"],
|
||||
"compilerOptions": {
|
||||
"target": "ES2015",
|
||||
"rootDir": "./src",
|
||||
}
|
||||
"outDir": "dist",
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"exclude": [
|
||||
"__tests__"
|
||||
]
|
||||
}
|
||||
|
Reference in New Issue
Block a user