GithubHelp home page GithubHelp logo

chirivulpes / scryfall-sdk Goto Github PK

View Code? Open in Web Editor NEW
94.0 4.0 13.0 561 KB

A Node.js SDK for https://scryfall.com/docs/api, written in TypeScript.

License: MIT License

TypeScript 99.73% JavaScript 0.27%
scryfall scryfall-sdk scryfall-api typescript magic-the-gathering mtg mtg-cards mtg-api

scryfall-sdk's Introduction

scryfall-sdk

npm GitHub issues Travis

A Node.js SDK for Scryfall written in Typescript.

As of October 23rd, 2023, all features described in the Scryfall documentation are supported. If you see something that isn't supported, make an issue!

Installation

npm install scryfall-sdk

Using a node.js version older than v18?

Install the axios dependency alongside scryfall-sdk and it will automatically use it.

Basic Example Usage

import * as Scry from "scryfall-sdk";

// ...in some function somewhere...
const chalice = await Scry.Cards.byName("Chalice of the Void");
console.log(chalice.name, chalice.set); // "Chalice of the Void", "a25"

const prints = await chalice.getPrints();
console.log(prints.length); // 7

This module supports all features of Scryfall, along with automatically paginating through results, downloading bulk data streams, etc. There's also documentation on every single part of the SDK:

Contributing

Thanks for wanting to help out! Here's the setup you'll have to do:

git clone https://github.com/ChiriVulpes/scryfall-sdk
cd scryfall-sdk
npm install

You can now make changes to the repository.

To compile, then test:

gulp build

To compile and then test on every file change:

gulp watch

MIT License

Copyright 2017-2022 Chiri Vulpes

scryfall-sdk's People

Contributors

apkiernan avatar chirivulpes avatar codetheweb avatar dantolini avatar dependabot[bot] avatar furgin avatar kevinlowe0x3f7 avatar lordnox avatar mlavina avatar noriokaki avatar sili3011 avatar studio315b avatar thejoecode avatar usersaurus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

scryfall-sdk's Issues

Failed Fuzzy search returns a strange format

If I:

const Scry = require("scryfall-sdk");
await Scry.Cards.byName("rstdrdtst", true);

I get an object like this, which doesn't actually tell me that I've encountered an error or what the error was:

{
  "data": [],
  "not_found": []
}

However querying the actual Scryfall API with a similar request (curl 'https://api.scryfall.com/cards/named?fuzzy=rstdrdtst') , I get a much more helpful response:

{
  "object": "error",
  "code": "not_found",
  "status": 404,
  "details": "No cards found matching “rstdrdtst”"
}

It would be great if we could get this response instead.

Update type Card

Trying to assign a downloaded literal to a variable of type Card shows that

  • frame expects years to be numbers instead of strings,
  • set_type is missing and
  • artist_ids is missing.

Search for a set

Would it be possible to implement some way for searching for a set by it's name? If not, I'm willing to make a PR.

TsLint assumes system file structure

TsLint attempts to enherit from "../tslint.json/tslint.json" which is outside the bounds of the git repository. I was able to find your tslint repo and set it up appropriately, but this seems sub optimal, and is not in your setup instructions. I would suggest either making your tslint rules a package that you require, or as a git submodule.

webpack - node:events error in EventEmitter

I'm getting the following error when I installed and tried to use the latest version 4.1.1:

Module build failed: UnhandledSchemeError: Reading from "node:events" is not handled by plugins (Unhandled scheme). Webpack supports "data:" and "file:" URIs by default. You may need an additional plugin to handle "node:" URIs. Import trace for requested module: node:events ./node_modules/scryfall-sdk/out/util/EventEmitter.js ./node_modules/scryfall-sdk/out/util/MagicEmitter.js ./node_modules/scryfall-sdk/out/api/Cards.js ./node_modules/scryfall-sdk/out/Scry.js

I am using it in a Next.js project, v13, and using Node 18.

Then I tried installing version 3.3.0 and the error went away and everything seems to work fine. So I'm guessing it's something to do with switching from axios to fetch.

