├── .babelrc
├── .env.default
├── .eslintrc.json
├── .gitignore
├── .snyk
├── LICENSE.md
├── README.md
├── doc
├── CHANGELOG.md
├── README.md
└── ROADMAP.md
├── knexfile.js
├── package.json
├── scripts
├── populate.js
├── reset.js
└── utilities
│ ├── apollo.js
│ ├── cards.js
│ ├── colors.js
│ ├── index.js
│ ├── languages.js
│ ├── sets.js
│ └── types.js
├── setup.js
├── src
├── config
│ ├── bookshelf.config.js
│ ├── graphql.config.js
│ └── server.config.js
├── models
│ ├── index.js
│ ├── lists
│ │ ├── abilityTypeCards.js
│ │ ├── abilityTypes.js
│ │ ├── artistCards.js
│ │ ├── blockSets.js
│ │ ├── cardColors.js
│ │ ├── categories.js
│ │ ├── categoryCards.js
│ │ ├── colors.js
│ │ ├── formatSets.js
│ │ ├── icons.js
│ │ ├── images.js
│ │ ├── index.js
│ │ ├── keywordCards.js
│ │ ├── keywords.js
│ │ ├── legalities.js
│ │ ├── legalityCards.js
│ │ ├── nameCards.js
│ │ ├── names.js
│ │ ├── printings.js
│ │ ├── rulingCards.js
│ │ ├── rulings.js
│ │ ├── sides.js
│ │ ├── subtypes.js
│ │ ├── supertypes.js
│ │ ├── types.js
│ │ └── variations.js
│ └── tables
│ │ ├── abilityType.js
│ │ ├── artist.js
│ │ ├── block.js
│ │ ├── booster.js
│ │ ├── card.js
│ │ ├── category.js
│ │ ├── color.js
│ │ ├── colorIdentity.js
│ │ ├── format.js
│ │ ├── icon.js
│ │ ├── image.js
│ │ ├── index.js
│ │ ├── keyword.js
│ │ ├── language.js
│ │ ├── languageCode.js
│ │ ├── layout.js
│ │ ├── legality.js
│ │ ├── name.js
│ │ ├── printing.js
│ │ ├── rarity.js
│ │ ├── ruling.js
│ │ ├── set.js
│ │ ├── setType.js
│ │ ├── subtype.js
│ │ ├── supertype.js
│ │ └── type.js
├── routes
│ ├── example
│ │ └── example.js
│ ├── index.js
│ ├── login
│ │ └── login.js
│ ├── ping
│ │ └── ping.js
│ └── signup
│ │ └── signup.js
├── schema.js
├── server.js
└── types
│ ├── abilityType.js
│ ├── artist.js
│ ├── block.js
│ ├── booster.js
│ ├── card.js
│ ├── category.js
│ ├── color.js
│ ├── colorIdentity.js
│ ├── format.js
│ ├── icon.js
│ ├── image.js
│ ├── index.js
│ ├── keyword.js
│ ├── language.js
│ ├── languageCode.js
│ ├── layout.js
│ ├── legality.js
│ ├── name.js
│ ├── printing.js
│ ├── rarity.js
│ ├── ruling.js
│ ├── set.js
│ ├── setType.js
│ ├── subtype.js
│ ├── supertype.js
│ ├── type.js
│ └── utilities
│ ├── create.js
│ ├── destroy.js
│ ├── index.js
│ ├── order.js
│ ├── read.js
│ ├── sort.js
│ └── update.js
├── test
└── karma.conf.js
├── wallaby.config.js
├── webpack.config.babel.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "transform-es2015-shorthand-properties",
4 | "transform-decorators-legacy",
5 | "transform-object-rest-spread",
6 | "transform-class-properties",
7 | "import-glob"
8 | ],
9 | "presets": [
10 | "es2015",
11 | [
12 | "env",
13 | {
14 | "targets": {
15 | "node": "current"
16 | },
17 | "modules": false,
18 | "loose": true,
19 | "useBuiltIns": true
20 | }
21 | ]
22 | ],
23 | "sourceMaps": "both"
24 | }
25 |
--------------------------------------------------------------------------------
/.env.default:
--------------------------------------------------------------------------------
1 | JWT_PUBLIC_KEY="rsa_public_key"
2 | JWT_PRIVATE_KEY="rsa_private_key"
3 | DB_HOST="database_host"
4 | DB_USERNAME="database_username"
5 | DB_PASSWORD="database_password"
6 | DB_NAME="database_name"
7 | HTTP="1337"
8 | HTTPS="8080"
9 | LOGLEVEL="info"
10 | LOGGLY_TOKEN="token"
11 | LOGGLY_SUBDOMAIN="subdomain"
12 | OPBEAT_APP_ID="app id"
13 | OPBEAT_ORGANIZATION_ID="org id"
14 | OPBEAT_SECRET_TOKEN="token"
15 | DD_API_KEY="datadog_api_key"
16 | NODE_ENV="development"
17 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "babel-eslint",
4 | "env": {
5 | "node": true
6 | },
7 | "ecmaFeatures": {
8 | "arrowFunctions": true,
9 | "blockBindings": true,
10 | "classes": true,
11 | "defaultParams": true,
12 | "destructuring": true,
13 | "forOf": true,
14 | "generators": false,
15 | "modules": true,
16 | "objectLiteralComputedProperties": true,
17 | "objectLiteralDuplicateProperties": false,
18 | "objectLiteralShorthandMethods": true,
19 | "objectLiteralShorthandProperties": true,
20 | "spread": true,
21 | "superInFunctions": true,
22 | "templateStrings": true,
23 | "jsx": false
24 | },
25 | "rules": {
26 | "strict": [2, "never"],
27 |
28 | "no-var": 2,
29 | "prefer-const": 0,
30 |
31 | "no-shadow": 2,
32 | "no-shadow-restricted-names": 2,
33 | "no-unused-vars": [2, {
34 | "vars": "local",
35 | "args": "none"
36 | }],
37 | "no-use-before-define": 0,
38 |
39 | "comma-dangle": [2, "never"],
40 | "no-cond-assign": [2, "always"],
41 | "no-debugger": 1,
42 | "no-alert": 1,
43 | "no-constant-condition": 1,
44 | "no-dupe-keys": 2,
45 | "no-duplicate-case": 2,
46 | "no-empty": 2,
47 | "no-ex-assign": 2,
48 | "no-extra-boolean-cast": 0,
49 | "no-extra-semi": 2,
50 | "no-func-assign": 2,
51 | "no-inner-declarations": 2,
52 | "no-invalid-regexp": 2,
53 | "no-irregular-whitespace": 2,
54 | "no-obj-calls": 2,
55 | "no-sparse-arrays": 2,
56 | "no-unreachable": 2,
57 | "use-isnan": 2,
58 | "block-scoped-var": 0,
59 |
60 | "consistent-return": 0,
61 | "curly": [2, "multi-line"],
62 | "default-case": 2,
63 | "dot-notation": [2, {
64 | "allowKeywords": true
65 | }],
66 | "eqeqeq": 2,
67 | "guard-for-in": 0,
68 | "no-caller": 2,
69 | "no-else-return": 2,
70 | "no-eq-null": 2,
71 | "no-eval": 2,
72 | "no-extend-native": 2,
73 | "no-extra-bind": 2,
74 | "no-fallthrough": 2,
75 | "no-floating-decimal": 2,
76 | "no-implied-eval": 2,
77 | "no-lone-blocks": 2,
78 | "no-loop-func": 2,
79 | "no-multi-str": 2,
80 | "no-native-reassign": 2,
81 | "no-new": 2,
82 | "no-new-func": 2,
83 | "no-new-wrappers": 2,
84 | "no-octal": 2,
85 | "no-octal-escape": 2,
86 | "no-param-reassign": 0,
87 | "no-proto": 2,
88 | "no-redeclare": 2,
89 | "no-script-url": 2,
90 | "no-self-compare": 2,
91 | "no-sequences": 2,
92 | "no-throw-literal": 2,
93 | "no-with": 2,
94 | "radix": 2,
95 | "vars-on-top": 2,
96 | "wrap-iife": [2, "any"],
97 | "yoda": 2,
98 |
99 | "indent": [2, 2],
100 | "brace-style": [2,
101 | "1tbs", {
102 | "allowSingleLine": true
103 | }],
104 | "quotes": [
105 | 2, "backtick", "avoid-escape"
106 | ],
107 | "camelcase": [2, {
108 | "properties": "never"
109 | }],
110 | "comma-spacing": [2, {
111 | "before": false,
112 | "after": true
113 | }],
114 | "comma-style": [2, "last"],
115 | "eol-last": 2,
116 | "func-names": 0,
117 | "new-cap": [2, {
118 | "newIsCap": true
119 | }],
120 | "no-multiple-empty-lines": [2, {
121 | "max": 2
122 | }],
123 | "no-nested-ternary": 2,
124 | "no-new-object": 2,
125 | "no-spaced-func": 2,
126 | "no-trailing-spaces": 2,
127 | "no-extra-parens": [2, "functions"],
128 | "no-underscore-dangle": 0,
129 | "one-var": [2, "never"],
130 | "padded-blocks": [2, "never"],
131 | "semi": ["error", "never"],
132 | "semi-spacing": [2, {
133 | "before": false,
134 | "after": true
135 | }],
136 | "keyword-spacing": [2, {
137 | "before": true,
138 | "after": true
139 | }],
140 | "space-before-blocks": 2,
141 | "space-before-function-paren": [2, "never"],
142 | "space-infix-ops": 2,
143 | "spaced-comment": [0, "always", {
144 | "exceptions": ["*"],
145 | "markers": ["*"]
146 | }]
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_STORE
3 | npm-debug.log*
4 | .env
5 | /dist
6 | /build
7 | /typings
8 | /.awcache
9 | /.ssh
10 | /electron.js*
11 | /release
12 | /test/coverage
13 | /src/scribe.sqlite
14 | /src/images
15 |
--------------------------------------------------------------------------------
/.snyk:
--------------------------------------------------------------------------------
1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
2 | version: v1.7.1
3 | ignore: {}
4 | # patches apply the minimum changes required to fix a vulnerability
5 | patch:
6 | 'npm:debug:20170905':
7 | - karma > socket.io > socket.io-adapter > debug:
8 | patched: '2017-10-12T13:05:35.644Z'
9 | - karma > socket.io > engine.io > debug:
10 | patched: '2017-10-12T13:05:35.644Z'
11 | - karma > socket.io > socket.io-client > debug:
12 | patched: '2017-10-12T13:05:35.644Z'
13 | - karma > socket.io > socket.io-client > engine.io-client > debug:
14 | patched: '2017-10-12T13:05:35.644Z'
15 | - karma > socket.io > socket.io-client > socket.io-parser > debug:
16 | patched: '2017-10-12T13:05:35.644Z'
17 | - karma > socket.io > socket.io-parser > debug:
18 | patched: '2017-10-12T13:05:35.644Z'
19 | - hapijs-status-monitor > socket.io > socket.io-adapter > socket.io-parser > debug:
20 | patched: '2017-10-12T13:05:35.644Z'
21 | - karma > socket.io > socket.io-adapter > socket.io-parser > debug:
22 | patched: '2017-10-12T13:05:35.644Z'
23 | - karma > socket.io > debug:
24 | patched: '2017-10-12T13:05:35.644Z'
25 | 'npm:ms:20170412':
26 | - karma > socket.io > socket.io-adapter > socket.io-parser > debug > ms:
27 | patched: '2017-10-12T13:05:35.644Z'
28 | - karma > socket.io > debug > ms:
29 | patched: '2017-10-12T13:05:35.644Z'
30 | - karma > socket.io > engine.io > debug > ms:
31 | patched: '2017-10-12T13:05:35.644Z'
32 | - karma > socket.io > socket.io-client > debug > ms:
33 | patched: '2017-10-12T13:05:35.644Z'
34 | - karma > socket.io > socket.io-client > engine.io-client > debug > ms:
35 | patched: '2017-10-12T13:05:35.644Z'
36 | - karma > socket.io > socket.io-client > socket.io-parser > debug > ms:
37 | patched: '2017-10-12T13:05:35.644Z'
38 | - karma > socket.io > socket.io-parser > debug > ms:
39 | patched: '2017-10-12T13:05:35.644Z'
40 | - hapijs-status-monitor > socket.io > socket.io-adapter > socket.io-parser > debug > ms:
41 | patched: '2017-10-12T13:05:35.644Z'
42 | - karma > socket.io > socket.io-adapter > debug > ms:
43 | patched: '2017-10-12T13:05:35.644Z'
44 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016-2017 Drake Costa drake@saeris.io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Scribe
2 | *A GraphQL Magic: The Gathering API Server*
3 |
4 | ## Table of Contents
5 |
6 | - [Getting Started](#start)
7 | - [Installation](#install)
8 | - [Running the Server Locally](#run)
9 | - [Running the Server in Production](#production)
10 | - [Resetting the Database](#reset)
11 | - [License Information](#license)
12 | - [Prior Art](#priorart)
13 | - [Further Reading](doc/README.md)
14 |
15 | ## Getting Started
16 |
17 | > *[Back to Top](#contents)*
18 |
19 | ## Installation
20 |
21 | Before you start, make sure you have a working [NodeJS](http://nodejs.org/) environment, with NPM 3. Preferably use [Yarn](https://yarnpkg.com/) instead of NPM for installation of packages to ensure that you'll use exactly the same dependencies as the project.
22 |
23 | From the project folder, execute the following command:
24 |
25 | ```shell
26 | npm install
27 | ```
28 |
29 | Or if you are using Yarn, execute this command instead:
30 |
31 | ```shell
32 | yarn
33 | ```
34 |
35 | Once installation of project dependencies completes, run the following command to set up your local development environment:
36 |
37 | ```shell
38 | npm run setup
39 | ```
40 |
41 | First this will create a default `.env` file in which you can define various environment variables such as your MySQL connection details, should you like to use it instead of SQLite3. `.env` is used to store sensitive information you do not want to commit.
42 |
43 | Second, it will create a new database file under `src/scribe.sqlite` to serve as your default local development database. It will then run a set of Knex.js migrations to set up the default database schema.
44 |
45 | Your development environment is now ready to go!
46 |
47 | > *[Back to Top](#contents)*
48 |
49 | ## Running the Server Locally
50 |
51 | To start the server, simply run the following command:
52 |
53 | ```shell
54 | npm start
55 | ```
56 |
57 | The server should now be listening on port `1337`. To access GraphiQL and begin exploring the API documentation, navigate to [http://127.0.0.1:1337/graphiql](http://127.0.0.1:1337/graphiql) in your browser of choice.
58 |
59 | Next, you can begin to populate your newly created database by running the following in a second terminal window:
60 |
61 | ```shell
62 | npm run populate
63 | ```
64 |
65 | This will populate the database with data from the [Magic: The Gathering API](https://docs.magicthegathering.io/) and download all card images to `src/images`.
66 |
67 | > **Please note:** `populate` may take many hours to fully run! You can cancel the script at any time during execution. It is recommended that you at least allow it to run until some cards from the first set are added to the database in order to have a decent amount of seed data to play with. Execution may run faster using MySQL instead of SQlite3. Please refer to [Running the Server in Production](#production) for more information.
68 |
69 | > *[Back to Top](#contents)*
70 |
71 | ## Running the Server in Production
72 |
73 | If you would like to run the server in "production" mode, you will first need to install and setup [MySQL](https://dev.mysql.com/downloads/mysql/) on your local machine. Once complete, set your connection details in `.env`. Scribe uses this file to configure the database connection, otherwise it will use defaults defined in `src/config/server.config.js`.
74 |
75 | To reset your production database schema, run:
76 |
77 | ```shell
78 | npm run resetdb:prod
79 | ```
80 |
81 | > **Warning:** this will first attempt to **drop** any database named 'scribe'.
82 |
83 | When completed, you can then run the server in production using:
84 |
85 | ```shell
86 | npm run start:prod
87 | ```
88 |
89 | To switch back to development, simply run:
90 |
91 | ```shell
92 | npm run start:dev
93 | ```
94 |
95 | > *[Back to Top](#contents)*
96 |
97 | ## Resetting the Database
98 |
99 | To delete all the data in the database and start from scratch, run one of the following commands:
100 |
101 | **Development (Sqlite3):**
102 | ```shell
103 | npm run resetdb
104 | ```
105 |
106 | **Production (MySQL):**
107 | ```shell
108 | npm run resetdb:prod
109 | ```
110 |
111 | This is useful when making changes to the database schema, the populate script, or simply when you need to clear out existing data.
112 |
113 | > *[Back to Top](#contents)*
114 |
115 | ## License Information
116 |
117 | This application uses images and data that are copyright of Wizards of the Coast (http://magic.wizards.com/en)
118 |
119 | Scribe is made available under the MIT License (https://opensource.org/licenses/mit-license.html)
120 |
121 | Attribution is greatly appreciated! Please feel free to fork the project and submit pull requests.
122 |
123 | > *[Back to Top](#contents)*
124 |
125 | ## Prior Art
126 |
127 | Scribe would not be possible without the fantastic work of
128 | Andrew Backes @adback03 on his [Magic: The Gathering API](https://magicthegathering.io/) project.
129 |
130 | > *[Back to Top](#contents)*
131 |
--------------------------------------------------------------------------------
/doc/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Project Changelog
2 |
3 | > *[Return to Directory](README.md)*
4 |
5 | ## v0.1.1
6 |
7 | - Fixed the outstanding errors with SQLite3 migrations. Because SQLite3 does not supposrt adding foreign keys after a table is created, foreign key creation is now conditionally added based on the environment.
8 | - Another issue with migrations was fixed by moving all table definitions back to a subfolder, because Knex's migrations API doesn't seem to allow you to exclude files.
9 | - Added some documentation, including a project Roadmap and a Changelog.
10 | - Added missing dependency Winston-Loggly-Bulk.
11 | - Removed leftover references to previous express server implementation in routes.
12 |
--------------------------------------------------------------------------------
/doc/README.md:
--------------------------------------------------------------------------------
1 | # Scribe Documentation
2 |
3 | ## Table of Contents
4 |
5 | - [Project Roadmap](ROADMAP.md)
6 | - [Changelog](CHANGELOG.md)
7 |
--------------------------------------------------------------------------------
/doc/ROADMAP.md:
--------------------------------------------------------------------------------
1 | # Project Roadmap
2 |
3 | > *[Return to Directory](README.md)*
4 |
5 | ## v0.2.0
6 |
7 | - [ ] ~~Refactor Types/Models to condense data schema into one place per table.~~
8 | - [ ] Write basic project documentation (setup, getting started, etc) ie: [README](../README.md)
9 | - [ ] Wire-up Hapi Routes
10 | - [X] Troubleshoot remaining issues with SQLite Migrations / Knex schema
11 | - [ ] Add remaining Bookshelf Model Relations
12 | - [X] Add pagination query arguments for lists
13 |
14 | ## v0.3.0
15 |
16 | - [X] Add remaining mutations to enable populating the database via the API
17 | - [ ] Add private tables / type definitions
18 | - [ ] Tables: Account, Collection, Binders, Decks, OwnedCards, misc
19 | - [ ] Type definitions/queries/mutations for above
20 |
21 | ## v0.4.0
22 |
23 | - [ ] Setup login/signup REST API
24 | - [ ] Add authentication layer to GraphQL API for private Tables
25 | - [ ] Add rate-limiting to public GraphQL API
26 |
27 | ## v0.5.0
28 |
29 | - [ ] Add application state history table / frontend utility APIs
30 | - [ ] Add trading API / services
31 | - [ ] Create service to grab pricing data from public API sources
32 | - [ ] Add GraphQL types/queries to expose pricing data
33 | - [ ] Add tables / type definitions for Trading platform
34 |
35 | ## v0.6.0
36 |
37 | - [ ] Refactor GraphQL resolvers to use batch SQL querying (speculative)
38 | - [ ] ...?
39 |
--------------------------------------------------------------------------------
/knexfile.js:
--------------------------------------------------------------------------------
1 | require('babel-register')
2 | const config = require('./src/config/server.config').default
3 |
4 | module.exports = config.db
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "scribe",
3 | "version": "0.1.1",
4 | "description": "A GraphQL Magic: The Gathering API Server",
5 | "main": "src/app.js",
6 | "productName": "Scribe",
7 | "scripts": {
8 | "setup": "node setup.js && npm run resetdb",
9 | "lint": "eslint .",
10 | "test": "",
11 | "clean": "npm cache clean && del-cli node_modules",
12 | "clean:dist": "del-cli dist",
13 | "start": "nodemon --watch src src/server.js --exec babel-node --color",
14 | "start:dev": "cross-env NODE_ENV=development npm run start",
15 | "start:prod": "cross-env NODE_ENV=production npm run start",
16 | "build": "npm run build:dev",
17 | "prebuild:dev": "npm run clean:dist",
18 | "build:dev": "cross-env NODE_ENV=development npm run webpack -- --progress --profile",
19 | "prebuild:prod": "npm run clean:dist",
20 | "build:prod": "cross-env NODE_ENV=production npm run webpack -- --progress --profile",
21 | "serve": "nodemon --watch dist dist/server.bundle.js --exec babel-node -- color --inspect=1338",
22 | "migrate:latest": "./node_modules/.bin/knex migrate:latest",
23 | "migrate:latest:dev": "cross-env NODE_ENV=development npm run migrate:latest",
24 | "migrate:latest:prod": "cross-env NODE_ENV=production npm run migrate:latest",
25 | "resetdb": "del-cli src/scribe.sqlite && touch src/scribe.sqlite && npm run migrate:latest",
26 | "resetdb:dev": "cross-env NODE_ENV=development npm run resetdb",
27 | "resetdb:prod": "cross-env NODE_ENV=production && babel-node scripts/reset.js && npm run migrate:latest:prod",
28 | "populate": "nodemon --watch scripts scripts/populate.js --exec babel-node --color --inspect=1338",
29 | "webpack": "./node_modules/.bin/webpack",
30 | "snyk-protect": "snyk protect",
31 | "prepublish": "npm run snyk-protect"
32 | },
33 | "repository": {
34 | "type": "git",
35 | "url": "git+ssh://git@github.com:Saeris/Scribe.git"
36 | },
37 | "license": "MIT",
38 | "author": "Drake Costa (http://saeris.github.io/)",
39 | "engines": {
40 | "node": "6.9.1"
41 | },
42 | "dependencies": {
43 | "@easy-webpack/config-babel": "^4.0.2",
44 | "@easy-webpack/config-env-development": "^2.1.4",
45 | "@easy-webpack/core": "^2.0.0",
46 | "apollo-client": "^1.2.0",
47 | "babel-cli": "^6.18.0",
48 | "babel-eslint": "^7.1.1",
49 | "babel-plugin-import-glob": "^1.0.1",
50 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
51 | "babel-preset-env": "^1.4.0",
52 | "babel-preset-es2015": "^6.18.0",
53 | "babel-preset-stage-2": "^6.18.0",
54 | "body-parser": "^1.15.2",
55 | "bookshelf": "^0.10.2",
56 | "bookshelf-modelbase": "^2.10.2",
57 | "chalk": "^1.1.3",
58 | "cors": "^2.8.3",
59 | "cross-env": "^4.0.0",
60 | "dataloader": "^1.3.0",
61 | "del-cli": "^0.2.1",
62 | "dotenv": "^4.0.0",
63 | "errorhandler": "^1.5.0",
64 | "eslint": "^3.19.0",
65 | "glob": "^7.1.1",
66 | "good": "^7.1.0",
67 | "good-winston": "^3.1.0",
68 | "graphql": "^0.9.3",
69 | "graphql-iso-date": "^3.1.1",
70 | "graphql-server-hapi": "^0.7.1",
71 | "graphql-tag": "^2.0.0",
72 | "hapi": "^16.1.1",
73 | "hapi-auth-jwt2": "^7.2.3",
74 | "hapi-boom-decorators": "^2.2.0",
75 | "hapijs-status-monitor": "^0.6.0",
76 | "ignore-loader": "^0.1.2",
77 | "isomorphic-fetch": "^2.2.1",
78 | "jasmine": "^2.5.2",
79 | "jasmine-core": "^2.5.2",
80 | "jsonwebtoken": "^7.1.9",
81 | "karma": "^1.6.0",
82 | "karma-jasmine": "^1.0.2",
83 | "karma-mocha-reporter": "^2.2.1",
84 | "knex": "^0.13.0",
85 | "minimist": "^1.2.0",
86 | "mkdirp": "^0.5.1",
87 | "moment": "^2.18.1",
88 | "morgan": "^1.7.0",
89 | "mysql": "^2.12.0",
90 | "nodemon": "^1.11.0",
91 | "passport": "^0.3.2",
92 | "passport-http-bearer": "^1.0.1",
93 | "passport-local": "^1.0.0",
94 | "passport-oauth2": "^1.1.2",
95 | "present": "^1.0.0",
96 | "source-map-support": "^0.4.15",
97 | "sqlite3": "^3.1.8",
98 | "test-runner-config": "^0.5.0",
99 | "webpack": "^2.5.1",
100 | "winston": "^2.3.0",
101 | "winston-loggly-bulk": "^2.0.0",
102 | "snyk": "^1.42.6"
103 | },
104 | "snyk": true
105 | }
106 |
--------------------------------------------------------------------------------
/scripts/populate.js:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk'
2 | import present from 'present'
3 | import moment from 'moment'
4 | import {
5 | insertTypes, fetchTypes,
6 | insertColors,
7 | insertSets, fetchSets,
8 | insertLanguages,
9 | insertCards, fetchCards
10 | } from './utilities'
11 |
12 | const { log, error } = console
13 | const duration = ms => moment.utc(ms).format(`HH:mm:ss.SSS`)
14 |
15 | async function populate() {
16 | try {
17 | const start = present()
18 | const prefix = `${chalk.green(`[populate]: `)}`
19 | log(`${prefix}Begin populating database...`)
20 | await insertTypes(await fetchTypes())
21 | log(`${prefix}Successfully added type data!`)
22 | await insertColors()
23 | log(`${prefix}Successfully added set data!`)
24 | await insertLanguages()
25 | log(`${prefix}Successfully added color data!`)
26 | const sets = await insertSets(await fetchSets())
27 | log(`${prefix}Successfully added language data!`)
28 | for (let set of sets) {
29 | await insertCards(await fetchCards(set.code), set)
30 | log(`${prefix}Successfully added cards for set ${set.code}`)
31 | }
32 | const end = present()
33 | log(`${prefix}Finished populating database! (${duration(end - start)})`)
34 | } catch (err) {
35 | error(err)
36 | }
37 | }
38 |
39 | populate()
40 |
--------------------------------------------------------------------------------
/scripts/reset.js:
--------------------------------------------------------------------------------
1 | import dotenv from 'dotenv'
2 | import knex from 'knex'
3 |
4 | dotenv.config()
5 |
6 | // connect without database selected
7 | const db = knex({
8 | client: `mysql`,
9 | connection: {
10 | host: process.env.DB_HOST || `127.0.0.1`,
11 | user: process.env.DB_USERNAME || `root`,
12 | password: process.env.DB_PASSWORD || `password`,
13 | charset: `utf8`
14 | }
15 | })
16 |
17 | async function resetdb() {
18 | await db.raw(`DROP DATABASE IF EXISTS scribe;`).then(res => res)
19 | await db.raw(`CREATE DATABASE IF NOT EXISTS scribe;`).then(res => res)
20 | db.destroy()
21 | }
22 |
23 | resetdb()
24 |
--------------------------------------------------------------------------------
/scripts/utilities/apollo.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import ApolloClient, { createBatchingNetworkInterface } from 'apollo-client'
3 |
4 | const client = new ApolloClient({
5 | networkInterface: createBatchingNetworkInterface({
6 | uri: `http://localhost:1337/api`,
7 | batchInterval: 10
8 | }),
9 | queryDeduplication: true
10 | })
11 |
12 | export default client
13 |
--------------------------------------------------------------------------------
/scripts/utilities/cards.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import fs from 'fs'
3 | import mkdirp from 'mkdirp'
4 | import client from './apollo'
5 | import gql from 'graphql-tag'
6 | import chalk from 'chalk'
7 | import present from 'present'
8 | import moment from 'moment'
9 | import minimist from 'minimist'
10 | import { getSupertype, getType, getSubtype } from './types'
11 | import { getColor, getColorIdentity } from './colors'
12 | import { getLanguageCode } from './languages'
13 |
14 | const BaseUrl = `https://api.magicthegathering.io/v1`
15 | const { info, log, error } = console
16 | const duration = ms => moment.utc(ms).format(`HH:mm:ss.SSS`)
17 |
18 | const updateCard = async input => await client
19 | .mutate({
20 | mutation: gql`mutation updateCard($input: CardInput) {
21 | updateCard(input: $input) {
22 | id
23 | }
24 | }`,
25 | variables: { input }
26 | })
27 | .then(res => res.data.updateCard.id)
28 | .catch(err => log(`Failed to update Card.`, input, err))
29 |
30 | const updatePrinting = async input => await client
31 | .mutate({
32 | mutation: gql`mutation updatePrinting($input: PrintingInput) {
33 | updatePrinting(input: $input) {
34 | id
35 | }
36 | }`,
37 | variables: { input }
38 | })
39 | .then(res => res.data.updatePrinting.id)
40 | .catch(err => log(`Failed to update Printing.`, input, err))
41 |
42 | const updateName = async input => await client
43 | .mutate({
44 | mutation: gql`mutation updateName($input: NameInput) {
45 | updateName(input: $input) {
46 | id
47 | }
48 | }`,
49 | variables: { input: input }
50 | })
51 | .then(res => res.data.updateName.id)
52 | .catch(err => log(`Failed to update Name.`, input, err))
53 |
54 | const fetchImage = async (url, set, num, language) => {
55 | if (!!!minimist(process.argv.slice(2)).getImages) return url
56 |
57 | const dir = `./src/images/sets/${set}`
58 | const image = `${dir}/${set}_${num}_${language}.jpg`
59 |
60 | if (fs.existsSync(image)) return image
61 | if (!fs.existsSync(dir)) mkdirp.sync(dir)
62 |
63 | await fetch(url).then(resp => resp.body.pipe(fs.createWriteStream(image)))
64 |
65 | return image
66 | }
67 |
68 | const updateImage = async input => await client
69 | .mutate({
70 | mutation: gql`mutation updateImage($input: ImageInput) {
71 | updateImage(input: $input) {
72 | id
73 | }
74 | }`,
75 | variables: { input }
76 | })
77 | .then(res => res.data.updateImage.id)
78 | .catch(err => log(`Failed to update Image.`, input, err))
79 |
80 | const updateArtist = async input => await client
81 | .mutate({
82 | mutation: gql`mutation updateArtist($input: ArtistInput) {
83 | updateArtist(input: $input) {
84 | id
85 | }
86 | }`,
87 | variables: { input }
88 | })
89 | .then(res => res.data.updateArtist.id)
90 | .catch(err => log(`Failed to update Artist.`, input, err))
91 |
92 | const updateLayout = async input => await client
93 | .mutate({
94 | mutation: gql`mutation updateLayout($input: LayoutInput) {
95 | updateLayout(input: $input) {
96 | id
97 | }
98 | }`,
99 | variables: { input }
100 | })
101 | .then(res => res.data.updateLayout.id)
102 | .catch(err => log(`Failed to update Layout.`, input, err))
103 |
104 | const updateRarity = async input => await client
105 | .mutate({
106 | mutation: gql`mutation updateRarity($input: RarityInput) {
107 | updateRarity(input: $input) {
108 | id
109 | }
110 | }`,
111 | variables: { input }
112 | })
113 | .then(res => res.data.updateRarity.id)
114 | .catch(err => log(`Failed to update Rarity.`, input, err))
115 |
116 | export { updateCard, updateName, updateImage, updateArtist, updateLayout, updateRarity }
117 |
118 | export async function fetchCards(setCode) {
119 | const start = present()
120 | const prefix = `${chalk.cyan(`[fetchCards]: `)}`
121 | try {
122 | let page = 1
123 | let remaining
124 | let done = true
125 | let cards = []
126 | log(`${prefix}Fetching card data for set ${chalk.green(setCode)}...`)
127 | do {
128 | let response = await fetch(`${BaseUrl}/cards?set=${setCode}&page=${page}`).then(resp => resp)
129 | let data = await response.json()
130 | cards.push(...data.cards)
131 | let total = response.headers.get(`total-count`)
132 | remaining = total - (page * 100)
133 | info(`${prefix}Retrieved page ${page}: ${cards.length} of ${total} cards.`)
134 | remaining <= 0 ? done = false : page++
135 | } while (done)
136 | const end = present()
137 | log(`${prefix}Finished fetching cards for set ${chalk.green(setCode)}! (${duration(end - start)})`)
138 | return cards
139 | } catch (err) {
140 | const end = present()
141 | error(`${prefix}Failed to fetch all cards. (${duration(end - start)})`, err)
142 | }
143 | }
144 |
145 | export async function insertCards(cards, set) {
146 | const start = present()
147 | const prefix = `${chalk.magenta(`[insertCards]: `)}`
148 | log(`${prefix}Adding card data for set ${chalk.green(set.code)}`)
149 | try {
150 | let i = 1
151 | for (let card of await cards) {
152 | info(`${prefix}Adding card ${chalk.green(card.name)}`)
153 | const number = (!!card.number && card.number !== 0) ? card.number : i++
154 |
155 | let names = []
156 | let srcImages = []
157 |
158 | if (!!card.multiverseid) {
159 | names.push(await updateName({ name: card.name, language: 1 }))
160 | srcImages.push({ url: card.imageUrl, multiverseid: card.multiverseid, code: `en-US`, codeID: 1 })
161 | }
162 | if (!!card.foreignNames) {
163 | for (let name of card.foreignNames) {
164 | if (!!name.multiverseid) {
165 | const languageCode = await getLanguageCode([`${name.language}`])
166 | log(`Adding name: ${name.name}, language: ${name.language}, code: ${languageCode.code}`)
167 | names.push(await updateName({ name: name.name, language: languageCode.id }))
168 | srcImages.push({ url: name.imageUrl, multiverseid: name.multiverseid, code: languageCode.code, codeID: languageCode.id })
169 | }
170 | }
171 | }
172 |
173 | let images = []
174 | for (let image of srcImages) {
175 | images.push(await updateImage({
176 | url: await fetchImage(image.url, set.code, number, image.code),
177 | multiverseid: image.multiverseid,
178 | language: image.codeID
179 | }))
180 | }
181 |
182 | let colorIdentity = ``
183 | if (!!card.colorIdentity && !!card.colors) {
184 | for (let identity of card.colors) colorIdentity = `${colorIdentity}/${identity}`
185 | }
186 |
187 | const cardID = await updateCard({
188 | name: card.name,
189 | names: names,
190 | border: !!card.border ? card.border : null,
191 | layout: await updateLayout({ name:card.layout }),
192 | watermark: null,
193 | manaCost: !!card.manaCost ? card.manaCost : null,
194 | cmc: !!card.cmc ? card.cmc : 0,
195 | colors: !!card.colorIdentity ? await getColor(card.colorIdentity.map(color => `{${color}}`)) : null,
196 | colorIdentity: colorIdentity !== `` ? await getColorIdentity([colorIdentity.substring(1)]) : 6,
197 | typeLine: card.type,
198 | supertypes: !!card.supertypes ? await getSupertype(card.supertypes.map(name => `${name}`)) : null,
199 | types: !!card.types ? await getType(card.types.map(name => `${name}`)) : null,
200 | subtypes: !!card.subtypes ? await getSubtype(card.subtypes.map(name => `${name}`)) : null,
201 | rarity: await updateRarity({ name: card.rarity, class: `ss-${card.rarity.toLowerCase()}` }),
202 | text: !!card.text ? card.text : null,
203 | categories: null,
204 | abilityTypes: null,
205 | keywords: null,
206 | hand: !!card.hand ? card.hand : null,
207 | life: !!card.life ? card.life : null,
208 | power: !!card.power ? card.power : null,
209 | toughness: !!card.toughness ? card.toughness : null,
210 | loyalty: !!card.loyalty ? card.loyalty : null,
211 | legalities: [],
212 | rulings: []
213 | })
214 |
215 | await updatePrinting({
216 | card: cardID,
217 | set: set.id,
218 | images: images,
219 | artist: await updateArtist({ name: card.artist }),
220 | sides: [],
221 | variations: [],
222 | originalType: card.originalType,
223 | originalText: !!card.originalText ? card.originalText : null,
224 | flavor: !!card.flavor ? card.flavor : null,
225 | number: number,
226 | timeshifted: !!card.timeshifted ? card.timeshifted : false,
227 | starter: !!card.starter ? card.starter : false,
228 | reserved: !!card.reserved ? card.reserved : false,
229 | source: !!card.source ? card.source : null
230 | })
231 | }
232 | const end = present()
233 | log(`${prefix}Finished inserting cards for set ${chalk.green(set.code)}! (${duration(end - start)})`)
234 | } catch (err) {
235 | const end = present()
236 | error(`${prefix}Failed to insert all cards for set ${chalk.green(set.code)}! (${duration(end - start)})`, err)
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/scripts/utilities/colors.js:
--------------------------------------------------------------------------------
1 | import client from './apollo'
2 | import gql from 'graphql-tag'
3 | import chalk from 'chalk'
4 | import present from 'present'
5 | import moment from 'moment'
6 |
7 | const { info, log, error } = console
8 | const duration = ms => moment.utc(ms).format(`HH:mm:ss.SSS`)
9 |
10 | const getColor = async input => await client
11 | .query({
12 | query: gql`query getColor($input: [String]) {
13 | color(filter: {symbol: $input}) {
14 | id
15 | }
16 | }`,
17 | variables: { input },
18 | fetchPolicy: `cache-first`
19 | })
20 | .then(res => res.data.color.map(color => color.id))
21 | .catch(err => log(`Failed to get Color.`, input, err))
22 |
23 | const getColorIdentity = async input => await client
24 | .query({
25 | query: gql`query getColorIdentity($input: [String]) {
26 | colorIdentity(filter: { name: $input }) {
27 | id
28 | }
29 | }`,
30 | variables: { input },
31 | fetchPolicy: `cache-first`
32 | })
33 | .then(res => res.data.colorIdentity.map(identity => identity.id))
34 | .catch(err => log(`Failed to get Color Identity.`, input, err))
35 |
36 | const updateColorIcon = input => client
37 | .mutate({
38 | mutation: gql`mutation updateColorIcon($input: IconInput) {
39 | updateIcon(input: $input) {
40 | id
41 | }
42 | }`,
43 | variables: { input }
44 | })
45 | .then(res => res.data.updateIcon.id)
46 | .catch(err => log(`Failed to update Color Icon.`, input, err))
47 |
48 | const updateColorIdentity = input => client
49 | .mutate({
50 | mutation: gql`mutation updateColorIdentity($input: ColorIdentityInput) {
51 | updateColorIdentity(input: $input) {
52 | id
53 | }
54 | }`,
55 | variables: { input }
56 | })
57 | .then(res => res.data.updateColorIdentity.id)
58 | .catch(err => log(`Failed to update Color Identity.`, input, err))
59 |
60 | const updateColor = input => client
61 | .mutate({
62 | mutation: gql`mutation updateColor($input: ColorInput) {
63 | updateColor(input: $input) {
64 | id
65 | }
66 | }`,
67 | variables: { input }
68 | })
69 | .then(res => res.data.updateColor.id)
70 | .catch(err => log(`Failed to update Color.`, input, err))
71 |
72 | export { getColor, getColorIdentity, updateColorIcon, updateColorIdentity, updateColor }
73 |
74 | export async function insertColors() {
75 | const start = present()
76 | const prefix = `${chalk.red(`[insertColors]: `)}`
77 | try {
78 | log(`${prefix}Adding all colors and identities to database...`)
79 | const colorIdentities = [
80 | { name: `White`, alias: `White`, colorList: [1], multicolored: false, devoid: false },
81 | { name: `Blue`, alias: `Blue`, colorList: [2], multicolored: false, devoid: false },
82 | { name: `Black`, alias: `Black`, colorList: [3], multicolored: false, devoid: false },
83 | { name: `Red`, alias: `Red`, colorList: [4], multicolored: false, devoid: false },
84 | { name: `Green`, alias: `Green`, colorList: [5], multicolored: false, devoid: false },
85 | { name: `Colorless`, alias: `Colorless`, colorList: Array(33 - 6 + 1).fill().map((_, i) => 6 + i), multicolored: false, devoid: false },
86 | { name: `Devoid`, alias: `Devoid`, colorList: [6], multicolored: false, devoid: true },
87 | { name: `Snow`, alias: `Snow`, colorList: [34], multicolored: false, devoid: false },
88 | { name: `White/Blue`, alias: `Azorius Senate`, colorList: [1, 2], multicolored: true, devoid: false },
89 | { name: `Blue/Black`, alias: `House Dimir`, colorList: [2, 3], multicolored: true, devoid: false },
90 | { name: `Black/Red`, alias: `Cult of Rakdos`, colorList: [3, 4], multicolored: true, devoid: false },
91 | { name: `Red/Green`, alias: `Gruul Clans`, colorList: [4, 5], multicolored: true, devoid: false },
92 | { name: `White/Green`, alias: `Selesnya Conclave`, colorList: [5, 1], multicolored: true, devoid: false },
93 | { name: `White/Black`, alias: `Orzhov Syndicate`, colorList: [1, 3], multicolored: true, devoid: false },
94 | { name: `Blue/Red`, alias: `Izzet League`, colorList: [2, 4], multicolored: true, devoid: false },
95 | { name: `Black/Green`, alias: `Golgari Swarm`, colorList: [3, 5], multicolored: true, devoid: false },
96 | { name: `White/Red`, alias: `Boros Legion`, colorList: [4, 1], multicolored: true, devoid: false },
97 | { name: `Blue/Green`, alias: `Simic Combine`, colorList: [5, 2], multicolored: true, devoid: false },
98 | { name: `White/Blue/Green`, alias: `Bant`, colorList: [5, 1, 2], multicolored: true, devoid: false },
99 | { name: `White/Blue/Black`, alias: `Esper`, colorList: [1, 2, 3], multicolored: true, devoid: false },
100 | { name: `Blue/Black/Red`, alias: `Grixis`, colorList: [2, 3, 4], multicolored: true, devoid: false },
101 | { name: `Black/Red/Green`, alias: `Jund`, colorList: [3, 4, 5], multicolored: true, devoid: false },
102 | { name: `White/Red/Green`, alias: `Naya`, colorList: [4, 5, 1], multicolored: true, devoid: false },
103 | { name: `White/Black/Green`, alias: `Abzan Houses`, colorList: [1, 3, 5], multicolored: true, devoid: false },
104 | { name: `White/Blue/Red`, alias: `Jeskai Way`, colorList: [2, 4, 1], multicolored: true, devoid: false },
105 | { name: `Blue/Black/Green`, alias: `Sultai Brood`, colorList: [3, 5, 2], multicolored: true, devoid: false },
106 | { name: `White/Black/Red`, alias: `Mardu Horde`, colorList: [4, 1, 3], multicolored: true, devoid: false },
107 | { name: `Blue/Red/Green`, alias: `Temur Frontier`, colorList: [5, 2, 4], multicolored: true, devoid: false },
108 | { name: `White/Blue/Black/Red`, alias: `Artifice`, colorList: [1, 2, 3, 4], multicolored: true, devoid: false },
109 | { name: `Blue/Black/Red/Green`, alias: `Chaos`, colorList: [2, 3, 4, 5], multicolored: true, devoid: false },
110 | { name: `White/Black/Red/Green`, alias: `Aggression`, colorList: [3, 4, 5, 1], multicolored: true, devoid: false },
111 | { name: `White/Blue/Red/Green`, alias: `Altruism`, colorList: [4, 5, 1, 2], multicolored: true, devoid: false },
112 | { name: `White/Blue/Black/Green`, alias: `Growth`, colorList: [5, 1, 2, 3], multicolored: true, devoid: false },
113 | { name: `White/Blue/Black/Red/Green`, alias: `Chromatic`, colorList: [1, 2, 3, 4, 5], multicolored: true, devoid: false }
114 | ]
115 |
116 | const colors = [
117 | { symbol: `{W}`, className: `ms-w`, identity: 1 },
118 | { symbol: `{U}`, className: `ms-u`, identity: 2 },
119 | { symbol: `{B}`, className: `ms-b`, identity: 3 },
120 | { symbol: `{R}`, className: `ms-r`, identity: 4 },
121 | { symbol: `{G}`, className: `ms-g`, identity: 5 },
122 | { symbol: `{C}`, className: `ms-c`, identity: 7 },
123 | { symbol: `{0}`, className: `ms-0`, identity: 6 },
124 | { symbol: `{1}`, className: `ms-1`, identity: 6 },
125 | { symbol: `{2}`, className: `ms-2`, identity: 6 },
126 | { symbol: `{3}`, className: `ms-3`, identity: 6 },
127 | { symbol: `{4}`, className: `ms-4`, identity: 6 },
128 | { symbol: `{5}`, className: `ms-5`, identity: 6 },
129 | { symbol: `{6}`, className: `ms-6`, identity: 6 },
130 | { symbol: `{7}`, className: `ms-7`, identity: 6 },
131 | { symbol: `{8}`, className: `ms-8`, identity: 6 },
132 | { symbol: `{9}`, className: `ms-9`, identity: 6 },
133 | { symbol: `{10}`, className: `ms-10`, identity: 6 },
134 | { symbol: `{11}`, className: `ms-11`, identity: 6 },
135 | { symbol: `{12}`, className: `ms-12`, identity: 6 },
136 | { symbol: `{13}`, className: `ms-13`, identity: 6 },
137 | { symbol: `{14}`, className: `ms-14`, identity: 6 },
138 | { symbol: `{15}`, className: `ms-15`, identity: 6 },
139 | { symbol: `{16}`, className: `ms-16`, identity: 6 },
140 | { symbol: `{17}`, className: `ms-17`, identity: 6 },
141 | { symbol: `{18}`, className: `ms-18`, identity: 6 },
142 | { symbol: `{19}`, className: `ms-19`, identity: 6 },
143 | { symbol: `{20}`, className: `ms-20`, identity: 6 },
144 | { symbol: `{100}`, className: `ms-100`, identity: 6 },
145 | { symbol: `{1000000}`, className: `ms-1000000`, identity: 6 },
146 | { symbol: `{infinity}`, className: `ms-infinity`, identity: 6 },
147 | { symbol: `{X}`, className: `ms-x`, identity: 6 },
148 | { symbol: `{Y}`, className: `ms-y`, identity: 6 },
149 | { symbol: `{Z}`, className: `ms-z`, identity: 6 },
150 | { symbol: `{S}`, className: `ms-s`, identity: 8 },
151 | { symbol: `{W/U}`, className: `ms-wu ms-split`, identity: 9 },
152 | { symbol: `{U/B}`, className: `ms-ub ms-split`, identity: 10 },
153 | { symbol: `{B/R}`, className: `ms-br ms-split`, identity: 11 },
154 | { symbol: `{R/G}`, className: `ms-rg ms-split`, identity: 12 },
155 | { symbol: `{G/W}`, className: `ms-gw ms-split`, identity: 13 },
156 | { symbol: `{W/B}`, className: `ms-wb ms-split`, identity: 14 },
157 | { symbol: `{U/R}`, className: `ms-ur ms-split`, identity: 15 },
158 | { symbol: `{B/G}`, className: `ms-bg ms-split`, identity: 16 },
159 | { symbol: `{R/W}`, className: `ms-rw ms-split`, identity: 17 },
160 | { symbol: `{G/U}`, className: `ms-gu ms-split`, identity: 18 },
161 | { symbol: `{2/W}`, className: `ms-2w ms-split`, identity: 1 },
162 | { symbol: `{2/U}`, className: `ms-2u ms-split`, identity: 2 },
163 | { symbol: `{2/B}`, className: `ms-2b ms-split`, identity: 3 },
164 | { symbol: `{2/R}`, className: `ms-2r ms-split`, identity: 4 },
165 | { symbol: `{2/G}`, className: `ms-2g ms-split`, identity: 5 },
166 | { symbol: `{W/P}`, className: `ms-wp ms-split`, identity: 1 },
167 | { symbol: `{U/P}`, className: `ms-up ms-split`, identity: 2 },
168 | { symbol: `{B/P}`, className: `ms-bp-split`, identity: 3 },
169 | { symbol: `{R/P}`, className: `ms-rp ms-split`, identity: 4 },
170 | { symbol: `{G/P}`, className: `ms-gp ms-split`, identity: 5 }
171 | ]
172 |
173 | await Promise.all(colorIdentities.map(({ name, alias, colorList, multicolored, devoid }) => {
174 | info(`${prefix}Adding color identity ${chalk.green(alias)}`)
175 | updateColorIdentity({ name, alias, colors: colorList, multicolored, devoid })
176 | }))
177 | .then(info(`${prefix}Finished adding Color Identities.`))
178 | .catch(err => error(`${prefix}Failed to add Color Identities.`, { err }))
179 |
180 | await Promise.all(colors.map(async ({ symbol, className, identity }) => {
181 | info(`${prefix}Adding color ${chalk.green(symbol)}`)
182 | const icon = await updateColorIcon({ name: symbol, class: className })
183 | updateColor({ symbol, icon, identity })
184 | }))
185 | .then(info(`${prefix}Finished adding Colors.`))
186 | .catch(err => error(`${prefix}Failed to add Colors.`, { err }))
187 | const end = present()
188 | log(`${prefix}Finished inserting all colors and identities! (${duration(end - start)})`)
189 | } catch (err) {
190 | const end = present()
191 | error(`${prefix}Failed to add all colors and identities to the database. (${duration(end - start)})`, err)
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/scripts/utilities/index.js:
--------------------------------------------------------------------------------
1 | export * from './colors'
2 | export * from './cards'
3 | export * from './languages'
4 | export * from './sets'
5 | export * from './types'
6 |
--------------------------------------------------------------------------------
/scripts/utilities/languages.js:
--------------------------------------------------------------------------------
1 | import client from './apollo'
2 | import gql from 'graphql-tag'
3 | import chalk from 'chalk'
4 | import present from 'present'
5 | import moment from 'moment'
6 |
7 | const { info, log, error } = console
8 | const duration = ms => moment.utc(ms).format(`HH:mm:ss.SSS`)
9 |
10 | const updateLanguageCode = input => client
11 | .mutate({
12 | mutation: gql`mutation updateLanguageCode($input: LanguageCodeInput) {
13 | updateLanguageCode(input: $input) {
14 | id
15 | }
16 | }`,
17 | variables: { input }
18 | })
19 | .then(res => res.data.updateLanguageCode)
20 | .catch(err => log(`Failed to update Language Code.`, input, err))
21 |
22 | const getLanguageCode = async input => await client
23 | .query({
24 | query: gql`query getLanguageCode($input: [String]) {
25 | language(filter: { name: $input }) {
26 | id
27 | code {
28 | id
29 | code
30 | }
31 | }
32 | }`,
33 | variables: { input },
34 | fetchPolicy: `cache-first`
35 | })
36 | .then(res => res.data.language[0].code)
37 | .catch(err => log(`Failed to get Language Code.`, input, err))
38 |
39 | const updateLanguage = input => client
40 | .mutate({
41 | mutation: gql`mutation updateLangauge($input: LanguageInput) {
42 | updateLanguage(input: $input) {
43 | id
44 | }
45 | }`,
46 | variables: { input }
47 | })
48 | .then(res => res.data.updateLanguage)
49 | .catch(err => log(`Failed to update Language.`, input, err))
50 |
51 | export { updateLanguageCode, getLanguageCode, updateLanguage }
52 |
53 | export async function insertLanguages() {
54 | const start = present()
55 | const prefix = `${chalk.green(`[insertLanguages]: `)}`
56 | try {
57 | log(`${prefix}Begin adding languages to database...`)
58 | const languages = [
59 | { code: `en-US`, language: `English`},
60 | { code: `zh-Hans`, language: `Chinese Simplified`},
61 | { code: `zh-Hant`, language: `Chinese Traditional`},
62 | { code: `fr`, language: `French`},
63 | { code: `de`, language: `German`},
64 | { code: `it`, language: `Italian`},
65 | { code: `ja`, language: `Japanese`},
66 | { code: `ko`, language: `Korean`},
67 | { code: `pt`, language: `Portuguese`},
68 | { code: `ru`, language: `Russian`},
69 | { code: `es`, language: `Spanish`},
70 | { code: `pt-br`, language: `Portuguese (Brazil)`}
71 | ]
72 | await Promise.all(languages.map(({code, language}, index) => {
73 | info(`${prefix}Adding language ${chalk.green(language)}`)
74 | updateLanguageCode({ code, language: index })
75 | updateLanguage({ name: language, code: index })
76 | }))
77 | .then(info(`${prefix}Finished adding Languages.`))
78 | .catch(err => error(`${prefix}Failed to add Languages.`, { err }))
79 | const end = present()
80 | log(`${prefix}Finished inserting languages! (${duration(end - start)})`)
81 | } catch (err) {
82 | const end = present()
83 | error(`${prefix}Failed to add languages to the database. (${duration(end - start)})`, err)
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/scripts/utilities/sets.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import client from './apollo'
3 | import gql from 'graphql-tag'
4 | import chalk from 'chalk'
5 | import present from 'present'
6 | import moment from 'moment'
7 |
8 | const { info, log, error } = console
9 | const BaseUrl = `https://api.magicthegathering.io/v1`
10 |
11 | const duration = ms => moment.utc(ms).format(`HH:mm:ss.SSS`)
12 |
13 | const updateSet = async input => await client
14 | .mutate({
15 | mutation: gql`mutation updateSet($input: SetInput) {
16 | updateSet(input: $input) {
17 | id
18 | code
19 | }
20 | }`,
21 | variables: { input }
22 | })
23 | .then(res => res.data.updateSet)
24 | .catch(err => log(`Failed to update Set.`, input, err))
25 |
26 | const updateSetType = async input => await client
27 | .mutate({
28 | mutation: gql`mutation updateSetType($input: SetTypeInput) {
29 | updateSetType(input: $input) {
30 | id
31 | }
32 | }`,
33 | variables: { input }
34 | })
35 | .then(res => res.data.updateSetType.id)
36 | .catch(err => log(`Failed to update Set Type.`, input, err))
37 |
38 | const updateSetIcon = async input => await client
39 | .mutate({
40 | mutation: gql`mutation updateIcon($input: IconInput) {
41 | updateIcon(input: $input) {
42 | id
43 | }
44 | }`,
45 | variables: { input }
46 | })
47 | .then(res => res.data.updateIcon.id)
48 | .catch(err => log(`Failed to update Set Icon.`, input, err))
49 |
50 | const updateBlock = async input => await client
51 | .mutate({
52 | mutation: gql`mutation updateBlock($input: BlockInput) {
53 | updateBlock(input: $input) {
54 | id
55 | }
56 | }`,
57 | variables: { input }
58 | })
59 | .then(res => res.data.updateBlock.id)
60 | .catch(err => log(`Failed to update Block.`, input, err))
61 |
62 | export { updateSet, updateSetType, updateSetIcon, updateBlock }
63 |
64 | export async function fetchSets() {
65 | try {
66 | let data = await fetch(`${BaseUrl}/sets`).then(response => response.json())
67 | return data.sets
68 | } catch (err) {
69 | error(err)
70 | }
71 | }
72 |
73 | export async function insertSets(sets) {
74 | const start = present()
75 | const prefix = `${chalk.blue(`[insertSets]: `)}`
76 | try {
77 | log(`${prefix}Adding all sets to database`)
78 | let results = []
79 | for (let set of await sets) {
80 | info(`${prefix}Adding set ${chalk.green(set.name)}`)
81 | const code = set.code.toLowerCase()
82 | set.type = await updateSetType({ name: set.type })
83 | set.icon = await updateSetIcon({ name: code, class: `ss-${code}` })
84 | if (!!set.block) set.block = await updateBlock({ name: set.block.toString() })
85 | results.push(await updateSet(new Set(set)))
86 | }
87 | const end = present()
88 | log(`${prefix}Finished inserting all sets! (${duration(end - start)})`)
89 | return results
90 | } catch (err) {
91 | const end = present()
92 | error(`${prefix}Failed to add all sets to the database. (${duration(end - start)})`, err)
93 | }
94 | }
95 |
96 | class Set {
97 | constructor(data) {
98 | this.name = data.name
99 | this.code = data.code
100 | this.block = !!data.block ? data.block : null
101 | this.type = data.type
102 | this.icon = data.icon
103 | this.border = data.border
104 | this.releaseDate = moment(data.releaseDate).format(`YYYY-MM-DD`)
105 | this.booster = null
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/scripts/utilities/types.js:
--------------------------------------------------------------------------------
1 | import 'isomorphic-fetch'
2 | import client from './apollo'
3 | import gql from 'graphql-tag'
4 | import chalk from 'chalk'
5 | import present from 'present'
6 | import moment from 'moment'
7 |
8 | const BaseUrl = `https://api.magicthegathering.io/v1`
9 | const { info, log, error } = console
10 | const duration = ms => moment.utc(ms).format(`HH:mm:ss.SSS`)
11 |
12 | const updateType = input => client
13 | .mutate({
14 | mutation: gql`mutation updateType($input: TypeInput) {
15 | updateType(input: $input) {
16 | id
17 | }
18 | }`,
19 | variables: { input }
20 | })
21 | .then(res => res.data.updateType.id)
22 | .catch(err => log(`Failed to update Type.`, input, err))
23 |
24 | const getType = async input => await client
25 | .query({
26 | query: gql`query getType($input: [String]) {
27 | type(filter: { name: $input }) {
28 | id
29 | }
30 | }`,
31 | variables: { input },
32 | fetchPolicy: `cache-first`
33 | })
34 | .then(res => res.data.type.map(type => type.id))
35 | .catch(err => log(`Failed to get Type.`, input, err))
36 |
37 | const updateSubtype = input => client
38 | .mutate({
39 | mutation: gql`mutation updateSubtype($input: SubtypeInput) {
40 | updateSubtype(input: $input) {
41 | id
42 | }
43 | }`,
44 | variables: { input }
45 | })
46 | .then(res => res.data.updateSubtype.id)
47 | .catch(err => log(`Failed to update Subtype.`, input, err))
48 |
49 | const getSubtype = async input => await client
50 | .query({
51 | query: gql`query getSubtype($input: [String]) {
52 | subtype(filter: { name: $input }) {
53 | id
54 | }
55 | }`,
56 | variables: { input },
57 | fetchPolicy: `cache-first`
58 | })
59 | .then(res => res.data.subtype.map(subtype => subtype.id))
60 | .catch(err => log(`Failed to get Subtype.`, input, err))
61 |
62 | const updateSupertype = input => client
63 | .mutate({
64 | mutation: gql`mutation updateSupertype($input: SupertypeInput) {
65 | updateSupertype(input: $input) {
66 | id
67 | }
68 | }`,
69 | variables: { input }
70 | })
71 | .then(res => res.data.updateSupertype.id)
72 | .catch(err => log(`Failed to update Supertype.`, input, err))
73 |
74 | const getSupertype = async input => await client
75 | .query({
76 | query: gql`query getSupertype($input: [String]) {
77 | supertype(filter: { name: $input }) {
78 | id
79 | }
80 | }`,
81 | variables: { input },
82 | fetchPolicy: `cache-first`
83 | })
84 | .then(res => res.data.supertype.map(supertype => supertype.id))
85 | .catch(err => log(`Failed to get Supertype.`, input, err))
86 |
87 | export { updateSupertype, updateType, updateSubtype, getSupertype, getType, getSubtype }
88 |
89 | export async function fetchTypes() {
90 | try {
91 | let supertypes = await fetch(`${BaseUrl}/supertypes`).then(response => response.json())
92 | let types = await fetch(`${BaseUrl}/types`).then(response => response.json())
93 | let subtypes = await fetch(`${BaseUrl}/subtypes`).then(response => response.json())
94 | return { ...supertypes, ...types, ...subtypes }
95 | } catch (err) {
96 | error(err)
97 | }
98 | }
99 |
100 | export async function insertTypes(data) {
101 | const start = present()
102 | const prefix = `${chalk.yellow(`[insertTypes]: `)}`
103 | try {
104 | let results = {
105 | subtypes: [],
106 | supertypes: [],
107 | types: []
108 | }
109 | let types = await data
110 | log(`${prefix}Adding all types to database.`)
111 |
112 | results.supertypes = await Promise
113 | .all(types.supertypes.map(supertype => {
114 | info(`${prefix}Adding Supertype ${chalk.green(supertype)}`)
115 | return updateSupertype({ name: supertype })
116 | }))
117 | .then(info(`${prefix}Finished adding Supertypes`))
118 | .catch(err => error(`${prefix}Failed to add Supertypes.`, { err }))
119 |
120 | results.types = await Promise
121 | .all(types.types.map(type => {
122 | info(`${prefix}Adding Type ${chalk.green(type)}`)
123 | return updateType({ name: type })
124 | }))
125 | .then(info(`${prefix}Finished adding Types`))
126 | .catch(err => error(`${prefix}Failed to add Types.`, { err }))
127 |
128 | results.types = await Promise
129 | .all(types.subtypes.map(subtype => {
130 | info(`${prefix}Adding Subtype ${chalk.green(subtype)}`)
131 | return updateSubtype({ name: subtype })
132 | }))
133 | .then(info(`${prefix}Finished adding Subtypes`))
134 | .catch(err => error(`${prefix}Failed to add Subtypes.`, { err }))
135 |
136 | const end = present()
137 | log(`${prefix}Finished inserting all types! (${duration(end - start)})`)
138 | return results
139 | } catch (err) {
140 | const end = present()
141 | error(`${prefix}Failed to add all types to the database. (${duration(end - start)})`, err)
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/setup.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fs = require('fs');
3 | fs.createReadStream('.env.default')
4 | .pipe(fs.createWriteStream('.env'));
5 |
--------------------------------------------------------------------------------
/src/config/bookshelf.config.js:
--------------------------------------------------------------------------------
1 | import knex from 'knex'// http://knexjs.org/
2 | import bookshelf from 'bookshelf' // http://bookshelfjs.org/
3 | import modelbase from 'bookshelf-modelbase' // https://github.com/bsiddiqui/bookshelf-modelbase
4 | import config from './server.config'
5 |
6 | const db = bookshelf(knex(config.db))
7 |
8 | db.plugin(modelbase.pluggable)
9 | db.plugin(`registry`) // https://github.com/tgriesser/bookshelf/wiki/Plugin:-Model-Registry
10 | db.plugin(`visibility`) // https://github.com/tgriesser/bookshelf/wiki/Plugin:-Visibility
11 | db.plugin(`pagination`) // https://github.com/tgriesser/bookshelf/wiki/Plugin:-Pagination
12 |
13 | export default db
14 |
--------------------------------------------------------------------------------
/src/config/graphql.config.js:
--------------------------------------------------------------------------------
1 | import Schema from '../schema'
2 |
3 | class Graphql {
4 | // API Endpoint Settings
5 | api = {
6 | path: `/api`,
7 | graphqlOptions: (request) => {
8 | let options = {
9 | schema: Schema,
10 | root_value: Schema,
11 | debug: true
12 | }
13 | return options
14 | }
15 | }
16 |
17 | // GraphiQL Editor Settings
18 | graphiql = {
19 | path: `/graphiql`,
20 | graphiqlOptions: {
21 | endpointURL: `/api`
22 | }
23 | }
24 | }
25 |
26 | export default new Graphql()
27 |
--------------------------------------------------------------------------------
/src/config/server.config.js:
--------------------------------------------------------------------------------
1 | import dotenv from 'dotenv' // https://github.com/motdotla/dotenv
2 | import Winston from 'winston' // https://github.com/winstonjs/winston
3 | import 'winston-loggly-bulk' // https://github.com/loggly/winston-loggly-bulk
4 |
5 | dotenv.config()
6 |
7 | class Config {
8 | ENV = process.env.NODE_ENV && process.env.NODE_ENV.toLowerCase() || (process.env.NODE_ENV === `development`)
9 |
10 | // HTTP Server Settings
11 | http = {
12 | host: `127.0.0.1`,
13 | port: process.env.HTTP || 1337,
14 | routes: {
15 | cors: true
16 | }
17 | }
18 |
19 | // HTTPS Server Settings
20 | https = {
21 | host: `127.0.0.1`,
22 | port: process.env.HTTPS || 8080,
23 | routes: {
24 | cors: true
25 | }
26 | }
27 |
28 | // Sets the server's log level
29 | level = process.env.LOGLEVEL || `info`
30 |
31 | // Winston Logger Settings
32 | winston = {
33 | transports: [
34 | new (Winston.transports.Loggly)({
35 | token: process.env.LOGGLY_TOKEN,
36 | subdomain: process.env.LOGGLY_SUBDOMAIN,
37 | tags: [`Winston-NodeJS`, `Scribe`],
38 | json: true
39 | }),
40 | new (Winston.transports.Console)({
41 | level: this.level,
42 | prettyPrint: true,
43 | handleExceptions: true,
44 | humanReadableUnhandledException: true,
45 | json: false,
46 | colorize: true
47 | })
48 | ]
49 | }
50 |
51 | // Good Logger Settings
52 | good = {
53 | ops: {
54 | interval: 1000
55 | },
56 | reporters: {
57 | winston: [{
58 | module: `good-winston`,
59 | args: [new Winston.Logger(this.winston), {
60 | error_level: `error`,
61 | ops_level: `debug`,
62 | request_level: `debug`,
63 | response_level: `info`,
64 | other_level: `info`
65 | }]
66 | }]
67 | }
68 | }
69 |
70 | // Settings for MySQL Database
71 | mysql = {
72 | host: process.env.DB_HOST || `127.0.0.1`,
73 | user: process.env.DB_USERNAME || `root`,
74 | password: process.env.DB_PASSWORD || `password`,
75 | database: process.env.DB_NAME || `scribe`,
76 | charset: `utf8`
77 | }
78 |
79 | // Settings for SQLite3 Database
80 | sqlite = {
81 | filename: `./src/scribe.sqlite`
82 | }
83 |
84 | // Settings for Knex
85 | db = {
86 | client: this.ENV === `test` || this.ENV === `development` ? `sqlite` : `mysql`,
87 | connection: this.ENV === `test` || this.ENV === `development` ? this.sqlite : this.mysql,
88 | migrations: {
89 | directory: `./src/models`,
90 | tableName: `migrations`
91 | },
92 | useNullAsDefault: this.ENV === `test` || this.ENV === `development` ? true : false
93 | }
94 | }
95 |
96 | export default new Config()
97 |
--------------------------------------------------------------------------------
/src/models/index.js:
--------------------------------------------------------------------------------
1 | import config from '../config/server.config'
2 | import * as Tables from './tables'
3 | import * as Lists from './lists'
4 | const { log, error } = console
5 |
6 | export const Models = { ...Tables, ...Lists }
7 |
8 | export default Models
9 |
10 | const create = (knex) => Object.values(Models)
11 | .filter(migration => (!!migration.fields || !!migration.foreignKeys))
12 | .map(migration => knex.schema.createTableIfNotExists(migration.name, (table) => {
13 | migration.fields(table)
14 | if (config.ENV === `test` || config.ENV === `development` && !!migration.foreignKeys) migration.foreignKeys(table)
15 | })
16 | .then(() => log(`Created table: ${migration.name}`))
17 | .catch(err => error(`Failed to create table: ${migration.name}`, err)))
18 |
19 | const update = (knex) => Object.values(Models)
20 | .filter(migration => !!migration.foreignKeys)
21 | .map(migration => knex.schema.table(migration.name, table => migration.foreignKeys(table))
22 | .then(() => log(`Set Foreign Keys on table: ${migration.name}`))
23 | .catch(err => error(`Failed to alter table: ${migration.name}`, err)))
24 |
25 | const destroy = (knex) => Object.values(Models)
26 | .map(migration => knex.schema.dropTableIfExists(migration.name)
27 | .then(() => log(`Destroyed table: ${migration.name}`))
28 | .catch(err => error(`Failed to destroy table: ${migration.name}`, err)))
29 |
30 | // http://knexjs.org/#Migrations-API
31 |
32 | const pragma = `
33 | PRAGMA foreign_keys = ON;
34 | PRAGMA synchronous = OFF;
35 | PRAGMA journal_mode = MEMORY;
36 | PRAGMA temp_store = MEMORY;
37 | PRAGMA count_changes = OFF;
38 | `
39 |
40 | export const up = (knex, Promise) => knex
41 | .raw(`${ config.ENV === `production` ? `SET foreign_key_checks = 0;` : pragma }`)
42 | .then(() => Promise.all(create(knex)))
43 | .then(() => config.ENV === `production` ? Promise.all(update(knex)) : null)
44 | .then(() => config.ENV === `production` ? knex.raw(`SET foreign_key_checks = 1;`) : null)
45 |
46 | export const down = (knex, Promise) => knex
47 | .raw(`${ config.ENV === `production` ? `SET foreign_key_checks = 0;` : `` }`)
48 | .then(() => Promise.all(destroy(knex)))
49 | .then(() => config.ENV === `production` ? knex.raw(`SET foreign_key_checks = 1;`) : null)
50 |
--------------------------------------------------------------------------------
/src/models/lists/abilityTypeCards.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Card, AbilityType } from '../tables'
3 |
4 | export default class AbilityTypeCards extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Fields
8 | table.bigInteger(`abilitytype`)
9 | .comment(`The abilityType associated with this card.`)
10 | .notNullable()
11 | .unsigned()
12 | .index(`abilitytypecards_abilitytype`)
13 |
14 | table.bigInteger(`card`)
15 | .comment(`The card associated with this abilityType.`)
16 | .notNullable()
17 | .unsigned()
18 | .index(`abilitytypecards_card`)
19 |
20 | // Timestamps
21 | table.timestamps()
22 |
23 | // Keys
24 | table.primary([`abilitytype`, `card`])
25 | }
26 |
27 | // Bookshelf Relation Definitions
28 | get tableName() { return `abilitytypecards` }
29 |
30 | get hasTimestamps() { return true }
31 |
32 | abilityType() {
33 | return this.belongsTo(AbilityType)
34 | }
35 |
36 | card() {
37 | return this.hasMany(Card)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/models/lists/abilityTypes.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class AbilityTypes extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this abilityType.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`abilitytypes_card`)
12 |
13 | table.bigInteger(`abilitytype`)
14 | .comment(`The abilityType associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`abilitytypes_abilitytype`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `abilitytype`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `abilitytypes` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/artistCards.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class ArtistCards extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`artist`)
8 | .comment(`The artist associated with this card.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`artistcards_artist`)
12 |
13 | table.bigInteger(`card`)
14 | .comment(`The card associated with this artist.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`artistcards_card`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`artist`, `card`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `artistcards` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/blockSets.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class BlockSets extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`block`)
8 | .comment(`The block associated with this set.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`blocksets_block`)
12 |
13 | table.bigInteger(`set`)
14 | .comment(`The set associated with this block.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`blocksets_set`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`block`, `set`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `blocksets` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/cardColors.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class CardColors extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with the color.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`cardColors_card`)
12 |
13 | table.bigInteger(`color`)
14 | .comment(`The color associated with the card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`cardColors_color`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `color`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `cardColors` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/categories.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Categories extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this category.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`categories_card`)
12 |
13 | table.bigInteger(`category`)
14 | .comment(`The category associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`categories_category`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `category`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `categories` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/categoryCards.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class CategoryCards extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`category`)
8 | .comment(`The category associated with this card.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`categorycards_category`)
12 |
13 | table.bigInteger(`card`)
14 | .comment(`The card associated with this category.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`categorycards_card`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`category`, `card`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `categorycards` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/colors.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Colors extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`coloridentity`)
8 | .comment(`The colorIdentity associated with the color.`)
9 | .notNullable()
10 | .unsigned()
11 |
12 | table.bigInteger(`color`)
13 | .comment(`The color associated with the colorIdentity.`)
14 | .notNullable()
15 | .unsigned()
16 |
17 | // Timestamps
18 | table.timestamps()
19 |
20 | // Keys
21 | table.primary([`coloridentity`, `color`])
22 | }
23 |
24 | // Bookshelf Relation Definitions
25 | get tableName() { return `colors` }
26 |
27 | get hasTimestamps() { return true }
28 | }
29 |
--------------------------------------------------------------------------------
/src/models/lists/formatSets.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class FormatSets extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`format`)
8 | .comment(`The format associated with this set.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`formatsets_format`)
12 |
13 | table.bigInteger(`set`)
14 | .comment(`The set associated with this format.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`formatsets_set`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`format`, `set`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `formatsets` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/icons.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Icons extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`layout`)
8 | .comment(`The layout associated with this icon.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`icons_layout`)
12 |
13 | table.bigInteger(`icon`)
14 | .comment(`The icon associated with this layout.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`icons_icon`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`layout`, `icon`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `icons` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/images.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Images extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`printing`)
8 | .comment(`The printing associated with this image.`)
9 | .notNullable()
10 | .unsigned()
11 |
12 | table.bigInteger(`image`)
13 | .comment(`The image associated with this printing.`)
14 | .notNullable()
15 | .unsigned()
16 |
17 | // Timestamps
18 | table.timestamps()
19 |
20 | // Keys
21 | table.primary([`printing`, `image`])
22 | }
23 |
24 | // Bookshelf Relation Definitions
25 | get tableName() { return `images` }
26 |
27 | get hasTimestamps() { return true }
28 | }
29 |
--------------------------------------------------------------------------------
/src/models/lists/index.js:
--------------------------------------------------------------------------------
1 | export { default as AbilityTypeCards } from './abilityTypeCards'
2 | export { default as AbilityTypes } from './abilityTypes'
3 | export { default as ArtistCards } from './artistCards'
4 | export { default as BlockSets } from './blockSets'
5 | export { default as CardColors } from './cardColors'
6 | export { default as Categories } from './categories'
7 | export { default as Colors } from './colors'
8 | export { default as FormatSets } from './formatSets'
9 | export { default as Icons } from './icons'
10 | export { default as Images } from './images'
11 | export { default as KeywordCards } from './keywordCards'
12 | export { default as Keywords } from './keywords'
13 | export { default as Legalities } from './legalities'
14 | export { default as LegalityCards } from './legalityCards'
15 | export { default as NameCards } from './nameCards'
16 | export { default as Names } from './names'
17 | export { default as Printings } from './printings'
18 | export { default as RulingCards } from './rulingCards'
19 | export { default as Rulings } from './rulings'
20 | export { default as Sides } from './sides'
21 | export { default as Subtypes } from './subtypes'
22 | export { default as Supertypes } from './supertypes'
23 | export { default as Types } from './types'
24 | export { default as Variations } from './variations'
25 |
--------------------------------------------------------------------------------
/src/models/lists/keywordCards.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class KeywordCards extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`keyword`)
8 | .comment(`The keyword associated with this card.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`keywordcards_keyword`)
12 |
13 | table.bigInteger(`card`)
14 | .comment(`The card associated with this keyword.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`keywordcards_card`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`keyword`, `card`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `keywordcards` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/keywords.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Keywords extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this keyword.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`keywords_card`)
12 |
13 | table.bigInteger(`keyword`)
14 | .comment(`The keyword associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`keywords_keyword`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `keyword`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `keywords` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/legalities.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Legalities extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this legality.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`legalities_card`)
12 |
13 | table.bigInteger(`legality`)
14 | .comment(`The legality associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`legalities_legality`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `legality`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `legalities` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/legalityCards.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class LegalityCards extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`legality`)
8 | .comment(`The legality associated with this card.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`legalitycards_legality`)
12 |
13 | table.bigInteger(`card`)
14 | .comment(`The card associated with this legality.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`legalitycards_card`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`legality`, `card`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `legalitycards` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/nameCards.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class NameCards extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`name`)
8 | .comment(`The name associated with this card.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`namecards_name`)
12 |
13 | table.bigInteger(`card`)
14 | .comment(`The card associated with this name.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`namecards_card`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`name`, `card`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `namecards` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/names.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Names extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this name.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`names_card`)
12 |
13 | table.bigInteger(`name`)
14 | .comment(`The name associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`names_name`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `name`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `names` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/printings.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Printings extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this printing.`)
9 | .notNullable()
10 | .unsigned()
11 |
12 | table.bigInteger(`printing`)
13 | .comment(`The printing associated with this card.`)
14 | .notNullable()
15 | .unsigned()
16 |
17 | // Timestamps
18 | table.timestamps()
19 |
20 | // Keys
21 | table.primary([`card`, `printing`])
22 | }
23 |
24 | // Bookshelf Relation Definitions
25 | get tableName() { return `printings` }
26 |
27 | get hasTimestamps() { return true }
28 | }
29 |
--------------------------------------------------------------------------------
/src/models/lists/rulingCards.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class RulingCards extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`ruling`)
8 | .comment(`The ruling associated with this card.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`rulingcards_ruling`)
12 |
13 | table.bigInteger(`card`)
14 | .comment(`The card associated with this ruling.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`rulingcards_card`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`ruling`, `card`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `rulingcards` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/rulings.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Rulings extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this ruling.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`rulings_card`)
12 |
13 | table.bigInteger(`ruling`)
14 | .comment(`The ruling associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`rulings_ruling`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `ruling`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `rulings` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/sides.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Sides extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this side.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`sides_card`)
12 |
13 | table.bigInteger(`side`)
14 | .comment(`The side associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`sides_side`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `side`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `sides` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/subtypes.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Subtypes extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this subtype.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`subtypes_card`)
12 |
13 | table.bigInteger(`subtype`)
14 | .comment(`The subtype associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`subtypes_subtype`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `subtype`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `subtypes` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/supertypes.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Supertypes extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this supertype.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`supertypes_card`)
12 |
13 | table.bigInteger(`supertype`)
14 | .comment(`The supertype associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`supertypes_supertype`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `supertype`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `supertypes` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/types.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Types extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this type.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`types_card`)
12 |
13 | table.bigInteger(`type`)
14 | .comment(`The type associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`types_type`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `type`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `types` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/lists/variations.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Variations extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigInteger(`card`)
8 | .comment(`The card associated with this variation.`)
9 | .notNullable()
10 | .unsigned()
11 | .index(`variations_card`)
12 |
13 | table.bigInteger(`variation`)
14 | .comment(`The variation associated with this card.`)
15 | .notNullable()
16 | .unsigned()
17 | .index(`variations_variation`)
18 |
19 | // Timestamps
20 | table.timestamps()
21 |
22 | // Keys
23 | table.primary([`card`, `variation`])
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `variations` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/tables/abilityType.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Card } from './'
3 | import { AbilityTypes, AbilityTypeCards } from '../lists'
4 |
5 | export default class AbilityType extends db.Model {
6 | // Knex Schema Definitions
7 | static fields(table) {
8 | // Fields
9 | table.bigIncrements(`id`)
10 | .notNullable()
11 | .unsigned()
12 | .primary()
13 | .unique()
14 |
15 | table.string(`name`)
16 | .comment(`The name of the ability type.`)
17 | .notNullable()
18 | .unique()
19 |
20 | table.text(`description`)
21 | .comment(`Description of the ability type.`)
22 |
23 | table.bigInteger(`cards`)
24 | .comment(`The cards associated with this abilityType.`)
25 | .notNullable()
26 | .unsigned()
27 | .index(`abilitytype_cards`)
28 |
29 | // Timestamps
30 | table.timestamps()
31 | }
32 |
33 | // Bookshelf Relation Definitions
34 | get tableName() { return `abilitytype` }
35 |
36 | get hasTimestamps() { return true }
37 |
38 | abilityTypes = () => this.belongsTo(AbilityTypes)
39 |
40 | cards = () => this.hasMany(Card, `card`).through(AbilityTypeCards)
41 | }
42 |
--------------------------------------------------------------------------------
/src/models/tables/artist.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Card } from './'
3 | import { ArtistCards } from '../lists'
4 |
5 | export default class Artist extends db.Model {
6 | // Knex Schema Definitions
7 | static fields(table) {
8 | // Fields
9 | table.bigIncrements(`id`)
10 | .notNullable()
11 | .unsigned()
12 | .primary()
13 | .unique()
14 |
15 | table.string(`name`)
16 | .comment(`The name of the artist.`)
17 | .notNullable()
18 | .unique()
19 |
20 | table.text(`website`)
21 | .comment(`The website of the artist, if they have one.`)
22 |
23 | table.bigInteger(`cards`)
24 | .comment(`The cards associated with this artist.`)
25 | .unsigned()
26 | .index(`artist_cards`)
27 |
28 | // Timestamps
29 | table.timestamps()
30 | }
31 |
32 | // Bookshelf Relation Definitions
33 | get tableName() { return `artist` }
34 |
35 | get hasTimestamps() { return true }
36 |
37 | cards = () => this.hasMany(Card, `cards`).through(ArtistCards)
38 | }
39 |
--------------------------------------------------------------------------------
/src/models/tables/block.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Set } from './'
3 | import { BlockSets } from '../lists'
4 |
5 | export default class Block extends db.Model {
6 | // Knex Schema Definitions
7 | static fields(table) {
8 | // Fields
9 | table.bigIncrements(`id`)
10 | .notNullable()
11 | .unsigned()
12 | .primary()
13 | .unique()
14 |
15 | table.string(`name`)
16 | .comment(`The name of the block.`)
17 | .notNullable()
18 | .unique()
19 |
20 | // Timestamps
21 | table.timestamps()
22 | }
23 |
24 | // Bookshelf Relation Definitions
25 | get tableName() { return `block` }
26 |
27 | get hasTimestamps() { return true }
28 |
29 | sets = () => this.hasMany(Set, `id`).through(BlockSets, `id`, `block`, `set`)
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/tables/booster.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Booster extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigIncrements(`id`)
8 | .notNullable()
9 | .unsigned()
10 | .primary()
11 | .unique()
12 |
13 | // Timestamps
14 | table.timestamps()
15 | }
16 |
17 | // Bookshelf Relation Definitions
18 | get tableName() { return `booster` }
19 |
20 | get hasTimestamps() { return true }
21 | }
22 |
--------------------------------------------------------------------------------
/src/models/tables/card.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Name, Layout, Color, ColorIdentity, Supertype, Type, Subtype, Rarity, Category, AbilityType, Keyword, Legality, Ruling, Printing } from './'
3 | import { Names, CardColors, Supertypes, Types, Subtypes, Categories, AbilityTypes, Keywords, Legalities, Rulings, Printings } from '../lists'
4 |
5 | export default class Card extends db.Model {
6 | // Knex Schema Definitions
7 | static fields(table) {
8 | // Fields
9 | table.bigIncrements(`id`)
10 | .notNullable()
11 | .unsigned()
12 | .primary()
13 | .unique()
14 |
15 | table.string(`name`)
16 | .comment(`The English name of the card.`)
17 | .notNullable()
18 | .unique()
19 |
20 | table.string(`border`)
21 | .comment(`If the border for this specific card is DIFFERENT than the border specified in the top level set JSON, then it will be specified here. (Example: Unglued has silver borders, except for the lands which are black bordered)`)
22 |
23 | table.bigInteger(`layout`)
24 | .comment(`The card layout.`)
25 | .notNullable()
26 | .unsigned()
27 |
28 | table.string(`watermark`)
29 | .comment(`The watermark on the card. Note: Split cards don’t currently have this field set, despite having a watermark on each side of the split card.`)
30 |
31 | table.string(`manacost`)
32 | .comment(`The mana cost of this card. Consists of one or more mana symbols. (use cmc and colors to query)`)
33 |
34 | table.integer(`cmc`)
35 | .comment(`Converted mana cost.`)
36 | .notNullable()
37 |
38 | table.bigInteger(`colorIdentity`)
39 | .comment(`The card colors by color code. [“Red”, “Blue”] becomes [“R”, “U”]`)
40 | .notNullable()
41 | .unsigned()
42 |
43 | table.string(`typeLine`)
44 | .comment(`The card type. This is the type you would see on the card if printed today. Note: The dash is a UTF8 long dash as per the MTG rules.`)
45 | .notNullable()
46 |
47 | table.bigInteger(`rarity`)
48 | .comment(`The rarity of the card.`)
49 | .notNullable()
50 | .unsigned()
51 |
52 | table.text(`text`)
53 | .comment(`The text of the card.`)
54 |
55 | table.string(`hand`)
56 | .comment(`Maximum hand size modifier. Only exists for Vanguard cards.`)
57 |
58 | table.string(`life`)
59 | .comment(`Starting life total modifier. Only exists for Vanguard cards.`)
60 |
61 | table.string(`power`)
62 | .comment(`The power of the card. This is only present for creatures. This is a string, not an integer, because some cards have powers like: “1+*”`)
63 |
64 | table.string(`toughness`)
65 | .comment(`The toughness of the card. This is only present for creatures. This is a string, not an integer, because some cards have toughness like: “1+*”`)
66 |
67 | table.integer(`loyalty`)
68 | .comment(`The loyalty of the card. This is only present for planeswalkers.`)
69 | // Timestamps
70 | table.timestamps()
71 | }
72 |
73 | // Bookshelf Relation Definitions
74 | get tableName() { return `card` }
75 |
76 | get hasTimestamps() { return true }
77 |
78 | names = () => this.hasMany(Name, `id`).through(Names, `id`, `card`, `name`)
79 |
80 | layout = () => this.hasOne(Layout, `id`, `layout`)
81 |
82 | colors = () => this.hasMany(Color, `id`).through(CardColors, `id`, `card`, `color`)
83 |
84 | colorIdentity = () => this.hasOne(ColorIdentity, `id`, `colorIdentity`)
85 |
86 | supertypes = () => this.hasMany(Supertype, `id`).through(Supertypes, `id`, `card`, `supertype`)
87 |
88 | types = () => this.hasMany(Type, `id`).through(Types, `id`, `card`, `type`)
89 |
90 | subtypes = () => this.hasMany(Subtype, `id`).through(Subtypes, `id`, `card`, `subtype`)
91 |
92 | categories = () => this.hasMany(Category, `id`).through(Categories, `id`, `card`, `category`)
93 |
94 | keywords = () => this.hasMany(Keyword, `id`).through(Keywords, `id`, `card`, `keyword`)
95 |
96 | abilityTypes = () => this.hasMany(AbilityType, `id`).through(AbilityTypes, `id`, `card`, `abilityType`)
97 |
98 | legalities = () => this.hasMany(Legality, `id`).through(Legalities, `id`, `card`, `legality`)
99 |
100 | rulings = () => this.hasMany(Ruling, `id`).through(Rulings, `id`, `card`, `ruling`)
101 |
102 | printings = () => this.hasMany(Printing, `id`).through(Printings, `id`, `card`, `printing`)
103 |
104 | rarity = () => this.hasOne(Rarity, `id`, `rarity`)
105 | }
106 |
--------------------------------------------------------------------------------
/src/models/tables/category.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Card } from './'
3 | import { CategoryCards } from '../lists'
4 |
5 | export default class Category extends db.Model {
6 | // Knex Schema Definitions
7 | static fields(table) {
8 | // Fields
9 | table.bigIncrements(`id`)
10 | .notNullable()
11 | .unsigned()
12 | .primary()
13 | .unique()
14 |
15 | table.string(`name`)
16 | .comment(`The name of the category.`)
17 | .notNullable()
18 | .unique()
19 |
20 | table.text(`description`)
21 | .comment(`The description of the category.`)
22 |
23 | table.bigInteger(`cards`)
24 | .comment(`A list of cards that have this category.`)
25 | .notNullable()
26 | .unsigned()
27 | .index(`category_cards`)
28 |
29 | // Timestamps
30 | table.timestamps()
31 | }
32 |
33 | // Bookshelf Relation Definitions
34 | get tableName() { return `category` }
35 |
36 | get hasTimestamps() { return true }
37 |
38 | cards = () => this.hasMany(Card).through(CategoryCards, `category`)
39 | }
40 |
--------------------------------------------------------------------------------
/src/models/tables/color.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Icon, ColorIdentity } from './'
3 | import { Colors } from '../lists'
4 |
5 | export default class Color extends db.Model {
6 | // Knex Schema Definitions
7 | static fields(table) {
8 | // Fields
9 | table.bigIncrements(`id`)
10 | .notNullable()
11 | .unsigned()
12 | .primary()
13 | .unique()
14 |
15 | table.string(`symbol`)
16 | .comment(`The color symbol code for this color.`)
17 | .notNullable()
18 | .notNullable()
19 | .unique()
20 |
21 | table.bigInteger(`icon`)
22 | .comment(`The icon associated with the color.`)
23 | .unsigned()
24 | .references(`id`)
25 | .inTable(`icon`)
26 | .onDelete(`NO ACTION`)
27 | .onUpdate(`NO ACTION`)
28 |
29 | table.bigInteger(`identity`)
30 | .comment(`The color identity associated with the color.`)
31 | .unsigned()
32 | .references(`id`)
33 | .inTable(`coloridentity`)
34 | .onDelete(`NO ACTION`)
35 | .onUpdate(`NO ACTION`)
36 |
37 | // Timestamps
38 | table.timestamps()
39 | }
40 |
41 | // Bookshelf Relation Definitions
42 | get tableName() { return `color` }
43 |
44 | get hasTimestamps() { return true }
45 |
46 | icon = () => this.hasOne(Icon, `id`, `icon`)
47 |
48 | identity = () => this.hasOne(ColorIdentity, `id`, `identity`)
49 |
50 | identities = () => this.belongsToMany(ColorIdentity, `id`).through(Colors, `id`, `coloridentity`, `color`)
51 | }
52 |
--------------------------------------------------------------------------------
/src/models/tables/colorIdentity.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Color } from './'
3 | import { Colors } from '../lists'
4 |
5 | export default class ColorIdentity extends db.Model {
6 | // Knex Schema Definitions
7 | static fields(table) {
8 | // Fields
9 | table.bigIncrements(`id`)
10 | .notNullable()
11 | .unsigned()
12 | .primary()
13 | .unique()
14 |
15 | table.string(`name`)
16 | .comment(`The name of the color identity.`)
17 | .notNullable()
18 | .unique()
19 |
20 | table.string(`alias`)
21 | .comment(`The alias of the color identity. Examples: Bant, Jeskai`)
22 |
23 | table.boolean(`multicolored`)
24 | .comment(`True if the color identity has more than one color.`)
25 | .notNullable()
26 |
27 | table.boolean(`devoid`)
28 | .comment(`True if the color identity is ruled to be colorless.`)
29 | .notNullable()
30 |
31 | // Timestamps
32 | table.timestamps()
33 | }
34 |
35 | // Bookshelf Relation Definitions
36 | get tableName() { return `colorIdentity` }
37 |
38 | get hasTimestamps() { return true }
39 |
40 | colors = () => this.hasMany(Color, `id`).through(Colors, `id`, `coloridentity`, `color`)
41 | }
42 |
--------------------------------------------------------------------------------
/src/models/tables/format.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Set } from './'
3 |
4 | export default class Format extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Fields
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | table.string(`name`)
15 | .comment(`The name of the format.`)
16 | .notNullable()
17 | .unique()
18 |
19 | table.bigInteger(`sets`)
20 | .comment(`List of sets that are included in this format.`)
21 | .notNullable()
22 | .unsigned()
23 | .index(`format_sets`)
24 |
25 | // Timestamps
26 | table.timestamps()
27 | }
28 |
29 | // Bookshelf Relation Definitions
30 | get tableName() { return `format` }
31 |
32 | get hasTimestamps() { return true }
33 |
34 | sets = () => this.hasMany(Set, `sets`)
35 | }
36 |
--------------------------------------------------------------------------------
/src/models/tables/icon.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Icon extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigIncrements(`id`)
8 | .notNullable()
9 | .unsigned()
10 | .primary()
11 | .unique()
12 |
13 | table.string(`name`)
14 | .comment(`The name of the icon.`)
15 | .notNullable()
16 |
17 | table.text(`image`)
18 | .comment(`A URL pointing to an image of the icon.`)
19 |
20 | table.string(`class`)
21 | .comment(`CSS class name used to display the icon.`)
22 |
23 | // Timestamps
24 | table.timestamps()
25 | }
26 |
27 | // Bookshelf Relation Definitions
28 | get tableName() { return `icon` }
29 |
30 | get hasTimestamps() { return true }
31 | }
32 |
--------------------------------------------------------------------------------
/src/models/tables/image.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { LanguageCode } from './'
3 |
4 | export default class Image extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Fields
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | table.string(`multiverseid`)
15 | .comment(`The multiverseid of the printing on Wizard’s Gatherer web page. Cards from sets that do not exist on Gatherer will NOT have a multiverseid.`)
16 | .notNullable()
17 | .unique()
18 |
19 | table.text(`url`)
20 | .comment(`A URL pointing to an image of the card.`)
21 | .notNullable()
22 |
23 | table.bigInteger(`language`)
24 | .comment(`The language code of the language the image is localized in.`)
25 | .notNullable()
26 | .unsigned()
27 |
28 | // Timestamps
29 | table.timestamps()
30 | }
31 |
32 | // Bookshelf Relation Definitions
33 | get tableName() { return `image` }
34 |
35 | get hasTimestamps() { return true }
36 |
37 | language = () => this.hasOne(LanguageCode, `language`)
38 | }
39 |
--------------------------------------------------------------------------------
/src/models/tables/index.js:
--------------------------------------------------------------------------------
1 | export { default as AbilityType } from './abilityType'
2 | export { default as Artist } from './artist'
3 | export { default as Block } from './block'
4 | export { default as Booster } from './booster'
5 | export { default as Card } from './card'
6 | export { default as Category } from './category'
7 | export { default as Color } from './color'
8 | export { default as ColorIdentity } from './colorIdentity'
9 | export { default as Format } from './format'
10 | export { default as Icon } from './icon'
11 | export { default as Image } from './image'
12 | export { default as Keyword } from './keyword'
13 | export { default as Language } from './language'
14 | export { default as LanguageCode } from './languageCode'
15 | export { default as Layout } from './layout'
16 | export { default as Legality } from './legality'
17 | export { default as Name } from './name'
18 | export { default as Printing } from './printing'
19 | export { default as Rarity } from './rarity'
20 | export { default as Ruling } from './ruling'
21 | export { default as Set } from './set'
22 | export { default as SetType } from './setType'
23 | export { default as Subtype } from './subtype'
24 | export { default as Supertype } from './supertype'
25 | export { default as Type } from './type'
26 |
--------------------------------------------------------------------------------
/src/models/tables/keyword.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Card, LanguageCode } from './'
3 |
4 | export default class Keyword extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Fields
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | table.string(`name`)
15 | .comment(`The name of the keyword.`)
16 | .notNullable()
17 | .unique()
18 |
19 | table.text(`reminderText`)
20 | .comment(`A short description of the keyword rules.`)
21 |
22 | table.bigInteger(`languageCode`)
23 | .comment(`The language code the reminder text of keyword is localized in.`)
24 | .notNullable()
25 | .unsigned()
26 | .index(`keyword_code`)
27 |
28 | table.bigInteger(`cards`)
29 | .comment(`A list of cards that have this keyword.`)
30 | .notNullable()
31 | .unsigned()
32 | .index(`keyword_cards`)
33 |
34 | // Timestamps
35 | table.timestamps()
36 | }
37 |
38 | // Bookshelf Relation Definitions
39 | get tableName() { return `keyword` }
40 |
41 | get hasTimestamps() { return true }
42 |
43 | languageCode = () => this.hasOne(LanguageCode, `languageCode`)
44 |
45 | cards = () => this.belongsToMany(Card, `cards`)
46 | }
47 |
--------------------------------------------------------------------------------
/src/models/tables/language.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { LanguageCode } from './'
3 |
4 | export default class Language extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Fields
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | table.string(`name`)
15 | .comment(`The name of the language.`)
16 | .notNullable()
17 | .unique()
18 |
19 | table.bigInteger(`code`)
20 | .comment(`The language code associated with this language.`)
21 | .notNullable()
22 | .unsigned()
23 | .index(`language_code`)
24 |
25 | // Timestamps
26 | table.timestamps()
27 | }
28 |
29 | // Bookshelf Relation Definitions
30 | get tableName() { return `language` }
31 |
32 | get hasTimestamps() { return true }
33 |
34 | code = () => this.hasOne(LanguageCode, `id`, `code`)
35 | }
36 |
--------------------------------------------------------------------------------
/src/models/tables/languageCode.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Language } from './'
3 |
4 | export default class LanguageCode extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Fields
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | table.string(`code`)
15 | .comment(`The language code.`)
16 | .notNullable()
17 | .unique()
18 |
19 | table.bigInteger(`language`)
20 | .comment(`The language associated with the language code.`)
21 | .notNullable()
22 | .unsigned()
23 | .index(`languagecode_language`)
24 |
25 | // Timestamps
26 | table.timestamps()
27 | }
28 |
29 | // Bookshelf Relation Definitions
30 | get tableName() { return `languagecode` }
31 |
32 | get hasTimestamps() { return true }
33 |
34 | language = () => this.belongsTo(Language, `language`)
35 | }
36 |
--------------------------------------------------------------------------------
/src/models/tables/layout.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Icon } from './'
3 |
4 | export default class Layout extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Fields
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | table.string(`name`)
15 | .comment(`The name of the layout.`)
16 | .notNullable()
17 | .unique()
18 |
19 | table.bigInteger(`watermark`)
20 | .comment(`Watermark icon used in this layout.`)
21 | .unsigned()
22 | .index(`layout_watermark`)
23 |
24 | table.bigInteger(`icons`)
25 | .comment(`List of icons used in this layout.`)
26 | .unsigned()
27 | .index(`layout_icons`)
28 |
29 | // Timestamps
30 | table.timestamps()
31 | }
32 |
33 | // Bookshelf Relation Definitions
34 | get tableName() { return `layout` }
35 |
36 | get hasTimestamps() { return true }
37 |
38 | icons = () => this.hasMany(Icon, `icons`)
39 | }
40 |
--------------------------------------------------------------------------------
/src/models/tables/legality.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Format, Card } from './'
3 |
4 | export default class Legality extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Indexes
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | // Fields
15 | table.bigInteger(`format`)
16 | .comment(`The format associated with this legality.`)
17 | .notNullable()
18 | .unsigned()
19 | .index(`legality_format`)
20 |
21 | table.boolean(`legal`)
22 | .comment(`True if the card is legal in the associated format.`)
23 | .notNullable()
24 |
25 | table.boolean(`restricted`)
26 | .comment(`True if the card is restricted in the associated format.`)
27 | .notNullable()
28 |
29 | table.bigInteger(`cards`)
30 | .comment(`List of cards that have this legality ruling.`)
31 | .notNullable()
32 | .unsigned()
33 | .index(`legality_cards`)
34 |
35 | // Timestamps
36 | table.timestamps()
37 | }
38 |
39 | // Bookshelf Relation Definitions
40 | get tableName() { return `legality` }
41 |
42 | get hasTimestamps() { return true }
43 |
44 | format = () => this.hasOne(Format, `format`)
45 |
46 | cards = () => this.belongsToMany(Card, `cards`)
47 | }
48 |
--------------------------------------------------------------------------------
/src/models/tables/name.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Card, Language } from './'
3 |
4 | export default class Name extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Fields
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | table.string(`name`)
15 | .comment(`The localized name of the card.`)
16 | .notNullable()
17 |
18 | table.bigInteger(`language`)
19 | .comment(`The language code of the language the name is localized in.`)
20 | .notNullable()
21 | .unsigned()
22 | .index(`name_language`)
23 |
24 | table.bigInteger(`cards`)
25 | .comment(`A list of cards that have this name.`)
26 | .unsigned()
27 | .index(`name_cards`)
28 |
29 | // Timestamps
30 | table.timestamps()
31 | }
32 |
33 | // Bookshelf Relation Definitions
34 | get tableName() { return `name` }
35 |
36 | get hasTimestamps() { return true }
37 |
38 | cards = () => this.belongsTo(Card, `id`, `card`)
39 |
40 | language = () => this.hasOne(Language, `id`, `language`)
41 | }
42 |
--------------------------------------------------------------------------------
/src/models/tables/printing.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Card, Set, Image, Artist } from './'
3 | import { Images, Sides, Variations } from '../lists'
4 |
5 | export default class Printing extends db.Model {
6 | // Knex Schema Definitions
7 | static fields(table) {
8 | // Fields
9 | table.bigIncrements(`id`)
10 | .notNullable()
11 | .unsigned()
12 | .primary()
13 | .unique()
14 |
15 | table.bigInteger(`card`)
16 | .comment(`The card this is a printing of.`)
17 | .notNullable()
18 | .unsigned()
19 |
20 | table.bigInteger(`set`)
21 | .comment(`The set the card printed in.`)
22 | .notNullable()
23 | .unsigned()
24 |
25 | table.bigInteger(`artist`)
26 | .comment(`The artist of the card on this printing.`)
27 | .notNullable()
28 | .unsigned()
29 |
30 | table.string(`originaltype`)
31 | .comment(`The original type on the card at the time it was printed.`)
32 |
33 | table.text(`originaltext`)
34 | .comment(`The original text on the card at the time it was printed.`)
35 |
36 | table.text(`flavor`)
37 | .comment(`The flavor text on the card for this printing.`)
38 |
39 | table.string(`number`)
40 | .comment(`The card number. This is printed at the bottom-center of the card in small text. This is a string, not an integer, because some cards have letters in their numbers.`)
41 | .notNullable()
42 |
43 | table.boolean(`timeshifted`)
44 | .comment(`If this card was a timeshifted card in the set.`)
45 |
46 | table.boolean(`starter`)
47 | .comment(`Set to true if this card was only released as part of a core box set. These are technically part of the core sets and are tournament legal despite not being available in boosters.`)
48 |
49 | table.boolean(`reserved`)
50 | .comment(`Set to true if this card is reserved by Wizards Official Reprint Policy.`)
51 |
52 | table.string(`source`)
53 | .comment(`For promo cards, this is where this card was originally obtained. For box sets that are theme decks, this is which theme deck the card is from.`)
54 |
55 | // Timestamps
56 | table.timestamps()
57 | }
58 |
59 | // Bookshelf Relation Definitions
60 | get tableName() { return `printing` }
61 |
62 | get hasTimestamps() { return true }
63 |
64 | card = () => this.belongsTo(Card, `card`, `id`)
65 |
66 | set = () => this.belongsTo(Set, `set`, `id`)
67 |
68 | images = () => this.hasMany(Image, `id`).through(Images, `id`, `printing`, `image`)
69 |
70 | artist = () => this.hasOne(Artist, `artist`)
71 |
72 | sides = () => this.hasMany(Card, `id`).through(Sides, `id`, `printing`, `side`)
73 |
74 | variations = () => this.hasMany(Card, `id`).through(Variations, `id`, `printing`, `variation`)
75 | }
76 |
--------------------------------------------------------------------------------
/src/models/tables/rarity.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Rarity extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigIncrements(`id`)
8 | .notNullable()
9 | .unsigned()
10 | .primary()
11 | .unique()
12 |
13 | table.string(`name`)
14 | .comment(`The name of the rarity.`)
15 | .notNullable()
16 | .unique()
17 |
18 | table.string(`class`)
19 | .comment(`CSS class name used to display the rarity.`)
20 | .notNullable()
21 |
22 | // Timestamps
23 | table.timestamps()
24 | }
25 |
26 | // Bookshelf Relation Definitions
27 | get tableName() { return `rarity` }
28 |
29 | get hasTimestamps() { return true }
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/tables/ruling.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 | import { Card, LanguageCode } from './'
3 |
4 | export default class Ruling extends db.Model {
5 | // Knex Schema Definitions
6 | static fields(table) {
7 | // Indexes
8 | table.bigIncrements(`id`)
9 | .notNullable()
10 | .unsigned()
11 | .primary()
12 | .unique()
13 |
14 | // Fields
15 | table.text(`text`)
16 | .comment(`The localized text of the ruling.`)
17 | .notNullable()
18 |
19 | table.date(`date`)
20 | .comment(`The date the ruling was issued.`)
21 | .notNullable()
22 |
23 | table.bigInteger(`language`)
24 | .comment(`The language code of this ruling.`)
25 | .notNullable()
26 | .unsigned()
27 | .index(`ruling_language`)
28 |
29 | table.bigInteger(`cards`)
30 | .comment(`List of cards that have this ruling.`)
31 | .notNullable()
32 | .unsigned()
33 | .index(`ruling_cards`)
34 |
35 | // Timestamps
36 | table.timestamps()
37 | }
38 |
39 | // Bookshelf Relation Definitions
40 | get tableName() { return `ruling` }
41 |
42 | get hasTimestamps() { return true }
43 |
44 | language = () => this.hasOne(LanguageCode, `language`)
45 |
46 | cards = () => this.belongsToMany(Card, `cards`)
47 | }
48 |
--------------------------------------------------------------------------------
/src/models/tables/set.js:
--------------------------------------------------------------------------------
1 | import moment from 'moment'
2 | import db from '../../config/bookshelf.config'
3 | import { Icon, Block, Booster, SetType } from './'
4 | import { BlockSets } from '../lists'
5 |
6 | export default class Set extends db.Model {
7 | // Knex Schema Definitions
8 | static fields(table) {
9 | // Fields
10 | table.bigIncrements(`id`)
11 | .notNullable()
12 | .unsigned()
13 | .primary()
14 | .unique()
15 |
16 | table.string(`name`)
17 | .comment(`The name of the set.`)
18 | .notNullable()
19 | .unique()
20 |
21 | table.string(`code`)
22 | .comment(`The set code.`)
23 | .notNullable()
24 | .unique()
25 |
26 | table.bigInteger(`block`)
27 | .comment(`The block the set belongs to.`)
28 | .unsigned()
29 | .index(`set_block`)
30 |
31 | table.bigInteger(`type`)
32 | .comment(`The type of the set.`)
33 | .notNullable()
34 | .unsigned()
35 | .index(`set_type`)
36 |
37 | table.bigInteger(`icon`)
38 | .comment(`The icon associated with the set.`)
39 | .notNullable()
40 | .unsigned()
41 | .index(`set_icon`)
42 |
43 | table.string(`border`)
44 | .comment(`The border color of the set.`)
45 | .notNullable()
46 |
47 | table.date(`releaseDate`)
48 | .comment(`The date on which the set was released.`)
49 | .notNullable()
50 |
51 | table.bigInteger(`booster`)
52 | .comment(`Booster pack generation rules for this set.`)
53 | .unsigned()
54 | .index(`set_booster`)
55 |
56 | // Timestamps
57 | table.timestamps()
58 | }
59 |
60 | // Bookshelf Relation Definitions
61 | get tableName() { return `set` }
62 |
63 | get hasTimestamps() { return true }
64 |
65 | block = () => this.belongsTo(Block, `block`).through(BlockSets, `id`, `block`, `set`)
66 |
67 | type = () => this.hasOne(SetType, `id`, `type`)
68 |
69 | icon = () => this.hasOne(Icon, `id`, `icon`)
70 |
71 | booster = () => this.hasOne(Booster, `id`, `booster`)
72 |
73 | toJSON() {
74 | let attrs = db.Model.prototype.toJSON.apply(this, arguments)
75 | attrs.releaseDate = moment(this.get(`releaseDate`)).format(`YYYY-MM-DD`)
76 | return attrs
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/models/tables/setType.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class SetType extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigIncrements(`id`)
8 | .notNullable()
9 | .unsigned()
10 | .primary()
11 | .unique()
12 |
13 | table.string(`name`)
14 | .comment(`The name of the set type.`)
15 | .notNullable()
16 | .unique()
17 |
18 | table.text(`description`)
19 | .comment(`The description of the set type.`)
20 |
21 | // Timestamps
22 | table.timestamps()
23 | }
24 |
25 | // Bookshelf Relation Definitions
26 | get tableName() { return `setType` }
27 |
28 | get hasTimestamps() { return true }
29 | }
30 |
--------------------------------------------------------------------------------
/src/models/tables/subtype.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Subtype extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigIncrements(`id`)
8 | .notNullable()
9 | .unsigned()
10 | .primary()
11 | .unique()
12 |
13 | table.string(`name`)
14 | .comment(`The name of the subtype.`)
15 | .notNullable()
16 | .unique()
17 |
18 | // Timestamps
19 | table.timestamps()
20 | }
21 |
22 | // Bookshelf Relation Definitions
23 | get tableName() { return `subtype` }
24 |
25 | get hasTimestamps() { return true }
26 | }
27 |
--------------------------------------------------------------------------------
/src/models/tables/supertype.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Supertype extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigIncrements(`id`)
8 | .notNullable()
9 | .unsigned()
10 | .primary()
11 | .unique()
12 |
13 | table.string(`name`)
14 | .comment(`The name of the supertype.`)
15 | .notNullable()
16 | .unique()
17 |
18 | // Timestamps
19 | table.timestamps()
20 | }
21 |
22 | // Bookshelf Relation Definitions
23 | get tableName() { return `supertype` }
24 |
25 | get hasTimestamps() { return true }
26 | }
27 |
--------------------------------------------------------------------------------
/src/models/tables/type.js:
--------------------------------------------------------------------------------
1 | import db from '../../config/bookshelf.config'
2 |
3 | export default class Type extends db.Model {
4 | // Knex Schema Definitions
5 | static fields(table) {
6 | // Fields
7 | table.bigIncrements(`id`)
8 | .notNullable()
9 | .unsigned()
10 | .primary()
11 | .unique()
12 |
13 | table.string(`name`)
14 | .comment(`The name of the type.`)
15 | .notNullable()
16 | .unique()
17 |
18 | // Timestamps
19 | table.timestamps()
20 | }
21 |
22 | // Bookshelf Relation Definitions
23 | get tableName() { return `type` }
24 |
25 | get hasTimestamps() { return true }
26 | }
27 |
--------------------------------------------------------------------------------
/src/routes/example/example.js:
--------------------------------------------------------------------------------
1 | export default class Example {
2 |
3 | /** GET / - List all entities */
4 | list(req, res) {
5 | res.json({
6 | message: `yay I work!`
7 | })
8 | }
9 |
10 | /** POST / - Create a new entity */
11 | create(req, res) {
12 | console.log(req.body)
13 | res.json(req.body)
14 | }
15 |
16 | /** GET /:id - Return a given entity */
17 | read(req, res) {
18 |
19 | }
20 |
21 | /** PUT /:id - Update a given entity */
22 | update(req, res) {
23 |
24 | }
25 |
26 | /** DELETE /:id - Delete a given entity */
27 | delete(req, res) {
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/routes/index.js:
--------------------------------------------------------------------------------
1 | import path from 'path'
2 | import glob from 'glob' // https://github.com/isaacs/node-glob
3 |
4 | export default (router) => {
5 | glob.sync(`${__dirname}/**/!(*.spec).js`)
6 | .forEach( file => {
7 | if (file !== `index.js`) {
8 | let filename = path.basename(file)
9 | let basename = filename.split(`.`)[0]
10 | let resource = require(file).default
11 | console.log(`✓ Loaded Resource: /${basename}`)
12 | }
13 | })
14 | }
15 |
--------------------------------------------------------------------------------
/src/routes/login/login.js:
--------------------------------------------------------------------------------
1 | import jwt from 'jsonwebtoken'
2 | import passport from 'passport'
3 | import BearerStrategy from 'passport-http-bearer'
4 |
5 | export default class Login {
6 | payload = {
7 |
8 | }
9 |
10 | secret = process.env.JWT_PRIVATE_KEY
11 |
12 | options = {
13 | algorithm: `RS256`,
14 | expiresIn: `2h`
15 | }
16 |
17 | constructor() {
18 | passport.use(new BearerStrategy((token, cb) => {
19 | db.users.findByToken(token, (err, user) => {
20 | if (err) return cb(err)
21 | if (!user) return cb(null, false)
22 | return cb(null, user)
23 | })
24 | }))
25 | console.log(`✓ Passport configured with Bearer Strategy`)
26 | }
27 |
28 | list(req, res) {
29 | res.send(`Login`)
30 | }
31 |
32 | createToken(user) {
33 | return jwt.sign(this.payload, this.secret, this.options)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/routes/ping/ping.js:
--------------------------------------------------------------------------------
1 | export default class Ping {
2 |
3 | /** GET / - List all entities */
4 | list(req, res) {
5 | res.send(`pong`)
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/signup/signup.js:
--------------------------------------------------------------------------------
1 | export default class Signup {
2 |
3 | /** GET / - List all entities */
4 | list(req, res) {
5 |
6 | }
7 |
8 | /** POST / - Create a new entity */
9 | create(req, res) {
10 |
11 | }
12 |
13 | /** GET /:id - Return a given entity */
14 | read(req, res) {
15 |
16 | }
17 |
18 | /** PUT /:id - Update a given entity */
19 | update(req, res) {
20 |
21 | }
22 |
23 | /** DELETE /:id - Delete a given entity */
24 | delete(req, res) {
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/schema.js:
--------------------------------------------------------------------------------
1 | import { GraphQLSchema, GraphQLObjectType } from 'graphql'
2 | import * as Types from './types'
3 |
4 | export default new GraphQLSchema({
5 | types: Object.values(Types).filter(type => !!type.Definition).map(type => type.Definition ),
6 | query: new GraphQLObjectType({
7 | name: `Query`,
8 | description: `The root query handler for Scribe's GraphQL interface.`,
9 | fields: () => Object.assign({}, ...Object.values(Types).filter(type => !!type.Queries).map(type => type.Queries))
10 | }),
11 | mutation: new GraphQLObjectType({
12 | name: `Mutation`,
13 | description: `The root query for implementing GraphQL mutations.`,
14 | fields: () => Object.assign({}, ...Object.values(Types).filter(type => !!type.Mutations).map(type => type.Mutations))
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/src/server.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import hapi from 'hapi' // http://hapijs.com/api
3 | //import jwt from 'hapi-auth-jwt2' // https://github.com/dwyl/hapi-auth-jwt2
4 | import boomDecorators from 'hapi-boom-decorators' // https://github.com/brainsiq/hapi-boom-decorators
5 | import statMon from 'hapijs-status-monitor' // https://github.com/ziyasal/hapijs-status-monitor
6 | import { graphqlHapi, graphiqlHapi } from 'graphql-server-hapi' // http://dev.apollodata.com/tools/graphql-server
7 | import good from 'good' // https://github.com/hapijs/good
8 | import 'good-winston' // https://github.com/lancespeelmon/good-winston
9 | import { configure, info, error } from 'winston'
10 | import config from './config/server.config' // HTTP Server Settings
11 | import graphql from './config/graphql.config' // GraphQL Settings
12 | //import routes from './routes' // REST API Endpoints
13 |
14 | configure(config.winston)
15 |
16 | const server = new hapi.Server()
17 |
18 | // Start the server
19 | server.connection(config.http)
20 |
21 | // Setup Boom Decorators
22 | server.register({
23 | register: boomDecorators
24 | })
25 |
26 | server.register({
27 | register: statMon
28 | })
29 |
30 | // Register the Public GraphQL API Endpoint
31 | server.register({
32 | register: graphqlHapi,
33 | options: graphql.api
34 | })
35 |
36 | // Register the GrahiQL Editor Endpoint
37 | server.register({
38 | register: graphiqlHapi,
39 | options: graphql.graphiql
40 | })
41 |
42 | // Setup Logging and Start the Server
43 | server.register({
44 | register: good,
45 | options: config.good
46 | }, (err) => {
47 | if (err) return error(err)
48 | info(`Bookshelf configured using: ${config.db.client}`)
49 | server.start(() => info(`Server started at ${ server.info.uri }`))
50 | })
51 |
--------------------------------------------------------------------------------
/src/types/abilityType.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Card } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `AbilityTypeInput`,
8 | description: `Required fields for a new Ability Type object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | description: { type: GraphQLString },
12 | cards: { type: new GraphQLList(GraphQLID) }
13 | })
14 | })
15 |
16 | const Filter = new GraphQLInputObjectType({
17 | name: `AbilityTypeFilter`,
18 | description: `Queryable fields for AbilityType.`,
19 | fields: () => ({
20 | name: { type: new GraphQLList(GraphQLString) },
21 | cards: { type: new GraphQLList(GraphQLID) }
22 | })
23 | })
24 |
25 | const Fields = new GraphQLEnumType({
26 | name: `AbilityTypeFields`,
27 | description: `Field names for AbilityType.`,
28 | values: {
29 | name: { value: `name` }
30 | }
31 | })
32 |
33 | export const Definition = new GraphQLObjectType({
34 | name: `AbilityType`,
35 | description: `An Ability Type object`,
36 | fields: () => ({
37 | id: {
38 | type: GraphQLID,
39 | description: `A unique id for this ability type.`
40 | },
41 | name: {
42 | type: GraphQLString,
43 | description: `The name of the ability type.`
44 | },
45 | description: {
46 | type: GraphQLString,
47 | description: `Description of the ability type.`
48 | },
49 | cards: {
50 | type: new GraphQLList(Card.Definition),
51 | description: `The cards associated with this abilityType.`,
52 | resolve: (root, { id }) => Models.AbilityType
53 | .forge({ id })
54 | .fetch({ withRelated: [`cards`] })
55 | .then(model => model.toJSON().cards)
56 | }
57 | })
58 | })
59 |
60 | export const Queries = {
61 | abilityType: {
62 | type: new GraphQLList(Definition),
63 | description: `Returns a AbilityType.`,
64 | args: {
65 | id: { type: new GraphQLList(GraphQLID) },
66 | filter: {
67 | type: Filter
68 | },
69 | limit: { type: GraphQLInt },
70 | offset: { type: GraphQLInt },
71 | orderBy: { type: order(`abilityType`, Fields) }
72 | },
73 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
74 | }
75 | }
76 |
77 | export const Mutations = {
78 | createAbilityType: {
79 | type: Definition,
80 | description: `Creates a new AbilityType`,
81 | args: { input: { type: Input } },
82 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
83 | },
84 | updateAbilityType: {
85 | type: Definition,
86 | description: `Updates an existing AbilityType, creates it if it does not already exist`,
87 | args: { input: { type: Input } },
88 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
89 | },
90 | deleteAbilityType: {
91 | type: Definition,
92 | description: `Deletes a AbilityType by id`,
93 | args: { id: { type: GraphQLID } },
94 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/types/artist.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Card } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `ArtistInput`,
8 | description: `Required fields for a new Artist object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | website: { type: GraphQLString },
12 | cards: { type: new GraphQLList(GraphQLID) }
13 | })
14 | })
15 |
16 | const Filter = new GraphQLInputObjectType({
17 | name: `ArtistFilter`,
18 | description: `Queryable fields for Artist.`,
19 | fields: () => ({
20 | name: { type: new GraphQLList(GraphQLString) },
21 | cards: { type: new GraphQLList(GraphQLID) }
22 | })
23 | })
24 |
25 | const Fields = new GraphQLEnumType({
26 | name: `ArtistFields`,
27 | description: `Field names for Artist.`,
28 | values: {
29 | name: { value: `name` }
30 | }
31 | })
32 |
33 | export const Definition = new GraphQLObjectType({
34 | name: `Artist`,
35 | description: `An Artist object`,
36 | fields: () => ({
37 | id: {
38 | type: GraphQLID,
39 | description: `A unique id for this artist.`
40 | },
41 | name: {
42 | type: GraphQLString,
43 | description: `The name of the artist.`
44 | },
45 | website: {
46 | type: GraphQLString,
47 | description: `A URL to the artist's website, if they have one.`
48 | },
49 | cards: {
50 | type: new GraphQLList(Card.Definition),
51 | description: `A list of cards featuring art from this artist.`,
52 | resolve: (root, { id }) => Models.Artist
53 | .forge({ id })
54 | .fetch({ withRelated: [`cards`] })
55 | .then(model => model.toJSON().cards)
56 | }
57 | })
58 | })
59 |
60 | export const Queries = {
61 | artist: {
62 | type: new GraphQLList(Definition),
63 | description: `Returns a Artist.`,
64 | args: {
65 | id: { type: new GraphQLList(GraphQLID) },
66 | filter: {
67 | type: Filter
68 | },
69 | limit: { type: GraphQLInt },
70 | offset: { type: GraphQLInt },
71 | orderBy: { type: order(`artist`, Fields) }
72 | },
73 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
74 | }
75 | }
76 |
77 | export const Mutations = {
78 | createArtist: {
79 | type: Definition,
80 | description: `Creates a new Artist`,
81 | args: { input: { type: Input } },
82 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
83 | },
84 | updateArtist: {
85 | type: Definition,
86 | description: `Updates an existing Artist, creates it if it does not already exist`,
87 | args: { input: { type: Input } },
88 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
89 | },
90 | deleteArtist: {
91 | type: Definition,
92 | description: `Deletes a Rarity by id`,
93 | args: { id: { type: GraphQLID } },
94 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/types/block.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Set } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `BlockInput`,
8 | description: `Required fields for a new Block object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) }
11 | })
12 | })
13 |
14 | const Filter = new GraphQLInputObjectType({
15 | name: `BlockFilter`,
16 | description: `Queryable fields for Block.`,
17 | fields: () => ({
18 | name: { type: new GraphQLList(GraphQLString) },
19 | sets: { type: new GraphQLList(GraphQLID) }
20 | })
21 | })
22 |
23 | const Fields = new GraphQLEnumType({
24 | name: `BlockFields`,
25 | description: `Field names for Block.`,
26 | values: {
27 | name: { value: `name` }
28 | }
29 | })
30 |
31 | export const Definition = new GraphQLObjectType({
32 | name: `Block`,
33 | description: `A Block object`,
34 | fields: () => ({
35 | id: {
36 | type: GraphQLID,
37 | description: `A unique id for this block.`
38 | },
39 | name: {
40 | type: GraphQLString,
41 | description: `The name of the block.`
42 | },
43 | sets: {
44 | type: new GraphQLList(Set.Definition),
45 | description: `List of sets that are included in this block.`,
46 | resolve: (type) => Models.Block
47 | .findById(type.id, { withRelated: [`sets`] })
48 | .then(model => model.toJSON().sets)
49 | }
50 | })
51 | })
52 |
53 | export const Queries = {
54 | block: {
55 | type: new GraphQLList(Definition),
56 | description: `Returns a Block.`,
57 | args: {
58 | id: { type: new GraphQLList(GraphQLID) },
59 | filter: {
60 | type: Filter
61 | },
62 | limit: { type: GraphQLInt },
63 | offset: { type: GraphQLInt },
64 | orderBy: { type: order(`block`, Fields) }
65 | },
66 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
67 | }
68 | }
69 |
70 | export const Mutations = {
71 | createBlock: {
72 | type: Definition,
73 | description: `Creates a new Block`,
74 | args: { input: { type: Input } },
75 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
76 | },
77 | updateBlock: {
78 | type: Definition,
79 | description: `Updates an existing Block, creates it if it does not already exist`,
80 | args: { input: { type: Input } },
81 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
82 | },
83 | deleteBlock: {
84 | type: Definition,
85 | description: `Deletes a Block by id`,
86 | args: { id: { type: GraphQLID } },
87 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/types/booster.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLEnumType, GraphQLList, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import Models from '../models'
3 |
4 | export const Input = new GraphQLInputObjectType({
5 | name: `BoosterInput`,
6 | description: `Required fields for a new Booster object`,
7 | fields: () => ({
8 | id: { type: GraphQLID }
9 | })
10 | })
11 |
12 | export const Definition = new GraphQLObjectType({
13 | name: `Booster`,
14 | description: `A Booster object`,
15 | fields: () => ({
16 | id: {
17 | type: GraphQLID,
18 | description: `A unique id for this booster.`
19 | }
20 | })
21 | })
22 |
23 | export const Queries = {
24 |
25 | }
26 |
27 | export const Mutations = {
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/types/category.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Card } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `CategoryInput`,
8 | description: `Required fields for a new Category object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | description: { type: new GraphQLNonNull(GraphQLString) },
12 | cards: { type: new GraphQLList(GraphQLID) }
13 | })
14 | })
15 |
16 | const Filter = new GraphQLInputObjectType({
17 | name: `CategoryFilter`,
18 | description: `Queryable fields for Category.`,
19 | fields: () => ({
20 | name: { type: new GraphQLList(GraphQLString) },
21 | cards: { type: new GraphQLList(GraphQLID) }
22 | })
23 | })
24 |
25 | const Fields = new GraphQLEnumType({
26 | name: `CategoryFields`,
27 | description: `Field names for Category.`,
28 | values: {
29 | name: { value: `name` }
30 | }
31 | })
32 |
33 | export const Definition = new GraphQLObjectType({
34 | name: `Category`,
35 | description: `A Category object`,
36 | fields: () => ({
37 | id: {
38 | type: GraphQLID,
39 | description: `A unique id for this category.`
40 | },
41 | name: {
42 | type: GraphQLString,
43 | description: `The category name.`
44 | },
45 | description: {
46 | type: GraphQLString,
47 | description: `The description of the category.`
48 | },
49 | cards: {
50 | type: new GraphQLList(Card.Definition),
51 | description: `A list of cards that have this category.`,
52 | resolve: (root, { id }) => Models.Category
53 | .forge({ id })
54 | .fetch({ withRelated: [`cards`] })
55 | .then(model => model.toJSON().cards)
56 | }
57 | })
58 | })
59 |
60 | export const Queries = {
61 | category: {
62 | type: new GraphQLList(Definition),
63 | description: `Returns a Category.`,
64 | args: {
65 | id: { type: new GraphQLList(GraphQLID) },
66 | filter: {
67 | type: Filter
68 | },
69 | limit: { type: GraphQLInt },
70 | offset: { type: GraphQLInt },
71 | orderBy: { type: order(`category`, Fields) }
72 | },
73 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
74 | }
75 | }
76 |
77 | export const Mutations = {
78 | createCategory: {
79 | type: Definition,
80 | description: `Creates a new Category`,
81 | args: { input: { type: Input } },
82 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
83 | },
84 | updateCategory: {
85 | type: Definition,
86 | description: `Updates an existing Category, creates it if it does not already exist`,
87 | args: { input: { type: Input } },
88 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
89 | },
90 | deleteCategory: {
91 | type: Definition,
92 | description: `Deletes a Category by id`,
93 | args: { id: { type: GraphQLID } },
94 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/types/color.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { ColorIdentity, Icon } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `ColorInput`,
8 | description: `Required fields for a new Color object`,
9 | fields: () => ({
10 | symbol: { type: new GraphQLNonNull(GraphQLString) },
11 | icon: { type: GraphQLID },
12 | identity: { type: GraphQLID }
13 | })
14 | })
15 |
16 | const Filter = new GraphQLInputObjectType({
17 | name: `ColorFilter`,
18 | description: `Queryable fields for Color.`,
19 | fields: () => ({
20 | symbol: { type: new GraphQLList(GraphQLString) },
21 | icon: { type: new GraphQLList(GraphQLID) },
22 | identity: { type: new GraphQLList(GraphQLID) }
23 | })
24 | })
25 |
26 | const Fields = new GraphQLEnumType({
27 | name: `ColorFields`,
28 | description: `Field names for Color.`,
29 | values: {
30 | symbol: { value: `symbol` },
31 | icon: { value: `icon` }
32 | }
33 | })
34 |
35 | export const Definition = new GraphQLObjectType({
36 | name: `Color`,
37 | description: `A Color object`,
38 | fields: () => ({
39 | id: {
40 | type: GraphQLID,
41 | description: `A unique id for this color.`
42 | },
43 | symbol: {
44 | type: GraphQLString,
45 | description: `The color symbol code for this color.`
46 | },
47 | icon: {
48 | type: Icon.Definition,
49 | description: `A CSS class used to display a mana symbol for this color.`,
50 | resolve: (type) => Models.Color
51 | .findById(type.id, { withRelated: [`icon`] })
52 | .then(model => model.toJSON().icon)
53 | },
54 | identity: {
55 | type: ColorIdentity.Definition,
56 | description: `The color identity of this color.`,
57 | resolve: (type) => Models.Color
58 | .findById(type.id, { withRelated: [`identity`] })
59 | .then(model => model.toJSON().identity)
60 | }
61 | })
62 | })
63 |
64 | export const Queries = {
65 | color: {
66 | type: new GraphQLList(Definition),
67 | description: `Returns a Color.`,
68 | args: {
69 | id: { type: new GraphQLList(GraphQLID) },
70 | filter: {
71 | type: Filter
72 | },
73 | limit: { type: GraphQLInt },
74 | offset: { type: GraphQLInt },
75 | orderBy: { type: order(`color`, Fields) }
76 | },
77 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
78 | }
79 | }
80 |
81 | export const Mutations = {
82 | createColor: {
83 | type: Definition,
84 | description: `Creates a new Color`,
85 | args: { input: { type: Input } },
86 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
87 | },
88 | updateColor: {
89 | type: Definition,
90 | description: `Updates an existing Color, creates it if it does not already exist`,
91 | args: { input: { type: Input } },
92 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `symbol`)
93 | },
94 | deleteColor: {
95 | type: Definition,
96 | description: `Deletes a Color by id`,
97 | args: { id: { type: GraphQLID } },
98 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/types/colorIdentity.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLBoolean, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { destroy, order, read } from './utilities'
3 | import Models from '../models'
4 | import { Color } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `ColorIdentityInput`,
8 | description: `Required fields for a new Color Identity object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | alias: { type: GraphQLString },
12 | colors: { type: new GraphQLList(GraphQLID) },
13 | multicolored: { type: GraphQLBoolean },
14 | devoid: { type: GraphQLBoolean }
15 | })
16 | })
17 |
18 | const Filter = new GraphQLInputObjectType({
19 | name: `ColorIdentityFilter`,
20 | description: `Queryable fields for ColorIdentity.`,
21 | fields: () => ({
22 | name: { type: new GraphQLList(GraphQLString) },
23 | alias: { type: new GraphQLList(GraphQLString) },
24 | multicolored: { type: GraphQLBoolean },
25 | devoid: { type: GraphQLBoolean }
26 | })
27 | })
28 |
29 | const Fields = new GraphQLEnumType({
30 | name: `ColorIdentityFields`,
31 | description: `Field names for ColorIdentity.`,
32 | values: {
33 | name: { value: `name` },
34 | alias: { value: `alias` },
35 | multicolored: { value: `multicolored` },
36 | devoid: { value: `devoid` }
37 | }
38 | })
39 |
40 | export const Definition = new GraphQLObjectType({
41 | name: `ColorIdentity`,
42 | description: `A Color Identity object`,
43 | fields: () => ({
44 | id: {
45 | type: GraphQLID,
46 | description: `A unique id for this color identity.`
47 | },
48 | name: {
49 | type: GraphQLString,
50 | description: `The color identity name.`
51 | },
52 | alias: {
53 | type: GraphQLString,
54 | description: `The alias of the color identity. Examples: Bant, Jeskai`
55 | },
56 | colors: {
57 | type: new GraphQLList(Color.Definition),
58 | description: `A list of colors included in this color identity.`,
59 | resolve: (type) => Models.ColorIdentity
60 | .findById(type.id, { withRelated: [`colors`] })
61 | .then(model => model.toJSON().colors)
62 | },
63 | multicolored: {
64 | type: GraphQLBoolean,
65 | description: `Set to True if the color identity counts as multicolored.`
66 | },
67 | devoid: {
68 | type: GraphQLBoolean,
69 | description: `Set to True if the color identity counts as devoid.`
70 | }
71 | })
72 | })
73 |
74 | export const Queries = {
75 | colorIdentity: {
76 | type: new GraphQLList(Definition),
77 | description: `Returns a ColorIdentity.`,
78 | args: {
79 | id: { type: new GraphQLList(GraphQLID) },
80 | filter: {
81 | type: Filter
82 | },
83 | limit: { type: GraphQLInt },
84 | offset: { type: GraphQLInt },
85 | orderBy: { type: order(`colorIdentity`, Fields) }
86 | },
87 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
88 | }
89 | }
90 |
91 | export const Mutations = {
92 | createColorIdentity: {
93 | type: Definition,
94 | description: `Creates a new ColorIdentity`,
95 | args: { input: { type: Input } },
96 | resolve: (root, { input }) => {
97 | let { colors, ...fields } = input
98 | return Models.ColorIdentity
99 | .findOrCreate(fields)
100 | .then(model => {
101 | let identity = model.toJSON()
102 |
103 | if (!!colors) for (let color of colors) Models.Colors.findOrCreate({ coloridentity: identity.id, color })
104 |
105 | return identity
106 | })
107 | }
108 | },
109 | updateColorIdentity: {
110 | type: Definition,
111 | description: `Updates an existing ColorIdentity, creates it if it does not already exist`,
112 | args: { input: { type: Input } },
113 | resolve: (root, { input }) => {
114 | let { name, colors, ...fields } = input
115 | return Models.ColorIdentity
116 | .upsert({ name }, fields)
117 | .then(model => {
118 | let identity = model.toJSON()
119 |
120 | if (!!colors) for (let color of colors) Models.Colors.findOrCreate({ coloridentity: identity.id, color })
121 |
122 | return identity
123 | })
124 | }
125 | },
126 | deleteColorIdentity: {
127 | type: Definition,
128 | description: `Deletes a ColorIdentity by id`,
129 | args: { id: { type: GraphQLID } },
130 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/types/format.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Set } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `FormatInput`,
8 | description: `Required fields for a new Format object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | sets: { type: new GraphQLList(GraphQLID) }
12 | })
13 | })
14 |
15 | const Filter = new GraphQLInputObjectType({
16 | name: `FormatFilter`,
17 | description: `Queryable fields for Format.`,
18 | fields: () => ({
19 | name: { type: new GraphQLList(GraphQLString) }
20 | })
21 | })
22 |
23 | const Fields = new GraphQLEnumType({
24 | name: `FormatFields`,
25 | description: `Field names for Format.`,
26 | values: {
27 | name: { value: `name` }
28 | }
29 | })
30 |
31 | export const Definition = new GraphQLObjectType({
32 | name: `Format`,
33 | description: `A Format object`,
34 | fields: () => ({
35 | id: {
36 | type: GraphQLID,
37 | description: `A unique id for this format.`
38 | },
39 | name: {
40 | type: GraphQLString,
41 | description: `The format name.`
42 | },
43 | sets: {
44 | type: new GraphQLList(Set.Definition),
45 | description: `A list of sets included in this format`,
46 | resolve: (root, { id }) => Models.Format
47 | .forge({ id })
48 | .fetch({ withRelated: [`sets`] })
49 | .then(model => model.toJSON().sets)
50 | }
51 | })
52 | })
53 |
54 | export const Queries = {
55 | format: {
56 | type: new GraphQLList(Definition),
57 | description: `Returns a Format.`,
58 | args: {
59 | id: { type: new GraphQLList(GraphQLID) },
60 | filter: {
61 | type: Filter
62 | },
63 | limit: { type: GraphQLInt },
64 | offset: { type: GraphQLInt },
65 | orderBy: { type: order(`format`, Fields) }
66 | },
67 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
68 | }
69 | }
70 |
71 | export const Mutations = {
72 | createFormat: {
73 | type: Definition,
74 | description: `Creates a new Format`,
75 | args: { input: { type: Input } },
76 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
77 | },
78 | updateFormat: {
79 | type: Definition,
80 | description: `Updates an existing Format, creates it if it does not already exist`,
81 | args: { input: { type: Input } },
82 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
83 | },
84 | deleteFormat: {
85 | type: Definition,
86 | description: `Deletes a Format by id`,
87 | args: { id: { type: GraphQLID } },
88 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/types/icon.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Image } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `IconInput`,
8 | description: `Required fields for a new Icon object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | image: { type: GraphQLID },
12 | class: { type: GraphQLString }
13 | })
14 | })
15 |
16 | const Filter = new GraphQLInputObjectType({
17 | name: `IconFilter`,
18 | description: `Queryable fields for Icon.`,
19 | fields: () => ({
20 | name: { type: new GraphQLList(GraphQLString) },
21 | image: { type: new GraphQLList(GraphQLID) }
22 | })
23 | })
24 |
25 | const Fields = new GraphQLEnumType({
26 | name: `IconFields`,
27 | description: `Field names for Icon.`,
28 | values: {
29 | name: { value: `name` },
30 | image: { value: `image` }
31 | }
32 | })
33 |
34 | export const Definition = new GraphQLObjectType({
35 | name: `Icon`,
36 | description: `An Icon object`,
37 | fields: () => ({
38 | id: {
39 | type: GraphQLID,
40 | description: `A unique id for this icon.`
41 | },
42 | name: {
43 | type: GraphQLString,
44 | description: `The name of the icon.`
45 | },
46 | image: {
47 | type: Image.Definition,
48 | description: `The language image.`,
49 | resolve: (type) => Models.Icon
50 | .findById(type.id, { withRelated: [`image`] })
51 | .then(model => model.toJSON().image)
52 | },
53 | class: {
54 | type: GraphQLString,
55 | description: `A CSS class used to display this icon.`
56 | }
57 | })
58 | })
59 |
60 | export const Queries = {
61 | icon: {
62 | type: new GraphQLList(Definition),
63 | description: `Returns an Icon.`,
64 | args: {
65 | id: { type: new GraphQLList(GraphQLID) },
66 | filter: {
67 | type: Filter
68 | },
69 | limit: { type: GraphQLInt },
70 | offset: { type: GraphQLInt },
71 | orderBy: { type: order(`icon`, Fields) }
72 | },
73 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
74 | }
75 | }
76 |
77 | export const Mutations = {
78 | createIcon: {
79 | type: Definition,
80 | description: `Creates a new Icon`,
81 | args: { input: { type: Input } },
82 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
83 | },
84 | updateIcon: {
85 | type: Definition,
86 | description: `Updates an existing Icon, creates it if it does not already exist`,
87 | args: { input: { type: Input } },
88 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
89 | },
90 | deleteIcon: {
91 | type: Definition,
92 | description: `Deletes a Icon by id`,
93 | args: { id: { type: GraphQLID } },
94 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/types/image.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { LanguageCode } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `ImageInput`,
8 | description: `Required fields for a new Name object`,
9 | fields: () => ({
10 | multiverseid: { type: GraphQLString },
11 | url: { type: new GraphQLNonNull(GraphQLString) },
12 | language: { type: new GraphQLNonNull(GraphQLID) }
13 | })
14 | })
15 |
16 | const Filter = new GraphQLInputObjectType({
17 | name: `ImageFilter`,
18 | description: `Queryable fields for Image.`,
19 | fields: () => ({
20 | multiverseid: { type: new GraphQLList(GraphQLString) },
21 | language: { type: new GraphQLList(GraphQLID) }
22 | })
23 | })
24 |
25 | const Fields = new GraphQLEnumType({
26 | name: `ImageFields`,
27 | description: `Field names for Image.`,
28 | values: {
29 | multiverseid: { value: `multiverseid` },
30 | language: { value: `language` }
31 | }
32 | })
33 |
34 | export const Definition = new GraphQLObjectType({
35 | name: `Image`,
36 | description: `An Image object`,
37 | fields: () => ({
38 | id: {
39 | type: GraphQLID,
40 | description: `A unique id for this image.`
41 | },
42 | multiverseid: {
43 | type: GraphQLString,
44 | description: `The multiverseid of the card on Wizard’s Gatherer web page.`
45 | },
46 | url: {
47 | type: GraphQLString,
48 | description: `The localized image of a card.`
49 | },
50 | language: {
51 | type: LanguageCode.Definition,
52 | description: `The language image.`,
53 | resolve: (type) => Models.LanguageCode
54 | .findById(type.language)
55 | .then(model => model.toJSON())
56 | }
57 | })
58 | })
59 |
60 | export const Queries = {
61 | image: {
62 | type: new GraphQLList(Definition),
63 | description: `Returns an Image.`,
64 | args: {
65 | id: { type: new GraphQLList(GraphQLID) },
66 | filter: {
67 | type: Filter
68 | },
69 | limit: { type: GraphQLInt },
70 | offset: { type: GraphQLInt },
71 | orderBy: { type: order(`image`, Fields) }
72 | },
73 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
74 | }
75 | }
76 |
77 | export const Mutations = {
78 | createImage: {
79 | type: Definition,
80 | description: `Creates a new Image`,
81 | args: { input: { type: Input } },
82 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
83 | },
84 | updateImage: {
85 | type: Definition,
86 | description: `Updates an existing Image, creates it if it does not already exist`,
87 | args: { input: { type: Input } },
88 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `multiverseid`)
89 | },
90 | deleteImage: {
91 | type: Definition,
92 | description: `Deletes a Image by id`,
93 | args: { id: { type: GraphQLID } },
94 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/types/index.js:
--------------------------------------------------------------------------------
1 | import * as AbilityType from './abilityType'
2 | import * as Artist from './artist'
3 | import * as Block from './block'
4 | import * as Booster from './booster'
5 | import * as Card from './card'
6 | import * as Category from './category'
7 | import * as Color from './color'
8 | import * as ColorIdentity from './colorIdentity'
9 | import * as Format from './format'
10 | import * as Icon from './icon'
11 | import * as Image from './image'
12 | import * as Keyword from './keyword'
13 | import * as Language from './language'
14 | import * as LanguageCode from './languageCode'
15 | import * as Layout from './layout'
16 | import * as Legality from './legality'
17 | import * as Name from './name'
18 | import * as Printing from './printing'
19 | import * as Rarity from './rarity'
20 | import * as Ruling from './ruling'
21 | import * as Set from './set'
22 | import * as SetType from './setType'
23 | import * as Subtype from './subtype'
24 | import * as Supertype from './supertype'
25 | import * as Type from './type'
26 |
27 | export {
28 | AbilityType,
29 | Artist,
30 | Block,
31 | Booster,
32 | Card,
33 | Category,
34 | Color,
35 | ColorIdentity,
36 | Format,
37 | Icon,
38 | Image,
39 | Keyword,
40 | Language,
41 | LanguageCode,
42 | Layout,
43 | Legality,
44 | Name,
45 | Printing,
46 | Rarity,
47 | Ruling,
48 | Set,
49 | SetType,
50 | Subtype,
51 | Supertype,
52 | Type
53 | }
54 |
--------------------------------------------------------------------------------
/src/types/keyword.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Card, LanguageCode } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `KeywordInput`,
8 | description: `Required fields for a new Keyword object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | reminderText: { type: GraphQLString },
12 | languageCode: { type: new GraphQLNonNull(GraphQLID) },
13 | cards: { type: new GraphQLList(GraphQLID) }
14 | })
15 | })
16 |
17 | const Filter = new GraphQLInputObjectType({
18 | name: `KeywordFilter`,
19 | description: `Queryable fields for Keyword.`,
20 | fields: () => ({
21 | name: { type: new GraphQLList(GraphQLString) },
22 | reminderText: { type: GraphQLString },
23 | languageCode: { type: new GraphQLList(GraphQLID) },
24 | cards: { type: new GraphQLList(GraphQLID) }
25 | })
26 | })
27 |
28 | const Fields = new GraphQLEnumType({
29 | name: `KeywordFields`,
30 | description: `Field names for Keyword.`,
31 | values: {
32 | name: { value: `name` },
33 | reminderText: { value: `reminderText` },
34 | languageCode: { value: `languageCode` }
35 | }
36 | })
37 |
38 | export const Definition = new GraphQLObjectType({
39 | name: `Keyword`,
40 | description: `A Keyword object`,
41 | fields: () => ({
42 | id: {
43 | type: GraphQLID,
44 | description: `A unique id for this keyword.`
45 | },
46 | name: {
47 | type: GraphQLString,
48 | description: `The name of the keyword.`
49 | },
50 | reminderText: {
51 | type: GraphQLString,
52 | description: `A short description of the keyword ability's rules.`
53 | },
54 | languageCode: {
55 | type: LanguageCode.Definition,
56 | description: `The language code the reminder text of keyword is localized in.`,
57 | resolve: (root, { id }) => Models.Keyword
58 | .forge({ id })
59 | .fetch({ withRelated: [`LanguageCode`] })
60 | .then(model => model.toJSON().languageCode)
61 | },
62 | cards: {
63 | type: new GraphQLList(Card.Definition),
64 | description: `A list of cards featuring art from this artist.`,
65 | resolve: (root, { id }) => Models.Keyword
66 | .forge({ id })
67 | .fetch({ withRelated: [`cards`] })
68 | .then(model => model.toJSON().cards)
69 | }
70 | })
71 | })
72 |
73 | export const Queries = {
74 | keyword: {
75 | type: new GraphQLList(Definition),
76 | description: `Returns a Keyword.`,
77 | args: {
78 | id: { type: new GraphQLList(GraphQLID) },
79 | filter: {
80 | type: Filter
81 | },
82 | limit: { type: GraphQLInt },
83 | offset: { type: GraphQLInt },
84 | orderBy: { type: order(`keyword`, Fields) }
85 | },
86 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
87 | }
88 | }
89 |
90 | export const Mutations = {
91 | createKeyword: {
92 | type: Definition,
93 | description: `Creates a new Keyword`,
94 | args: { input: { type: Input } },
95 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
96 | },
97 | updateKeyword: {
98 | type: Definition,
99 | description: `Updates an existing Keyword, creates it if it does not already exist`,
100 | args: { input: { type: Input } },
101 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
102 | },
103 | deleteKeyword: {
104 | type: Definition,
105 | description: `Deletes a Keyword by id`,
106 | args: { id: { type: GraphQLID } },
107 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/types/language.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { LanguageCode } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `LanguageInput`,
8 | description: `Required fields for a new language object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | code: { type: new GraphQLNonNull(GraphQLID) }
12 | })
13 | })
14 |
15 | const Filter = new GraphQLInputObjectType({
16 | name: `LanguageFilter`,
17 | description: `Queryable fields for Language.`,
18 | fields: () => ({
19 | name: { type: new GraphQLList(GraphQLString) },
20 | code: { type: new GraphQLList(GraphQLID) }
21 | })
22 | })
23 |
24 | const Fields = new GraphQLEnumType({
25 | name: `LanguageFields`,
26 | description: `Field names for Language.`,
27 | values: {
28 | name: { value: `name` },
29 | code: { value: `code` }
30 | }
31 | })
32 |
33 | export const Definition = new GraphQLObjectType({
34 | name: `Language`,
35 | description: `A language object`,
36 | fields: () => ({
37 | id: {
38 | type: GraphQLID,
39 | description: `A unique id for this language.`
40 | },
41 | name: {
42 | type: GraphQLString,
43 | description: `The name of the language.`
44 | },
45 | code: {
46 | type: LanguageCode.Definition,
47 | description: `The language code associated with this language.`,
48 | resolve: (type) => Models.LanguageCode
49 | .findById(type.code)
50 | .then(model => model.toJSON())
51 | }
52 | })
53 | })
54 |
55 | export const Queries = {
56 | language: {
57 | type: new GraphQLList(Definition),
58 | description: `Returns a Language.`,
59 | args: {
60 | id: { type: new GraphQLList(GraphQLID) },
61 | filter: {
62 | type: Filter
63 | },
64 | limit: { type: GraphQLInt },
65 | offset: { type: GraphQLInt },
66 | orderBy: { type: order(`language`, Fields) }
67 | },
68 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
69 | }
70 | }
71 |
72 | export const Mutations = {
73 | createLanguage: {
74 | type: Definition,
75 | description: `Creates a new Language`,
76 | args: { input: { type: Input } },
77 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
78 | },
79 | updateLanguage: {
80 | type: Definition,
81 | description: `Updates an existing Language, creates it if it does not already exist`,
82 | args: { input: { type: Input } },
83 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
84 | },
85 | deleteLanguage: {
86 | type: Definition,
87 | description: `Deletes a Language by id`,
88 | args: { id: { type: GraphQLID } },
89 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/types/languageCode.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Language } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `LanguageCodeInput`,
8 | description: `Required fields for a new language code object`,
9 | fields: () => ({
10 | code: { type: new GraphQLNonNull(GraphQLString) },
11 | language: { type: new GraphQLNonNull(GraphQLID) }
12 | })
13 | })
14 |
15 | const Filter = new GraphQLInputObjectType({
16 | name: `LanguageCodeFilter`,
17 | description: `Queryable fields for LanguageCode.`,
18 | fields: () => ({
19 | code: { type: new GraphQLList(GraphQLString) },
20 | language: { type: new GraphQLList(GraphQLID) }
21 | })
22 | })
23 |
24 | const Fields = new GraphQLEnumType({
25 | name: `LanguageCodeFields`,
26 | description: `Field names for LanguageCode.`,
27 | values: {
28 | code: { value: `code` },
29 | language : { value: `language` }
30 | }
31 | })
32 |
33 | export const Definition = new GraphQLObjectType({
34 | name: `LanguageCode`,
35 | description: `A language code object`,
36 | fields: () => ({
37 | id: {
38 | type: GraphQLID,
39 | description: `A unique id for this language.`
40 | },
41 | code: {
42 | type: GraphQLString,
43 | description: `The language code.`
44 | },
45 | language: {
46 | type: Language.Definition,
47 | description: `The language associated with the language code.`,
48 | resolve: (type) => Models.Language
49 | .findById(type.language)
50 | .then(model => model.toJSON())
51 | }
52 | })
53 | })
54 |
55 | export const Queries = {
56 | languageCode: {
57 | type: new GraphQLList(Definition),
58 | description: `Returns a LanguageCode.`,
59 | args: {
60 | id: { type: new GraphQLList(GraphQLID) },
61 | filter: {
62 | type: Filter
63 | },
64 | limit: { type: GraphQLInt },
65 | offset: { type: GraphQLInt },
66 | orderBy: { type: order(`languageCode`, Fields) }
67 | },
68 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
69 | }
70 | }
71 |
72 | export const Mutations = {
73 | createLanguageCode: {
74 | type: Definition,
75 | description: `Creates a new LanguageCode`,
76 | args: { input: { type: Input } },
77 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
78 | },
79 | updateLanguageCode: {
80 | type: Definition,
81 | description: `Updates an existing LanguageCode, creates it if it does not already exist`,
82 | args: { input: { type: Input } },
83 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `code`)
84 | },
85 | deleteLanguageCode: {
86 | type: Definition,
87 | description: `Deletes a LanguageCode by id`,
88 | args: { id: { type: GraphQLID } },
89 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/types/layout.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Icon } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `LayoutInput`,
8 | description: `Required fields for a new Layout object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | watermark: { type: GraphQLString },
12 | icons: { type: new GraphQLList(GraphQLID) }
13 | })
14 | })
15 |
16 | const Filter = new GraphQLInputObjectType({
17 | name: `LayoutFilter`,
18 | description: `Queryable fields for Layout.`,
19 | fields: () => ({
20 | name: { type: new GraphQLList(GraphQLString) },
21 | icons: { type: new GraphQLList(GraphQLID) }
22 | })
23 | })
24 |
25 | const Fields = new GraphQLEnumType({
26 | name: `LayoutFields`,
27 | description: `Field names for Layout.`,
28 | values: {
29 | name: { value: `name` }
30 | }
31 | })
32 |
33 | export const Definition = new GraphQLObjectType({
34 | name: `Layout`,
35 | description: `A Layout object`,
36 | fields: () => ({
37 | id: {
38 | type: GraphQLID,
39 | description: `A unique id for this layout.`
40 | },
41 | name: {
42 | type: GraphQLString,
43 | description: `The name of the layout type.`
44 | },
45 | watermark: {
46 | type: GraphQLString,
47 | description: `Watermark that appears in this layout.`
48 | },
49 | icons: {
50 | type: new GraphQLList(Icon.Definition),
51 | description: `A list of icons featured on this card.`,
52 | resolve: (root, { id }) => Models.Layout
53 | .forge({ id })
54 | .fetch({ withRelated: [`icons`] })
55 | .then(model => model.toJSON().icons)
56 | }
57 | })
58 | })
59 |
60 | export const Queries = {
61 | layout: {
62 | type: new GraphQLList(Definition),
63 | description: `Returns a Layout.`,
64 | args: {
65 | id: { type: new GraphQLList(GraphQLID) },
66 | filter: {
67 | type: Filter
68 | },
69 | limit: { type: GraphQLInt },
70 | offset: { type: GraphQLInt },
71 | orderBy: { type: order(`layout`, Fields) }
72 | },
73 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
74 | }
75 | }
76 |
77 | export const Mutations = {
78 | createLayout: {
79 | type: Definition,
80 | description: `Creates a new Layout`,
81 | args: { input: { type: Input } },
82 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
83 | },
84 | updateLayout: {
85 | type: Definition,
86 | description: `Updates an existing Layout, creates it if it does not already exist`,
87 | args: { input: { type: Input } },
88 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
89 | },
90 | deleteLayout: {
91 | type: Definition,
92 | description: `Deletes a Layout by id`,
93 | args: { id: { type: GraphQLID } },
94 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/types/legality.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLBoolean, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Card, Format } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `LegalityInput`,
8 | description: `Required fields for a new Legality object`,
9 | fields: () => ({
10 | cards: { type: new GraphQLNonNull(new GraphQLList(GraphQLID)) },
11 | format: { type: new GraphQLNonNull(GraphQLID) },
12 | legal: { type: new GraphQLNonNull(GraphQLBoolean) },
13 | restricted: { type: new GraphQLNonNull(GraphQLBoolean) }
14 | })
15 | })
16 |
17 | const Filter = new GraphQLInputObjectType({
18 | name: `LegalityFilter`,
19 | description: `Queryable fields for Legality.`,
20 | fields: () => ({
21 | cards: { type: new GraphQLList(GraphQLID) },
22 | format: { type: new GraphQLList(GraphQLID) },
23 | legal: { type: GraphQLBoolean },
24 | restricted: { type: GraphQLBoolean }
25 | })
26 | })
27 |
28 | const Fields = new GraphQLEnumType({
29 | name: `LegalityFields`,
30 | description: `Field names for Legality.`,
31 | values: {
32 | format: { value: `format` },
33 | legal: { value: `legal` },
34 | restricted: { value: `restricted` }
35 | }
36 | })
37 |
38 | export const Definition = new GraphQLObjectType({
39 | name: `Legality`,
40 | description: `A Legality object`,
41 | fields: () => ({
42 | id: {
43 | type: GraphQLID,
44 | description: `A unique id for this name.`
45 | },
46 | cards: {
47 | type: new GraphQLList(Card.Definition),
48 | description: `The ID of the card.`,
49 | resolve: (root, { id }) => Models.Legality
50 | .forge({ id })
51 | .fetch({ withRelated: [`cards`] })
52 | .then(model => model.toJSON().cards)
53 | },
54 | format: {
55 | type: Format.Definition,
56 | description: `The format the card is legal in.`,
57 | resolve: (root, { id }) => Models.Legality
58 | .forge({ id })
59 | .fetch({ withRelated: [`format`] })
60 | .then(model => model.toJSON().format)
61 | },
62 | legal: {
63 | type: GraphQLBoolean,
64 | description: `Set to True if the card is Legal to play in the given format.`
65 | },
66 | restricted: {
67 | type: GraphQLBoolean,
68 | description: `Set to True if the card is restricted in the given format.`
69 | }
70 | })
71 | })
72 |
73 | export const Queries = {
74 | legality: {
75 | type: new GraphQLList(Definition),
76 | description: `Returns a Legality.`,
77 | args: {
78 | id: { type: new GraphQLList(GraphQLID) },
79 | filter: {
80 | type: Filter
81 | },
82 | limit: { type: GraphQLInt },
83 | offset: { type: GraphQLInt },
84 | orderBy: { type: order(`legality`, Fields) }
85 | },
86 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
87 | }
88 | }
89 |
90 | export const Mutations = {
91 | createLegality: {
92 | type: Definition,
93 | description: `Creates a new Legality`,
94 | args: { input: { type: Input } },
95 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
96 | },
97 | updateLegality: {
98 | type: Definition,
99 | description: `Updates an existing Legality, creates it if it does not already exist`,
100 | args: { input: { type: Input } },
101 | resolve: (parent, args, context) => update(parent, args, context, Definition.name)
102 | },
103 | deleteLegality: {
104 | type: Definition,
105 | description: `Deletes a Legality by id`,
106 | args: { id: { type: GraphQLID } },
107 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/types/name.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 | import Models from '../models'
4 | import { Card, Language } from './'
5 |
6 | export const Input = new GraphQLInputObjectType({
7 | name: `NameInput`,
8 | description: `Required fields for a new Name object`,
9 | fields: () => ({
10 | name: { type: new GraphQLNonNull(GraphQLString) },
11 | language: { type: new GraphQLNonNull(GraphQLID) }
12 | })
13 | })
14 |
15 | const Filter = new GraphQLInputObjectType({
16 | name: `NameFilter`,
17 | description: `Queryable fields for Name.`,
18 | fields: () => ({
19 | name: { type: new GraphQLList(GraphQLString) },
20 | language: { type: new GraphQLList(GraphQLID) },
21 | cards: { type: new GraphQLList(GraphQLID) }
22 | })
23 | })
24 |
25 | const Fields = new GraphQLEnumType({
26 | name: `NameFields`,
27 | description: `Field names for Name.`,
28 | values: {
29 | name: { value: `name` },
30 | language: { value: `language` }
31 | }
32 | })
33 |
34 | export const Definition = new GraphQLObjectType({
35 | name: `Name`,
36 | description: `A Name object`,
37 | fields: () => ({
38 | id: {
39 | type: GraphQLID,
40 | description: `A unique id for this name.`
41 | },
42 | name: {
43 | type: GraphQLString,
44 | description: `The localized name of a card.`
45 | },
46 | language: {
47 | type: Language.Definition,
48 | description: `The language name.`,
49 | resolve: (type) => Models.Language
50 | .findById(type.language)
51 | .then(model => model.toJSON())
52 | },
53 | cards: {
54 | type: new GraphQLList(Card.Definition),
55 | description: `A list of cards featuring art from this artist.`,
56 | resolve: (type) => Models.Name
57 | .findById(type.id, { withRelated: [`cards`] })
58 | .then(model => model.toJSON().cards)
59 | }
60 | })
61 | })
62 |
63 | export const Queries = {
64 | name: {
65 | type: new GraphQLList(Definition),
66 | description: `Returns a Name.`,
67 | args: {
68 | id: { type: new GraphQLList(GraphQLID) },
69 | filter: {
70 | type: Filter
71 | },
72 | limit: { type: GraphQLInt },
73 | offset: { type: GraphQLInt },
74 | orderBy: { type: order(`name`, Fields) }
75 | },
76 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
77 | }
78 | }
79 |
80 | export const Mutations = {
81 | createName: {
82 | type: Definition,
83 | description: `Creates a new Name`,
84 | args: { input: { type: Input } },
85 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
86 | },
87 | updateName: {
88 | type: Definition,
89 | description: `Updates an existing Name, creates it if it does not already exist`,
90 | args: { input: { type: Input } },
91 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
92 | },
93 | deleteName: {
94 | type: Definition,
95 | description: `Deletes a Name by id`,
96 | args: { id: { type: GraphQLID } },
97 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/types/printing.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLNonNull, GraphQLInt, GraphQLEnumType, GraphQLString, GraphQLBoolean, GraphQLList, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { destroy, order, read } from './utilities'
3 | import { info, error } from 'winston'
4 | import Models from '../models'
5 | import { Card, Set, Image, Artist } from './'
6 |
7 | export const Input = new GraphQLInputObjectType({
8 | name: `PrintingInput`,
9 | description: `Required fields for a new Printing object`,
10 | fields: () => ({
11 | card: { type: GraphQLID },
12 | set: { type: GraphQLID },
13 | images: { type: new GraphQLList(GraphQLID) },
14 | sides: { type: new GraphQLList(GraphQLID) },
15 | variations: { type: new GraphQLList(GraphQLID) },
16 | originalType: { type: GraphQLString },
17 | originalText: { type: GraphQLString },
18 | flavor: { type: GraphQLString },
19 | artist: { type: new GraphQLNonNull(GraphQLID) },
20 | number: { type: GraphQLString },
21 | timeshifted: { type: GraphQLBoolean },
22 | starter: { type: GraphQLBoolean },
23 | reserved: { type: GraphQLBoolean },
24 | source: { type: GraphQLString }
25 | })
26 | })
27 |
28 | const Filter = new GraphQLInputObjectType({
29 | name: `PrintingFilter`,
30 | description: `Queryable fields for Printing.`,
31 | fields: () => ({
32 | card: { type: new GraphQLList(GraphQLID) },
33 | set: { type: new GraphQLList(GraphQLID) },
34 | originalType: { type: GraphQLString },
35 | originalText: { type: GraphQLString },
36 | flavor: { type: GraphQLString },
37 | artist: { type: new GraphQLList(GraphQLID) },
38 | number: { type: new GraphQLList(GraphQLString) },
39 | timeshifted: { type: GraphQLBoolean },
40 | starter: { type: GraphQLBoolean },
41 | reserved: { type: GraphQLBoolean }
42 | })
43 | })
44 |
45 | const Fields = new GraphQLEnumType({
46 | name: `PrintingFields`,
47 | description: `Field names for Printing.`,
48 | values: {
49 | card: { value: `card` },
50 | set: { value: `set` },
51 | originalType: { type: `originalType`},
52 | originalText: { value: `originalText` },
53 | artist: { value: `artist` },
54 | number: { value: `number` },
55 | timeshifted: { value: `timeshifted` },
56 | starter: { value: `starter` },
57 | reserved: { value: `reserved` }
58 | }
59 | })
60 |
61 | export const Definition = new GraphQLObjectType({
62 | name: `Printing`,
63 | description: `A Printing object`,
64 | fields: () => ({
65 | id: {
66 | type: GraphQLID,
67 | description: `A unique id for this card.`
68 | },
69 | card: {
70 | type: Card.Definition,
71 | description: `The Card represented by this Printing.`,
72 | resolve: (type) => Models.Card
73 | .findById(type.card)
74 | .then(model => model.toJSON())
75 | },
76 | set: {
77 | type: Set.Definition,
78 | description: `The set the card belongs to (set code).`,
79 | resolve: (type) => Models.Set
80 | .findById(type.set)
81 | .then(model => model.toJSON())
82 | },
83 | images: {
84 | type: new GraphQLList(Image.Definition),
85 | description: `The card images. This includes a list of foreign images indexed by a language code. Example: enUS`,
86 | resolve: (type) => Models.Printing
87 | .findById(type.id, { withRelated: [`images`] })
88 | .then(model => model.toJSON().images)
89 | },
90 | artist: {
91 | type: Artist.Definition,
92 | description: `The artist of the image. This may not match what is on the card as MTGJSON corrects many card misprints.`,
93 | resolve: (type) => Models.Artist
94 | .findById(type.artist)
95 | .then(model => model.toJSON())
96 | },
97 | sides: {
98 | type: new GraphQLList(Definition),
99 | description: `Only used for split, flip and dual cards. Will contain a lit of cards representing each side of this card, front or back.`,
100 | resolve: (type) => Models.Card
101 | .findById(type.id, { withRelated: [`sides`] })
102 | .then(model => model.toJSON().sides)
103 | },
104 | variations: {
105 | type: new GraphQLList(Definition),
106 | description: `If a card has alternate art (for example, 4 different Forests, or the 2 Brothers Yamazaki) then each other variation’s card will be listed here, NOT including the current card.`,
107 | resolve: (type) => Models.Card
108 | .findById(type.id, { withRelated: [`variations`] })
109 | .then(model => model.toJSON().variations)
110 | },
111 | originalType: {
112 | type: GraphQLString,
113 | description: `The original type on the card at the time it was printed. This field is not available for promo cards.`
114 | },
115 | originalText: {
116 | type: GraphQLString,
117 | description: `The original text on the card at the time it was printed. This field is not available for promo cards.`
118 | },
119 | flavor: {
120 | type: GraphQLString,
121 | description: `The flavor text of the card.`
122 | },
123 | number: {
124 | type: GraphQLString,
125 | description: `The card number. This is printed at the bottom-center of the card in small text. This is a string, not an integer, because some cards have letters in their numbers.`
126 | },
127 | timeshifted: {
128 | type: GraphQLBoolean,
129 | description: `If this card was a timeshifted card in the set.`
130 | },
131 | starter: {
132 | type: GraphQLBoolean,
133 | description: `Set to true if this card was only released as part of a core box set. These are technically part of the core sets and are tournament legal despite not being available in boosters.`
134 | },
135 | reserved: {
136 | type: GraphQLBoolean,
137 | description: `Set to true if this card is reserved by Wizards Official Reprint Policy`
138 | },
139 | source: {
140 | type: GraphQLString,
141 | description: `For promo cards, this is where this card was originally obtained. For box sets that are theme decks, this is which theme deck the card is from.`
142 | }
143 | })
144 | })
145 |
146 | export const Queries = {
147 | printing: {
148 | type: new GraphQLList(Definition),
149 | description: `Returns a Printing.`,
150 | args: {
151 | id: { type: new GraphQLList(GraphQLID) },
152 | filter: {
153 | type: Filter
154 | },
155 | limit: { type: GraphQLInt },
156 | offset: { type: GraphQLInt },
157 | orderBy: { type: order(`printing`, Fields) }
158 | },
159 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
160 | }
161 | }
162 |
163 | export const Mutations = {
164 | createPrinting: {
165 | type: Definition,
166 | description: `Creates a new Printing`,
167 | args: { input: { type: Input } },
168 | resolve: (parent, { input }, context) => {
169 | let { images, sides, variations, ...fields } = input
170 | return Models.Printing
171 | .findOrCreate(fields)
172 | .then(model => {
173 | let printing = model.toJSON()
174 |
175 | if (!!images) for (let image of images) Models.Images.findOrCreate({ printing: printing.id, image })
176 |
177 | Models.Printings.findOrCreate({ card: printing.card, printing: printing.id })
178 |
179 | return printing
180 | })
181 | .catch(err => error(`Failed to run Mutation: create${Definition.name}`, err))
182 | .finally(info(`Resolved Mutation: create${Definition.name}`, { parent, input, context}))
183 | }
184 | },
185 | updatePrinting: {
186 | type: Definition,
187 | description: `Updates an existing Printing, creates it if it does not already exist`,
188 | args: { input: { type: Input } },
189 | resolve: (parent, { input }, context) => {
190 | const { card, set, number, images, sides, variations, ...fields } = input
191 | return Models.Printing
192 | .upsert({ card, set, number }, fields)
193 | .then(model => {
194 | let printing = model.toJSON()
195 | //console.log(model)
196 | if (!!images) for (let image of images) Models.Images.findOrCreate({ printing: printing.id, image })
197 |
198 | Models.Printings.findOrCreate({ card: printing.card, printing: printing.id })
199 |
200 | return printing
201 | })
202 | .catch(err => error(`Failed to run Mutation: update${Definition.name}`, err))
203 | .finally(info(`Resolved Mutation: update${Definition.name}`, { parent, input, context}))
204 | }
205 | },
206 | deleteCard: {
207 | type: Definition,
208 | description: `Deletes a Card by id`,
209 | args: { id: { type: GraphQLID } },
210 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/src/types/rarity.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 |
4 | export const Input = new GraphQLInputObjectType({
5 | name: `RarityInput`,
6 | description: `Required fields for a new Rarity object`,
7 | fields: () => ({
8 | name: { type: new GraphQLNonNull(GraphQLString) },
9 | class: { type: new GraphQLNonNull(GraphQLString) }
10 | })
11 | })
12 |
13 | const Filter = new GraphQLInputObjectType({
14 | name: `RarityFilter`,
15 | description: `Queryable fields for Rarity.`,
16 | fields: () => ({
17 | name: { type: new GraphQLList(GraphQLString) }
18 | })
19 | })
20 |
21 | const Fields = new GraphQLEnumType({
22 | name: `RarityFields`,
23 | description: `Field names for Rarity.`,
24 | values: {
25 | name: { value: `name` }
26 | }
27 | })
28 |
29 | export const Definition = new GraphQLObjectType({
30 | name: `Rarity`,
31 | description: `A Rarity object`,
32 | fields: () => ({
33 | id: {
34 | type: GraphQLID,
35 | description: `A unique id for this rarity.`
36 | },
37 | name: {
38 | type: GraphQLString,
39 | description: `The name of the rarity.`
40 | },
41 | class: {
42 | type: GraphQLString,
43 | description: `A CSS class used to display this rarity.`
44 | }
45 | })
46 | })
47 |
48 | export const Queries = {
49 | rarity: {
50 | type: new GraphQLList(Definition),
51 | description: `Returns a Rarity.`,
52 | args: {
53 | id: { type: new GraphQLList(GraphQLID) },
54 | filter: {
55 | type: Filter
56 | },
57 | limit: { type: GraphQLInt },
58 | offset: { type: GraphQLInt },
59 | orderBy: { type: order(`rarity`, Fields) }
60 | },
61 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
62 | }
63 | }
64 |
65 | export const Mutations = {
66 | createRarity: {
67 | type: Definition,
68 | description: `Creates a new Rarity`,
69 | args: { input: { type: Input } },
70 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
71 | },
72 | updateRarity: {
73 | type: Definition,
74 | description: `Updates an existing Rarity, creates it if it does not already exist`,
75 | args: { input: { type: Input } },
76 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
77 | },
78 | deleteRarity: {
79 | type: Definition,
80 | description: `Deletes a Rarity by id`,
81 | args: { id: { type: GraphQLID } },
82 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/types/ruling.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { GraphQLDate } from 'graphql-iso-date'
3 | import { create, destroy, order, read, update } from './utilities'
4 | import Models from '../models'
5 | import { Card, LanguageCode } from './'
6 |
7 | export const Input = new GraphQLInputObjectType({
8 | name: `RulingInput`,
9 | description: `Required fields for a new Ruling object`,
10 | fields: () => ({
11 | text: { type: new GraphQLNonNull(GraphQLString) },
12 | date: { type: new GraphQLNonNull(GraphQLDate) },
13 | language: { type: new GraphQLNonNull(GraphQLID) },
14 | cards: { type: new GraphQLNonNull(new GraphQLList(GraphQLID)) }
15 | })
16 | })
17 |
18 | const Filter = new GraphQLInputObjectType({
19 | name: `RulingFilter`,
20 | description: `Queryable fields for Ruling.`,
21 | fields: () => ({
22 | text: { type: GraphQLString },
23 | date: { type: new GraphQLList(GraphQLDate) },
24 | language: { type: new GraphQLList(GraphQLID) },
25 | cards: { type: new GraphQLList(GraphQLID) }
26 | })
27 | })
28 |
29 | const Fields = new GraphQLEnumType({
30 | name: `RulingFields`,
31 | description: `Field names for Ruling.`,
32 | values: {
33 | date: { value: `date` },
34 | language: { value: `language` }
35 | }
36 | })
37 |
38 | export const Definition = new GraphQLObjectType({
39 | name: `Ruling`,
40 | description: `A Ruling object`,
41 | fields: () => ({
42 | id: {
43 | type: GraphQLID,
44 | description: `A unique id for this ruling.`
45 | },
46 | text: {
47 | type: GraphQLString,
48 | description: `The text of the ruling.`
49 | },
50 | date: {
51 | type: GraphQLDate,
52 | description: `The date this ruling was issued.`
53 | },
54 | language: {
55 | type: LanguageCode.Definition,
56 | description: `The language code of this ruling.`,
57 | resolve: (root, { id }) => Models.Ruling
58 | .forge({ id })
59 | .fetch({ withRelated: [`language`] })
60 | .then(model => model.toJSON().language)
61 | },
62 | cards: {
63 | type: new GraphQLList(Card.Definition),
64 | description: `List of cards that have this ruling.`,
65 | resolve: (root, { id }) => Models.Ruling
66 | .forge({ id })
67 | .fetch({ withRelated: [`cards`] })
68 | .then(model => model.toJSON().cards)
69 | }
70 | })
71 | })
72 |
73 | export const Queries = {
74 | ruling: {
75 | type: new GraphQLList(Definition),
76 | description: `Returns a Ruling.`,
77 | args: {
78 | id: { type: new GraphQLList(GraphQLID) },
79 | filter: {
80 | type: Filter
81 | },
82 | limit: { type: GraphQLInt },
83 | offset: { type: GraphQLInt },
84 | orderBy: { type: order(`ruling`, Fields) }
85 | },
86 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
87 | }
88 | }
89 |
90 | export const Mutations = {
91 | createRuling: {
92 | type: Definition,
93 | description: `Creates a new Ruling`,
94 | args: { input: { type: Input } },
95 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
96 | },
97 | updateRuling: {
98 | type: Definition,
99 | description: `Updates an existing Ruling, creates it if it does not already exist`,
100 | args: { input: { type: Input } },
101 | resolve: (parent, args, context) => update(parent, args, context, Definition.name)
102 | },
103 | deleteRuling: {
104 | type: Definition,
105 | description: `Deletes a Ruling by id`,
106 | args: { id: { type: GraphQLID } },
107 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/types/set.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { GraphQLDate } from 'graphql-iso-date'
3 | import { destroy, order, read } from './utilities'
4 | import { info, error } from 'winston'
5 | import Models from '../models'
6 | import { Block, SetType, Icon, Booster } from './'
7 |
8 | export const Input = new GraphQLInputObjectType({
9 | name: `SetInput`,
10 | description: `Required fields for a new Set object`,
11 | fields: () => ({
12 | name: { type: new GraphQLNonNull(GraphQLString) },
13 | code: { type: new GraphQLNonNull(GraphQLString) },
14 | block: { type: GraphQLID },
15 | type: { type: new GraphQLNonNull(GraphQLID)},
16 | icon: { type: new GraphQLNonNull(GraphQLID) },
17 | border: { type: new GraphQLNonNull(GraphQLString) },
18 | releaseDate: { type: new GraphQLNonNull(GraphQLDate) },
19 | booster: { type: GraphQLID }
20 | })
21 | })
22 |
23 | const Filter = new GraphQLInputObjectType({
24 | name: `SetFilter`,
25 | description: `Queryable fields for Set.`,
26 | fields: () => ({
27 | name: { type: new GraphQLList(GraphQLString) },
28 | code: { type: new GraphQLList(GraphQLString) },
29 | block: { type: new GraphQLList(GraphQLID) },
30 | type: { type: new GraphQLList(GraphQLID) },
31 | border: { type: new GraphQLList(GraphQLString) },
32 | releaseDate: { type: new GraphQLList(GraphQLDate) }
33 | })
34 | })
35 |
36 | const Fields = new GraphQLEnumType({
37 | name: `SetFields`,
38 | description: `Field names for Set.`,
39 | values: {
40 | name: { value: `name` },
41 | code: { value: `code` },
42 | block: { value: `block` },
43 | type: { value: `type` },
44 | border: { value: `border` },
45 | releaseDate: { value: `releaseDate` }
46 | }
47 | })
48 |
49 | export const Definition = new GraphQLObjectType({
50 | name: `Set`,
51 | description: `A Set object`,
52 | fields: () => ({
53 | id: {
54 | type: GraphQLID,
55 | description: `A unique id for this set.`
56 | },
57 | name: {
58 | type: GraphQLString,
59 | description: `The set name.`
60 | },
61 | code: {
62 | type: GraphQLString,
63 | description: `The set code for this set.`
64 | },
65 | block: {
66 | type: Block.Definition,
67 | description: `The block the set belongs to.`,
68 | resolve: (type) => Models.Set
69 | .findById(type.id, { withRelated: [`block`] })
70 | .then(model => model.toJSON().block)
71 | },
72 | type: {
73 | type: SetType.Definition,
74 | description: `The set type.`,
75 | resolve: (type) => Models.SetType
76 | .findById(type.type)
77 | .then(model => model.toJSON())
78 | },
79 | icon: {
80 | type: Icon.Definition,
81 | description: `The icon associated with the set.`,
82 | resolve: (type) => Models.Icon
83 | .findById(type.icon)
84 | .then(model => model.toJSON())
85 | },
86 | border: {
87 | type: GraphQLString,
88 | description: `The card border color for this set.`
89 | },
90 | releaseDate: {
91 | type: GraphQLDate,
92 | description: `The date this card was released. This is only set for promo cards. The date may not be accurate to an exact day and month, thus only a partial date may be set (YYYY-MM-DD or YYYY-MM or YYYY). Some promo cards do not have a known release date.`
93 | },
94 | booster: {
95 | type: Booster.Definition,
96 | description: `A booster pack for this set`,
97 | resolve: (type) => Models.Booster
98 | .findById(type.booster)
99 | .then(model => model.toJSON())
100 | }
101 | })
102 | })
103 |
104 | export const Queries = {
105 | set: {
106 | type: new GraphQLList(Definition),
107 | description: `Returns a Set.`,
108 | args: {
109 | id: { type: new GraphQLList(GraphQLID) },
110 | filter: {
111 | type: Filter
112 | },
113 | limit: { type: GraphQLInt },
114 | offset: { type: GraphQLInt },
115 | orderBy: { type: order(`set`, Fields) }
116 | },
117 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
118 | }
119 | }
120 |
121 | export const Mutations = {
122 | createSet: {
123 | type: Definition,
124 | description: `Creates a new Set`,
125 | args: { input: { type: Input } },
126 | resolve: (parent, { input }, context) => Models.Set
127 | .findOrCreate(input)
128 | .then(model => {
129 | let set = model.toJSON()
130 |
131 | if (!!set.block) Models.BlockSets.findOrCreate({ block: set.block, set: set.id })
132 |
133 | return set
134 | })
135 | .catch(err => error(`Failed to run Mutation: create${Definition.name}`, err))
136 | .finally(info(`Resolved Mutation: create${Definition.name}`, { parent, input, context}))
137 | },
138 | updateSet: {
139 | type: Definition,
140 | description: `Updates an existing Set, creates it if it does not already exist`,
141 | args: { input: { type: Input } },
142 | resolve: (parent, { input }, context) => {
143 | const { name, ...fields } = input
144 | return Models.Set
145 | .upsert({ name }, { ...fields })
146 | .then(model => {
147 | let set = model.toJSON()
148 |
149 | if (!!set.block) Models.BlockSets.findOrCreate({ block: set.block, set: set.id })
150 |
151 | return set
152 | })
153 | .catch(err => error(`Failed to run Mutation: update${Definition.name}`, err))
154 | .finally(info(`Resolved Mutation: update${Definition.name}`, { parent, input, context}))
155 | }
156 | },
157 | deleteSet: {
158 | type: Definition,
159 | description: `Deletes a Set by id`,
160 | args: { id: { type: GraphQLID } },
161 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/src/types/setType.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 |
4 | export const Input = new GraphQLInputObjectType({
5 | name: `SetTypeInput`,
6 | description: `Required fields for a new Set Type object`,
7 | fields: () => ({
8 | name: { type: new GraphQLNonNull(GraphQLString) },
9 | description: { type: GraphQLString }
10 | })
11 | })
12 |
13 | const Filter = new GraphQLInputObjectType({
14 | name: `SetTypeFilter`,
15 | description: `Queryable fields for SetType.`,
16 | fields: () => ({
17 | name: { type: new GraphQLList(GraphQLString) }
18 | })
19 | })
20 |
21 | const Fields = new GraphQLEnumType({
22 | name: `SetTypeFields`,
23 | description: `Field names for SetType.`,
24 | values: {
25 | name: { value: `name` }
26 | }
27 | })
28 |
29 | export const Definition = new GraphQLObjectType({
30 | name: `SetType`,
31 | description: `A Set Type object`,
32 | fields: () => ({
33 | id: {
34 | type: GraphQLID,
35 | description: `A unique id for this Set Type.`
36 | },
37 | name: {
38 | type: GraphQLString,
39 | description: `The Set Type name.`
40 | },
41 | description: {
42 | type: GraphQLString,
43 | description: `The description of the Set Type.`
44 | }
45 | })
46 | })
47 |
48 | export const Queries = {
49 | setType: {
50 | type: new GraphQLList(Definition),
51 | description: `Returns a Set Type.`,
52 | args: {
53 | id: { type: new GraphQLList(GraphQLID) },
54 | filter: {
55 | type: Filter
56 | },
57 | limit: { type: GraphQLInt },
58 | offset: { type: GraphQLInt },
59 | orderBy: { type: order(`setType`, Fields) }
60 | },
61 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
62 | }
63 | }
64 |
65 | export const Mutations = {
66 | createSetType: {
67 | type: Definition,
68 | description: `Creates a new SetType`,
69 | args: { input: { type: Input } },
70 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
71 | },
72 | updateSetType: {
73 | type: Definition,
74 | description: `Updates an existing SetType, creates it if it does not already exist`,
75 | args: { input: { type: Input } },
76 | resolve: (parent, args, context) => update(parent, args, context, Definition.name, `name`)
77 | },
78 | deleteSetType: {
79 | type: Definition,
80 | description: `Deletes a SetType by id`,
81 | args: { id: { type: GraphQLID } },
82 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/types/subtype.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 |
4 | export const Input = new GraphQLInputObjectType({
5 | name: `SubtypeInput`,
6 | description: `Required fields for a new Subtype object`,
7 | fields: () => ({
8 | name: { type: new GraphQLNonNull(GraphQLString) }
9 | })
10 | })
11 |
12 | const Filter = new GraphQLInputObjectType({
13 | name: `SubtypeFilter`,
14 | description: `Queryable fields for Subtype.`,
15 | fields: () => ({
16 | name: { type: new GraphQLList(GraphQLString) }
17 | })
18 | })
19 |
20 | const Fields = new GraphQLEnumType({
21 | name: `SubtypeFields`,
22 | description: `Field names for Subtype.`,
23 | values: {
24 | name: { value: `name` }
25 | }
26 | })
27 |
28 | export const Definition = new GraphQLObjectType({
29 | name: `Subtype`,
30 | description: `A Subtype object`,
31 | fields: () => ({
32 | id: {
33 | type: GraphQLID,
34 | description: `A unique id for this subtype.`
35 | },
36 | name: {
37 | type: GraphQLString,
38 | description: `The subtype name.`
39 | }
40 | })
41 | })
42 |
43 | export const Queries = {
44 | subtype: {
45 | type: new GraphQLList(Definition),
46 | description: `Returns a Subtype.`,
47 | args: {
48 | id: { type: new GraphQLList(GraphQLID) },
49 | filter: {
50 | type: Filter
51 | },
52 | limit: { type: GraphQLInt },
53 | offset: { type: GraphQLInt },
54 | orderBy: { type: order(`subtype`, Fields) }
55 | },
56 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
57 | }
58 | }
59 |
60 | export const Mutations = {
61 | createSubtype: {
62 | type: Definition,
63 | description: `Creates a new Subtype`,
64 | args: { input: { type: Input } },
65 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
66 | },
67 | updateSubtype: {
68 | type: Definition,
69 | description: `Updates an existing Subtype, creates it if it does not already exist`,
70 | args: { input: { type: Input } },
71 | resolve: (parent, args, context) => update(parent, args, context, Definition.name)
72 | },
73 | deleteSubtype: {
74 | type: Definition,
75 | description: `Deletes a Subtype by id`,
76 | args: { id: { type: GraphQLID } },
77 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/types/supertype.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 |
4 | export const Input = new GraphQLInputObjectType({
5 | name: `SupertypeInput`,
6 | description: `Required fields for a new Supertype object`,
7 | fields: () => ({
8 | name: { type: new GraphQLNonNull(GraphQLString) }
9 | })
10 | })
11 |
12 | const Filter = new GraphQLInputObjectType({
13 | name: `SupertypeFilter`,
14 | description: `Queryable fields for Supertype.`,
15 | fields: () => ({
16 | name: { type: new GraphQLList(GraphQLString) }
17 | })
18 | })
19 |
20 | const Fields = new GraphQLEnumType({
21 | name: `SupertypeFields`,
22 | description: `Field names for Supertype.`,
23 | values: {
24 | name: { value: `name` }
25 | }
26 | })
27 |
28 | export const Definition = new GraphQLObjectType({
29 | name: `Supertype`,
30 | description: `A Supertype object`,
31 | fields: () => ({
32 | id: {
33 | type: GraphQLID,
34 | description: `A unique id for this supertype.`
35 | },
36 | name: {
37 | type: GraphQLString,
38 | description: `The supertype name.`
39 | }
40 | })
41 | })
42 |
43 | export const Queries = {
44 | supertype: {
45 | type: new GraphQLList(Definition),
46 | description: `Returns a Supertype.`,
47 | args: {
48 | id: { type: new GraphQLList(GraphQLID) },
49 | filter: {
50 | type: Filter
51 | },
52 | limit: { type: GraphQLInt },
53 | offset: { type: GraphQLInt },
54 | orderBy: { type: order(`supertype`, Fields) }
55 | },
56 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
57 | }
58 | }
59 |
60 | export const Mutations = {
61 | createSupertype: {
62 | type: Definition,
63 | description: `Creates a new Supertype`,
64 | args: { input: { type: Input } },
65 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
66 | },
67 | updateSupertype: {
68 | type: Definition,
69 | description: `Updates an existing Supertype, creates it if it does not already exist`,
70 | args: { input: { type: Input } },
71 | resolve: (parent, args, context) => update(parent, args, context, Definition.name)
72 | },
73 | deleteSupertype: {
74 | type: Definition,
75 | description: `Deletes a Supertype by id`,
76 | args: { id: { type: GraphQLID } },
77 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/types/type.js:
--------------------------------------------------------------------------------
1 | import { GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLEnumType, GraphQLList, GraphQLString, GraphQLObjectType, GraphQLInputObjectType } from 'graphql'
2 | import { create, destroy, order, read, update } from './utilities'
3 |
4 | export const Input = new GraphQLInputObjectType({
5 | name: `TypeInput`,
6 | description: `Required fields for a new Type object`,
7 | fields: () => ({
8 | id: { type: GraphQLID },
9 | name: { type: new GraphQLNonNull(GraphQLString) }
10 | })
11 | })
12 |
13 | const Filter = new GraphQLInputObjectType({
14 | name: `TypeFilter`,
15 | description: `Queryable fields for Type.`,
16 | fields: () => ({
17 | name: { type: new GraphQLList(GraphQLString) }
18 | })
19 | })
20 |
21 | const Fields = new GraphQLEnumType({
22 | name: `TypeFields`,
23 | description: `Field names for Type.`,
24 | values: {
25 | name: { value: `name` }
26 | }
27 | })
28 |
29 | export const Definition = new GraphQLObjectType({
30 | name: `Type`,
31 | description: `A Type object`,
32 | fields: () => ({
33 | id: {
34 | type: GraphQLID,
35 | description: `A unique id for this type.`
36 | },
37 | name: {
38 | type: GraphQLString,
39 | description: `The type name.`
40 | }
41 | })
42 | })
43 |
44 | export const Queries = {
45 | type: {
46 | type: new GraphQLList(Definition),
47 | description: `Returns a Type.`,
48 | args: {
49 | id: { type: new GraphQLList(GraphQLID) },
50 | filter: {
51 | type: Filter
52 | },
53 | limit: { type: GraphQLInt },
54 | offset: { type: GraphQLInt },
55 | orderBy: { type: order(`type`, Fields) }
56 | },
57 | resolve: (parent, args, context) => read(parent, args, context, Definition.name)
58 | }
59 | }
60 |
61 | export const Mutations = {
62 | createType: {
63 | type: Definition,
64 | description: `Creates a new Type`,
65 | args: { input: { type: Input } },
66 | resolve: (parent, args, context) => create(parent, args, context, Definition.name)
67 | },
68 | updateType: {
69 | type: Definition,
70 | description: `Updates an existing Type, creates it if it does not already exist`,
71 | args: { input: { type: Input } },
72 | resolve: (parent, args, context) => update(parent, args, context, Definition.name)
73 | },
74 | destroyType: {
75 | type: Definition,
76 | description: `Deletes a Type by id`,
77 | args: { id: { type: GraphQLID } },
78 | resolve: (parent, args, context) => destroy(parent, args, context, Definition.name)
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/types/utilities/create.js:
--------------------------------------------------------------------------------
1 | import { info, error } from 'winston'
2 | import Models from '../../models'
3 |
4 | const create = (parent, { input }, context, type, callback) => Models[`${type}`]
5 | .findOrCreate(input)
6 | .then(model => !!callback ? callback(model) : model.toJSON())
7 | .catch(err => error(`Failed to run Mutation: create${type}`, err))
8 | .finally(info(`Resolved Mutation: create${type}`, { parent, input, context }))
9 |
10 | export default create
11 |
--------------------------------------------------------------------------------
/src/types/utilities/destroy.js:
--------------------------------------------------------------------------------
1 | import { info, error } from 'winston'
2 | import Models from '../../models'
3 |
4 | const destroy = (parent, { id }, context, type) => Models[`${type}`]
5 | .destroy({ id })
6 | .then(model => model.toJSON())
7 | .catch(err => error(`Failed to run Mutation: destroy${type}`, err))
8 | .finally(info(`Resolved Mutation: destroy${type}`, { parent, id, context }))
9 |
10 | export default destroy
11 |
--------------------------------------------------------------------------------
/src/types/utilities/index.js:
--------------------------------------------------------------------------------
1 | export { default as create } from './create'
2 | export { default as destroy } from './destroy'
3 | export { default as order } from './order'
4 | export { default as read } from './read'
5 | export { default as sort } from './sort'
6 | export { default as update } from './update'
7 |
--------------------------------------------------------------------------------
/src/types/utilities/order.js:
--------------------------------------------------------------------------------
1 | import { GraphQLInputObjectType, GraphQLNonNull } from 'graphql'
2 | import { sort } from './'
3 |
4 | const order = (name, fields) => new GraphQLInputObjectType({
5 | name: `${name}OrderBy`,
6 | fields: () => ({
7 | order: { type: new GraphQLNonNull(fields) },
8 | sort: { type: sort }
9 | })
10 | })
11 |
12 | export default order
13 |
--------------------------------------------------------------------------------
/src/types/utilities/read.js:
--------------------------------------------------------------------------------
1 | import { info, error } from 'winston'
2 | import Models from '../../models'
3 |
4 | const read = (parent, args, context, type) => {
5 | const { id, filter, limit, offset, orderBy } = args
6 | return Models[`${type}`]
7 | .query(qb => {
8 | if (!!id) qb.whereIn(`id`, id)
9 | if (!!filter) for (let field in filter) qb.whereIn(field, filter[field])
10 | if (!!limit) qb.limit(limit)
11 | if (!!offset) qb.offset(offset)
12 | if (!!orderBy) qb.orderBy(...Object.values(orderBy))
13 | })
14 | .fetchAll()
15 | .then(collection => collection.toJSON())
16 | .catch(err => error(`Failed to resolve Query: ${type}`, err))
17 | .finally(info(`Resolved Query: ${type}`, { parent, args, context }))
18 | }
19 |
20 | export default read
21 |
--------------------------------------------------------------------------------
/src/types/utilities/sort.js:
--------------------------------------------------------------------------------
1 | import { GraphQLEnumType } from 'graphql'
2 |
3 | const sort = new GraphQLEnumType({
4 | name: `Sort`,
5 | description: `Sort options for OrderBy`,
6 | values: {
7 | ascending: { value: `asc` },
8 | descending: { value: `desc`}
9 | }
10 | })
11 |
12 | export default sort
13 |
--------------------------------------------------------------------------------
/src/types/utilities/update.js:
--------------------------------------------------------------------------------
1 | import { info, error } from 'winston'
2 | import Models from '../../models'
3 |
4 | const update = (parent, { input }, context, type, selection, callback) => {
5 | if (!!selection && typeof selection === `string`) selection = [`${selection}`]
6 |
7 | const filter = !!selection
8 | ? Object.keys(input)
9 | .filter(key => selection.includes(key))
10 | .reduce((obj, key) => {
11 | obj[key] = input[key]
12 | return obj
13 | }, {})
14 | : input
15 |
16 | return Models[`${type}`]
17 | .upsert(filter, input)
18 | .then(model => !!callback ? callback(model) : model.toJSON())
19 | .catch(err => error(`Failed to run Mutation: update${type}`, err))
20 | .finally(info(`Resolved Mutation: update${type}`, { parent, input, context, selection }))
21 | }
22 |
23 | export default update
24 |
--------------------------------------------------------------------------------
/test/karma.conf.js:
--------------------------------------------------------------------------------
1 | import testRunnerConfig from 'test-runner-config'
2 |
3 | let karmaFiles = testRunnerConfig.getKarmaFiles(files)
4 |
5 | export default (config) => {
6 | config.set({
7 | basePath: __dirname,
8 | frameworks: [`jasmine`],
9 | exclude: [ ],
10 | files: karmaFiles.files,
11 | reporters: [ `mocha` ],
12 | port: 47357,
13 | colors: true,
14 | logLevel: config.LOG_INFO,
15 | autoWatch: false,
16 | browsers: [`Chrome_no_sandbox`],
17 | customLaunchers: {
18 | Chrome_no_sandbox: {
19 | base: `Chrome`,
20 | flags: [`--no-sandbox`]
21 | }
22 | },
23 | singleRun: true
24 | })
25 | }
26 |
--------------------------------------------------------------------------------
/wallaby.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (wallaby) {
2 | return {
3 | files: [
4 | {
5 | pattern: 'src/**/*.js',
6 | load: false
7 | },
8 | {
9 | pattern: 'src/**/*.spec.js',
10 | ignore: true
11 | }
12 | ],
13 |
14 | tests: [
15 | 'src/**/*.spec.js'
16 | ],
17 |
18 | compilers: {
19 | 'src/**/*.js': wallaby.compilers.babel({
20 | babel: require('babel-core'),
21 | babelrc: true
22 | })
23 | },
24 |
25 | env: {
26 | type: 'node',
27 | runner: 'node',
28 | params: {
29 | // Specify Environment Variables Here
30 | }
31 | },
32 |
33 | testFramework: 'jasmine',
34 |
35 | debug: true
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/webpack.config.babel.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack'
2 | import path from 'path'
3 | import fs from 'fs'
4 | import dotenv from 'dotenv' // https://github.com/motdotla/dotenv
5 | import { generateConfig, stripMetadata } from '@easy-webpack/core'
6 | import envDev from '@easy-webpack/config-env-development'
7 | import babel from '@easy-webpack/config-babel'
8 |
9 | dotenv.config()
10 |
11 | process.env.BABEL_ENV = `webpack`
12 | const ENV = process.env.NODE_ENV && process.env.NODE_ENV.toLowerCase() || (process.env.NODE_ENV = `development`)
13 |
14 | const nodeModules = {}
15 | fs.readdirSync(`node_modules`)
16 | .filter(x => [`.bin`].indexOf(x) === -1)
17 | .forEach(mod => nodeModules[mod] = `commonjs ` + mod)
18 |
19 | // Main Webpack Configuration
20 | const config = generateConfig(
21 | {
22 | entry: {
23 | 'server': `./src/server`
24 | },
25 | target: `node`,
26 | output: {
27 | path: path.resolve(`dist`),
28 | filename: `server.js`
29 | },
30 | externals: nodeModules
31 | },
32 |
33 | ENV === `test` ? envDev({devtool: `inline-source-map`}) : envDev(),
34 |
35 | babel(),
36 |
37 | ENV === `production` ? {
38 | plugins: [
39 | new webpack.optimize.UglifyJsPlugin({
40 | compress: {
41 | warnings: false,
42 | conditionals: true,
43 | unused: true,
44 | comparisons: true,
45 | sequences: true,
46 | dead_code: true,
47 | evaluate: true,
48 | join_vars: true,
49 | if_return: true
50 | },
51 | output: {
52 | comments: false
53 | }
54 | })
55 | ]} : { plugins: [
56 | new webpack.optimize.UglifyJsPlugin({
57 | beautify: true,
58 | mangle: false,
59 | dead_code: true,
60 | unused: true,
61 | compress: {
62 | keep_fnames: true,
63 | drop_debugger: false,
64 | dead_code: true,
65 | unused: true,
66 | warnings: false
67 | },
68 | comments: true
69 | })
70 | ]},
71 |
72 | ENV === `development` ? { performance: { hints: false } } : {},
73 |
74 | {
75 | module: {
76 | rules: [
77 | { test: /\.(graphql|gql)$/, exclude: /node_modules/, loader: `graphql-tag/loader` },
78 | { test: /\src\/images$/, loader: `ignore-loader` }
79 | ]
80 | },
81 | plugins: [
82 | new webpack.EnvironmentPlugin([
83 | `HTTP`,
84 | `HTTPS`,
85 | `LOGLEVEL`,
86 | `DB_HOST`,
87 | `DB_USERNAME`,
88 | `DB_PASSWORD`,
89 | `DB_NAME`,
90 | `LOGGLY_TOKEN`,
91 | `LOGGLY_SUBDOMAIN`,
92 | `DD_API_KEY`
93 | ]),
94 | new webpack.BannerPlugin({ banner: `require("source-map-support").install();`, raw: true, entryOnly: false })
95 | ]
96 | }
97 | )
98 |
99 | module.exports = stripMetadata(config)
100 |
--------------------------------------------------------------------------------