diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md new file mode 100644 index 0000000..7f9fdea --- /dev/null +++ b/doc/CHANGELOG.md @@ -0,0 +1,11 @@ +# Project Changelog + +> *[Return to Directory](README.md)* + +## v0.1.1 + +- 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. +- 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. +- Added some documentation, including a project Roadmap and a Changelog. +- Added missing dependency Winston-Loggly-Bulk. +- Removed leftover references to previous express server implementation in routes. diff --git a/doc/README.md b/doc/README.md index e69de29..6b8de0a 100644 --- a/doc/README.md +++ b/doc/README.md @@ -0,0 +1,6 @@ +# Scribe Documentation + +## Table of Contents + + - [Project Roadmap](ROADMAP.md) + - [Changelog](CHANGELOG.md) diff --git a/doc/ROADMAP.md b/doc/ROADMAP.md new file mode 100644 index 0000000..34a8705 --- /dev/null +++ b/doc/ROADMAP.md @@ -0,0 +1,37 @@ +# Project Roadmap + +> *[Return to Directory](README.md)* + +## v0.2.0 + +- [ ] Refactor Types/Models to condense data schema into one place per table. +- [ ] Write basic project documentation (setup, getting started, etc) ie: [README](../README.md) +- [ ] Wire-up Hapi Routes +- [X] Troubleshoot remaining issues with SQLite Migrations / Knex schema +- [ ] Add pagination query arguments for lists + +## v0.3.0 + +- [ ] Add remaining mutations to enable populating the database via the API +- [ ] Add private tables / type definitions + - [ ] Tables: Account, Collection, Binders, Decks, OwnedCards, misc + - [ ] Type definitions/queries/mutations for above + +## v0.4.0 + +- [ ] Setup login/signup REST API +- [ ] Add authentication layer to GraphQL API for private Tables +- [ ] Add rate-limiting to public GraphQL API + +## v0.5.0 + +- [ ] Add application state history table / frontend utility APIs +- [ ] Add trading API / services + - [ ] Create service to grab pricing data from public API sources + - [ ] Add GraphQL types/queries to expose pricing data + - [ ] Add tables / type definitions for Trading platform + +## v0.6.0 + +- [ ] Refactor GraphQL resolvers to use batch SQL querying (speculative) +- [ ] ...? diff --git a/package.json b/package.json index 6402dcf..e26f88c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scribe", - "version": "0.1.0", + "version": "0.1.1", "description": "A GraphQL Magic: The Gathering API Server", "main": "src/app.js", "productName": "Scribe", @@ -67,6 +67,7 @@ "passport-oauth2": "^1.1.2", "sqlite3": "^3.1.8", "test-runner-config": "^0.5.0", - "winston": "^2.3.0" + "winston": "^2.3.0", + "winston-loggly-bulk": "^1.3.4" } } diff --git a/src/models/index.js b/src/models/index.js index 0ad3942..12e9a97 100644 --- a/src/models/index.js +++ b/src/models/index.js @@ -1,5 +1,6 @@ import path from 'path' import glob from 'glob' // https://github.com/isaacs/node-glob +import config from '../config/server.config' export function loadModels() { let modelsArray = [] @@ -50,6 +51,7 @@ function create(knex, migrations) { toBeCreated.push( knex.schema.createTableIfNotExists(migration.name, (table) => { migration.fields(table) + if(config.ENV === 'test' || config.ENV === 'development') migration.foreignKeys(table) }) .then(() => { console.log(`✓ Created table: ${migration.name}`) @@ -108,24 +110,24 @@ function destroy(knex, migrations) { // http://knexjs.org/#Migrations-API export function up(knex, Promise) { - return knex.raw('SET foreign_key_checks = 0;') + return knex.raw(`${ config.ENV === 'production' ? 'SET foreign_key_checks = 0;' : 'PRAGMA foreign_keys = ON' }`) .then(() => { return Promise.all(loadMigrations(knex, create)) }) .then(() => { - return Promise.all(loadMigrations(knex, update)) + if(config.ENV === 'production') return Promise.all(loadMigrations(knex, update)) }) .then(() => { - return knex.raw('SET foreign_key_checks = 1;') + if(config.ENV === 'production') return knex.raw('SET foreign_key_checks = 1;') }) } export function down(knex, Promise) { - return knex.raw('SET foreign_key_checks = 0;') + return knex.raw(`${ config.ENV === 'production' ? 'SET foreign_key_checks = 0;' : '' }`) .then(() => { return Promise.all(loadMigrations(knex, destroy)) }) .then(() => { - return knex.raw('SET foreign_key_checks = 1;') + if(config.ENV === 'production') return knex.raw('SET foreign_key_checks = 1;') }) } diff --git a/src/models/tables/abilityType.js b/src/models/tables/abilityType.js new file mode 100644 index 0000000..2f8d3c2 --- /dev/null +++ b/src/models/tables/abilityType.js @@ -0,0 +1,53 @@ +import db from '../../config/bookshelf.config' + +import Card from './card' +import AbilityTypes from './abilityTypes' +import AbilityTypeCards from './abilityTypeCards' + +export default class abilityType extends db.Model { + get tableName() { + return 'abilitytype' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the ability type.`) + .notNullable() + + table.text(`description`) + .comment(`Description of the ability type.`) + + table.bigInteger(`cards`) + .comment(`The cards associated with this abilityType.`) + .notNullable() + .unsigned() + .index(`abilityType_cards`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`cards`) + .references(`abilitytype`) + .inTable(`abilitytypecards`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } + + abilityTypes() { + return this.belongsTo(AbilityTypes) + } + + cards() { + return this.hasMany(Card, `card`) + .through(AbilityTypeCards) + } +} + +export const AbilityType = new abilityType() diff --git a/src/models/tables/abilityTypeCards.js b/src/models/tables/abilityTypeCards.js new file mode 100644 index 0000000..2f039c6 --- /dev/null +++ b/src/models/tables/abilityTypeCards.js @@ -0,0 +1,49 @@ +import db from '../../config/bookshelf.config' + +import Card from './card' +import AbilityType from './abilityType' + +export default class abilityTypeCards extends db.Model { + get tableName() { + return 'abilitytypecards' + } + + static fields(table) { + // Fields + table.bigInteger(`abilitytype`) + .comment(`The abilityType associated with this card.`) + .notNullable() + .unsigned() + .index(`abilityTypeCards_abilitytype`) + + table.bigInteger(`card`) + .comment(`The card associated with this abilityType.`) + .notNullable() + .unsigned() + .index(`abilityTypeCards_card`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`abilitytype`, `card`]) + } + + static foreignKeys(table) { + table.foreign(`card`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } + + abilityType() { + return this.belongsTo(AbilityType) + } + + card() { + return this.hasMany(Card) + } +} + +export const AbilityTypeCards = new abilityTypeCards() diff --git a/src/models/tables/abilityTypes.js b/src/models/tables/abilityTypes.js new file mode 100644 index 0000000..e7c69f2 --- /dev/null +++ b/src/models/tables/abilityTypes.js @@ -0,0 +1,49 @@ +import db from '../../config/bookshelf.config' + +import Card from './card' +import AbilityType from './abilityType' + +export default class abilityTypes extends db.Model { + get tableName() { + return 'abilitytypes' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this abilityType.`) + .notNullable() + .unsigned() + .index(`abilitytypes_card`) + + table.bigInteger(`abilitytype`) + .comment(`The abilityType associated with this card.`) + .notNullable() + .unsigned() + .index(`abilitytypes_abilitytype`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `abilitytype`]) + } + + static foreignKeys(table) { + table.foreign(`abilitytype`) + .references(`id`) + .inTable(`abilitytype`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } + + abilityType() { + return this.belongsTo(AbilityType) + } + + card() { + return this.hasMany(Card) + } +} + +export const AbilityTypes = new abilityTypes() diff --git a/src/models/tables/artist.js b/src/models/tables/artist.js new file mode 100644 index 0000000..9b69555 --- /dev/null +++ b/src/models/tables/artist.js @@ -0,0 +1,52 @@ +import db from '../../config/bookshelf.config' + +import Card from './card' +import ArtistCards from './artistCards' + +export default class artist extends db.Model { + get tableName() { + return `artist` + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the artist.`) + .notNullable() + + table.text(`website`) + .comment(`The website of the artist, if they have one.`) + + table.bigInteger(`cards`) + .comment(`The cards associated with this artist.`) + .notNullable() + .unsigned() + .index(`artist_cards`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`cards`) + .references(`artist`) + .inTable(`artistcards`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } + + card() { + return this.belongsTo(Card, 'artist') + } + + cards() { + return this.hasMany(Card, `card`) + .through(ArtistCards) + } +} + +export const Artist = new artist() diff --git a/src/models/tables/artistCards.js b/src/models/tables/artistCards.js new file mode 100644 index 0000000..18bd59f --- /dev/null +++ b/src/models/tables/artistCards.js @@ -0,0 +1,49 @@ +import db from '../../config/bookshelf.config' + +import Card from './card' +import Artist from './artist' + +export default class artistCards extends db.Model { + get tableName() { + return `artistcards` + } + + static fields(table) { + // Fields + table.bigInteger(`artist`) + .comment(`The artist associated with this card.`) + .notNullable() + .unsigned() + .index(`artistCards_artist`) + + table.bigInteger(`card`) + .comment(`The card associated with this artist.`) + .notNullable() + .unsigned() + .index(`artistCards_card`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`artist`, `card`]) + } + + static foreignKeys(table) { + table.foreign(`card`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } + + artist() { + return this.belongsTo(Artist) + } + + card() { + return this.hasMany(Card) + } +} + +export const ArtistCards = new artistCards() diff --git a/src/models/tables/block.js b/src/models/tables/block.js new file mode 100644 index 0000000..caba150 --- /dev/null +++ b/src/models/tables/block.js @@ -0,0 +1,49 @@ +import db from '../../config/bookshelf.config' + +import Set from './set' +import BlockSets from './blockSets' + +export default class block extends db.Model { + get tableName() { + return 'block' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the block.`) + .notNullable() + + table.bigInteger(`sets`) + .comment(`List of sets that are included in this block.`) + .notNullable() + .unsigned() + .index(`block_sets`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`sets`) + .references(`block`) + .inTable(`blockSets`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } + + set() { + return this.belongsTo(Set, 'block') + } + + sets() { + return this.hasMany(Set) + .through(BlockSets) + } +} + +export const Block = new block() diff --git a/src/models/tables/blockSets.js b/src/models/tables/blockSets.js new file mode 100644 index 0000000..a5cb280 --- /dev/null +++ b/src/models/tables/blockSets.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class blockSets extends db.Model { + get tableName() { + return 'blocksets' + } + + static fields(table) { + // Fields + table.bigInteger(`block`) + .comment(`The block associated with this set.`) + .notNullable() + .unsigned() + .index(`blockSets_block`) + + table.bigInteger(`set`) + .comment(`The set associated with this block.`) + .notNullable() + .unsigned() + .index(`blockSets_set`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`block`, `set`]) + } + + static foreignKeys(table) { + table.foreign(`set`) + .references(`id`) + .inTable(`set`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } +} + +export const BlockSets = new blockSets() diff --git a/src/models/tables/card.js b/src/models/tables/card.js new file mode 100644 index 0000000..3a41017 --- /dev/null +++ b/src/models/tables/card.js @@ -0,0 +1,357 @@ +import db from '../../config/bookshelf.config' + +import Name from './name' +import Sides from './sides' +import Variations from './variations' +import Color from './color' +import Supertype from './supertype' +import Type from './type' +import Subtype from './subtype' +import Category from './category' +import AbilityType from './abilityType' +import Keyword from './keyword' +import Legality from './legality' +import Ruling from './ruling' +import Artist from './artist' +import Printings from './printings' + +export default class card extends db.Model { + get tableName() { + return 'card' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`multiverseid`) + .comment(`The multiverseid of the card on Wizard’s Gatherer web page. Cards from sets that do not exist on Gatherer will NOT have a multiverseid.`) + .notNullable() + + table.bigInteger(`names`) + .comment(`The card names. This includes a list of foreign names indexed by a language code. Example: enUS`) + .notNullable() + .unsigned() + .index(`card_names`) + + table.bigInteger(`sides`) + .comment(`Only used for split, flip and dual cards. Will contain a lit of cards representing each side of this card, front or back.`) + .unsigned() + .index(`card_sides`) + + table.bigInteger(`variations`) + .comment(`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.`) + .unsigned() + .index(`card_variations`) + + table.string(`border`) + .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)`) + + table.bigInteger(`layout`) + .comment(`The card layout.`) + .notNullable() + .unsigned() + .index(`card_layout`) + + table.string(`image`) + .comment(`The image url for a card. Only exists if the card has a multiverse id.`) + .notNullable() + + table.string(`manacost`) + .comment(`The mana cost of this card. Consists of one or more mana symbols. (use cmc and colors to query)`) + + table.integer(`cmc`) + .comment(`Converted mana cost.`) + .notNullable() + + table.bigInteger(`coloridentity`) + .comment(`The card colors by color code. [“Red”, “Blue”] becomes [“R”, “U”]`) + .notNullable() + .unsigned() + .index(`card_coloridentity`) + + table.string(`typeLine`) + .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.`) + .notNullable() + + table.string(`originaltype`) + .comment(`The original type on the card at the time it was printed. This field is not available for promo cards.`) + + table.bigInteger(`supertypes`) + .comment(`The supertypes of the card. These appear to the far left of the card type.`) + .unsigned() + .index(`card_supertypes`) + + table.bigInteger(`types`) + .comment(`The types of the card. These appear to the left of the dash in a card type.`) + .notNullable() + .unsigned() + .index(`card_types`) + + table.bigInteger(`subtypes`) + .comment(`The subtypes of the card. These appear to the right of the dash in a card type. Usually each word is its own subtype.`) + .unsigned() + .index(`card_subtypes`) + + table.bigInteger(`rarity`) + .comment(`The rarity of the card.`) + .notNullable() + .unsigned() + .index(`card_rarity`) + + table.bigInteger(`set`) + .comment(`The set the card belongs to.`) + .notNullable() + .unsigned() + .index(`card_set`) + + table.text(`text`) + .comment(`The text of the card.`) + .notNullable() + + table.text(`originaltext`) + .comment(`The original text on the card at the time it was printed. This field is not available for promo cards.`) + + table.bigInteger(`categories`) + .comment(`A list of categories describind this card. Examples: Acceleration, Removal`) + .unsigned() + .index(`card_categories`) + + table.bigInteger(`abilitytypes`) + .comment(`A list of Ability Types this card has. Examples: Activated, Triggered`) + .unsigned() + .index(`card_abilityTypes`) + + table.bigInteger(`keywords`) + .comment(`A list of keyword abilities this card has. Examples: Haste, Trample`) + .unsigned() + .index(`card_keywords`) + + table.text(`flavor`) + .comment(`The flavor text of the card.`) + + table.string(`hand`) + .comment(`Maximum hand size modifier. Only exists for Vanguard cards.`) + + table.string(`life`) + .comment(`Starting life total modifier. Only exists for Vanguard cards.`) + + table.string(`power`) + .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+*”`) + + table.string(`toughness`) + .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+*”`) + + table.integer(`loyalty`) + .comment(`The loyalty of the card. This is only present for planeswalkers.`) + + table.bigInteger(`legalities`) + .comment(`The legality of the card for a given format, such as Legal, Banned or Restricted.`) + .notNullable() + .unsigned() + .index(`card_legalities`) + + table.bigInteger(`rulings`) + .comment(`The rulings for the card. An array of objects, each object having date and text keys.`) + .unsigned() + .index(`card_rulings`) + + table.bigInteger(`artist`) + .comment(`The artist of the card. This may not match what is on the card as MTGJSON corrects many card misprints.`) + .notNullable() + .unsigned() + .index(`card_artist`) + + table.string(`number`) + .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.`) + .notNullable() + + table.date(`releasedate`) + .comment(`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.`) + + table.bigInteger(`printings`) + .comment(`The sets that this card was printed in, expressed as an array of set codes.`) + .notNullable() + .unsigned() + .index(`card_printings`) + + table.boolean(`timeshifted`) + .comment(`If this card was a timeshifted card in the set.`) + + table.boolean(`starter`) + .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.`) + + table.boolean(`reserved`) + .comment(`Set to true if this card is reserved by Wizards Official Reprint Policy.`) + + table.string(`source`) + .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.`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`names`) + .references(`card`) + .inTable(`names`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`sides`) + .references(`card`) + .inTable(`sides`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`variations`) + .references(`card`) + .inTable(`variations`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`layout`) + .references(`id`) + .inTable(`layout`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`coloridentity`) + .references(`id`) + .inTable(`coloridentity`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`supertypes`) + .references(`card`) + .inTable(`supertypes`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`types`) + .references(`card`) + .inTable(`types`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`subtypes`) + .references(`card`) + .inTable(`subtypes`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`rarity`) + .references(`id`) + .inTable(`rarity`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`set`) + .references(`id`) + .inTable(`set`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`categories`) + .references(`card`) + .inTable(`categories`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`abilityTypes`) + .references(`card`) + .inTable(`abilitytypes`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`keywords`) + .references(`card`) + .inTable(`keywords`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`legalities`) + .references(`card`) + .inTable(`legalities`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`rulings`) + .references(`card`) + .inTable(`rulings`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + + table.foreign(`artist`) + .references(`id`) + .inTable(`artist`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`printings`) + .references(`card`) + .inTable(`printings`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } + + names() { + return this.hasMany(Name, "names") + } + + sides() { + return this.hasMany(Card, "sides") + } + + variations() { + return this.hasMany(Card, "variations") + } + + colors() { + return this.hasMany(Color, "colors") + } + + supertypes() { + return this.hasMany(Supertype, "supertypes") + } + + types() { + return this.hasMany(Type, "types") + } + + subtypes() { + return this.hasMany(Subtype, "subtypes") + } + + categories() { + return this.hasMany(Category, "categories") + } + + abilityTypes() { + return this.hasMany(AbilityType, "abilityTypes") + } + + keywords() { + return this.hasMany(Keyword, "keywords") + } + + legalities() { + return this.hasMany(Legality, "legalities") + } + + rulings() { + return this.hasMany(Ruling, "rulings") + } + + artist() { + return this.hasone(Artist, "artist") + } + + printings() { + return this.hasMany(Card, "printings") + } +} + +export const Card = new card() diff --git a/src/models/tables/categories.js b/src/models/tables/categories.js new file mode 100644 index 0000000..bcf65ee --- /dev/null +++ b/src/models/tables/categories.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class categories extends db.Model { + get tableName() { + return 'categories' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this category.`) + .notNullable() + .unsigned() + .index(`categories_card`) + + table.bigInteger(`category`) + .comment(`The category associated with this card.`) + .notNullable() + .unsigned() + .index(`categories_category`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `category`]) + } + + static foreignKeys(table) { + table.foreign(`category`) + .references(`id`) + .inTable(`category`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Categories = new categories() diff --git a/src/models/tables/category.js b/src/models/tables/category.js new file mode 100644 index 0000000..1724bda --- /dev/null +++ b/src/models/tables/category.js @@ -0,0 +1,54 @@ +import db from '../../config/bookshelf.config' + +import Card from './card' +import Categories from './categories' +import CategoryCards from './categoryCards' + +export default class category extends db.Model { + get tableName() { + return 'category' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the category.`) + .notNullable() + + table.text(`description`) + .comment(`The description of the category.`) + + table.bigInteger(`cards`) + .comment(`A list of cards that have this category.`) + .notNullable() + .unsigned() + .index(`category_cards`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`cards`) + .references(`category`) + .inTable(`categorycards`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } + + card() { + return this.belongsTo(Card, 'categories') + .through(Categories, 'category') + } + + cards() { + return this.hasMany(Card) + .through(CategoryCards, 'category') + } +} + +export const Category = new category() diff --git a/src/models/tables/categoryCards.js b/src/models/tables/categoryCards.js new file mode 100644 index 0000000..7e567cf --- /dev/null +++ b/src/models/tables/categoryCards.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class categoryCards extends db.Model { + get tableName() { + return 'categorycards' + } + + static fields(table) { + // Fields + table.bigInteger(`category`) + .comment(`The category associated with this card.`) + .notNullable() + .unsigned() + .index(`categoryCards_category`) + + table.bigInteger(`card`) + .comment(`The card associated with this category.`) + .notNullable() + .unsigned() + .index(`categoryCards_card`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`category`, `card`]) + } + + static foreignKeys(table) { + table.foreign(`card`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const CategoryCards = new categoryCards() diff --git a/src/models/tables/color.js b/src/models/tables/color.js new file mode 100644 index 0000000..42af7ab --- /dev/null +++ b/src/models/tables/color.js @@ -0,0 +1,49 @@ +import db from '../../config/bookshelf.config' + +export default class color extends db.Model { + get tableName() { + return 'color' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`symbol`) + .comment(`The color symbol code for this color.`) + .notNullable() + + table.bigInteger(`icon`) + .comment(`The icon associated with the color.`) + .notNullable() + .unsigned() + .index(`color_icon`) + + table.bigInteger(`identity`) + .comment(`The color identity associated with the color.`) + .notNullable() + .unsigned() + .index(`color_identity`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`icon`) + .references(`id`) + .inTable(`icon`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`identity`) + .references(`id`) + .inTable(`coloridentity`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Color = new color() diff --git a/src/models/tables/colorIdentity.js b/src/models/tables/colorIdentity.js new file mode 100644 index 0000000..b73e2c6 --- /dev/null +++ b/src/models/tables/colorIdentity.js @@ -0,0 +1,48 @@ +import db from '../../config/bookshelf.config' + +export default class colorIdentity extends db.Model { + get tableName() { + return 'colorIdentity' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the color identity.`) + .notNullable() + + table.string(`alias`) + .comment(`The alias of the color identity. Examples: Bant, Jeskai`) + + table.bigInteger(`colors`) + .comment(`List of colors included in this color identity.`) + .notNullable() + .unsigned() + .index(`colorIdentity_colors`) + + table.boolean(`multicolored`) + .comment(`True if the color identity has more than one color.`) + .notNullable() + + table.boolean(`devoid`) + .comment(`True if the color identity is ruled to be colorless.`) + .notNullable() + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`colors`) + .references(`coloridentity`) + .inTable(`colors`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } +} + +export const ColorIdentity = new colorIdentity() diff --git a/src/models/tables/colors.js b/src/models/tables/colors.js new file mode 100644 index 0000000..0e0c0b6 --- /dev/null +++ b/src/models/tables/colors.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class colors extends db.Model { + get tableName() { + return 'colors' + } + + static fields(table) { + // Fields + table.bigInteger(`coloridentity`) + .comment(`The colorIdentity associated with the color.`) + .notNullable() + .unsigned() + .index(`colors_coloridentity`) + + table.bigInteger(`color`) + .comment(`The color associated with the colorIdentity.`) + .notNullable() + .unsigned() + .index(`colors_color`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`coloridentity`, `color`]) + } + + static foreignKeys(table) { + table.foreign(`color`) + .references(`id`) + .inTable(`color`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Colors = new colors() diff --git a/src/models/tables/format.js b/src/models/tables/format.js new file mode 100644 index 0000000..2fa3a15 --- /dev/null +++ b/src/models/tables/format.js @@ -0,0 +1,37 @@ +import db from '../../config/bookshelf.config' + +export default class format extends db.Model { + get tableName() { + return 'format' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the format.`) + .notNullable() + + table.bigInteger(`sets`) + .comment(`List of sets that are included in this format.`) + .notNullable() + .unsigned() + .index(`format_sets`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`sets`) + .references(`format`) + .inTable(`formatSets`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } +} + +export const Format = new format() diff --git a/src/models/tables/formatSets.js b/src/models/tables/formatSets.js new file mode 100644 index 0000000..8b42d42 --- /dev/null +++ b/src/models/tables/formatSets.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class formatSets extends db.Model { + get tableName() { + return 'formatsets' + } + + static fields(table) { + // Fields + table.bigInteger(`format`) + .comment(`The format associated with this set.`) + .notNullable() + .unsigned() + .index(`formatSets_format`) + + table.bigInteger(`set`) + .comment(`The set associated with this format.`) + .notNullable() + .unsigned() + .index(`formatSets_set`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`format`, `set`]) + } + + static foreignKeys(table) { + table.foreign(`set`) + .references(`id`) + .inTable(`set`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const FormatSets = new formatSets() diff --git a/src/models/tables/icon.js b/src/models/tables/icon.js new file mode 100644 index 0000000..354ee56 --- /dev/null +++ b/src/models/tables/icon.js @@ -0,0 +1,35 @@ +import db from '../../config/bookshelf.config' + +export default class icon extends db.Model { + get tableName() { + return 'icon' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the icon.`) + .notNullable() + + table.text(`image`) + .comment(`A URL pointing to an image of the icon.`) + .notNullable() + + table.string(`class`) + .comment(`CSS class name used to display the icon.`) + .notNullable() + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + + } +} + +export const Icon = new icon() diff --git a/src/models/tables/icons.js b/src/models/tables/icons.js new file mode 100644 index 0000000..9f28bc6 --- /dev/null +++ b/src/models/tables/icons.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class icons extends db.Model { + get tableName() { + return 'icons' + } + + static fields(table) { + // Fields + table.bigInteger(`layout`) + .comment(`The layout associated with this icon.`) + .notNullable() + .unsigned() + .index(`icons_layout`) + + table.bigInteger(`icon`) + .comment(`The icon associated with this layout.`) + .notNullable() + .unsigned() + .index(`icons_icon`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`layout`, `icon`]) + } + + static foreignKeys(table) { + table.foreign(`icon`) + .references(`id`) + .inTable(`icon`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Icons = new icons() diff --git a/src/models/tables/keyword.js b/src/models/tables/keyword.js new file mode 100644 index 0000000..8d95faf --- /dev/null +++ b/src/models/tables/keyword.js @@ -0,0 +1,40 @@ +import db from '../../config/bookshelf.config' + +export default class keyword extends db.Model { + get tableName() { + return 'keyword' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the keyword.`) + .notNullable() + + table.text(`description`) + .comment(`The description of the keyword.`) + + table.bigInteger(`cards`) + .comment(`A list of cards that have this keyword.`) + .notNullable() + .unsigned() + .index(`keyword_cards`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`cards`) + .references(`keyword`) + .inTable(`keywordcards`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } +} + +export const Keyword = new keyword() diff --git a/src/models/tables/keywordCards.js b/src/models/tables/keywordCards.js new file mode 100644 index 0000000..61c0bd3 --- /dev/null +++ b/src/models/tables/keywordCards.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class keywordCards extends db.Model { + get tableName() { + return 'keywordcards' + } + + static fields(table) { + // Fields + table.bigInteger(`keyword`) + .comment(`The keyword associated with this card.`) + .notNullable() + .unsigned() + .index(`keywordCards_keyword`) + + table.bigInteger(`card`) + .comment(`The card associated with this keyword.`) + .notNullable() + .unsigned() + .index(`keywordCards_card`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`keyword`, `card`]) + } + + static foreignKeys(table) { + table.foreign(`card`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const KewordCards = new keywordCards() diff --git a/src/models/tables/keywords.js b/src/models/tables/keywords.js new file mode 100644 index 0000000..09a20a1 --- /dev/null +++ b/src/models/tables/keywords.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class keywords extends db.Model { + get tableName() { + return 'keywords' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this keyword.`) + .notNullable() + .unsigned() + .index(`keywords_card`) + + table.bigInteger(`keyword`) + .comment(`The keyword associated with this card.`) + .notNullable() + .unsigned() + .index(`keywords_keyword`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `keyword`]) + } + + static foreignKeys(table) { + table.foreign(`keyword`) + .references(`id`) + .inTable(`keyword`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Keywords = new keywords() diff --git a/src/models/tables/language.js b/src/models/tables/language.js new file mode 100644 index 0000000..b5265bf --- /dev/null +++ b/src/models/tables/language.js @@ -0,0 +1,37 @@ +import db from '../../config/bookshelf.config' + +export default class language extends db.Model { + get tableName() { + return 'language' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the language.`) + .notNullable() + + table.bigInteger(`code`) + .comment(`The language code associated with this language.`) + .notNullable() + .unsigned() + .index(`language_code`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`code`) + .references(`id`) + .inTable(`languagecode`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Language = new language() diff --git a/src/models/tables/languageCode.js b/src/models/tables/languageCode.js new file mode 100644 index 0000000..ca8f342 --- /dev/null +++ b/src/models/tables/languageCode.js @@ -0,0 +1,37 @@ +import db from '../../config/bookshelf.config' + +export default class languageCode extends db.Model { + get tableName() { + return 'languagecode' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`code`) + .comment(`The language code.`) + .notNullable() + + table.bigInteger(`language`) + .comment(`The language associated with the language code.`) + .notNullable() + .unsigned() + .index(`languageCode_language`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`language`) + .references(`id`) + .inTable(`language`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const LanguageCode = new languageCode() diff --git a/src/models/tables/layout.js b/src/models/tables/layout.js new file mode 100644 index 0000000..eedae61 --- /dev/null +++ b/src/models/tables/layout.js @@ -0,0 +1,42 @@ +import db from '../../config/bookshelf.config' + +export default class layout extends db.Model { + get tableName() { + return 'layout' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the layout.`) + .notNullable() + + table.bigInteger(`watermark`) + .comment(`Watermark icon used in this layout.`) + .unsigned() + .index(`layout_watermark`) + + table.bigInteger(`icons`) + .comment(`List of icons used in this layout.`) + .notNullable() + .unsigned() + .index(`layout_icons`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`icons`) + .references(`layout`) + .inTable(`icons`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } +} + +export const Layout = new layout() diff --git a/src/models/tables/legalities.js b/src/models/tables/legalities.js new file mode 100644 index 0000000..ff6e37e --- /dev/null +++ b/src/models/tables/legalities.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class legalities extends db.Model { + get tableName() { + return 'legalities' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this legality.`) + .notNullable() + .unsigned() + .index(`legalities_card`) + + table.bigInteger(`legality`) + .comment(`The legality associated with this card.`) + .notNullable() + .unsigned() + .index(`legalities_legality`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `legality`]) + } + + static foreignKeys(table) { + table.foreign(`legality`) + .references(`id`) + .inTable(`legality`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Legalities = new legalities() diff --git a/src/models/tables/legality.js b/src/models/tables/legality.js new file mode 100644 index 0000000..ae32776 --- /dev/null +++ b/src/models/tables/legality.js @@ -0,0 +1,54 @@ +import db from '../../config/bookshelf.config' + +export default class legality extends db.Model { + get tableName() { + return 'legality' + } + + static fields(table) { + // Indexes + table.bigIncrements(`id`) + .notNullable() + .primary() + + // Fields + table.bigInteger(`format`) + .comment(`The format associated with this legality.`) + .notNullable() + .unsigned() + .index(`legality_format`) + + table.boolean(`legal`) + .comment(`True if the card is legal in the associated format.`) + .notNullable() + + table.boolean(`restricted`) + .comment(`True if the card is restricted in the associated format.`) + .notNullable() + + table.bigInteger(`cards`) + .comment(`List of cards that have this legality ruling.`) + .notNullable() + .unsigned() + .index(`legality_cards`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`format`) + .references(`id`) + .inTable(`format`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`cards`) + .references(`legality`) + .inTable(`legalitycards`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } +} + +export const Legality = new legality() diff --git a/src/models/tables/legalityCards.js b/src/models/tables/legalityCards.js new file mode 100644 index 0000000..81214e8 --- /dev/null +++ b/src/models/tables/legalityCards.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class legalityCards extends db.Model { + get tableName() { + return 'legalitycards' + } + + static fields(table) { + // Fields + table.bigInteger(`legality`) + .comment(`The legality associated with this card.`) + .notNullable() + .unsigned() + .index(`legalityCards_legality`) + + table.bigInteger(`card`) + .comment(`The card associated with this legality.`) + .notNullable() + .unsigned() + .index(`legalityCards_card`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`legality`, `card`]) + } + + static foreignKeys(table) { + table.foreign(`card`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const LegalityCards = new legalityCards() diff --git a/src/models/tables/name.js b/src/models/tables/name.js new file mode 100644 index 0000000..7784dd8 --- /dev/null +++ b/src/models/tables/name.js @@ -0,0 +1,55 @@ +import db from '../../config/bookshelf.config' + +import Card from './card' + +export default class name extends db.Model { + get tableName() { + return 'name' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The localized name of the card.`) + .notNullable() + + table.bigInteger(`language`) + .comment(`The language code of the language the name is localized in.`) + .notNullable() + .unsigned() + .index(`name_language`) + + table.bigInteger(`cards`) + .comment(`A list of cards that have this name.`) + .notNullable() + .unsigned() + .index(`name_cards`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`language`) + .references(`id`) + .inTable(`languagecode`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`cards`) + .references(`name`) + .inTable(`namecards`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } + + cardID() { + return this.belongsTo(Card, "card") + } +} + +export const Name = new name() diff --git a/src/models/tables/nameCards.js b/src/models/tables/nameCards.js new file mode 100644 index 0000000..f896312 --- /dev/null +++ b/src/models/tables/nameCards.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class nameCards extends db.Model { + get tableName() { + return 'namecards' + } + + static fields(table) { + // Fields + table.bigInteger(`name`) + .comment(`The name associated with this card.`) + .notNullable() + .unsigned() + .index(`nameCards_name`) + + table.bigInteger(`card`) + .comment(`The card associated with this name.`) + .notNullable() + .unsigned() + .index(`nameCards_card`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`name`, `card`]) + } + + static foreignKeys(table) { + table.foreign(`card`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const NameCards = new nameCards() diff --git a/src/models/tables/names.js b/src/models/tables/names.js new file mode 100644 index 0000000..85b3959 --- /dev/null +++ b/src/models/tables/names.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class names extends db.Model { + get tableName() { + return 'names' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this name.`) + .notNullable() + .unsigned() + .index(`names_card`) + + table.bigInteger(`name`) + .comment(`The name associated with this card.`) + .notNullable() + .unsigned() + .index(`names_name`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `name`]) + } + + static foreignKeys(table) { + table.foreign(`name`) + .references(`id`) + .inTable(`name`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Names = new names() diff --git a/src/models/tables/printings.js b/src/models/tables/printings.js new file mode 100644 index 0000000..957cd5e --- /dev/null +++ b/src/models/tables/printings.js @@ -0,0 +1,49 @@ +import db from '../../config/bookshelf.config' + +import Card from './card' +import Set from './set' + +export default class printings extends db.Model { + get tableName() { + return 'printings' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this printing.`) + .notNullable() + .unsigned() + .index(`printings_card`) + + table.bigInteger(`set`) + .comment(`The set associated with this printing.`) + .notNullable() + .unsigned() + .index(`printings_set`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `set`]) + } + + static foreignKeys(table) { + table.foreign(`set`) + .references(`id`) + .inTable(`set`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } + + cardID() { + return this.belongsTo(Card, "card") + } + + set() { + return this.belongsTo(Set, "set") + } +} + +export const Printings = new printings() diff --git a/src/models/tables/rarity.js b/src/models/tables/rarity.js new file mode 100644 index 0000000..89c174d --- /dev/null +++ b/src/models/tables/rarity.js @@ -0,0 +1,31 @@ +import db from '../../config/bookshelf.config' + +export default class rarity extends db.Model { + get tableName() { + return 'rarity' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the rarity.`) + .notNullable() + + table.string(`class`) + .comment(`CSS class name used to display the rarity.`) + .notNullable() + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + + } +} + +export const Rarity = new rarity() diff --git a/src/models/tables/ruling.js b/src/models/tables/ruling.js new file mode 100644 index 0000000..53772df --- /dev/null +++ b/src/models/tables/ruling.js @@ -0,0 +1,54 @@ +import db from '../../config/bookshelf.config' + +export default class ruling extends db.Model { + get tableName() { + return 'ruling' + } + + static fields(table) { + // Indexes + table.bigIncrements(`id`) + .notNullable() + .primary() + + // Fields + table.text(`text`) + .comment(`The localized text of the ruling.`) + .notNullable() + + table.date(`date`) + .comment(`The date the ruling was issued.`) + .notNullable() + + table.bigInteger(`language`) + .comment(`The language code of this ruling.`) + .notNullable() + .unsigned() + .index(`ruling_language`) + + table.bigInteger(`cards`) + .comment(`List of cards that have this ruling.`) + .notNullable() + .unsigned() + .index(`ruling_cards`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`language`) + .references(`id`) + .inTable(`languagecode`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`cards`) + .references(`ruling`) + .inTable(`rulingcards`) + .onDelete(`CASCADE`) + .onUpdate(`NO ACTION`) + } +} + +export const Ruling = new ruling() diff --git a/src/models/tables/rulingCards.js b/src/models/tables/rulingCards.js new file mode 100644 index 0000000..0b94518 --- /dev/null +++ b/src/models/tables/rulingCards.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class rulingCards extends db.Model { + get tableName() { + return 'rulingcards' + } + + static fields(table) { + // Fields + table.bigInteger(`ruling`) + .comment(`The ruling associated with this card.`) + .notNullable() + .unsigned() + .index(`rulingCards_ruling`) + + table.bigInteger(`card`) + .comment(`The card associated with this ruling.`) + .notNullable() + .unsigned() + .index(`rulingCards_card`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`ruling`, `card`]) + } + + static foreignKeys(table) { + table.foreign(`card`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const RulingCards = new rulingCards() diff --git a/src/models/tables/rulings.js b/src/models/tables/rulings.js new file mode 100644 index 0000000..e36cce9 --- /dev/null +++ b/src/models/tables/rulings.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class rulings extends db.Model { + get tableName() { + return 'rulings' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this ruling.`) + .notNullable() + .unsigned() + .index(`rulings_card`) + + table.bigInteger(`ruling`) + .comment(`The ruling associated with this card.`) + .notNullable() + .unsigned() + .index(`rulings_ruling`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `ruling`]) + } + + static foreignKeys(table) { + table.foreign(`ruling`) + .references(`id`) + .inTable(`ruling`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Rulings = new rulings() diff --git a/src/models/tables/set.js b/src/models/tables/set.js new file mode 100644 index 0000000..da6d9c8 --- /dev/null +++ b/src/models/tables/set.js @@ -0,0 +1,73 @@ +import db from '../../config/bookshelf.config' + +export default class set extends db.Model { + get tableName() { + return 'set' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the set.`) + .notNullable() + + table.string(`code`) + .comment(`The set code.`) + .notNullable() + + table.bigInteger(`block`) + .comment(`The block the set belongs to.`) + .notNullable() + .unsigned() + .index(`set_block`) + + table.bigInteger(`type`) + .comment(`The type of the set.`) + .notNullable() + .unsigned() + .index(`set_type`) + + table.bigInteger(`icon`) + .comment(`The icon associated with the set.`) + .notNullable() + .unsigned() + .index(`set_icon`) + + table.string(`border`) + .comment(`The border color of the set.`) + .notNullable() + + table.date(`releasedate`) + .comment(`The date on which the set was released.`) + .notNullable() + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + table.foreign(`block`) + .references(`id`) + .inTable(`block`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`type`) + .references(`id`) + .inTable(`settype`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + + table.foreign(`icon`) + .references(`id`) + .inTable(`icon`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Set = new set() diff --git a/src/models/tables/setType.js b/src/models/tables/setType.js new file mode 100644 index 0000000..d1b694a --- /dev/null +++ b/src/models/tables/setType.js @@ -0,0 +1,30 @@ +import db from '../../config/bookshelf.config' + +export default class setType extends db.Model { + get tableName() { + return 'setType' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the set type.`) + .notNullable() + + table.text(`description`) + .comment(`The description of the set type.`) + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + + } +} + +export const SetType = new setType() diff --git a/src/models/tables/sides.js b/src/models/tables/sides.js new file mode 100644 index 0000000..f90afb2 --- /dev/null +++ b/src/models/tables/sides.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class sides extends db.Model { + get tableName() { + return 'sides' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this side.`) + .notNullable() + .unsigned() + .index(`sides_card`) + + table.bigInteger(`side`) + .comment(`The side associated with this card.`) + .notNullable() + .unsigned() + .index(`sides_side`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `side`]) + } + + static foreignKeys(table) { + table.foreign(`side`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Sides = new sides() diff --git a/src/models/tables/subtype.js b/src/models/tables/subtype.js new file mode 100644 index 0000000..f128780 --- /dev/null +++ b/src/models/tables/subtype.js @@ -0,0 +1,27 @@ +import db from '../../config/bookshelf.config' + +export default class subtype extends db.Model { + get tableName() { + return 'subtype' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the subtype.`) + .notNullable() + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + + } +} + +export const Subtype = new subtype() diff --git a/src/models/tables/subtypes.js b/src/models/tables/subtypes.js new file mode 100644 index 0000000..2094d33 --- /dev/null +++ b/src/models/tables/subtypes.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class subtypes extends db.Model { + get tableName() { + return 'subtypes' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this subtype.`) + .notNullable() + .unsigned() + .index(`subtypes_card`) + + table.bigInteger(`subtype`) + .comment(`The subtype associated with this card.`) + .notNullable() + .unsigned() + .index(`subtypes_subtype`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `subtype`]) + } + + static foreignKeys(table) { + table.foreign(`subtype`) + .references(`id`) + .inTable(`subtype`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Subtypes = new subtypes() diff --git a/src/models/tables/supertype.js b/src/models/tables/supertype.js new file mode 100644 index 0000000..9d079ca --- /dev/null +++ b/src/models/tables/supertype.js @@ -0,0 +1,27 @@ +import db from '../../config/bookshelf.config' + +export default class supertype extends db.Model { + get tableName() { + return 'supertype' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the supertype.`) + .notNullable() + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + + } +} + +export const Supertype = new supertype() diff --git a/src/models/tables/supertypes.js b/src/models/tables/supertypes.js new file mode 100644 index 0000000..bb1d87a --- /dev/null +++ b/src/models/tables/supertypes.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class supertypes extends db.Model { + get tableName() { + return 'supertypes' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this supertype.`) + .notNullable() + .unsigned() + .index(`supertypes_card`) + + table.bigInteger(`supertype`) + .comment(`The supertype associated with this card.`) + .notNullable() + .unsigned() + .index(`supertypes_supertype`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `supertype`]) + } + + static foreignKeys(table) { + table.foreign(`supertype`) + .references(`id`) + .inTable(`supertype`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Supertypes = new supertypes() diff --git a/src/models/tables/type.js b/src/models/tables/type.js new file mode 100644 index 0000000..e949940 --- /dev/null +++ b/src/models/tables/type.js @@ -0,0 +1,27 @@ +import db from '../../config/bookshelf.config' + +export default class type extends db.Model { + get tableName() { + return 'type' + } + + static fields(table) { + // Fields + table.bigIncrements(`id`) + .notNullable() + .primary() + + table.string(`name`) + .comment(`The name of the type.`) + .notNullable() + + // Timestamps + table.timestamps() + } + + static foreignKeys(table) { + + } +} + +export const Type = new type() diff --git a/src/models/tables/types.js b/src/models/tables/types.js new file mode 100644 index 0000000..0835b2e --- /dev/null +++ b/src/models/tables/types.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class types extends db.Model { + get tableName() { + return 'types' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this type.`) + .notNullable() + .unsigned() + .index(`types_card`) + + table.bigInteger(`type`) + .comment(`The type associated with this card.`) + .notNullable() + .unsigned() + .index(`types_type`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `type`]) + } + + static foreignKeys(table) { + table.foreign(`type`) + .references(`id`) + .inTable(`type`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Types = new types() diff --git a/src/models/tables/variations.js b/src/models/tables/variations.js new file mode 100644 index 0000000..317eda6 --- /dev/null +++ b/src/models/tables/variations.js @@ -0,0 +1,38 @@ +import db from '../../config/bookshelf.config' + +export default class variations extends db.Model { + get tableName() { + return 'variations' + } + + static fields(table) { + // Fields + table.bigInteger(`card`) + .comment(`The card associated with this variation.`) + .notNullable() + .unsigned() + .index(`variations_card`) + + table.bigInteger(`variation`) + .comment(`The variation associated with this card.`) + .notNullable() + .unsigned() + .index(`variations_variation`) + + // Timestamps + table.timestamps() + + // Keys + table.primary([`card`, `variation`]) + } + + static foreignKeys(table) { + table.foreign(`variation`) + .references(`id`) + .inTable(`card`) + .onDelete(`NO ACTION`) + .onUpdate(`NO ACTION`) + } +} + +export const Variations = new variations() diff --git a/src/routes/index.js b/src/routes/index.js index 491acc8..ec8cd01 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,10 +1,8 @@ -// http://billpatrianakos.me/blog/2015/12/01/organizing-express-routes/ import path from 'path' import glob from 'glob' // https://github.com/isaacs/node-glob -import { Router } from 'express' export default (router) => { - let api = Router() + glob.sync(`${__dirname}/**/!(*.spec).js`) .forEach( file => { if(file !== `index.js`) { @@ -12,8 +10,8 @@ export default (router) => { let basename = filename.split('.')[0] let resource = require(file).default console.log(`✓ Loaded Resource: /${basename}`) - api.use(`/${basename}`, resource) + } }) - return api + } diff --git a/src/types/index.js b/src/types/index.js index 6ed4992..5483ec8 100644 --- a/src/types/index.js +++ b/src/types/index.js @@ -18,8 +18,8 @@ export function definitions() { let definitions = {} loadTypes().forEach((type) => { - definitions[type.name] = type.Definition - console.log(`✓ Loaded Type Definition: ${type.name}`) + definitions[type.Definition.name] = type.Definition + console.log(`✓ Loaded Type Definition: ${type.Definition.name}`) }) return definitions