I have tried changing Node versions and tried adding axios explicitly but none of that seems to work with version 4.

Use a different network library so the sdk is usable in browser

The request and request-promise libraries do not work in the browser, (which is as intended) but it would be easy to replace them with a cross platform solution such as axios. I've started working on this in a fork for my own use, but I'd love to upstream my change for everyone to enjoy.

Test failures after Scryfall API changes

Tests for getImageURI - Looks like the host name for the image URLs have changed.
BulkData compressed_size - This field appears to have changed name to 'size'

this._listeners[eventName] is not iterable

Running a fairly simple search:

const commanders = [];
Scry.Cards.search('is:commander legal:commander game:paper')
	.on('data', card => {
		commanders.push(card);
	})
	.on('end', () => {
		console.log(`found ${commanders.length} results`);
	});

But getting this error:

<path>\node_modules\scryfall-sdk\out\util\EventEmitter.js:70
        for (const listener of this._listeners[eventName])
                                              ^

TypeError: this._listeners[eventName] is not iterable
    at MagicEmitter.emit (<path>\node_modules\scryfall-sdk\out\util\EventEmitter.js:70:47)
    at MagicEmitter.emit (<path>\node_modules\scryfall-sdk\out\util\MagicEmitter.js:51:22)
    at <path>\node_modules\scryfall-sdk\out\api\Cards.js:433:35
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Why add empty card_faces array?

In Cards.ts the constructor adds an almost empty card_faces array if the response from Scryfall is not present.

Why does this happen? I can't tell this is a mistake or I am misunderstanding how to use this array. Using the raw Scryfall API I would check if the faces array existed, to check where to find data about the card (either in the face or in the card object).

Pagination for /cards endpoint using Cards.all()

First of all, thanks for making this library! Definitely simplifies things 👍

It doesn't seem like it's possible to request a specific page to retrieve using Cards.all().
Every time this function is called it starts getting results from page 1. It would be nice if I could provide a page parameter to the function - I can then limit the returned items myself and create my own pagination logic.

What do you think about this? I'll happily help implementing this, but my TypeScript knowledge is not that great 😄

`gulp build` step emits declaration files with errors.

Summary
A number of declaration files in the scryfall-sdk package contain errors, resulting in build errors on my end.

Details
When using scryfall-sdk in my typescript project, I noticed that errors would pop up when building:

node_modules/scryfall-sdk/out/api/Cards.d.ts:132:5 - error TS2411: Property 'tcgplayer' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

132     tcgplayer?: string | null;
        ~~~~~~~~~

node_modules/scryfall-sdk/out/api/Cards.d.ts:133:5 - error TS2411: Property 'cardmarket' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

133     cardmarket?: string | null;
        ~~~~~~~~~~

node_modules/scryfall-sdk/out/api/Cards.d.ts:134:5 - error TS2411: Property 'cardhoarder' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

134     cardhoarder?: string | null;
        ~~~~~~~~~~~

node_modules/scryfall-sdk/out/api/Cards.d.ts:138:5 - error TS2411: Property 'gatherer' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

138     gatherer?: string | null;
        ~~~~~~~~

node_modules/scryfall-sdk/out/api/Cards.d.ts:139:5 - error TS2411: Property 'tcgplayer_decks' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

139     tcgplayer_decks?: string | null;
        ~~~~~~~~~~~~~~~

node_modules/scryfall-sdk/out/api/Cards.d.ts:140:5 - error TS2411: Property 'edhrec' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

140     edhrec?: string | null;
        ~~~~~~

node_modules/scryfall-sdk/out/api/Cards.d.ts:141:5 - error TS2411: Property 'mtgtop8' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

141     mtgtop8?: string | null;
        ~~~~~~~

Found 7 errors.

I checked out this repo and looked at the files and the way they are created. Running gulp build finished without error, but the Cards.d.ts file it created does contain the errors I noticed in my build.
image

It looks like your 'gulp build' step is somehow not giving you the feedback that the regular typescript compiler does.
With a small change to your tsconfig:

{
    "compilerOptions": {
        "target": "es2015",
        "module": "commonjs",
        "moduleResolution": "node",
        "forceConsistentCasingInFileNames": true,
        "removeComments": true,
        "declaration": true,
        "strict": true,
        "strictPropertyInitialization": false,
        "noImplicitReturns": true,
        "noUnusedLocals": true,
        "noUnusedParameters": false,
        "noEmitOnError": true,
        "outDir": "./out"
    },
    "files": [
        "src/Scry.ts"
    ]
}

Specifically the noEmitOnError, outDir and files fields, I was able to run the typescript compiler directly, without gulp.
Output of npx tsc:

src/api/Cards.ts:151:2 - error TS2411: Property 'tcgplayer' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

151  tcgplayer?: string | null;
     ~~~~~~~~~

src/api/Cards.ts:152:2 - error TS2411: Property 'cardmarket' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

152  cardmarket?: string | null;
     ~~~~~~~~~~

src/api/Cards.ts:153:2 - error TS2411: Property 'cardhoarder' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

153  cardhoarder?: string | null;
     ~~~~~~~~~~~

src/api/Cards.ts:158:2 - error TS2411: Property 'gatherer' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

158  gatherer?: string | null;
     ~~~~~~~~

src/api/Cards.ts:159:2 - error TS2411: Property 'tcgplayer_decks' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

159  tcgplayer_decks?: string | null;
     ~~~~~~~~~~~~~~~

src/api/Cards.ts:160:2 - error TS2411: Property 'edhrec' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

160  edhrec?: string | null;
     ~~~~~~

src/api/Cards.ts:161:2 - error TS2411: Property 'mtgtop8' of type 'string | null | undefined' is not assignable to string index type 'string | null'.

161  mtgtop8?: string | null;
     ~~~~~~~

src/api/Cards.ts:381:63 - error TS2322: Type 'string | undefined' is not assignable to type 'string | number'.
  Type 'undefined' is not assignable to type 'string | number'.

381     return this.query<Card>(["cards", setCode, collectorNumber, lang]);
                                                                    ~~~~

src/api/Cards.ts:438:36 - error TS2488: Type 'CardIdentifier[] | undefined' must have a '[Symbol.iterator]()' method that returns an iterator.

438             emitter.emitAll("not_found", ...not_found);
                                                ~~~~~~~~~

src/util/MagicQuerier.ts:62:33 - error TS2345: Argument of type 'SearchError | undefined' is not assignable to parameter of type 'SearchError'.
  Type 'undefined' is not assignable to type 'SearchError'.

62              if (result || !this.canRetry(lastError)) break;
                                             ~~~~~~~~~

Found 10 errors.

The first 7 errors are the same as the ones I got in my build, which was to be expected.
The last 3 errors are very surprising to me, they seem to indicate actual problems with the build and I don't know why gulp has let those slip through.

Possible solutions on your end

  • Change the settings in gulp to make the errors visible and the build to fail. My knowledge of gulp is limited so I don't know a way to do this off the top of my head.
  • Don't rely on gulp to build your typescript files. With the tsconfig changes I mentioned earlier you can use the typescript compiler directly, which will display the errors. There are several alternatives for running scripts automatically (including watch) that do not require gulp, like npm-watch or typescript watch.

Workarounds on my end

  • Add skipLibCheck to the tsconfig.
    • Undesirable because this will disable all type checking against library declaration files.

Further notes
I would be happy to help develop a solution for this, but changing of replacing the build system is not something I am comfortable doing without approval of the maintainers.

Possibly related to (or regression of) #11 ?

Runtime error with interfaces exported from Scry module: Cannot read property 'collection' of undefined

I'm getting the following error when I start my React ts app.

TypeError: Cannot read property 'collection' of undefined

   13 | 
   14 | componentDidMount() {
   15 |   const identifiers = cardList.map((cardName) => ({ name: cardName }));
>  16 |   Scry.Cards.collection(...identifiers)
   17 | ^   .waitForAll()
   18 |     .then((collection) => {
   19 |       this.setState({ collection: collection });

The same thing happens with everything I export from Scry, like Scry.CardIdentifier.

I think I'm using it as I saw in the documentation.

version
scryfall-sdk v1.6.3
typescript v3.7.5
node v12.14.1

Diffrent number of cards

Hi when I use Scryfall.Cards.search('s:' + 'kld').waitForAll().then, I got 439 cards for result.
But if I use https://api.scryfall.com/cards/search?q=s:kld, I get 264 cards for result. Should they not be the same number? I know I get duplicates and the have the same id from Scryfall. One example is "Key of the city".

Installing on vite

Hi,

Installing on new vite project throws :
Uncaught TypeError: Class extends value undefined is not a constructor or null at node_modules/scryfall-sdk/out/util/MagicEmitter.js (MagicEmitter.js:81:13) at __require (chunk-RSJERJUL.js?v=1b33f517:3:50) at node_modules/scryfall-sdk/out/api/Cards.js (Cards.js:21:24) at __require (chunk-RSJERJUL.js?v=1b33f517:3:50) at node_modules/scryfall-sdk/out/Scry.js (Scry.js:18:17) at __require (chunk-RSJERJUL.js?v=1b33f517:3:50) at Scry.js:89:26

my package.json
{ "name": "mtg-draft", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vue-tsc && vite build", "preview": "vite preview" }, "dependencies": { "scryfall-sdk": "^4.0.1", "vue": "^3.2.45" }, "devDependencies": { "@vitejs/plugin-vue": "^4.0.0", "typescript": "^4.9.3", "vite": "^4.1.0", "vue-tsc": "^1.0.24" } }

Property 'gatherer' of type 'string | undefined' is not assignable to string index type 'string'. importing the library in a clean project.

Importing the library in a clean create-react-app ts project is throwing the following error in IScry.d.ts

Property 'gatherer' of type 'string | undefined' is not assignable to string index type 'string'.

The same is happening in the following interfaces

export interface RelatedUris { gatherer?: string; tcgplayer_decks?: string; edhrec?: string; mtgtop8?: string; [key: string]: string; }

export interface PurchaseUris { amazon?: string; ebay?: string; tcgplayer?: string; magiccardmarket?: string; cardhoarder?: string; card_kingdom?: string; mtgo_traders?: string; coolstuffinc?: string; [key: string]: string; }

Removing ? in all these types fix the problem (and, as far as I know, that info is always populated by scryfall api).

Don't know if I'm missing something. If not, I'm able to PR the change.

Timeout with Cards.all()

Hi,
With your sdk i get an ETIMEOUT when i try to Cards.all() after 10 minutes. But all cards are not fetched

Add options arbitrary options argument

Currently there are options available in the scryfall api like "unique" which allows you to get different versions of cards. If I'm understanding correctly, it seems there is no way to add in these extra options.

I'd like to add an extra paramater accepting an object of arbitrary parameters that will be merged with the request object. For example, instead of search sending just

{q: search} it would send {q: search, ...otherOptions}

Would you accept this PR?

Card Imagery

Hiya,

How can I get card imagery through this SDK?

`.cancelAfterPage().waitForAll()` never resolves

I believe I've identified a bug. If you use await Scry.Cards.search(some_query).cancelAfterPage().waitForAll();, the promise never resolves so the function hangs forever. This is because waitForAll only resolves on end:

public async waitForAll () {
return new Promise<MagicArray<T, NOT_FOUND>>((resolve, reject) => {
const results: MagicArray<T, NOT_FOUND> = [] as any;
results.not_found = [];
this.on("data", result => { results.push(result); });
this.on("not_found", notFound => { results.not_found.push(notFound); });
this.on("end", () => resolve(results));
this.on("error", reject);
});
}

However if the emitter gets cancelled due to cancelAfterPage(), we skip emitting end, even though the query has successfully completed:

if (!emitter.cancelled)
emitter.emit("end");

Here is a reproducible example:

import * as Scry from "scryfall-sdk";

try {
    const cards = await Scry.Cards.search("lang:fr").cancelAfterPage().waitForAll();
    console.log(cards);
}
catch (e) {
    console.error(e);
}

It seems to immediately exit, because the promise never resolves or rejects, but also there are no pending events.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.