From e7e2f3f85cd8b9d9bbe960d2e1c1ee10ebdda60a Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sun, 19 Apr 2020 00:17:30 -0400 Subject: [PATCH 01/26] Added the eslint and pug-lint rules to master --- .eslintrc.js | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index e69de29..ef46313 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -0,0 +1,62 @@ +module.exports = { + "env": { + "es6": true, + "node": true, + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "rules": { + "array-bracket-spacing": ["error", "never"], + "array-element-newline": ["error", "consistent"], + "arrow-spacing": ["error", { "before": true, "after": true }], + "block-spacing": "error", + "camelcase": 0, + "comma-spacing": ["error", { "before": false, "after": true }], + "computed-property-spacing": ["error", "never"], + "dot-location": ["error", "property"], + "eol-last": ["error", "always"], + "func-call-spacing": ["error", "never"], + "function-paren-newline": ["error", "never"], + "implicit-arrow-linebreak": ["error", "beside"], + "indent": ["error", 2, { "SwitchCase": 1 }], + "key-spacing": ["error", { "afterColon": true }], + "keyword-spacing": ["error", { "before": true, "after": true }], + "linebreak-style": ["error", "unix"], + "max-len": ["error", { "code": 120, "ignoreComments": true, "ignoreTrailingComments": true }], + "no-console": "error", + "no-case-declarations": 0, + "no-mixed-spaces-and-tabs": "error", + "no-multi-spaces": "error", + "no-spaced-func": "error", + "no-trailing-spaces": ["error", { "ignoreComments": true }], + "no-whitespace-before-property": "error", + "nonblock-statement-body-position": ["error", "beside"], + "object-curly-newline": ["error", { "multiline": true, "minProperties": 5, "consistent": true }], + "object-curly-spacing": ["error", "always", { "arraysInObjects": true, "objectsInObjects": true }], + "object-property-newline": ["error", { "allowAllPropertiesOnSameLine": true }], + "one-var": ["error", "never"], + "operator-linebreak": ["error", "after", { "overrides": { "?": "before", ":": "before" } }], + "padded-blocks": ["error", "never"], + "padding-line-between-statements": [ + "error", + { blankLine: "always", prev: "*", next: "return" }, + { blankLine: "always", prev: ["const", "let", "var"], next: "*" }, + { blankLine: "any", prev: ["const", "let", "var"], next: ["const", "let", "var"] }, + ], + "quotes": ["error", "single"], + "rest-spread-spacing": ["error", "never"], + "space-before-blocks": "error", + "space-before-function-paren": ["error", { "anonymous": "always", "named": "never", "asyncArrow": "always" }], + "space-in-parens": ["error", "never"], + "space-infix-ops": "error", + "space-unary-ops": "error", + "spaced-comment": ["error", "always"], + "semi": ["error", "never"], + "semi-spacing": ["error", { "before": false, "after": true }], + "switch-colon-spacing": "error", + "template-tag-spacing": ["error", "always"], + } +}; \ No newline at end of file From c01f9b782c6de30728499e8b49ece8643754fc71 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sun, 19 Apr 2020 00:19:23 -0400 Subject: [PATCH 02/26] Actually added the pug-lint rules. --- .pug-lintrc.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .pug-lintrc.js diff --git a/.pug-lintrc.js b/.pug-lintrc.js new file mode 100644 index 0000000..5ae7099 --- /dev/null +++ b/.pug-lintrc.js @@ -0,0 +1,24 @@ +module.exports = { + disallowAttributeConcatenation: true, + disallowBlockExpansion: true, + disallowClassLiterals: true, + disallowDuplicateAttributes: true, + disallowHtmlText: true, + disallowIdLiterals: true, + disallowLegacyMixinCall: true, + disallowMultipleLineBreaks: true, + disallowSpacesInsideAttributeBrackets: true, + disallowStringConcatenation: 'aggressive', + disallowTagInterpolation: true, + disallowTrailingSpaces: true, + requireLineFeedAtFileEnd: true, + requireLowerCaseAttributes: true, + requireLowerCaseTags: true, + requireSpaceAfterCodeOperator: true, + requireStrictEqualityOperators: true, + validateAttributeQuoteMarks: '"', + validateExtensions: true, + validateIndentation: 2, + validateLineBreaks: 'LF', + validateTemplateString: true +} \ No newline at end of file From 606354311d093f4040aa616dedab654dce7daddb Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sun, 19 Apr 2020 00:22:26 -0400 Subject: [PATCH 03/26] Initial commit for branch part-one-answer. --- index.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..e69de29 From ed460ce2af0841a608a9dca6c4d29bb18d1ca992 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Thu, 23 Apr 2020 11:31:55 -0400 Subject: [PATCH 04/26] Set up some of the documentatin site and some of the styling. --- controllers/pug-index-controller.js | 27 +++++++++++++ index.js | 18 +++++++++ package.json | 2 +- public/css/styles.css | 39 ++++++++++++++++++ views/index.pug | 61 +++++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 controllers/pug-index-controller.js create mode 100644 public/css/styles.css create mode 100644 views/index.pug diff --git a/controllers/pug-index-controller.js b/controllers/pug-index-controller.js new file mode 100644 index 0000000..2c147af --- /dev/null +++ b/controllers/pug-index-controller.js @@ -0,0 +1,27 @@ +function activateEndpoint(id) { + var endPointId = id + '-end-point' + // eslint-disable-next-line no-undef + var endPoints = document.getElementsByClassName('endpoint') + + for (var i = 0; i < endPoints.length; i++) { + if (endPoints[i].id === endPointId) { + endPoints[i].classList.add('selected') + } else { + endPoints[i].classList.remove('selected') + } + } + + var docId = id + '-doc' + // eslint-disable-next-line no-undef + var docs = document.getElementsByClassName('doc') + + for (var j = 0; j < docs.length; j++) { + if (docs[j].id === docId) { + docs[j].classList.remove('hidden') + } else { + docs[j].classList.add('hidden') + } + } +} + +module.exports = activateEndpoint() diff --git a/index.js b/index.js index e69de29..ac6034b 100644 --- a/index.js +++ b/index.js @@ -0,0 +1,18 @@ +const express = require('express') + +const app = express() + +app.set('view engine', 'pug') +app.use(express.static('public')) + +app.get('/', (request, response) => { + return response.status(200).render('index') +}) + +app.all('*', (request, response) => { + return response.status(404).send('Looks like you found nothing in the pokedex.') +}) + +app.listen(1337, () => { + console.log('Listening on 1337...')// eslint-disable-line no-console +}) diff --git a/package.json b/package.json index 3e4bcde..c507d9c 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dev": "./node_modules/.bin/nodemon index.js", "lint": "run lint:pug-lint && run lint:eslint", "lint:eslint": "./node_modules/.bin/eslint --format codeframe .", - "lint:puglint": "./node_modules/.bin/pug-lint ." + "puglint": "./node_modules/.bin/pug-lint ." }, "repository": { "type": "git", diff --git a/public/css/styles.css b/public/css/styles.css new file mode 100644 index 0000000..846ff97 --- /dev/null +++ b/public/css/styles.css @@ -0,0 +1,39 @@ +h2{ + text-align: center; +} + +h3{ + margin-bottom: 5px; +} + +.get-generation, .get-pokemon{ + display: none; +} + +.get-all, .get-generation, .get-pokemon{ + position: absolute; +} + +.main-container{ + display: flex; + justify-content: center; + flex-direction: row; + position: relative; +} + +.left-container{ + align-self: center; + flex-direction: column; + margin: 0px 20px; +} + +.right-container{ + align-self: center; + flex-direction: row; + margin: 0px 20px; + position: relative; +} + +.tabs{ + margin-top: 10px; +} diff --git a/views/index.pug b/views/index.pug new file mode 100644 index 0000000..8df3498 --- /dev/null +++ b/views/index.pug @@ -0,0 +1,61 @@ +html + head + title Pokemon API + link(rel="stylesheet" href="/css/styles.css") + script(src="../controllers/pug-index-controller.js") + body + h2 Welcome to the Pokemon API + div(class="main-container") + div(class="left-container") + div(class="tabs" id="get") + span GET + span /pokemon + div(class="tabs" id="get") + span GET + span /generation/{genId} + + div(class="tabs" id="get") + span GET + span /pokemon/{pokemon name} + div /pokemon/{pokemon id} + + div(class="tabs" id="push") + span PUSH + span /pokemon + + div(class="right-container") + div(class="method-container") + h3 Method + div GET + h3 Route + div http://localhost:1337/pokemon + div(class="get-all") + h3 Headers + div None needed + div + h3 Decription + div Returns a list all of the pokemon in the databse. + + div(class="get-generation") + h3 Method + div GET + h3 Route + div http://localhost:1337/pokemon/generations/{id} + h3 Headers + div None needed + div + h3 Decription + div Returns a list of all pokemon associated with the generation of the numerical {id}. + + div(class="get-pokemon") + h3 Method + div GET + h3 Route + div http://localhost:1337/pokemon/pokemon/{id} + div(style="margin-left:110px") OR + div http://localhost:1337/pokemon/pokemon/{name} + h3 Headers + div None needed + div + h3 Decription + div Returns the pokemon associated with the numerical {id]} (pokedex number) or the {name} of the pokemon. From 860fc4c6cfb598c132b2959b6aaea8f779142f01 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Tue, 28 Apr 2020 00:05:26 -0400 Subject: [PATCH 05/26] Added some more styling and added the functionality to show and hide the correct method information. --- controllers/pug-index-controller.js | 27 ------- public/css/styles.css | 58 ++++++++++++--- public/pug-index-controller.js | 22 ++++++ views/index.pug | 110 +++++++++++++++++----------- 4 files changed, 136 insertions(+), 81 deletions(-) delete mode 100644 controllers/pug-index-controller.js create mode 100644 public/pug-index-controller.js diff --git a/controllers/pug-index-controller.js b/controllers/pug-index-controller.js deleted file mode 100644 index 2c147af..0000000 --- a/controllers/pug-index-controller.js +++ /dev/null @@ -1,27 +0,0 @@ -function activateEndpoint(id) { - var endPointId = id + '-end-point' - // eslint-disable-next-line no-undef - var endPoints = document.getElementsByClassName('endpoint') - - for (var i = 0; i < endPoints.length; i++) { - if (endPoints[i].id === endPointId) { - endPoints[i].classList.add('selected') - } else { - endPoints[i].classList.remove('selected') - } - } - - var docId = id + '-doc' - // eslint-disable-next-line no-undef - var docs = document.getElementsByClassName('doc') - - for (var j = 0; j < docs.length; j++) { - if (docs[j].id === docId) { - docs[j].classList.remove('hidden') - } else { - docs[j].classList.add('hidden') - } - } -} - -module.exports = activateEndpoint() diff --git a/public/css/styles.css b/public/css/styles.css index 846ff97..91cf69e 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -6,34 +6,70 @@ h3{ margin-bottom: 5px; } -.get-generation, .get-pokemon{ +.delete{ + color:red; + font-weight: bold; +} + +.hidden{ display: none; } -.get-all, .get-generation, .get-pokemon{ +.highlighted{ + width: 300px; + height: 25px; + position: relative; + background: lightgray; + padding-top: 5px; +} + +.highlighted:after { + content: ""; position: absolute; + right: -15px; + bottom: 0; + width: 0; + height: 0; + border-left: 15px solid lightgray; + border-top: 15px solid transparent; + border-bottom: 15px solid transparent; +} + +.get-all, .get-generation, .get-pokemon{ + padding: 0px; +} + +.get{ + color: green; + font-weight: bold; +} + +.left-container{ + flex-direction: row; + margin: 0px 20px; + padding-top: 30px; + width: 320px; } .main-container{ display: flex; - justify-content: center; flex-direction: row; - position: relative; + justify-content: center; } -.left-container{ - align-self: center; - flex-direction: column; - margin: 0px 20px; +.push{ + color: darkorange; + font-weight: bold; } .right-container{ - align-self: center; - flex-direction: row; margin: 0px 20px; position: relative; + width: 320px; } .tabs{ - margin-top: 10px; + cursor: pointer; + font-size: 20px; + margin: 20px; } diff --git a/public/pug-index-controller.js b/public/pug-index-controller.js new file mode 100644 index 0000000..e220b6e --- /dev/null +++ b/public/pug-index-controller.js @@ -0,0 +1,22 @@ +/* eslint-disable no-undef */ +// eslint-disable-next-line no-unused-vars +function updateSelected(id) { + const tabs = document.getElementsByClassName('tabs') + const methods = document.getElementsByClassName('method') + + for (let i = 0; i < tabs.length; i++) { + if (tabs[i].id === id) { + tabs[i].classList.add('highlighted') + } else { + tabs[i].classList.remove('highlighted') + } + } + + for (let i = 0; i < methods.length; i++) { + if (methods[i].id === id) { + methods[i].classList.remove('hidden') + } else { + methods[i].classList.add('hidden') + } + } +} diff --git a/views/index.pug b/views/index.pug index 8df3498..4f0d8b9 100644 --- a/views/index.pug +++ b/views/index.pug @@ -2,60 +2,84 @@ html head title Pokemon API link(rel="stylesheet" href="/css/styles.css") - script(src="../controllers/pug-index-controller.js") + script(src="/pug-index-controller.js") body h2 Welcome to the Pokemon API div(class="main-container") div(class="left-container") - div(class="tabs" id="get") - span GET + div(class="tabs highlighted" id="getAll" onclick="updateSelected('getAll')") + span(class="get") GET span /pokemon - div(class="tabs" id="get") - span GET + div(class="tabs" id="getGeneration" onclick="updateSelected('getGeneration')") + span(class="get") GET span /generation/{genId} - div(class="tabs" id="get") - span GET - span /pokemon/{pokemon name} - div /pokemon/{pokemon id} + div(class="tabs" id="getPokemonById" onclick="updateSelected('getPokemonById')") + span(class="get") GET + span /pokemon/{pokemonId} - div(class="tabs" id="push") - span PUSH + div(class="tabs" id="pushPokemon" onclick="updateSelected('pushPokemon')") + span(class="push") PUSH span /pokemon + div(class="tabs" id="deletePokemonById" onclick="updateSelected('deletePokemonById')") + span(class="delete") DELETE + span /pokemon/{pokemonId} + div(class="right-container") - div(class="method-container") + div(class="method" id="getAll") + h3 Method + div(class="get") GET + h3 Route + div http://localhost:1337/pokemon + h3 Headers + div None needed + div + h3 Decription + div Returns a list all of the pokemon in the databse. + + div(class="method hidden" id="getGeneration") + h3 Method + div(class="get") GET + h3 Route + div http://localhost:1337/pokemon/generations/{genId} + h3 Headers + div None needed + div + h3 Decription + div Returns the generation list of all pokemon associated with {genId}. + + div(class="method hidden" id="getPokemonById") + h3 Method + div(class="get") GET + h3 Route + div http://localhost:1337/pokemon/pokemon/{pokemonId} + h3 Headers + div None needed + div + h3 Decription + div Returns the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). + + div(class="method hidden" id="pushPokemon") h3 Method - div GET + div(class="push") PUSH h3 Route div http://localhost:1337/pokemon - div(class="get-all") - h3 Headers - div None needed - div - h3 Decription - div Returns a list all of the pokemon in the databse. - - div(class="get-generation") - h3 Method - div GET - h3 Route - div http://localhost:1337/pokemon/generations/{id} - h3 Headers - div None needed - div - h3 Decription - div Returns a list of all pokemon associated with the generation of the numerical {id}. - - div(class="get-pokemon") - h3 Method - div GET - h3 Route - div http://localhost:1337/pokemon/pokemon/{id} - div(style="margin-left:110px") OR - div http://localhost:1337/pokemon/pokemon/{name} - h3 Headers - div None needed - div - h3 Decription - div Returns the pokemon associated with the numerical {id]} (pokedex number) or the {name} of the pokemon. + h3 Headers + div Content-Type: application/json + div + h3 Body + div { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']"} + h3 Decription + div Returns a list all of the pokemon in the databse. + + div(class="method hidden" id="deletePokemonById") + h3 Method + div(class="delete") DELETE + h3 Route + div http://localhost:1337/pokemon/pokemon/{pokemonId} + h3 Headers + div None needed + div + h3 Decription + div Deletes the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). From d9e11ec7d57012e104787a0245f22a07a66d4a16 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Wed, 29 Apr 2020 15:19:51 -0400 Subject: [PATCH 06/26] Split the index.pug into partials, added a javascript folder in public and moved and renamed the indexPugInteractions.js file to the new folder, and deleted a dependency that was accidentally installed. --- package.json | 7 +- public/css/styles.css | 9 ++- public/javascripts/indexPugInteraction.js | 18 +++++ public/pug-index-controller.js | 22 ------- views/index.pug | 80 ++--------------------- views/partials/leftSideDocumentation.pug | 19 ++++++ views/partials/rightSideDocumentaion.pug | 52 +++++++++++++++ 7 files changed, 100 insertions(+), 107 deletions(-) create mode 100644 public/javascripts/indexPugInteraction.js delete mode 100644 public/pug-index-controller.js create mode 100644 views/partials/leftSideDocumentation.pug create mode 100644 views/partials/rightSideDocumentaion.pug diff --git a/package.json b/package.json index c507d9c..d2850fa 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "main": ".eslintrc.js", "scripts": { "dev": "./node_modules/.bin/nodemon index.js", - "lint": "run lint:pug-lint && run lint:eslint", + "lint": "run lint:puglint && run lint:eslint", "lint:eslint": "./node_modules/.bin/eslint --format codeframe .", - "puglint": "./node_modules/.bin/pug-lint ." + "lint:pug": "./node_modules/.bin/pug-lint ." }, "repository": { "type": "git", @@ -26,7 +26,6 @@ }, "dependencies": { "express": "^4.17.1", - "pug": "^2.0.4", - "s": "^1.0.0" + "pug": "^2.0.4" } } \ No newline at end of file diff --git a/public/css/styles.css b/public/css/styles.css index 91cf69e..1436635 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -17,10 +17,10 @@ h3{ .highlighted{ width: 300px; - height: 25px; + height: 30px; position: relative; background: lightgray; - padding-top: 5px; + } .highlighted:after { @@ -45,7 +45,6 @@ h3{ } .left-container{ - flex-direction: row; margin: 0px 20px; padding-top: 30px; width: 320px; @@ -57,7 +56,7 @@ h3{ justify-content: center; } -.push{ +.post{ color: darkorange; font-weight: bold; } @@ -71,5 +70,5 @@ h3{ .tabs{ cursor: pointer; font-size: 20px; - margin: 20px; + margin: 30px; } diff --git a/public/javascripts/indexPugInteraction.js b/public/javascripts/indexPugInteraction.js new file mode 100644 index 0000000..d3ad3af --- /dev/null +++ b/public/javascripts/indexPugInteraction.js @@ -0,0 +1,18 @@ +/* eslint-disable no-undef */ +// eslint-disable-next-line no-unused-vars +const updateSelected = (id) => { + const tabs = document.getElementsByClassName('tabs') + const methods = document.getElementsByClassName('method') + + for (let i = 0; i < tabs.length; i++) { + tabs[i].id === id + ? tabs[i].classList.add('highlighted') + : tabs[i].classList.remove('highlighted') + } + + for (let i = 0; i < methods.length; i++) { + methods[i].id === id + ? methods[i].classList.remove('hidden') + : methods[i].classList.add('hidden') + } +} diff --git a/public/pug-index-controller.js b/public/pug-index-controller.js deleted file mode 100644 index e220b6e..0000000 --- a/public/pug-index-controller.js +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable no-undef */ -// eslint-disable-next-line no-unused-vars -function updateSelected(id) { - const tabs = document.getElementsByClassName('tabs') - const methods = document.getElementsByClassName('method') - - for (let i = 0; i < tabs.length; i++) { - if (tabs[i].id === id) { - tabs[i].classList.add('highlighted') - } else { - tabs[i].classList.remove('highlighted') - } - } - - for (let i = 0; i < methods.length; i++) { - if (methods[i].id === id) { - methods[i].classList.remove('hidden') - } else { - methods[i].classList.add('hidden') - } - } -} diff --git a/views/index.pug b/views/index.pug index 4f0d8b9..972ff05 100644 --- a/views/index.pug +++ b/views/index.pug @@ -2,84 +2,12 @@ html head title Pokemon API link(rel="stylesheet" href="/css/styles.css") - script(src="/pug-index-controller.js") + script(src="/javascripts/indexPugInteraction.js") + body h2 Welcome to the Pokemon API div(class="main-container") - div(class="left-container") - div(class="tabs highlighted" id="getAll" onclick="updateSelected('getAll')") - span(class="get") GET - span /pokemon - div(class="tabs" id="getGeneration" onclick="updateSelected('getGeneration')") - span(class="get") GET - span /generation/{genId} - - div(class="tabs" id="getPokemonById" onclick="updateSelected('getPokemonById')") - span(class="get") GET - span /pokemon/{pokemonId} - - div(class="tabs" id="pushPokemon" onclick="updateSelected('pushPokemon')") - span(class="push") PUSH - span /pokemon - - div(class="tabs" id="deletePokemonById" onclick="updateSelected('deletePokemonById')") - span(class="delete") DELETE - span /pokemon/{pokemonId} - - div(class="right-container") - div(class="method" id="getAll") - h3 Method - div(class="get") GET - h3 Route - div http://localhost:1337/pokemon - h3 Headers - div None needed - div - h3 Decription - div Returns a list all of the pokemon in the databse. - - div(class="method hidden" id="getGeneration") - h3 Method - div(class="get") GET - h3 Route - div http://localhost:1337/pokemon/generations/{genId} - h3 Headers - div None needed - div - h3 Decription - div Returns the generation list of all pokemon associated with {genId}. - - div(class="method hidden" id="getPokemonById") - h3 Method - div(class="get") GET - h3 Route - div http://localhost:1337/pokemon/pokemon/{pokemonId} - h3 Headers - div None needed - div - h3 Decription - div Returns the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). - div(class="method hidden" id="pushPokemon") - h3 Method - div(class="push") PUSH - h3 Route - div http://localhost:1337/pokemon - h3 Headers - div Content-Type: application/json - div - h3 Body - div { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']"} - h3 Decription - div Returns a list all of the pokemon in the databse. + include partials/leftSideDocumentation.pug - div(class="method hidden" id="deletePokemonById") - h3 Method - div(class="delete") DELETE - h3 Route - div http://localhost:1337/pokemon/pokemon/{pokemonId} - h3 Headers - div None needed - div - h3 Decription - div Deletes the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). + include partials/rightSideDocumentaion.pug diff --git a/views/partials/leftSideDocumentation.pug b/views/partials/leftSideDocumentation.pug new file mode 100644 index 0000000..12c5c5c --- /dev/null +++ b/views/partials/leftSideDocumentation.pug @@ -0,0 +1,19 @@ +div(class="left-container") + div(class="tabs highlighted" id="getAll" onclick="updateSelected('getAll')") + span(class="get") GET + span /pokemon + div(class="tabs" id="getGeneration" onclick="updateSelected('getGeneration')") + span(class="get") GET + span /generation/{genId} + + div(class="tabs" id="getPokemonById" onclick="updateSelected('getPokemonById')") + span(class="get") GET + span /pokemon/{pokemonId} + + div(class="tabs" id="postPokemon" onclick="updateSelected('postPokemon')") + span(class="post") POST + span /pokemon + + div(class="tabs" id="deletePokemonById" onclick="updateSelected('deletePokemonById')") + span(class="delete") DELETE + span /pokemon/{pokemonId} diff --git a/views/partials/rightSideDocumentaion.pug b/views/partials/rightSideDocumentaion.pug new file mode 100644 index 0000000..3ad6c64 --- /dev/null +++ b/views/partials/rightSideDocumentaion.pug @@ -0,0 +1,52 @@ +div(class="right-container") + div(class="method" id="getAll") + h3 Method + div(class="get") GET + h3 Route + div http://localhost:1337/pokemon + h3 Headers + div None needed + h3 Decription + div Returns a list all of the pokemon in the databse. + + div(class="method hidden" id="getGeneration") + h3 Method + div(class="get") GET + h3 Route + div http://localhost:1337/pokemon/generations/{genId} + h3 Headers + div None needed + h3 Decription + div Returns the generation list of all pokemon associated with {genId}. + + div(class="method hidden" id="getPokemonById") + h3 Method + div(class="get") GET + h3 Route + div http://localhost:1337/pokemon/pokemon/{pokemonId} + h3 Headers + div None needed + h3 Decription + div Returns the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). + + div(class="method hidden" id="postPokemon") + h3 Method + div(class="post") POST + h3 Route + div http://localhost:1337/pokemon + h3 Headers + div Content-Type: application/json + h3 Body + div { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']"} + h3 Decription + div Returns a list all of the pokemon in the databse. + + div(class="method hidden" id="deletePokemonById") + h3 Method + div(class="delete") DELETE + h3 Route + div http://localhost:1337/pokemon/pokemon/{pokemonId} + h3 Headers + div None needed + h3 Decription + div Deletes the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). From 8da6bb618595e507071e686d083ec99aedb9ab05 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Wed, 29 Apr 2020 23:37:29 -0400 Subject: [PATCH 07/26] Adjusted styles.css to be sorted and adjusted some styling. --- public/css/styles.css | 51 ++++++++++++++---------- views/partials/rightSideDocumentaion.pug | 42 +++++++++---------- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/public/css/styles.css b/public/css/styles.css index 1436635..584a53d 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -1,3 +1,7 @@ +body{ + margin-top: 150px; +} + h2{ text-align: center; } @@ -7,46 +11,43 @@ h3{ } .delete{ - color:red; + color: crimson; font-weight: bold; } +.get{ + color: green; + font-weight: bold; +} + +.get-all, .get-generation, .get-pokemon{ + padding: 0px; +} + .hidden{ display: none; } .highlighted{ - width: 300px; - height: 30px; + background-color: lightgray; position: relative; - background: lightgray; + width: 300px; } .highlighted:after { + bottom: 0; + border-bottom: 15px solid transparent; + border-left: 15px solid lightgray; + border-top: 15px solid transparent; content: ""; position: absolute; right: -15px; - bottom: 0; width: 0; - height: 0; - border-left: 15px solid lightgray; - border-top: 15px solid transparent; - border-bottom: 15px solid transparent; -} - -.get-all, .get-generation, .get-pokemon{ - padding: 0px; -} - -.get{ - color: green; - font-weight: bold; } .left-container{ margin: 0px 20px; - padding-top: 30px; width: 320px; } @@ -64,11 +65,19 @@ h3{ .right-container{ margin: 0px 20px; position: relative; - width: 320px; + width: 340px; +} + +.spacing{ + margin: 20px 0px; + padding-left: 20px; } .tabs{ cursor: pointer; font-size: 20px; - margin: 30px; + margin: 30px 0; + padding-top: 4px; + padding-left: 5px; + padding-bottom: 3px; } diff --git a/views/partials/rightSideDocumentaion.pug b/views/partials/rightSideDocumentaion.pug index 3ad6c64..ec43195 100644 --- a/views/partials/rightSideDocumentaion.pug +++ b/views/partials/rightSideDocumentaion.pug @@ -1,52 +1,52 @@ div(class="right-container") div(class="method" id="getAll") h3 Method - div(class="get") GET + div(class="get spacing") GET h3 Route - div http://localhost:1337/pokemon + div(class="spacing") http://localhost:1337/pokemon h3 Headers - div None needed + div(class="spacing") None needed h3 Decription - div Returns a list all of the pokemon in the databse. + div(class="spacing") Returns a list all of the pokemon in the databse. div(class="method hidden" id="getGeneration") h3 Method - div(class="get") GET + div(class="spacing get") GET h3 Route - div http://localhost:1337/pokemon/generations/{genId} + div(class="spacing") http://localhost:1337/pokemon/generations/{genId} h3 Headers - div None needed + div(class="spacing") None needed h3 Decription - div Returns the generation list of all pokemon associated with {genId}. + div(class="spacing") Returns the generation list of all pokemon associated with {genId}. div(class="method hidden" id="getPokemonById") h3 Method - div(class="get") GET + div(class="spacing get") GET h3 Route - div http://localhost:1337/pokemon/pokemon/{pokemonId} + div(class="spacing") http://localhost:1337/pokemon/pokemon/{pokemonId} h3 Headers - div None needed + div(class="spacing") None needed h3 Decription - div Returns the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). + div(class="spacing") Returns the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). div(class="method hidden" id="postPokemon") h3 Method - div(class="post") POST + div(class="spacing post") POST h3 Route - div http://localhost:1337/pokemon + div(class="spacing") http://localhost:1337/pokemon h3 Headers - div Content-Type: application/json + div(class="spacing") Content-Type: application/json h3 Body - div { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']"} + div(class="spacing") { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']"} h3 Decription - div Returns a list all of the pokemon in the databse. + div(class="spacing") Returns a list all of the pokemon in the databse. div(class="method hidden" id="deletePokemonById") h3 Method - div(class="delete") DELETE + div(class="spacing delete") DELETE h3 Route - div http://localhost:1337/pokemon/pokemon/{pokemonId} + div(class="spacing") http://localhost:1337/pokemon/pokemon/{pokemonId} h3 Headers - div None needed + div(class="spacing") None needed h3 Decription - div Deletes the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). + div(class="spacing") Deletes the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). From 088fc2cd95eaddf0717db87ec6e728c8e444db0d Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Wed, 29 Apr 2020 23:41:27 -0400 Subject: [PATCH 08/26] Took out some code that wasn't doing anything in styles.css. --- public/css/styles.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/public/css/styles.css b/public/css/styles.css index 584a53d..080b9cf 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -20,10 +20,6 @@ h3{ font-weight: bold; } -.get-all, .get-generation, .get-pokemon{ - padding: 0px; -} - .hidden{ display: none; } From 332c07cee2e32f497ae96783def2c0cd2e6a3078 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Thu, 30 Apr 2020 12:55:49 -0400 Subject: [PATCH 09/26] Minor styling changes. --- public/css/styles.css | 12 ++++++++---- views/partials/rightSideDocumentaion.pug | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/public/css/styles.css b/public/css/styles.css index 080b9cf..7738eea 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -15,6 +15,10 @@ h3{ font-weight: bold; } +.delete, .get, .post{ + padding-right: 10px; +} + .get{ color: green; font-weight: bold; @@ -27,8 +31,7 @@ h3{ .highlighted{ background-color: lightgray; position: relative; - width: 300px; - + width: 320px; } .highlighted:after { @@ -43,7 +46,7 @@ h3{ } .left-container{ - margin: 0px 20px; + margin: 0px 30px; width: 320px; } @@ -61,7 +64,7 @@ h3{ .right-container{ margin: 0px 20px; position: relative; - width: 340px; + width: 440px; } .spacing{ @@ -72,6 +75,7 @@ h3{ .tabs{ cursor: pointer; font-size: 20px; + letter-spacing: 1px; margin: 30px 0; padding-top: 4px; padding-left: 5px; diff --git a/views/partials/rightSideDocumentaion.pug b/views/partials/rightSideDocumentaion.pug index ec43195..0eb036c 100644 --- a/views/partials/rightSideDocumentaion.pug +++ b/views/partials/rightSideDocumentaion.pug @@ -37,7 +37,7 @@ div(class="right-container") h3 Headers div(class="spacing") Content-Type: application/json h3 Body - div(class="spacing") { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']"} + div(class="spacing") { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']" } h3 Decription div(class="spacing") Returns a list all of the pokemon in the databse. From 42bcd27f28eb57c8ba70954ff9dbc6fbc19c7a6a Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Fri, 1 May 2020 22:20:12 -0400 Subject: [PATCH 10/26] Fixed some typos in /views/partials/rightSideocumentation.pug and fixed the script lint problem. --- package.json | 2 +- views/partials/rightSideDocumentaion.pug | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d2850fa..901879d 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": ".eslintrc.js", "scripts": { "dev": "./node_modules/.bin/nodemon index.js", - "lint": "run lint:puglint && run lint:eslint", + "lint": "npm run lint:pug && npm run lint:eslint", "lint:eslint": "./node_modules/.bin/eslint --format codeframe .", "lint:pug": "./node_modules/.bin/pug-lint ." }, diff --git a/views/partials/rightSideDocumentaion.pug b/views/partials/rightSideDocumentaion.pug index 0eb036c..c94b405 100644 --- a/views/partials/rightSideDocumentaion.pug +++ b/views/partials/rightSideDocumentaion.pug @@ -7,7 +7,7 @@ div(class="right-container") h3 Headers div(class="spacing") None needed h3 Decription - div(class="spacing") Returns a list all of the pokemon in the databse. + div(class="spacing") Returns a list all of the pokemon in the database. div(class="method hidden" id="getGeneration") h3 Method @@ -23,7 +23,7 @@ div(class="right-container") h3 Method div(class="spacing get") GET h3 Route - div(class="spacing") http://localhost:1337/pokemon/pokemon/{pokemonId} + div(class="spacing") http://localhost:1337/pokemon/{pokemonId} h3 Headers div(class="spacing") None needed h3 Decription @@ -39,13 +39,13 @@ div(class="right-container") h3 Body div(class="spacing") { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']" } h3 Decription - div(class="spacing") Returns a list all of the pokemon in the databse. + div(class="spacing") Saves a new pokemon to the database. div(class="method hidden" id="deletePokemonById") h3 Method div(class="spacing delete") DELETE h3 Route - div(class="spacing") http://localhost:1337/pokemon/pokemon/{pokemonId} + div(class="spacing") http://localhost:1337/pokemon/{pokemonId} h3 Headers div(class="spacing") None needed h3 Decription From 6077317a6e0f6cac0bcd662d4a587671258eafbd Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Tue, 12 May 2020 21:18:29 -0400 Subject: [PATCH 11/26] Set up the test and the esfix scripts. Installed tevDependencies: mocha, chai, sinon, and sinon-chai. Installed the dependencies: sequelize and mysql2. --- models/mocks/pokemon.js | 0 package-lock.json | 1046 ++++++++++++++++++++++++++++++++++++++- package.json | 16 +- 3 files changed, 1046 insertions(+), 16 deletions(-) create mode 100644 models/mocks/pokemon.js diff --git a/models/mocks/pokemon.js b/models/mocks/pokemon.js new file mode 100644 index 0000000..e69de29 diff --git a/package-lock.json b/package-lock.json index fffa8bf..ed9e42e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,51 @@ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", "dev": true }, + "@sinonjs/commons": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.2.tgz", + "integrity": "sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/formatio": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", + "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^5.0.2" + } + }, + "@sinonjs/samsam": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", + "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -64,6 +109,11 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/node": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.1.tgz", + "integrity": "sha512-FAYBGwC+W6F9+huFIDtn43cpy7+SzG+atzRiTfdp3inUKL2hXnd4rG8hylJLIh4+hqrQy1P17kvJByE/z825hA==" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -163,6 +213,12 @@ } } }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, "ansi-escapes": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", @@ -195,6 +251,16 @@ "color-convert": "^1.9.0" } }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -224,6 +290,12 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -267,6 +339,11 @@ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -386,6 +463,12 @@ "fill-range": "^7.0.1" } }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -435,6 +518,15 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", @@ -444,6 +536,20 @@ "lazy-cache": "^1.0.3" } }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -469,6 +575,12 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, "chokidar": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", @@ -539,6 +651,15 @@ "mimic-response": "^1.0.0" } }, + "cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", + "requires": { + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -656,7 +777,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -675,6 +795,15 @@ "mimic-response": "^1.0.0" } }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -693,6 +822,20 @@ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -703,6 +846,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -726,6 +875,11 @@ "is-obj": "^2.0.0" } }, + "dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -757,6 +911,36 @@ "once": "^1.4.0" } }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escape-goat": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", @@ -858,8 +1042,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { "version": "1.3.1", @@ -1046,6 +1229,32 @@ "integrity": "sha1-2wAjj/hoVRoYLnShA0FtKVqYyMo=", "dev": true }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + } + } + }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -1097,6 +1306,26 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -1172,6 +1401,12 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1186,12 +1421,24 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, "has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -1259,6 +1506,11 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1377,11 +1629,22 @@ "binary-extensions": "^2.0.0" } }, + "is-bluebird": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -1391,6 +1654,12 @@ "ci-info": "^2.0.0" } }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, "is-expression": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", @@ -1467,6 +1736,11 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, "is-regex": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", @@ -1475,6 +1749,15 @@ "has": "^1.0.3" } }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -1487,6 +1770,12 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1541,6 +1830,12 @@ "promise": "^7.0.1" } }, + "just-extend": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", + "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", + "dev": true + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -1582,11 +1877,41 @@ "type-check": "~0.3.2" } }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -1598,6 +1923,14 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, "make-dir": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", @@ -1676,11 +2009,178 @@ "minimist": "^1.2.5" } }, + "mocha": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.2.tgz", + "integrity": "sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "dependencies": { + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + } + } + }, + "moment": { + "version": "2.25.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz", + "integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg==" + }, + "moment-timezone": { + "version": "0.5.28", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz", + "integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==", + "requires": { + "moment": ">= 2.9.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "mute-stream": { "version": "0.0.8", @@ -1688,6 +2188,56 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mysql2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz", + "integrity": "sha512-9kGVyi930rG2KaHrz3sHwtc6K+GY9d8wWk1XRSYxQiunvGcn4DwuZxOwmK11ftuhhwrYDwGx9Ta4VBwznJn36A==", + "requires": { + "cardinal": "^2.1.1", + "denque": "^1.4.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.5.0", + "long": "^4.0.0", + "lru-cache": "^5.1.1", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.1" + }, + "dependencies": { + "iconv-lite": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz", + "integrity": "sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "requires": { + "lru-cache": "^4.1.3" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -1705,6 +2255,48 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "nise": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.3.tgz", + "integrity": "sha512-EGlhjm7/4KvmmE6B/UFsKh7eHykRl9VH+au8dduHLCyWUO/hr7+N+WtTvDUwc9zHuM1IaIJs/0lQ6Ag1jDkQSg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "nodemon": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.3.tgz", @@ -1766,6 +2358,40 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -1824,6 +2450,30 @@ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -1850,6 +2500,12 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1872,6 +2528,12 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -1913,6 +2575,11 @@ "ipaddr.js": "1.9.1" } }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, "pstree.remy": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz", @@ -2143,6 +2810,14 @@ "picomatch": "^2.0.7" } }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "requires": { + "esprima": "~4.0.0" + } + }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -2177,6 +2852,18 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "resolve": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz", @@ -2210,6 +2897,14 @@ "signal-exit": "^3.0.2" } }, + "retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "requires": { + "any-promise": "^1.3.0" + } + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -2245,11 +2940,6 @@ "tslib": "^1.9.0" } }, - "s": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/s/-/s-1.0.0.tgz", - "integrity": "sha512-Tz63UXhdEBvvIV6Q0a+AV2Dx1TPq+vVWNYBxyCT9TG0uqn9kySwFTjfq3C1YuGBRwYtt9Tof11L6GCKi88foqw==" - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -2263,8 +2953,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "semver-diff": { "version": "3.1.1", @@ -2317,6 +3006,38 @@ } } }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + }, + "sequelize": { + "version": "5.21.8", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.21.8.tgz", + "integrity": "sha512-UOxGMJ7eSnProTMWX9wRr0T9TcuW0YedFmU7s+YBZT9/RmfJeANYPdJXjXg4E+Yg+dJl4WWvBEu9r2oe+d/1/Q==", + "requires": { + "bluebird": "^3.5.0", + "cls-bluebird": "^2.1.0", + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.24.0", + "moment-timezone": "^0.5.21", + "retry-as-promised": "^3.2.0", + "semver": "^6.3.0", + "sequelize-pool": "^2.3.0", + "toposort-class": "^1.0.1", + "uuid": "^3.3.3", + "validator": "^10.11.0", + "wkx": "^0.4.8" + } + }, + "sequelize-pool": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", + "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==" + }, "serve-static": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", @@ -2328,6 +3049,12 @@ "send": "0.17.1" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -2348,12 +3075,61 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "sinon": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", + "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.2", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/formatio": "^5.0.1", + "@sinonjs/samsam": "^5.0.3", + "diff": "^4.0.2", + "nise": "^4.0.1", + "supports-color": "^7.1.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "sinon-chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.5.0.tgz", + "integrity": "sha512-IifbusYiQBpUxxFJkR3wTU68xzBN0+bxCScEaKMjBvAQERg6FnTTc1F17rseLb1tjmkJ23730AXpFI0c47FgAg==", + "dev": true + }, "slice-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", @@ -2384,6 +3160,11 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sqlstring": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", + "integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==" + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -2411,6 +3192,48 @@ } } }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -2537,6 +3360,11 @@ "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -2561,6 +3389,12 @@ "prelude-ls": "~1.1.2" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -2744,12 +3578,22 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, "v8-compile-cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2769,6 +3613,54 @@ "isexe": "^2.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -2799,6 +3691,14 @@ } } }, + "wkx": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz", + "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", + "requires": { + "@types/node": "*" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -2810,6 +3710,42 @@ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2843,6 +3779,17 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", @@ -2860,6 +3807,81 @@ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" } } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + } + } } } } diff --git a/package.json b/package.json index 901879d..964b73b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "dev": "./node_modules/.bin/nodemon index.js", "lint": "npm run lint:pug && npm run lint:eslint", "lint:eslint": "./node_modules/.bin/eslint --format codeframe .", - "lint:pug": "./node_modules/.bin/pug-lint ." + "lint:esfix": "./node_modules/.bin/eslint --fix --format codeframe .", + "lint:pug": "./node_modules/.bin/pug-lint .", + "test": "./node_modules/.bin/mocha tests/**/*.test.js" }, "repository": { "type": "git", @@ -20,12 +22,18 @@ }, "homepage": "https://github.com/orbitalbitmap/pokemon-api#readme", "devDependencies": { + "chai": "^4.2.0", "eslint": "^6.8.0", + "mocha": "^7.1.2", "nodemon": "^2.0.3", - "pug-lint": "^2.6.0" + "pug-lint": "^2.6.0", + "sinon": "^9.0.2", + "sinon-chai": "^3.5.0" }, "dependencies": { "express": "^4.17.1", - "pug": "^2.0.4" + "mysql2": "^2.1.0", + "pug": "^2.0.4", + "sequelize": "^5.21.8" } -} \ No newline at end of file +} From 79e88a384e1af2ccbdb7e40b1d2adfa71b701fe7 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sat, 16 May 2020 23:54:23 -0400 Subject: [PATCH 12/26] Fixed some folder structure and added the draft ERD. --- Pokemon-API-ERD.png | Bin 0 -> 96383 bytes {models => tests}/mocks/pokemon.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Pokemon-API-ERD.png rename {models => tests}/mocks/pokemon.js (100%) diff --git a/Pokemon-API-ERD.png b/Pokemon-API-ERD.png new file mode 100644 index 0000000000000000000000000000000000000000..c8952247ab3b022b8c1f82ceaea291cc12076d14 GIT binary patch literal 96383 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
^Q_L8-{Zx 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⁡g5#Fujn4;uC}A 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 Z@c;S+v$yqI;ss)?pLhI}sA+lZzW_L3KBE8t literal 0 HcmV?d00001 diff --git a/models/mocks/pokemon.js b/tests/mocks/pokemon.js similarity index 100% rename from models/mocks/pokemon.js rename to tests/mocks/pokemon.js From a98ad6d8d09f3eef5a2d1dfc913430add6c7aaf7 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Mon, 18 May 2020 12:38:27 -0400 Subject: [PATCH 13/26] The setup.sql file contains code to create the database, the tables, and populate the pokemons and pokemonTypes table with the first 2 generations of pokemon. --- setup.sql | 704 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 704 insertions(+) create mode 100644 setup.sql diff --git a/setup.sql b/setup.sql new file mode 100644 index 0000000..005d4b8 --- /dev/null +++ b/setup.sql @@ -0,0 +1,704 @@ +DROP DATABASE pokemonApi; +DROP USER 'ash'@'localhost'; + +CREATE DATABASE pokemonApi; + +CREATE USER 'ash'@'localhost' IDENTIFIED WITH mysql_native_password BY 'P1k4chU'; + +GRANT ALL ON pokemonApi.* TO 'ash'@'localhost'; + +USE pokemonAPI; + +CREATE TABLE Pokemons ( + pokedexNumber INT NOT NULL, + name VARCHAR(255) NOT NULL, + generationNumber VARCHAR(255) NOT NULL, + fromId INT DEFAULT NULL, + protected BOOLEAN NOT NULL, + createdAt DATETIME DEFAUlT NOW(), + updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), + deletedAt DATETIME, + PRIMARY KEY(pokedexNumber), + FOREIGN KEY(fromId) REFERENCES Pokemons(pokedexNumber) +); + +CREATE TABLE Types ( + id INT auto_increment, + name VARCHAR(255) NOT NULL, + createdAt DATETIME DEFAUlT NOW(), + updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), + deletedAt DATETIME, + PRIMARY KEY(id) +); + +CREATE TABLE AlternateForms ( + id INT NOT NULL, + name VARCHAR(255) NOT NULL, + createdAt DATETIME DEFAUlT NOW(), + updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), + deletedAt DATETIME, + PRIMARY KEY(id) +); + +CREATE TABLE PokemonTypes ( + pokemonId INT NOT NULL, + typeId INT NOT NULL, + createdAt DATETIME DEFAUlT NOW(), + updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), + deletedAt DATETIME, + PRIMARY KEY(pokemonId, typeId), + FOREIGN KEY(pokemonId) REFERENCES Pokemons(pokedexNumber), + FOREIGN KEY(typeId) REFERENCES Types(id) +); + +CREATE TABLE PokemonAlternateForms ( + pokemonId INT NOT NULL, + formId INT NOT NULL, + createdAt DATETIME DEFAUlT NOW(), + updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), + deletedAt DATETIME, + PRIMARY KEY(pokemonId, formId), + FOREIGN KEY(pokemonId) REFERENCES Pokemons(pokedexNumber), + FOREIGN KEY(formId) REFERENCES AlternateForms(id) +); + + +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(1, 'Bulbasaur', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(2, 'Ivysaur', 1, 1, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(3, 'Venusaur', 1, 2, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(4, 'Charmander', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(5, 'Charmeleon', 1, 4, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(6, 'Charizard', 1, 5, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(7, 'Squirtle', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(8, 'Wartortle', 1, 7, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(9, 'Blastoise', 1, 8, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(10, 'Caterpie', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(11, 'Metapod', 1, 10, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(12, 'Butterfree', 1, 11, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(13, 'Weedle', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(14, 'Kakuna', 1, 13, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(15, 'Beedrill', 1, 14, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(16, 'Pidgey', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(17, 'Pidgeotto', 1, 16, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(18, 'Pidgeot', 1, 17, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(19, 'Rattata', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(20, 'Raticate', 1, 19, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(21, 'Spearow', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(22, 'Fearow', 1, 21, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(23, 'Ekans', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(24, 'Arbok', 1, 23, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(25, 'Pikachu', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(26, 'Raichu', 1, 25, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(27, 'Sandshrew', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(28, 'Sandslash', 1, 27, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(29, 'Nidoran♀', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(30, 'Nidorina', 1, 29, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(31, 'Nidoqueen', 1, 30, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(32, 'Nidoran♂', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(33, 'Nidorino', 1, 32, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(34, 'Nidoking', 1, 33, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(35, 'Clefairy', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(36, 'Clefable', 1, 35, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(37, 'Vulpix', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(38, 'Ninetales', 1, 37, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(39, 'Jigglypuff', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(40, 'Wigglytuff', 1, 39, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(41, 'Zubat', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(42, 'Golbat', 1, 41, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(43, 'Oddish', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(44, 'Gloom', 1, 43, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(45, 'Vileplume', 1, 44, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(46, 'Paras', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(47, 'Parasect', 1, 46, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(48, 'Venonat', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(49, 'Venomoth', 1, 48, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(50, 'Diglett', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(51, 'Dugtrio', 1, 50, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(52, 'Meowth', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(53, 'Persian', 1, 52, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(54, 'Psyduck', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(55, 'Golduck', 1, 55, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(56, 'Mankey', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(57, 'Primeape', 1, 56, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(58, 'Growlithe', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(59, 'Arcanine', 1, 58, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(60, 'Poliwag', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(61, 'Poliwhirl', 1, 60, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(62, 'Poliwrath', 1, 61, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(63, 'Abra', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(64, 'Kadabra', 1, 63, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(65, 'Alakazam', 1, 64, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(66, 'Machop', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(67, 'Machoke', 1, 66, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(68, 'Machamp', 1, 67, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(69, 'Bellsprout', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(70, 'Weepinbell', 1, 69, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(71, 'Victreebel', 1, 70, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(72, 'Tentacool', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(73, 'Tentacruel', 1, 72, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(74, 'Geodude', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(75, 'Graveler', 1, 74, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(76, 'Golem', 1, 75, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(77, 'Ponyta', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(78, 'Rapidash', 1, 77, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(79, 'Slowpoke', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(80, 'Slowbro', 1, 79, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(81, 'Magnemite', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(82, 'Magneton', 1, 81, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(83, 'Farfetch\'d', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(84, 'Doduo', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(85, 'Dodrio', 1, 84, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(86, 'Seel', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(87, 'Dewgong', 1, 86, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(88, 'Grimer', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(89, 'Muk', 1, 88, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(90, 'Shellder', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(91, 'Cloyster', 1, 90, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(92, 'Gastly', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(93, 'Haunter', 1, 92, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(94, 'Gengar', 1, 93, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(95, 'Onix', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(96, 'Drowzee', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(97, 'Hypno', 1, 96, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(98, 'Krabby', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(99, 'Kingler', 1, 98, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(100, 'Voltorb', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(101, 'Electrode', 1, 100, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(102, 'Exeggcute', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(103, 'Exeggutor', 1, 102, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(104, 'Cubone', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(105, 'Marowak', 1, 104, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(106, 'Hitmonlee', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(107, 'Hitmonchan', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(108, 'Lickitung', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(109, 'Koffing', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(110, 'Weezing', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(111, 'Rhyhorn', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(112, 'Rhydon', 1, 111, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(113, 'Chansey', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(114, 'Tangela', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(115, 'Kangaskhan', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(116, 'Horsea', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(117, 'Seadra', 1, 116, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(118, 'Goldeen', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(119, 'Seaking', 1, 118, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(120, 'Staryu', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(121, 'Starmie', 1, 120, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(122, 'Mr. Mime', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(123, 'Scyther', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(124, 'Jynx', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(125, 'Electabuzz', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(126, 'Magmar', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(127, 'Pinsir', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(128, 'Tauros', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(129, 'Magikarp', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(130, 'Gyrados', 1, 129, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(131, 'Lapras', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(132, 'Ditto', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(133, 'Eevee', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(134, 'Vaporeon', 1, 133, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(135, 'Jolteon', 1, 133, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(136, 'Flareon', 1, 133, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(137, 'Porygon', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(138, 'Omanyte', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(139, 'Omastar', 1, 138, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(140, 'Kabuto', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(141, 'Kabutops', 1, 140, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(142, 'Aerodactyl', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(143, 'Snorlax', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(144, 'Articuno', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(145, 'Zapdos', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(146, 'Moltres', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(147, 'Dratini', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(148, 'Dragonair', 1, 147, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(149, 'Dragonite', 1, 148, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(150, 'Mewtwo', 1, null, 1); +INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(151, 'Mew', 1, null, 1); + +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (152, 'Chikorita', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (153, 'Bayleef', 2, 153, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (154, 'Meganium', 2, 154, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (155, 'Cyndaquil', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (156, 'Quilava', 2, 155, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (157, 'Typhlosion', 2, 156, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (158, 'Totodile', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (159, 'Croconaw', 2, 158, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (160, 'Feraligatr', 2, 159, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (161, 'Sentret', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (162, 'Furret', 2, 161, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (163, 'Hoothoot', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (164, 'Noctowl', 2, 163, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (165, 'Ledyba', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (166, 'Ledian', 2, 165, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (167, 'Spinarak', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (168, 'Ariados', 2, 167, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (169, 'Crobat', 2, 42, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (170, 'Chinchou', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (171, 'Lanturn', 2, 170, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (172, 'Pichu', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (173, 'Cleffa', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (174, 'Igglybuff', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (175, 'Togepi', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (176, 'Togetic', 2, 175, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (177, 'Natu', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (178, 'Xatu', 2, 177, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (179, 'Mareep', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (180, 'Flaaffy', 2, 179, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (181, 'Ampharos', 2, 180, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (182, 'Bellossom', 2, 44, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (183, 'Marill', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (184, 'Azumarill', 2, 183, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (185, 'Sudowoodo', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (186, 'Politoed', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (187, 'Hoppip', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (188, 'Skiploom', 2, 187, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (189, 'Jumpluff', 2, 188, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (190, 'Aipom', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (191, 'Sunkern', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (192, 'Sunflora', 2, 191, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (193, 'Yanma', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (194, 'Wooper', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (195, 'Quagsire', 2, 194, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (196, 'Espeon', 2, 133, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (197, 'Umbreon', 2, 133, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (198, 'Murkrow', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (199, 'Slowking', 2, 79, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (200, 'Misdreavus', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (201, 'Unown', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (202, 'Wobbuffet', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (203, 'Girafarig', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (204, 'Pineco', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (205, 'Forretress', 2, 204, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (206, 'Dunsparce', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (207, 'Gligar', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (208, 'Steelix', 2, 95, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (209, 'Snubbull', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (210, 'Granbull', 2, 209, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (211, 'Qwilfish', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (212, 'Scizor', 2, 12, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (213, 'Shuckle', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (214, 'Heracross', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (215, 'Sneasel', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (216, 'Teddiursa', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (217, 'Ursaring', 2, 216, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (218, 'Slugma', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (219, 'Magcargo', 2, 218, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (220, 'Swinub', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (221, 'Piloswine', 2, 220, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (222, 'Corsola', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (223, 'Remoraid', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (224, 'Octillery', 2, 223, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (225, 'Delibird', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (226, 'Mantine', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (227, 'Skarmory', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (228, 'Houndour', 2, 228, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (229, 'Houndoom', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (230, 'Kingdra', 2, 117, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (231, 'Phanpy', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (232, 'Donphan', 2, 231, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (233, 'Porygon2', 2, 137, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (234, 'Stantler', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (235, 'Smeargle', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (236, 'Tyrogue', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (237, 'Hitmontop', 2, 236, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (238, 'Smoochum', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (239, 'Elekid', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (240, 'Magby', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (241, 'Miltank', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (242, 'Blissey', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (243, 'Raikou', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (244, 'Entei', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (245, 'Suicune', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (246, 'Larvitar', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (247, 'Pupitar', 2, 246, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (248, 'Tyranitar', 2, 247, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (249, 'Lugia', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (250, 'Ho-Oh', 2, null, 1); +INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (251, 'Celebi', 2, null, 1); + +INSERT INTO Types (name) VALUES ('Bug'); +INSERT INTO Types (name) VALUES ('Dark'); +INSERT INTO Types (name) VALUES ('Dragon'); +INSERT INTO Types (name) VALUES ('Electric'); +INSERT INTO Types (name) VALUES ('Fairy'); +INSERT INTO Types (name) VALUES ('Fighting'); +INSERT INTO Types (name) VALUES ('Fire'); +INSERT INTO Types (name) VALUES ('Flying'); +INSERT INTO Types (name) VALUES ('Ghost'); +INSERT INTO Types (name) VALUES ('Grass'); +INSERT INTO Types (name) VALUES ('Ground'); +INSERT INTO Types (name) VALUES ('Ice'); +INSERT INTO Types (name) VALUES ('Normal'); +INSERT INTO Types (name) VALUES ('Poison'); +INSERT INTO Types (name) VALUES ('Psychic'); +INSERT INTO Types (name) VALUES ('Rock'); +INSERT INTO Types (name) VALUES ('Steel'); +INSERT INTO Types (name) VALUES ('Water'); + +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (1, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (1, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (2, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (2, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (3, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (3, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (4, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (5, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (6, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (6, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (7, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (8, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (9, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (10, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (11, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (12, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (12, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (13, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (13, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (14, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (14, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (15, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (15, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (16, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (16, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (17, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (17, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (18, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (18, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (19, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (20, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (21, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (21, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (22, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (22, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (23, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (24, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (25, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (26, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (27, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (28, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (29, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (30, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (31, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (31, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (32, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (33, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (34, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (34, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (35, 5 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (36, 5 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (37, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (38, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (39, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (39, 5 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (40, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (40, 5 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (41, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (41, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (42, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (42, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (43, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (43, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (44, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (44, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (45, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (45, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (46, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (46, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (47, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (47, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (48, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (48, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (49, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (49, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (50, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (51, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (52, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (53, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (54, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (55, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (56, 6 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (57, 6 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (58, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (59, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (60, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (61, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (62, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (62, 6 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (63, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (64, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (65, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (66, 6 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (67, 6 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (68, 6 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (69, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (69, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (70, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (70, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (71, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (71, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (72, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (72, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (73, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (73, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (74, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (74, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (75, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (75, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (76, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (76, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (77, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (78, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (79, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (79, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (80, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (80, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (81, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (81, 17 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (82, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (82, 17 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (83, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (83, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (84, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (84, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (85, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (85, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (86, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (87, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (87, 12 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (88, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (89, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (90, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (91, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (91, 12 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (92, 9 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (92, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (93, 9 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (93, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (94, 9 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (94, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (95, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (95, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (96, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (97, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (98, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (99, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (100, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (101, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (102, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (102, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (103, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (103, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (104, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (105, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (106, 6 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (107, 6 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (108, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (109, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (110, 14 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (111, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (111, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (112, 11 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (112, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (113, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (114, 10 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (115, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (116, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (117, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (118, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (119, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (120, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (121, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (121, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (122, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (122, 5 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (123, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (123, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (124, 12 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (124, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (125, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (126, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (127, 1 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (128, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (129, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (130, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (130, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (131, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (131, 12 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (132, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (133, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (134, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (135, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (136, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (137, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (138, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (138, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (139, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (139, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (140, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (140, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (141, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (141, 18 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (142, 16 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (142, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (143, 13 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (144, 12 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (144, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (145, 4 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (145, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (146, 7 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (146, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (147, 3 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (148, 3 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (149, 3 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (149, 8 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (150, 15 ); +INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (151, 15 ); + +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (152, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (153, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (154, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (155, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (156, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (157, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (158, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (159, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (160, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (161, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (162, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (163, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (163, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (164, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (164, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (165, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (165, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (166, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (166, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (167, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (167, 14); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (168, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (168, 14); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (169, 14); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (169, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (170, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (170, 4); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (171, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (171, 4); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (172, 4); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (173, 5); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (174, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (174, 5); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (175, 5); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (176, 5); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (176, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (177, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (177, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (178, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (178, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (179, 4); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (180, 4); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (181, 4); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (182, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (183, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (183, 5); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (184, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (184, 5); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (185, 16); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (186, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (187, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (187, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (188, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (188, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (189, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (189, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (190, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (191, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (192, 10); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (193, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (193, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (194, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (194, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (195, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (195, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (196, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (197, 2); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (198, 2); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (198, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (199, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (199, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (200, 9); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (201, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (202, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (203, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (203, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (204, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (205, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (205, 17); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (206, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (207, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (207, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (208, 17); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (208, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (209, 5); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (210, 5); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (211, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (211, 14); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (212, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (212, 17); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (213, 16); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (214, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (214, 16); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (215, 1); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (215, 6); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (216, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (217, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (218, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (219, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (219, 16); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (220, 12); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (220, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (221, 12); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (221, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (222, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (222, 16); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (223, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (224, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (225, 12); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (225, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (226, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (226, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (227, 17); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (227, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (228, 2); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (228, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (229, 2); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (229, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (230, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (230, 3); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (231, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (232, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (233, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (234, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (235, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (236, 6); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (237, 6); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (238, 12); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (238, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (239, 4); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (240, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (241, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (242, 13); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (243, 4); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (244, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (245, 18); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (246, 16); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (246, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (247, 16); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (247, 11); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (248, 16); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (248, 2); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (249, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (249, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (250, 7); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (250, 8); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (251, 15); +INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (251, 10); From ab12b183772cc8331998e9a53acab593978087c3 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sat, 23 May 2020 13:16:39 -0400 Subject: [PATCH 14/26] Added tests and then wrote code for accesssing the paths. Attempted to remove the setup.sql from commit history and put the file in the .gitignore file. --- .gitignore | 1 + controllers/AlternateForms.js | 29 + controllers/Pokemons.js | 32 ++ controllers/Types.js | 26 + index.js | 12 + models/AlternateForms.js | 14 + models/PokemonAlternateForms.js | 24 + models/PokemonTypes.js | 19 + models/Pokemons.js | 17 + models/Types.js | 14 + models/index.js | 31 + setup.sql | 704 ----------------------- tests/controllers/AlternateForms.test.js | 113 ++++ tests/controllers/Pokemons.test.js | 113 ++++ tests/controllers/Types.test.js | 113 ++++ tests/mocks/pokemon.js | 0 tests/mocks/pokemonData.js | 127 ++++ 17 files changed, 685 insertions(+), 704 deletions(-) create mode 100644 controllers/AlternateForms.js create mode 100644 controllers/Pokemons.js create mode 100644 controllers/Types.js create mode 100644 models/AlternateForms.js create mode 100644 models/PokemonAlternateForms.js create mode 100644 models/PokemonTypes.js create mode 100644 models/Pokemons.js create mode 100644 models/Types.js create mode 100644 models/index.js delete mode 100644 setup.sql create mode 100644 tests/controllers/AlternateForms.test.js create mode 100644 tests/controllers/Pokemons.test.js create mode 100644 tests/controllers/Types.test.js delete mode 100644 tests/mocks/pokemon.js create mode 100644 tests/mocks/pokemonData.js diff --git a/.gitignore b/.gitignore index 3c3629e..560a1f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +setup.sql \ No newline at end of file diff --git a/controllers/AlternateForms.js b/controllers/AlternateForms.js new file mode 100644 index 0000000..d4e696d --- /dev/null +++ b/controllers/AlternateForms.js @@ -0,0 +1,29 @@ +const models = require('../models') + +const getAllAlternateForms = async (request, response) => { + try { + const allAlternateForms = await models.AlternateForms.findAll() + + return response.send(allAlternateForms) + } catch (error) { + return response.status(500).send('Unable to retrieve all the alternate forms, please try again.') + } +} + +const getAlternateFormById = async (request, response) => { + try { + const { id } = request.params + const alternateForm = await models.AlternateForms.findOne({ + where: { name: id }, + include: [{ model: models.Pokemons }] + }) + + return alternateForm + ? response.status(200).send(alternateForm) + : response.status(404).send(`It appears there is no form called '${id}' does not exist.`) + } catch (error) { + return response.status(500).send('Unable to retrieve the alternate form, please try again.') + } +} + +module.exports = { getAllAlternateForms, getAlternateFormById } diff --git a/controllers/Pokemons.js b/controllers/Pokemons.js new file mode 100644 index 0000000..beda374 --- /dev/null +++ b/controllers/Pokemons.js @@ -0,0 +1,32 @@ +const models = require('../models') + +const getAllPokemon = async (request, response) => { + try { + const allPokemon = await models.Pokemons.findAll() + + return response.send(allPokemon) + } catch (error) { + return response.status(500).send('Could not retrieve all pokemon, please try again.') + } +} + +const getPokemonById = async (request, response) => { + try { + const { id } = request.params + const pokemon = await models.Pokemons.findOne({ + where: { name: id }, + include: [ + { model: models.AlternateForms }, + { model: models.Types } + ] + }) + + return pokemon + ? response.status(200).send(pokemon) + : response.status(404).send(`Could not find the pokemon ${id}.`) + } catch (error) { + return response.status(500).send('Could not retrieve the pokemon, please try again.') + } +} + +module.exports = { getAllPokemon, getPokemonById } diff --git a/controllers/Types.js b/controllers/Types.js new file mode 100644 index 0000000..5607d55 --- /dev/null +++ b/controllers/Types.js @@ -0,0 +1,26 @@ +const models = require('../models') + +const getAllTypes = async (request, response) => { + try { + const allTypes = await models.Types.findAll() + + return response.send(allTypes) + } catch (error) { + return response.status(500).send('Could not retrieve all the types, please try again.') + } +} + +const getTypeById = async (request, response) => { + try { + const { id } = request.params + const type = await models.Types.findOne({ where: { name: id }, include: [{ model: models.Pokemons }] }) + + return type + ? response.status(200).send(type) + : response.status(404).send(`Could not find the type: ${id}.`) + } catch (error) { + return response.status(500).send('Could not retrieve the specified type, please try again.') + } +} + +module.exports = { getAllTypes, getTypeById } diff --git a/index.js b/index.js index ac6034b..80f8f80 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,7 @@ const express = require('express') +const { getAllPokemon, getPokemonById } = require('./controllers/Pokemons') +const { getAllTypes, getTypeById } = require('./controllers/Types') +const { getAllAlternateForms, getAlternateFormById } = require('./controllers/AlternateForms') const app = express() @@ -9,6 +12,15 @@ app.get('/', (request, response) => { return response.status(200).render('index') }) +app.get('/pokemon', getAllPokemon) +app.get('/pokemon/:id', getPokemonById) + +app.get('/types', getAllTypes) +app.get('/types/:id', getTypeById) + +app.get('/alternate-forms', getAllAlternateForms) +app.get('/alternate-forms/:id', getAlternateFormById) + app.all('*', (request, response) => { return response.status(404).send('Looks like you found nothing in the pokedex.') }) diff --git a/models/AlternateForms.js b/models/AlternateForms.js new file mode 100644 index 0000000..f337ff8 --- /dev/null +++ b/models/AlternateForms.js @@ -0,0 +1,14 @@ +const AlternateForms = (connection, Sequelize) => { + return connection.define('AlternateForms', { + id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, + name: { type: Sequelize.STRING, allowNull: false } + }, { + defaultScope: { + attributes: { exclude: ['deletedAt'] } + } + }, { + paranoid: true, + }) +} + +module.exports = AlternateForms diff --git a/models/PokemonAlternateForms.js b/models/PokemonAlternateForms.js new file mode 100644 index 0000000..53205f6 --- /dev/null +++ b/models/PokemonAlternateForms.js @@ -0,0 +1,24 @@ +const PokemonAlternateForms = (connection, Sequelize, AlternateForms, Pokemons) => { + return connection.define('PokemonAlternateForms', { + PokemonPokedexNumber: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + references: { model: Pokemons, key: 'pokedexNumber' } + }, + AlternateFormId: { + type: Sequelize.STRING, + allowNull: false, + primaryKey: true, + references: { model: AlternateForms, key: 'id' } + } + }, { + defaultScope: { + attributes: { exclude: ['deletedAt'] } + } + }, { + paranoid: true, + }) +} + +module.exports = PokemonAlternateForms diff --git a/models/PokemonTypes.js b/models/PokemonTypes.js new file mode 100644 index 0000000..baca4b7 --- /dev/null +++ b/models/PokemonTypes.js @@ -0,0 +1,19 @@ +const PokemonTypes = (connection, Sequelize, Pokemons, Types) => { + return connection.define('PokemonTypes', { + PokemonPokedexNumber: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + references: { model: Pokemons, key: 'pokedexNumber' } + }, + TypeId: { type: Sequelize.STRING, allowNull: false, primaryKey: true, references: { model: Types, key: 'id' } } + }, { + defaultScope: { + attributes: { exclude: ['deletedAt'] } + } + }, { + paranoid: true, + }) +} + +module.exports = PokemonTypes diff --git a/models/Pokemons.js b/models/Pokemons.js new file mode 100644 index 0000000..5a120ee --- /dev/null +++ b/models/Pokemons.js @@ -0,0 +1,17 @@ +const Pokemons = (connection, Sequelize) => { + return connection.define('Pokemons', { + pokedexNumber: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, + name: { type: Sequelize.STRING, allowNull: false }, + generationNumber: { type: Sequelize.INTEGER, allowNull: false }, + fromId: { type: Sequelize.INTEGER, allowNull: true }, + protected: { type: Sequelize.TINYINT } + }, { + defaultScope: { + attributes: { exclude: ['deletedAt'] } + } + }, { + paranoid: true, + }) +} + +module.exports = Pokemons diff --git a/models/Types.js b/models/Types.js new file mode 100644 index 0000000..17c9860 --- /dev/null +++ b/models/Types.js @@ -0,0 +1,14 @@ +const Types = (connection, Sequelize) => { + return connection.define('Types', { + id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, + name: { type: Sequelize.STRING, allowNull: false }, + }, { + defaultScope: { + attributes: { exclude: ['deletedAt'] } + } + }, { + paranoid: true, + }) +} + +module.exports = Types diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..1a9f00e --- /dev/null +++ b/models/index.js @@ -0,0 +1,31 @@ +const Sequelize = require('sequelize') +const PokemonsModel = require('./Pokemons') +const AlternateFormsModel = require('./AlternateForms') +const TypesModel = require('./Types') +const PokemonAlternateFormsModel = require('./PokemonAlternateForms') +const PokemonTypesModel = require('./PokemonTypes') + +const connection = new Sequelize('pokemonApi', 'ash', 'P1k4chU', { + host: 'localhost', dialect: 'mysql' +}) + +const Pokemons = PokemonsModel(connection, Sequelize) +const AlternateForms = AlternateFormsModel(connection, Sequelize) +const Types = TypesModel(connection, Sequelize) +const PokemonAlternateForms = PokemonAlternateFormsModel(connection, Sequelize, AlternateForms, Pokemons) +const PokemonTypes = PokemonTypesModel(connection, Sequelize, Pokemons, Types) + +Pokemons.belongsToMany(Types, { through: PokemonTypes }) +Types.belongsToMany(Pokemons, { through: PokemonTypes }) + +Pokemons.belongsToMany(AlternateForms, { through: PokemonAlternateForms }) +AlternateForms.belongsToMany(Pokemons, { through: PokemonAlternateForms }) + +module.exports = { + Pokemons, + AlternateForms, + Types, + PokemonAlternateForms, + PokemonTypes, + Op: Sequelize.Op +} diff --git a/setup.sql b/setup.sql deleted file mode 100644 index 005d4b8..0000000 --- a/setup.sql +++ /dev/null @@ -1,704 +0,0 @@ -DROP DATABASE pokemonApi; -DROP USER 'ash'@'localhost'; - -CREATE DATABASE pokemonApi; - -CREATE USER 'ash'@'localhost' IDENTIFIED WITH mysql_native_password BY 'P1k4chU'; - -GRANT ALL ON pokemonApi.* TO 'ash'@'localhost'; - -USE pokemonAPI; - -CREATE TABLE Pokemons ( - pokedexNumber INT NOT NULL, - name VARCHAR(255) NOT NULL, - generationNumber VARCHAR(255) NOT NULL, - fromId INT DEFAULT NULL, - protected BOOLEAN NOT NULL, - createdAt DATETIME DEFAUlT NOW(), - updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), - deletedAt DATETIME, - PRIMARY KEY(pokedexNumber), - FOREIGN KEY(fromId) REFERENCES Pokemons(pokedexNumber) -); - -CREATE TABLE Types ( - id INT auto_increment, - name VARCHAR(255) NOT NULL, - createdAt DATETIME DEFAUlT NOW(), - updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), - deletedAt DATETIME, - PRIMARY KEY(id) -); - -CREATE TABLE AlternateForms ( - id INT NOT NULL, - name VARCHAR(255) NOT NULL, - createdAt DATETIME DEFAUlT NOW(), - updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), - deletedAt DATETIME, - PRIMARY KEY(id) -); - -CREATE TABLE PokemonTypes ( - pokemonId INT NOT NULL, - typeId INT NOT NULL, - createdAt DATETIME DEFAUlT NOW(), - updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), - deletedAt DATETIME, - PRIMARY KEY(pokemonId, typeId), - FOREIGN KEY(pokemonId) REFERENCES Pokemons(pokedexNumber), - FOREIGN KEY(typeId) REFERENCES Types(id) -); - -CREATE TABLE PokemonAlternateForms ( - pokemonId INT NOT NULL, - formId INT NOT NULL, - createdAt DATETIME DEFAUlT NOW(), - updatedAt DATETIME DEFAULT NOW() ON UPDATE NOW(), - deletedAt DATETIME, - PRIMARY KEY(pokemonId, formId), - FOREIGN KEY(pokemonId) REFERENCES Pokemons(pokedexNumber), - FOREIGN KEY(formId) REFERENCES AlternateForms(id) -); - - -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(1, 'Bulbasaur', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(2, 'Ivysaur', 1, 1, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(3, 'Venusaur', 1, 2, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(4, 'Charmander', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(5, 'Charmeleon', 1, 4, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(6, 'Charizard', 1, 5, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(7, 'Squirtle', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(8, 'Wartortle', 1, 7, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(9, 'Blastoise', 1, 8, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(10, 'Caterpie', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(11, 'Metapod', 1, 10, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(12, 'Butterfree', 1, 11, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(13, 'Weedle', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(14, 'Kakuna', 1, 13, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(15, 'Beedrill', 1, 14, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(16, 'Pidgey', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(17, 'Pidgeotto', 1, 16, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(18, 'Pidgeot', 1, 17, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(19, 'Rattata', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(20, 'Raticate', 1, 19, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(21, 'Spearow', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(22, 'Fearow', 1, 21, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(23, 'Ekans', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(24, 'Arbok', 1, 23, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(25, 'Pikachu', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(26, 'Raichu', 1, 25, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(27, 'Sandshrew', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(28, 'Sandslash', 1, 27, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(29, 'Nidoran♀', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(30, 'Nidorina', 1, 29, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(31, 'Nidoqueen', 1, 30, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(32, 'Nidoran♂', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(33, 'Nidorino', 1, 32, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(34, 'Nidoking', 1, 33, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(35, 'Clefairy', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(36, 'Clefable', 1, 35, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(37, 'Vulpix', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(38, 'Ninetales', 1, 37, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(39, 'Jigglypuff', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(40, 'Wigglytuff', 1, 39, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(41, 'Zubat', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(42, 'Golbat', 1, 41, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(43, 'Oddish', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(44, 'Gloom', 1, 43, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(45, 'Vileplume', 1, 44, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(46, 'Paras', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(47, 'Parasect', 1, 46, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(48, 'Venonat', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(49, 'Venomoth', 1, 48, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(50, 'Diglett', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(51, 'Dugtrio', 1, 50, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(52, 'Meowth', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(53, 'Persian', 1, 52, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(54, 'Psyduck', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(55, 'Golduck', 1, 55, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(56, 'Mankey', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(57, 'Primeape', 1, 56, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(58, 'Growlithe', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(59, 'Arcanine', 1, 58, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(60, 'Poliwag', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(61, 'Poliwhirl', 1, 60, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(62, 'Poliwrath', 1, 61, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(63, 'Abra', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(64, 'Kadabra', 1, 63, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(65, 'Alakazam', 1, 64, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(66, 'Machop', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(67, 'Machoke', 1, 66, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(68, 'Machamp', 1, 67, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(69, 'Bellsprout', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(70, 'Weepinbell', 1, 69, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(71, 'Victreebel', 1, 70, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(72, 'Tentacool', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(73, 'Tentacruel', 1, 72, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(74, 'Geodude', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(75, 'Graveler', 1, 74, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(76, 'Golem', 1, 75, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(77, 'Ponyta', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(78, 'Rapidash', 1, 77, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(79, 'Slowpoke', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(80, 'Slowbro', 1, 79, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(81, 'Magnemite', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(82, 'Magneton', 1, 81, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(83, 'Farfetch\'d', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(84, 'Doduo', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(85, 'Dodrio', 1, 84, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(86, 'Seel', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(87, 'Dewgong', 1, 86, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(88, 'Grimer', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(89, 'Muk', 1, 88, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(90, 'Shellder', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(91, 'Cloyster', 1, 90, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(92, 'Gastly', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(93, 'Haunter', 1, 92, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(94, 'Gengar', 1, 93, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(95, 'Onix', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(96, 'Drowzee', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(97, 'Hypno', 1, 96, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(98, 'Krabby', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(99, 'Kingler', 1, 98, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(100, 'Voltorb', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(101, 'Electrode', 1, 100, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(102, 'Exeggcute', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(103, 'Exeggutor', 1, 102, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(104, 'Cubone', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(105, 'Marowak', 1, 104, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(106, 'Hitmonlee', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(107, 'Hitmonchan', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(108, 'Lickitung', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(109, 'Koffing', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(110, 'Weezing', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(111, 'Rhyhorn', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(112, 'Rhydon', 1, 111, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(113, 'Chansey', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(114, 'Tangela', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(115, 'Kangaskhan', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(116, 'Horsea', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(117, 'Seadra', 1, 116, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(118, 'Goldeen', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(119, 'Seaking', 1, 118, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(120, 'Staryu', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(121, 'Starmie', 1, 120, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(122, 'Mr. Mime', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(123, 'Scyther', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(124, 'Jynx', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(125, 'Electabuzz', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(126, 'Magmar', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(127, 'Pinsir', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(128, 'Tauros', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(129, 'Magikarp', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(130, 'Gyrados', 1, 129, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(131, 'Lapras', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(132, 'Ditto', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(133, 'Eevee', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(134, 'Vaporeon', 1, 133, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(135, 'Jolteon', 1, 133, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(136, 'Flareon', 1, 133, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(137, 'Porygon', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(138, 'Omanyte', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(139, 'Omastar', 1, 138, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(140, 'Kabuto', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(141, 'Kabutops', 1, 140, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(142, 'Aerodactyl', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(143, 'Snorlax', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(144, 'Articuno', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(145, 'Zapdos', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(146, 'Moltres', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(147, 'Dratini', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(148, 'Dragonair', 1, 147, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(149, 'Dragonite', 1, 148, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(150, 'Mewtwo', 1, null, 1); -INSERT INTO Pokemons(pokedexNumber, name, generationNumber, fromId, protected) VALUES(151, 'Mew', 1, null, 1); - -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (152, 'Chikorita', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (153, 'Bayleef', 2, 153, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (154, 'Meganium', 2, 154, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (155, 'Cyndaquil', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (156, 'Quilava', 2, 155, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (157, 'Typhlosion', 2, 156, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (158, 'Totodile', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (159, 'Croconaw', 2, 158, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (160, 'Feraligatr', 2, 159, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (161, 'Sentret', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (162, 'Furret', 2, 161, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (163, 'Hoothoot', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (164, 'Noctowl', 2, 163, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (165, 'Ledyba', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (166, 'Ledian', 2, 165, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (167, 'Spinarak', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (168, 'Ariados', 2, 167, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (169, 'Crobat', 2, 42, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (170, 'Chinchou', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (171, 'Lanturn', 2, 170, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (172, 'Pichu', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (173, 'Cleffa', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (174, 'Igglybuff', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (175, 'Togepi', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (176, 'Togetic', 2, 175, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (177, 'Natu', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (178, 'Xatu', 2, 177, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (179, 'Mareep', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (180, 'Flaaffy', 2, 179, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (181, 'Ampharos', 2, 180, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (182, 'Bellossom', 2, 44, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (183, 'Marill', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (184, 'Azumarill', 2, 183, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (185, 'Sudowoodo', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (186, 'Politoed', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (187, 'Hoppip', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (188, 'Skiploom', 2, 187, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (189, 'Jumpluff', 2, 188, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (190, 'Aipom', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (191, 'Sunkern', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (192, 'Sunflora', 2, 191, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (193, 'Yanma', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (194, 'Wooper', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (195, 'Quagsire', 2, 194, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (196, 'Espeon', 2, 133, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (197, 'Umbreon', 2, 133, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (198, 'Murkrow', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (199, 'Slowking', 2, 79, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (200, 'Misdreavus', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (201, 'Unown', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (202, 'Wobbuffet', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (203, 'Girafarig', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (204, 'Pineco', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (205, 'Forretress', 2, 204, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (206, 'Dunsparce', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (207, 'Gligar', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (208, 'Steelix', 2, 95, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (209, 'Snubbull', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (210, 'Granbull', 2, 209, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (211, 'Qwilfish', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (212, 'Scizor', 2, 12, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (213, 'Shuckle', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (214, 'Heracross', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (215, 'Sneasel', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (216, 'Teddiursa', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (217, 'Ursaring', 2, 216, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (218, 'Slugma', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (219, 'Magcargo', 2, 218, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (220, 'Swinub', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (221, 'Piloswine', 2, 220, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (222, 'Corsola', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (223, 'Remoraid', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (224, 'Octillery', 2, 223, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (225, 'Delibird', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (226, 'Mantine', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (227, 'Skarmory', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (228, 'Houndour', 2, 228, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (229, 'Houndoom', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (230, 'Kingdra', 2, 117, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (231, 'Phanpy', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (232, 'Donphan', 2, 231, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (233, 'Porygon2', 2, 137, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (234, 'Stantler', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (235, 'Smeargle', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (236, 'Tyrogue', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (237, 'Hitmontop', 2, 236, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (238, 'Smoochum', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (239, 'Elekid', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (240, 'Magby', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (241, 'Miltank', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (242, 'Blissey', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (243, 'Raikou', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (244, 'Entei', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (245, 'Suicune', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (246, 'Larvitar', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (247, 'Pupitar', 2, 246, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (248, 'Tyranitar', 2, 247, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (249, 'Lugia', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (250, 'Ho-Oh', 2, null, 1); -INSERT INTO Pokemons (pokedexNumber, name, generationNumber, fromId, protected) VALUES (251, 'Celebi', 2, null, 1); - -INSERT INTO Types (name) VALUES ('Bug'); -INSERT INTO Types (name) VALUES ('Dark'); -INSERT INTO Types (name) VALUES ('Dragon'); -INSERT INTO Types (name) VALUES ('Electric'); -INSERT INTO Types (name) VALUES ('Fairy'); -INSERT INTO Types (name) VALUES ('Fighting'); -INSERT INTO Types (name) VALUES ('Fire'); -INSERT INTO Types (name) VALUES ('Flying'); -INSERT INTO Types (name) VALUES ('Ghost'); -INSERT INTO Types (name) VALUES ('Grass'); -INSERT INTO Types (name) VALUES ('Ground'); -INSERT INTO Types (name) VALUES ('Ice'); -INSERT INTO Types (name) VALUES ('Normal'); -INSERT INTO Types (name) VALUES ('Poison'); -INSERT INTO Types (name) VALUES ('Psychic'); -INSERT INTO Types (name) VALUES ('Rock'); -INSERT INTO Types (name) VALUES ('Steel'); -INSERT INTO Types (name) VALUES ('Water'); - -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (1, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (1, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (2, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (2, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (3, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (3, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (4, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (5, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (6, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (6, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (7, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (8, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (9, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (10, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (11, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (12, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (12, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (13, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (13, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (14, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (14, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (15, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (15, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (16, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (16, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (17, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (17, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (18, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (18, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (19, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (20, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (21, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (21, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (22, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (22, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (23, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (24, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (25, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (26, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (27, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (28, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (29, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (30, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (31, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (31, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (32, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (33, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (34, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (34, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (35, 5 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (36, 5 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (37, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (38, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (39, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (39, 5 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (40, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (40, 5 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (41, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (41, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (42, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (42, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (43, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (43, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (44, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (44, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (45, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (45, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (46, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (46, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (47, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (47, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (48, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (48, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (49, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (49, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (50, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (51, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (52, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (53, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (54, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (55, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (56, 6 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (57, 6 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (58, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (59, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (60, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (61, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (62, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (62, 6 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (63, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (64, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (65, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (66, 6 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (67, 6 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (68, 6 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (69, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (69, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (70, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (70, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (71, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (71, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (72, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (72, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (73, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (73, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (74, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (74, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (75, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (75, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (76, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (76, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (77, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (78, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (79, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (79, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (80, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (80, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (81, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (81, 17 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (82, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (82, 17 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (83, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (83, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (84, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (84, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (85, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (85, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (86, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (87, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (87, 12 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (88, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (89, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (90, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (91, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (91, 12 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (92, 9 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (92, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (93, 9 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (93, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (94, 9 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (94, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (95, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (95, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (96, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (97, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (98, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (99, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (100, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (101, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (102, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (102, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (103, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (103, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (104, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (105, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (106, 6 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (107, 6 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (108, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (109, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (110, 14 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (111, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (111, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (112, 11 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (112, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (113, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (114, 10 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (115, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (116, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (117, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (118, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (119, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (120, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (121, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (121, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (122, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (122, 5 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (123, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (123, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (124, 12 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (124, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (125, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (126, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (127, 1 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (128, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (129, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (130, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (130, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (131, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (131, 12 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (132, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (133, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (134, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (135, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (136, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (137, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (138, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (138, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (139, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (139, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (140, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (140, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (141, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (141, 18 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (142, 16 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (142, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (143, 13 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (144, 12 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (144, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (145, 4 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (145, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (146, 7 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (146, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (147, 3 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (148, 3 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (149, 3 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (149, 8 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (150, 15 ); -INSERT INTO PokemonTypes (pokemonId, typeId) VALUES (151, 15 ); - -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (152, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (153, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (154, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (155, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (156, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (157, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (158, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (159, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (160, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (161, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (162, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (163, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (163, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (164, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (164, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (165, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (165, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (166, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (166, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (167, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (167, 14); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (168, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (168, 14); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (169, 14); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (169, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (170, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (170, 4); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (171, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (171, 4); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (172, 4); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (173, 5); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (174, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (174, 5); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (175, 5); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (176, 5); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (176, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (177, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (177, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (178, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (178, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (179, 4); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (180, 4); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (181, 4); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (182, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (183, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (183, 5); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (184, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (184, 5); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (185, 16); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (186, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (187, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (187, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (188, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (188, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (189, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (189, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (190, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (191, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (192, 10); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (193, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (193, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (194, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (194, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (195, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (195, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (196, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (197, 2); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (198, 2); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (198, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (199, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (199, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (200, 9); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (201, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (202, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (203, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (203, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (204, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (205, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (205, 17); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (206, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (207, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (207, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (208, 17); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (208, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (209, 5); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (210, 5); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (211, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (211, 14); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (212, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (212, 17); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (213, 16); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (214, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (214, 16); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (215, 1); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (215, 6); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (216, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (217, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (218, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (219, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (219, 16); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (220, 12); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (220, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (221, 12); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (221, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (222, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (222, 16); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (223, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (224, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (225, 12); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (225, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (226, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (226, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (227, 17); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (227, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (228, 2); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (228, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (229, 2); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (229, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (230, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (230, 3); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (231, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (232, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (233, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (234, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (235, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (236, 6); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (237, 6); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (238, 12); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (238, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (239, 4); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (240, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (241, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (242, 13); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (243, 4); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (244, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (245, 18); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (246, 16); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (246, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (247, 16); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (247, 11); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (248, 16); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (248, 2); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (249, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (249, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (250, 7); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (250, 8); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (251, 15); -INSERT INTO pokemonTypes (pokemonId, typeId) VALUES (251, 10); diff --git a/tests/controllers/AlternateForms.test.js b/tests/controllers/AlternateForms.test.js new file mode 100644 index 0000000..594bdcb --- /dev/null +++ b/tests/controllers/AlternateForms.test.js @@ -0,0 +1,113 @@ +/* eslint-disable max-len */ +const chai = require('chai') +const sinon = require('sinon') +const sinonChai = require('sinon-chai') +const models = require('../../models') +const { + after, afterEach, before, beforeEach, describe, it +} = require('mocha') +const { formsList, singleAltFormWithPokemon } = require('../mocks/pokemonData') +const { getAllAlternateForms, getAlternateFormById } = require('../../controllers/AlternateForms.js') + +chai.use(sinonChai) +const { expect } = chai + +describe('Controllers - AlternateForms', () => { + let sandbox + let stubbedFindAll + let stubbedFindOne + let stubbedSend + let response + let stubbedSendStatus + let stubbedStatusDotSend + let stubbedStatus + + before(() => { + sandbox = sinon.createSandbox() + + stubbedFindAll = sandbox.stub(models.AlternateForms, 'findAll') + stubbedFindOne = sandbox.stub(models.AlternateForms, 'findOne') + + stubbedSend = sandbox.stub() + stubbedSendStatus = sandbox.stub() + stubbedStatusDotSend = sandbox.stub() + stubbedStatus = sandbox.stub() + + response = { + send: stubbedSend, + sendStatus: stubbedSendStatus, + status: stubbedStatus, + } + }) + + beforeEach(() => { + stubbedStatus.returns({ send: stubbedStatusDotSend }) + }) + + afterEach(() => { + sandbox.reset() + }) + + after(() => { + sandbox.restore() + }) + + describe('getAllAlternateForms', () => { + it('retrieves a list of all alternate form names.', async () => { + stubbedFindAll.returns(formsList) + + await getAllAlternateForms({}, response) + + expect(stubbedFindAll).to.have.been.calledWith() + expect(stubbedSend).to.have.been.calledWith(formsList) + }) + + it('returns a 500 error with an error message when the database call throws an error.', async () => { + stubbedFindAll.throws('ERROR!') + + await getAllAlternateForms({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve all the alternate forms, please try again.') + }) + }) + + describe('getAlternateFormById', () => { + it('retrieves the alternate form associated with the id passed by the user with the pokemon that have that alternate form and responds with a 200 status and sends the list of pokemon back.', async () => { + stubbedFindOne.returns(singleAltFormWithPokemon) + const request = { params: { id: 'alolan' } } + + await getAlternateFormById(request, response) + + expect(stubbedFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Pokemons }] + }) + expect(stubbedStatus).to.have.been.calledWith(200) + expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) + }) + + it('returns a 404 status and a message when no alternate form is found matching the id provided by the user.', async () => { + stubbedFindOne.returns(null) + const request = { params: { id: 'pikachu' } } + + await getAlternateFormById(request, response) + + expect(stubbedFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Pokemons }] + }) + expect(stubbedStatus).to.have.been.calledWith(404) + expect(stubbedStatusDotSend).to.have.been.calledWith('It appears there is no form called \'pikachu\' does not exist.') + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedFindOne.throws('ERROR!') + + await getAlternateFormById({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve the alternate form, please try again.') + }) + }) +}) diff --git a/tests/controllers/Pokemons.test.js b/tests/controllers/Pokemons.test.js new file mode 100644 index 0000000..31a181b --- /dev/null +++ b/tests/controllers/Pokemons.test.js @@ -0,0 +1,113 @@ +/* eslint-disable max-len */ +const chai = require('chai') +const sinon = require('sinon') +const sinonChai = require('sinon-chai') +const models = require('../../models') +const { + after, afterEach, before, beforeEach, describe, it +} = require('mocha') +const { pokemonList, singleAltFormWithPokemon } = require('../mocks/pokemonData') +const { getAllPokemon, getPokemonById } = require('../../controllers/Pokemons.js') + +chai.use(sinonChai) +const { expect } = chai + +describe('Controllers - Pokemons', () => { + let sandbox + let stubbedFindAll + let stubbedFindOne + let stubbedSend + let response + let stubbedSendStatus + let stubbedStatusDotSend + let stubbedStatus + + before(() => { + sandbox = sinon.createSandbox() + + stubbedFindAll = sandbox.stub(models.Pokemons, 'findAll') + stubbedFindOne = sandbox.stub(models.Pokemons, 'findOne') + + stubbedSend = sandbox.stub() + stubbedSendStatus = sandbox.stub() + stubbedStatusDotSend = sandbox.stub() + stubbedStatus = sandbox.stub() + + response = { + send: stubbedSend, + sendStatus: stubbedSendStatus, + status: stubbedStatus, + } + }) + + beforeEach(() => { + stubbedStatus.returns({ send: stubbedStatusDotSend }) + }) + + afterEach(() => { + sandbox.reset() + }) + + after(() => { + sandbox.restore() + }) + + describe('getAllPokemon', () => { + it('retrieves a list of all alternate form names.', async () => { + stubbedFindAll.returns(pokemonList) + + await getAllPokemon({}, response) + + expect(stubbedFindAll).to.have.been.calledWith() + expect(stubbedSend).to.have.been.calledWith(pokemonList) + }) + + it('returns a 500 error with an error message when the database call throws an error.', async () => { + stubbedFindAll.throws('ERROR!') + + await getAllPokemon({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve all pokemon, please try again.') + }) + }) + + describe('getPokemonById', () => { + it('retrieves the alternate form associated with the id passed by the user with the pokemon that have that alternate form and responds with a 200 status and sends the list of pokemon back.', async () => { + stubbedFindOne.returns(singleAltFormWithPokemon) + const request = { params: { id: 'alolan' } } + + await getPokemonById(request, response) + + expect(stubbedFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.AlternateForms }, { model: models.Types }] + }) + expect(stubbedStatus).to.have.been.calledWith(200) + expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) + }) + + it('returns a 404 status and a message when no alternate form is found matching the id provided by the user.', async () => { + stubbedFindOne.returns(null) + const request = { params: { id: 'alolan' } } + + await getPokemonById(request, response) + + expect(stubbedFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.AlternateForms }, { model: models.Types }] + }) + expect(stubbedStatus).to.have.been.calledWith(404) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not find the pokemon alolan.') + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedFindOne.throws('ERROR!') + + await getPokemonById({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve the pokemon, please try again.') + }) + }) +}) diff --git a/tests/controllers/Types.test.js b/tests/controllers/Types.test.js new file mode 100644 index 0000000..7a4fa68 --- /dev/null +++ b/tests/controllers/Types.test.js @@ -0,0 +1,113 @@ +/* eslint-disable max-len */ +const chai = require('chai') +const sinon = require('sinon') +const sinonChai = require('sinon-chai') +const models = require('../../models') +const { + after, afterEach, before, beforeEach, describe, it +} = require('mocha') +const { pokemonList, singleAltFormWithPokemon } = require('../mocks/pokemonData') +const { getAllTypes, getTypeById } = require('../../controllers/Types.js') + +chai.use(sinonChai) +const { expect } = chai + +describe('Controllers - Types', () => { + let sandbox + let stubbedFindAll + let stubbedFindOne + let stubbedSend + let response + let stubbedSendStatus + let stubbedStatusDotSend + let stubbedStatus + + before(() => { + sandbox = sinon.createSandbox() + + stubbedFindAll = sandbox.stub(models.Types, 'findAll') + stubbedFindOne = sandbox.stub(models.Types, 'findOne') + + stubbedSend = sandbox.stub() + stubbedSendStatus = sandbox.stub() + stubbedStatusDotSend = sandbox.stub() + stubbedStatus = sandbox.stub() + + response = { + send: stubbedSend, + sendStatus: stubbedSendStatus, + status: stubbedStatus, + } + }) + + beforeEach(() => { + stubbedStatus.returns({ send: stubbedStatusDotSend }) + }) + + afterEach(() => { + sandbox.reset() + }) + + after(() => { + sandbox.restore() + }) + + describe('getAllTypes', () => { + it('retrieves a list of all alternate form names.', async () => { + stubbedFindAll.returns(pokemonList) + + await getAllTypes({}, response) + + expect(stubbedFindAll).to.have.been.calledWith() + expect(stubbedSend).to.have.been.calledWith(pokemonList) + }) + + it('returns a 500 error with an error message when the database call throws an error.', async () => { + stubbedFindAll.throws('ERROR!') + + await getAllTypes({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve all the types, please try again.') + }) + }) + + describe('getTypeById', () => { + it('retrieves the alternate form associated with the id passed by the user with the pokemon that have that alternate form and responds with a 200 status and sends the list of pokemon back.', async () => { + stubbedFindOne.returns(singleAltFormWithPokemon) + const request = { params: { id: 'alolan' } } + + await getTypeById(request, response) + + expect(stubbedFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Pokemons }] + }) + expect(stubbedStatus).to.have.been.calledWith(200) + expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) + }) + + it('returns a 404 status and a message when no alternate form is found matching the id provided by the user.', async () => { + stubbedFindOne.returns(null) + const request = { params: { id: 'shadow' } } + + await getTypeById(request, response) + + expect(stubbedFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Pokemons }] + }) + expect(stubbedStatus).to.have.been.calledWith(404) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not find the type: shadow.') + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedFindOne.throws('ERROR!') + + await getTypeById({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve the specified type, please try again.') + }) + }) +}) diff --git a/tests/mocks/pokemon.js b/tests/mocks/pokemon.js deleted file mode 100644 index e69de29..0000000 diff --git a/tests/mocks/pokemonData.js b/tests/mocks/pokemonData.js new file mode 100644 index 0000000..0dc0209 --- /dev/null +++ b/tests/mocks/pokemonData.js @@ -0,0 +1,127 @@ +const pokemonList = [{ + pokedexNumber: 1, + name: 'Bulbasaur', + generationNumber: 1, + fromId: null, + protected: 1, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z' +}, { + pokedexNumber: 1, + name: 'Bulbasaur', + generationNumber: 1, + fromId: null, + protected: 1, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z' +}] + +const formsList = [{ + id: 4, + name: 'Alolan', + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z' +}] + +const typesList = [{ + id: 1, + name: 'Bug', + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z' +}] + +const singlePokemonWithAltForm = { + pokedexNumber: 88, + name: 'Grimer', + generationNumber: 1, + fromId: null, + protected: 1, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + 'AlternateForms': [ + { + id: 4, + name: 'Alolan', + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + PokemonAlternateForms: { + PokemonPokedexNumber: 88, + AlternateFormId: 4, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z' + } + } + ], + Types: [ + { + id: 14, + name: 'Poison', + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + PokemonTypes: { + PokemonPokedexNumber: 88, + TypeId: 14, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + } + } + ] +} + +const singleAltFormWithPokemon = { + id: 4, + name: 'Alolan', + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + Pokemons: [ + { + pokedexNumber: 19, + name: 'Rattata', + generationNumber: 1, + fromId: null, + protected: 1, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + PokemonAlternateForms: { + PokemonPokedexNumber: 19, + AlternateFormId: 4, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z' + } + } + ] +} + +const singleTypeWithPokemon = { + id: 1, + name: 'Bug', + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + Pokemons: [ + { + pokedexNumber: 10, + name: 'Caterpie', + generationNumber: 1, + fromId: null, + protected: 1, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + PokemonTypes: { + PokemonPokedexNumber: 10, + TypeId: 1, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + } + } + ] +} + + +module.exports = { + pokemonList, + formsList, + typesList, + singlePokemonWithAltForm, + singleAltFormWithPokemon, + singleTypeWithPokemon +} From 39087fe38acf334aa0230c48ce11023f61ef42e9 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sat, 23 May 2020 13:28:08 -0400 Subject: [PATCH 15/26] Renamed AlternateForms to Forms to be simpler but also accurate. (Possibility of a form that is an alternate form and didn't want possible future confusion. --- controllers/AlternateForms.js | 29 ----------------- controllers/Forms.js | 29 +++++++++++++++++ index.js | 6 ++-- models/{AlternateForms.js => Forms.js} | 6 ++-- ...kemonAlternateForms.js => PokemonForms.js} | 10 +++--- models/index.js | 16 +++++----- .../{AlternateForms.test.js => Forms.test.js} | 32 +++++++++---------- 7 files changed, 64 insertions(+), 64 deletions(-) delete mode 100644 controllers/AlternateForms.js create mode 100644 controllers/Forms.js rename models/{AlternateForms.js => Forms.js} (65%) rename models/{PokemonAlternateForms.js => PokemonForms.js} (59%) rename tests/controllers/{AlternateForms.test.js => Forms.test.js} (69%) diff --git a/controllers/AlternateForms.js b/controllers/AlternateForms.js deleted file mode 100644 index d4e696d..0000000 --- a/controllers/AlternateForms.js +++ /dev/null @@ -1,29 +0,0 @@ -const models = require('../models') - -const getAllAlternateForms = async (request, response) => { - try { - const allAlternateForms = await models.AlternateForms.findAll() - - return response.send(allAlternateForms) - } catch (error) { - return response.status(500).send('Unable to retrieve all the alternate forms, please try again.') - } -} - -const getAlternateFormById = async (request, response) => { - try { - const { id } = request.params - const alternateForm = await models.AlternateForms.findOne({ - where: { name: id }, - include: [{ model: models.Pokemons }] - }) - - return alternateForm - ? response.status(200).send(alternateForm) - : response.status(404).send(`It appears there is no form called '${id}' does not exist.`) - } catch (error) { - return response.status(500).send('Unable to retrieve the alternate form, please try again.') - } -} - -module.exports = { getAllAlternateForms, getAlternateFormById } diff --git a/controllers/Forms.js b/controllers/Forms.js new file mode 100644 index 0000000..5bc2775 --- /dev/null +++ b/controllers/Forms.js @@ -0,0 +1,29 @@ +const models = require('../models') + +const getAllForms = async (request, response) => { + try { + const allForms = await models.Forms.findAll() + + return response.send(allForms) + } catch (error) { + return response.status(500).send('Unable to retrieve all the forms, please try again.') + } +} + +const getFormById = async (request, response) => { + try { + const { id } = request.params + const Form = await models.Forms.findOne({ + where: { name: id }, + include: [{ model: models.Pokemons }] + }) + + return Form + ? response.status(200).send(Form) + : response.status(404).send(`It appears there is no form called '${id}' does not exist.`) + } catch (error) { + return response.status(500).send('Unable to retrieve the form, please try again.') + } +} + +module.exports = { getAllForms, getFormById } diff --git a/index.js b/index.js index 80f8f80..dbed6b9 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ const express = require('express') const { getAllPokemon, getPokemonById } = require('./controllers/Pokemons') const { getAllTypes, getTypeById } = require('./controllers/Types') -const { getAllAlternateForms, getAlternateFormById } = require('./controllers/AlternateForms') +const { getAllForms, getFormById } = require('./controllers/Forms') const app = express() @@ -18,8 +18,8 @@ app.get('/pokemon/:id', getPokemonById) app.get('/types', getAllTypes) app.get('/types/:id', getTypeById) -app.get('/alternate-forms', getAllAlternateForms) -app.get('/alternate-forms/:id', getAlternateFormById) +app.get('/forms', getAllForms) +app.get('/forms/:id', getFormById) app.all('*', (request, response) => { return response.status(404).send('Looks like you found nothing in the pokedex.') diff --git a/models/AlternateForms.js b/models/Forms.js similarity index 65% rename from models/AlternateForms.js rename to models/Forms.js index f337ff8..0cdb20c 100644 --- a/models/AlternateForms.js +++ b/models/Forms.js @@ -1,5 +1,5 @@ -const AlternateForms = (connection, Sequelize) => { - return connection.define('AlternateForms', { +const Forms = (connection, Sequelize) => { + return connection.define('Forms', { id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, name: { type: Sequelize.STRING, allowNull: false } }, { @@ -11,4 +11,4 @@ const AlternateForms = (connection, Sequelize) => { }) } -module.exports = AlternateForms +module.exports = Forms diff --git a/models/PokemonAlternateForms.js b/models/PokemonForms.js similarity index 59% rename from models/PokemonAlternateForms.js rename to models/PokemonForms.js index 53205f6..7f8dcff 100644 --- a/models/PokemonAlternateForms.js +++ b/models/PokemonForms.js @@ -1,16 +1,16 @@ -const PokemonAlternateForms = (connection, Sequelize, AlternateForms, Pokemons) => { - return connection.define('PokemonAlternateForms', { +const PokemonForms = (connection, Sequelize, Forms, Pokemons) => { + return connection.define('PokemonForms', { PokemonPokedexNumber: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, references: { model: Pokemons, key: 'pokedexNumber' } }, - AlternateFormId: { + FormId: { type: Sequelize.STRING, allowNull: false, primaryKey: true, - references: { model: AlternateForms, key: 'id' } + references: { model: Forms, key: 'id' } } }, { defaultScope: { @@ -21,4 +21,4 @@ const PokemonAlternateForms = (connection, Sequelize, AlternateForms, Pokemons) }) } -module.exports = PokemonAlternateForms +module.exports = PokemonForms diff --git a/models/index.js b/models/index.js index 1a9f00e..e686fb3 100644 --- a/models/index.js +++ b/models/index.js @@ -1,8 +1,8 @@ const Sequelize = require('sequelize') const PokemonsModel = require('./Pokemons') -const AlternateFormsModel = require('./AlternateForms') +const FormsModel = require('./Forms') const TypesModel = require('./Types') -const PokemonAlternateFormsModel = require('./PokemonAlternateForms') +const PokemonFormsModel = require('./PokemonForms') const PokemonTypesModel = require('./PokemonTypes') const connection = new Sequelize('pokemonApi', 'ash', 'P1k4chU', { @@ -10,22 +10,22 @@ const connection = new Sequelize('pokemonApi', 'ash', 'P1k4chU', { }) const Pokemons = PokemonsModel(connection, Sequelize) -const AlternateForms = AlternateFormsModel(connection, Sequelize) +const Forms = FormsModel(connection, Sequelize) const Types = TypesModel(connection, Sequelize) -const PokemonAlternateForms = PokemonAlternateFormsModel(connection, Sequelize, AlternateForms, Pokemons) +const PokemonForms = PokemonFormsModel(connection, Sequelize, Forms, Pokemons) const PokemonTypes = PokemonTypesModel(connection, Sequelize, Pokemons, Types) Pokemons.belongsToMany(Types, { through: PokemonTypes }) Types.belongsToMany(Pokemons, { through: PokemonTypes }) -Pokemons.belongsToMany(AlternateForms, { through: PokemonAlternateForms }) -AlternateForms.belongsToMany(Pokemons, { through: PokemonAlternateForms }) +Pokemons.belongsToMany(Forms, { through: PokemonForms }) +Forms.belongsToMany(Pokemons, { through: PokemonForms }) module.exports = { Pokemons, - AlternateForms, + Forms, Types, - PokemonAlternateForms, + PokemonForms, PokemonTypes, Op: Sequelize.Op } diff --git a/tests/controllers/AlternateForms.test.js b/tests/controllers/Forms.test.js similarity index 69% rename from tests/controllers/AlternateForms.test.js rename to tests/controllers/Forms.test.js index 594bdcb..8cd7af7 100644 --- a/tests/controllers/AlternateForms.test.js +++ b/tests/controllers/Forms.test.js @@ -7,12 +7,12 @@ const { after, afterEach, before, beforeEach, describe, it } = require('mocha') const { formsList, singleAltFormWithPokemon } = require('../mocks/pokemonData') -const { getAllAlternateForms, getAlternateFormById } = require('../../controllers/AlternateForms.js') +const { getAllForms, getFormById } = require('../../controllers/Forms.js') chai.use(sinonChai) const { expect } = chai -describe('Controllers - AlternateForms', () => { +describe('Controllers - Forms', () => { let sandbox let stubbedFindAll let stubbedFindOne @@ -25,8 +25,8 @@ describe('Controllers - AlternateForms', () => { before(() => { sandbox = sinon.createSandbox() - stubbedFindAll = sandbox.stub(models.AlternateForms, 'findAll') - stubbedFindOne = sandbox.stub(models.AlternateForms, 'findOne') + stubbedFindAll = sandbox.stub(models.Forms, 'findAll') + stubbedFindOne = sandbox.stub(models.Forms, 'findOne') stubbedSend = sandbox.stub() stubbedSendStatus = sandbox.stub() @@ -52,11 +52,11 @@ describe('Controllers - AlternateForms', () => { sandbox.restore() }) - describe('getAllAlternateForms', () => { - it('retrieves a list of all alternate form names.', async () => { + describe('getAllForms', () => { + it('retrieves a list of all form names.', async () => { stubbedFindAll.returns(formsList) - await getAllAlternateForms({}, response) + await getAllForms({}, response) expect(stubbedFindAll).to.have.been.calledWith() expect(stubbedSend).to.have.been.calledWith(formsList) @@ -65,19 +65,19 @@ describe('Controllers - AlternateForms', () => { it('returns a 500 error with an error message when the database call throws an error.', async () => { stubbedFindAll.throws('ERROR!') - await getAllAlternateForms({}, response) + await getAllForms({}, response) expect(stubbedStatus).to.have.been.calledWith(500) - expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve all the alternate forms, please try again.') + expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve all the forms, please try again.') }) }) - describe('getAlternateFormById', () => { - it('retrieves the alternate form associated with the id passed by the user with the pokemon that have that alternate form and responds with a 200 status and sends the list of pokemon back.', async () => { + describe('getFormById', () => { + it('retrieves the form associated with the id passed by the user with the pokemon that have that form and responds with a 200 status and sends the list of pokemon back.', async () => { stubbedFindOne.returns(singleAltFormWithPokemon) const request = { params: { id: 'alolan' } } - await getAlternateFormById(request, response) + await getFormById(request, response) expect(stubbedFindOne).to.be.calledWith({ where: { name: request.params.id }, @@ -87,11 +87,11 @@ describe('Controllers - AlternateForms', () => { expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) }) - it('returns a 404 status and a message when no alternate form is found matching the id provided by the user.', async () => { + it('returns a 404 status and a message when no form is found matching the id provided by the user.', async () => { stubbedFindOne.returns(null) const request = { params: { id: 'pikachu' } } - await getAlternateFormById(request, response) + await getFormById(request, response) expect(stubbedFindOne).to.be.calledWith({ where: { name: request.params.id }, @@ -104,10 +104,10 @@ describe('Controllers - AlternateForms', () => { it('returns a 500 status with a message when the database call throws an error.', async () => { stubbedFindOne.throws('ERROR!') - await getAlternateFormById({}, response) + await getFormById({}, response) expect(stubbedStatus).to.have.been.calledWith(500) - expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve the alternate form, please try again.') + expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve the form, please try again.') }) }) }) From 9da34e7bd8fdb09a324166bc6f8523958dcd5e4a Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sat, 23 May 2020 16:30:27 -0400 Subject: [PATCH 16/26] Added test for generation search and the request path for generation search. --- controllers/Pokemons.js | 15 ++++++++++++++- index.js | 4 +++- tests/controllers/Pokemons.test.js | 16 +++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/controllers/Pokemons.js b/controllers/Pokemons.js index beda374..8d64841 100644 --- a/controllers/Pokemons.js +++ b/controllers/Pokemons.js @@ -29,4 +29,17 @@ const getPokemonById = async (request, response) => { } } -module.exports = { getAllPokemon, getPokemonById } +const getPokemonByGenerationId = async (request, response) => { + try { + const { id } = request.params + const allPokemonInGeneration = await models.Pokemons.findAll({ where: { generationNumber: id } }) + + return allPokemonInGeneration.length + ? response.send(allPokemonInGeneration) + : response.status(404).send(`No generation ${id} pokemon currently exists.`) + } catch (error) { + return response.status(500).send('Could not retrieve the pokemon by the sepcified generation, please try again.') + } +} + +module.exports = { getAllPokemon, getPokemonById, getPokemonByGenerationId } diff --git a/index.js b/index.js index dbed6b9..088e511 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ const express = require('express') -const { getAllPokemon, getPokemonById } = require('./controllers/Pokemons') +const { getAllPokemon, getPokemonById, getPokemonByGenerationId } = require('./controllers/Pokemons') const { getAllTypes, getTypeById } = require('./controllers/Types') const { getAllForms, getFormById } = require('./controllers/Forms') @@ -15,6 +15,8 @@ app.get('/', (request, response) => { app.get('/pokemon', getAllPokemon) app.get('/pokemon/:id', getPokemonById) +app.get('/generation/:id', getPokemonByGenerationId) + app.get('/types', getAllTypes) app.get('/types/:id', getTypeById) diff --git a/tests/controllers/Pokemons.test.js b/tests/controllers/Pokemons.test.js index 31a181b..a692bac 100644 --- a/tests/controllers/Pokemons.test.js +++ b/tests/controllers/Pokemons.test.js @@ -7,7 +7,7 @@ const { after, afterEach, before, beforeEach, describe, it } = require('mocha') const { pokemonList, singleAltFormWithPokemon } = require('../mocks/pokemonData') -const { getAllPokemon, getPokemonById } = require('../../controllers/Pokemons.js') +const { getAllPokemon, getPokemonById, getPokemonByGenerationId } = require('../../controllers/Pokemons.js') chai.use(sinonChai) const { expect } = chai @@ -110,4 +110,18 @@ describe('Controllers - Pokemons', () => { expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve the pokemon, please try again.') }) }) + + describe('getPokemonByGenerationId', () => { + it('retrieves all the pokemon in the user specified id.', async () => { + stubbedFindAll.returns(pokemonList) + + const request = { params: { id: '1' } } + + + await getPokemonByGenerationId(request, response) + + expect(stubbedFindAll).to.have.been.calledWith({ where: { generationNumber: request.params.id } }) + expect(stubbedSend).to.have.been.calledWith(pokemonList) + }) + }) }) From a4ae41b11cb1956cfddb3400b3a156d9afdb1e8f Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sun, 24 May 2020 18:19:56 -0400 Subject: [PATCH 17/26] More tests and paths coded. --- controllers/Pokemons.js | 83 +++++- index.js | 11 +- models/Pokemons.js | 2 +- package.json | 5 +- tests/controllers/Forms.test.js | 113 -------- tests/controllers/Pokemons.test.js | 127 --------- tests/controllers/Types.test.js | 113 -------- tests/controllers/api.tests.js | 406 +++++++++++++++++++++++++++++ tests/mocks/pokemonData.js | 46 +++- 9 files changed, 541 insertions(+), 365 deletions(-) delete mode 100644 tests/controllers/Forms.test.js delete mode 100644 tests/controllers/Pokemons.test.js delete mode 100644 tests/controllers/Types.test.js create mode 100644 tests/controllers/api.tests.js diff --git a/controllers/Pokemons.js b/controllers/Pokemons.js index 8d64841..1849af2 100644 --- a/controllers/Pokemons.js +++ b/controllers/Pokemons.js @@ -16,7 +16,7 @@ const getPokemonById = async (request, response) => { const pokemon = await models.Pokemons.findOne({ where: { name: id }, include: [ - { model: models.AlternateForms }, + { model: models.Forms }, { model: models.Types } ] }) @@ -42,4 +42,83 @@ const getPokemonByGenerationId = async (request, response) => { } } -module.exports = { getAllPokemon, getPokemonById, getPokemonByGenerationId } +const saveNewPokemon = async (request, response) => { + try { + const { + name, + generationNumber, + fromId, + types + } = request.body + const isProtected = request.body.isPortected || 0 + + + if (!name || !generationNumber) { + return response + .status(400) + .send('At least one of the following attributes is missing: pokedexNumber, name, or generationNumber') + } + + const [savedPokemon, created] = await models.Pokemons.findOrCreate({ + where: { name }, + defaults: { generationNumber, fromId, isProtected } + }) + + Promise.resolve(savedPokemon) + + if (created) { + const promisedTypesId = types.map(async typeName => { + const [type] = await models.Types.findOrCreate({ where: { name: typeName } }) + + return type.id + }) + + + const typesId = await Promise.all(promisedTypesId) + const { pokedexNumber } = savedPokemon + + typesId.map(async (typeId) => { + const promisedPokemonType = await models.PokemonTypes.findOrCreate({ + where: { PokemonPokedexNumber: pokedexNumber }, + defaults: { TypeId: typeId } + }) + + const pokemonType = Promise.resolve(promisedPokemonType) + + return pokemonType + }) + } + + + return response.status(201).send(savedPokemon) + } catch (error) { + return response.status(500).send('Could not reach the database, please try again.') + } +} + +const deletePokemon = async (request, response) => { + try { + const { name } = request.params + + const pokemon = await models.Pokemons.findOne({ where: { name } }) + + if (!pokemon) return response.status(404).send(`No pokemon matching the name: ${name}`) + + if (pokemon.isProtected) return response.status(409).send('Cannot delete protected pokemon') + + await models.PokemonTypes.destroy({ where: { PokemonPokedexNumber: pokemon.pokedexNumber } }) + await models.Pokemons.destroy({ where: { name } }) + + return response.send(`Successfully deleted the pokemon: ${name}.`) + } catch (error) { + return response.status(500).send('Unknown error while deleting pokemon, please try again.') + } +} + +module.exports = { + getAllPokemon, + getPokemonById, + getPokemonByGenerationId, + saveNewPokemon, + deletePokemon +} diff --git a/index.js b/index.js index 088e511..0854244 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,12 @@ const express = require('express') -const { getAllPokemon, getPokemonById, getPokemonByGenerationId } = require('./controllers/Pokemons') +const bodyParser = require('body-parser') +const { + getAllPokemon, + getPokemonById, + getPokemonByGenerationId, + saveNewPokemon, + deletePokemon +} = require('./controllers/Pokemons') const { getAllTypes, getTypeById } = require('./controllers/Types') const { getAllForms, getFormById } = require('./controllers/Forms') @@ -13,7 +20,9 @@ app.get('/', (request, response) => { }) app.get('/pokemon', getAllPokemon) +app.post('/pokemon', bodyParser.json(), saveNewPokemon) app.get('/pokemon/:id', getPokemonById) +app.delete('/pokemon/:name', deletePokemon) app.get('/generation/:id', getPokemonByGenerationId) diff --git a/models/Pokemons.js b/models/Pokemons.js index 5a120ee..64556c9 100644 --- a/models/Pokemons.js +++ b/models/Pokemons.js @@ -4,7 +4,7 @@ const Pokemons = (connection, Sequelize) => { name: { type: Sequelize.STRING, allowNull: false }, generationNumber: { type: Sequelize.INTEGER, allowNull: false }, fromId: { type: Sequelize.INTEGER, allowNull: true }, - protected: { type: Sequelize.TINYINT } + isProtected: { type: Sequelize.TINYINT, default: 0 } }, { defaultScope: { attributes: { exclude: ['deletedAt'] } diff --git a/package.json b/package.json index 964b73b..d43a5ca 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint:eslint": "./node_modules/.bin/eslint --format codeframe .", "lint:esfix": "./node_modules/.bin/eslint --fix --format codeframe .", "lint:pug": "./node_modules/.bin/pug-lint .", - "test": "./node_modules/.bin/mocha tests/**/*.test.js" + "test": "./node_modules/.bin/mocha tests/**/*.tests.js" }, "repository": { "type": "git", @@ -31,9 +31,10 @@ "sinon-chai": "^3.5.0" }, "dependencies": { + "body-parser": "^1.19.0", "express": "^4.17.1", "mysql2": "^2.1.0", "pug": "^2.0.4", "sequelize": "^5.21.8" } -} +} \ No newline at end of file diff --git a/tests/controllers/Forms.test.js b/tests/controllers/Forms.test.js deleted file mode 100644 index 8cd7af7..0000000 --- a/tests/controllers/Forms.test.js +++ /dev/null @@ -1,113 +0,0 @@ -/* eslint-disable max-len */ -const chai = require('chai') -const sinon = require('sinon') -const sinonChai = require('sinon-chai') -const models = require('../../models') -const { - after, afterEach, before, beforeEach, describe, it -} = require('mocha') -const { formsList, singleAltFormWithPokemon } = require('../mocks/pokemonData') -const { getAllForms, getFormById } = require('../../controllers/Forms.js') - -chai.use(sinonChai) -const { expect } = chai - -describe('Controllers - Forms', () => { - let sandbox - let stubbedFindAll - let stubbedFindOne - let stubbedSend - let response - let stubbedSendStatus - let stubbedStatusDotSend - let stubbedStatus - - before(() => { - sandbox = sinon.createSandbox() - - stubbedFindAll = sandbox.stub(models.Forms, 'findAll') - stubbedFindOne = sandbox.stub(models.Forms, 'findOne') - - stubbedSend = sandbox.stub() - stubbedSendStatus = sandbox.stub() - stubbedStatusDotSend = sandbox.stub() - stubbedStatus = sandbox.stub() - - response = { - send: stubbedSend, - sendStatus: stubbedSendStatus, - status: stubbedStatus, - } - }) - - beforeEach(() => { - stubbedStatus.returns({ send: stubbedStatusDotSend }) - }) - - afterEach(() => { - sandbox.reset() - }) - - after(() => { - sandbox.restore() - }) - - describe('getAllForms', () => { - it('retrieves a list of all form names.', async () => { - stubbedFindAll.returns(formsList) - - await getAllForms({}, response) - - expect(stubbedFindAll).to.have.been.calledWith() - expect(stubbedSend).to.have.been.calledWith(formsList) - }) - - it('returns a 500 error with an error message when the database call throws an error.', async () => { - stubbedFindAll.throws('ERROR!') - - await getAllForms({}, response) - - expect(stubbedStatus).to.have.been.calledWith(500) - expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve all the forms, please try again.') - }) - }) - - describe('getFormById', () => { - it('retrieves the form associated with the id passed by the user with the pokemon that have that form and responds with a 200 status and sends the list of pokemon back.', async () => { - stubbedFindOne.returns(singleAltFormWithPokemon) - const request = { params: { id: 'alolan' } } - - await getFormById(request, response) - - expect(stubbedFindOne).to.be.calledWith({ - where: { name: request.params.id }, - include: [{ model: models.Pokemons }] - }) - expect(stubbedStatus).to.have.been.calledWith(200) - expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) - }) - - it('returns a 404 status and a message when no form is found matching the id provided by the user.', async () => { - stubbedFindOne.returns(null) - const request = { params: { id: 'pikachu' } } - - await getFormById(request, response) - - expect(stubbedFindOne).to.be.calledWith({ - where: { name: request.params.id }, - include: [{ model: models.Pokemons }] - }) - expect(stubbedStatus).to.have.been.calledWith(404) - expect(stubbedStatusDotSend).to.have.been.calledWith('It appears there is no form called \'pikachu\' does not exist.') - }) - - it('returns a 500 status with a message when the database call throws an error.', async () => { - stubbedFindOne.throws('ERROR!') - - await getFormById({}, response) - - expect(stubbedStatus).to.have.been.calledWith(500) - expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve the form, please try again.') - }) - }) -}) diff --git a/tests/controllers/Pokemons.test.js b/tests/controllers/Pokemons.test.js deleted file mode 100644 index a692bac..0000000 --- a/tests/controllers/Pokemons.test.js +++ /dev/null @@ -1,127 +0,0 @@ -/* eslint-disable max-len */ -const chai = require('chai') -const sinon = require('sinon') -const sinonChai = require('sinon-chai') -const models = require('../../models') -const { - after, afterEach, before, beforeEach, describe, it -} = require('mocha') -const { pokemonList, singleAltFormWithPokemon } = require('../mocks/pokemonData') -const { getAllPokemon, getPokemonById, getPokemonByGenerationId } = require('../../controllers/Pokemons.js') - -chai.use(sinonChai) -const { expect } = chai - -describe('Controllers - Pokemons', () => { - let sandbox - let stubbedFindAll - let stubbedFindOne - let stubbedSend - let response - let stubbedSendStatus - let stubbedStatusDotSend - let stubbedStatus - - before(() => { - sandbox = sinon.createSandbox() - - stubbedFindAll = sandbox.stub(models.Pokemons, 'findAll') - stubbedFindOne = sandbox.stub(models.Pokemons, 'findOne') - - stubbedSend = sandbox.stub() - stubbedSendStatus = sandbox.stub() - stubbedStatusDotSend = sandbox.stub() - stubbedStatus = sandbox.stub() - - response = { - send: stubbedSend, - sendStatus: stubbedSendStatus, - status: stubbedStatus, - } - }) - - beforeEach(() => { - stubbedStatus.returns({ send: stubbedStatusDotSend }) - }) - - afterEach(() => { - sandbox.reset() - }) - - after(() => { - sandbox.restore() - }) - - describe('getAllPokemon', () => { - it('retrieves a list of all alternate form names.', async () => { - stubbedFindAll.returns(pokemonList) - - await getAllPokemon({}, response) - - expect(stubbedFindAll).to.have.been.calledWith() - expect(stubbedSend).to.have.been.calledWith(pokemonList) - }) - - it('returns a 500 error with an error message when the database call throws an error.', async () => { - stubbedFindAll.throws('ERROR!') - - await getAllPokemon({}, response) - - expect(stubbedStatus).to.have.been.calledWith(500) - expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve all pokemon, please try again.') - }) - }) - - describe('getPokemonById', () => { - it('retrieves the alternate form associated with the id passed by the user with the pokemon that have that alternate form and responds with a 200 status and sends the list of pokemon back.', async () => { - stubbedFindOne.returns(singleAltFormWithPokemon) - const request = { params: { id: 'alolan' } } - - await getPokemonById(request, response) - - expect(stubbedFindOne).to.be.calledWith({ - where: { name: request.params.id }, - include: [{ model: models.AlternateForms }, { model: models.Types }] - }) - expect(stubbedStatus).to.have.been.calledWith(200) - expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) - }) - - it('returns a 404 status and a message when no alternate form is found matching the id provided by the user.', async () => { - stubbedFindOne.returns(null) - const request = { params: { id: 'alolan' } } - - await getPokemonById(request, response) - - expect(stubbedFindOne).to.be.calledWith({ - where: { name: request.params.id }, - include: [{ model: models.AlternateForms }, { model: models.Types }] - }) - expect(stubbedStatus).to.have.been.calledWith(404) - expect(stubbedStatusDotSend).to.have.been.calledWith('Could not find the pokemon alolan.') - }) - - it('returns a 500 status with a message when the database call throws an error.', async () => { - stubbedFindOne.throws('ERROR!') - - await getPokemonById({}, response) - - expect(stubbedStatus).to.have.been.calledWith(500) - expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve the pokemon, please try again.') - }) - }) - - describe('getPokemonByGenerationId', () => { - it('retrieves all the pokemon in the user specified id.', async () => { - stubbedFindAll.returns(pokemonList) - - const request = { params: { id: '1' } } - - - await getPokemonByGenerationId(request, response) - - expect(stubbedFindAll).to.have.been.calledWith({ where: { generationNumber: request.params.id } }) - expect(stubbedSend).to.have.been.calledWith(pokemonList) - }) - }) -}) diff --git a/tests/controllers/Types.test.js b/tests/controllers/Types.test.js deleted file mode 100644 index 7a4fa68..0000000 --- a/tests/controllers/Types.test.js +++ /dev/null @@ -1,113 +0,0 @@ -/* eslint-disable max-len */ -const chai = require('chai') -const sinon = require('sinon') -const sinonChai = require('sinon-chai') -const models = require('../../models') -const { - after, afterEach, before, beforeEach, describe, it -} = require('mocha') -const { pokemonList, singleAltFormWithPokemon } = require('../mocks/pokemonData') -const { getAllTypes, getTypeById } = require('../../controllers/Types.js') - -chai.use(sinonChai) -const { expect } = chai - -describe('Controllers - Types', () => { - let sandbox - let stubbedFindAll - let stubbedFindOne - let stubbedSend - let response - let stubbedSendStatus - let stubbedStatusDotSend - let stubbedStatus - - before(() => { - sandbox = sinon.createSandbox() - - stubbedFindAll = sandbox.stub(models.Types, 'findAll') - stubbedFindOne = sandbox.stub(models.Types, 'findOne') - - stubbedSend = sandbox.stub() - stubbedSendStatus = sandbox.stub() - stubbedStatusDotSend = sandbox.stub() - stubbedStatus = sandbox.stub() - - response = { - send: stubbedSend, - sendStatus: stubbedSendStatus, - status: stubbedStatus, - } - }) - - beforeEach(() => { - stubbedStatus.returns({ send: stubbedStatusDotSend }) - }) - - afterEach(() => { - sandbox.reset() - }) - - after(() => { - sandbox.restore() - }) - - describe('getAllTypes', () => { - it('retrieves a list of all alternate form names.', async () => { - stubbedFindAll.returns(pokemonList) - - await getAllTypes({}, response) - - expect(stubbedFindAll).to.have.been.calledWith() - expect(stubbedSend).to.have.been.calledWith(pokemonList) - }) - - it('returns a 500 error with an error message when the database call throws an error.', async () => { - stubbedFindAll.throws('ERROR!') - - await getAllTypes({}, response) - - expect(stubbedStatus).to.have.been.calledWith(500) - expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve all the types, please try again.') - }) - }) - - describe('getTypeById', () => { - it('retrieves the alternate form associated with the id passed by the user with the pokemon that have that alternate form and responds with a 200 status and sends the list of pokemon back.', async () => { - stubbedFindOne.returns(singleAltFormWithPokemon) - const request = { params: { id: 'alolan' } } - - await getTypeById(request, response) - - expect(stubbedFindOne).to.be.calledWith({ - where: { name: request.params.id }, - include: [{ model: models.Pokemons }] - }) - expect(stubbedStatus).to.have.been.calledWith(200) - expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) - }) - - it('returns a 404 status and a message when no alternate form is found matching the id provided by the user.', async () => { - stubbedFindOne.returns(null) - const request = { params: { id: 'shadow' } } - - await getTypeById(request, response) - - expect(stubbedFindOne).to.be.calledWith({ - where: { name: request.params.id }, - include: [{ model: models.Pokemons }] - }) - expect(stubbedStatus).to.have.been.calledWith(404) - expect(stubbedStatusDotSend).to.have.been.calledWith('Could not find the type: shadow.') - }) - - it('returns a 500 status with a message when the database call throws an error.', async () => { - stubbedFindOne.throws('ERROR!') - - await getTypeById({}, response) - - expect(stubbedStatus).to.have.been.calledWith(500) - expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve the specified type, please try again.') - }) - }) -}) diff --git a/tests/controllers/api.tests.js b/tests/controllers/api.tests.js new file mode 100644 index 0000000..bfa2863 --- /dev/null +++ b/tests/controllers/api.tests.js @@ -0,0 +1,406 @@ +/* eslint-disable max-len */ +const chai = require('chai') +const sinon = require('sinon') +const sinonChai = require('sinon-chai') +const models = require('../../models') +const { + after, afterEach, before, beforeEach, describe, it +} = require('mocha') +const { getAllForms, getFormById } = require('../../controllers/Forms.js') +const { getAllTypes, getTypeById } = require('../../controllers/Types.js') + +const { + pokemonList, + singlePokemonWithAltForm, + newPokemon, + formsList, + singleAltFormWithPokemon, + unprotectedPokemon, + protectedPokemon +} = require('../mocks/pokemonData') + +const { + getAllPokemon, + getPokemonById, + getPokemonByGenerationId, + saveNewPokemon, + deletePokemon +} = require('../../controllers/Pokemons.js') + +chai.use(sinonChai) +const { expect } = chai + +describe('Controllers - API', () => { + let sandbox + let stubbedSend + let response + let stubbedSendStatus + let stubbedStatusDotSend + let stubbedStatus + + let stubbedPokemonsDestroy + let stubbedPokemonsFindAll + let stubbedPokemonsFindOne + let stubbedPokemonsFindOrCreate + + let stubbedFormsFindAll + let stubbedFormsFindOne + + let stubbedTypesFindAll + let stubbedTypesFindOne + let stubbedTypesFindOrCreate + + let stubbedPokemonTypesDestroy + let stubbedPokemonTypesFindOrCreate + + before(() => { + sandbox = sinon.createSandbox() + stubbedPokemonsDestroy = sandbox.stub(models.Pokemons, 'destroy') + stubbedPokemonsFindAll = sandbox.stub(models.Pokemons, 'findAll') + stubbedPokemonsFindOne = sandbox.stub(models.Pokemons, 'findOne') + stubbedPokemonsFindOrCreate = sandbox.stub(models.Pokemons, 'findOrCreate') + + stubbedFormsFindAll = sandbox.stub(models.Forms, 'findAll') + stubbedFormsFindOne = sandbox.stub(models.Forms, 'findOne') + + + stubbedTypesFindAll = sandbox.stub(models.Types, 'findAll') + stubbedTypesFindOne = sandbox.stub(models.Types, 'findOne') + stubbedTypesFindOrCreate = sandbox.stub(models.Types, 'findOrCreate') + + stubbedPokemonTypesDestroy = sandbox.stub(models.PokemonTypes, 'destroy') + stubbedPokemonTypesFindOrCreate = sandbox.stub(models.PokemonTypes, 'findOrCreate') + + + stubbedSend = sandbox.stub() + stubbedSendStatus = sandbox.stub() + stubbedStatusDotSend = sandbox.stub() + stubbedStatus = sandbox.stub() + + response = { + send: stubbedSend, + sendStatus: stubbedSendStatus, + status: stubbedStatus, + } + }) + + beforeEach(() => { + stubbedStatus.returns({ send: stubbedStatusDotSend }) + }) + + afterEach(() => { + sandbox.reset() + }) + + after(() => { + sandbox.restore() + }) + + describe('Controller - Pokemons', () => { + describe('getAllPokemon', () => { + it('retrieves a list of all pokemon.', async () => { + stubbedPokemonsFindAll.returns(pokemonList) + + await getAllPokemon({}, response) + + expect(stubbedPokemonsFindAll).to.have.been.calledWith() + expect(stubbedSend).to.have.been.calledWith(pokemonList) + }) + + it('returns a 500 error with an error message when the database call throws an error.', async () => { + stubbedPokemonsFindAll.throws('ERROR!') + + await getAllPokemon({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve all pokemon, please try again.') + }) + }) + + describe('getPokemonById', () => { + it('retrieves the pokemon associated with the id passed by the user with the pokemon\'s alternate formm and types and responds with a 200 status and sends the list of pokemon back.', async () => { + stubbedPokemonsFindOne.returns(singlePokemonWithAltForm) + const request = { params: { id: 'Grimer' } } + + await getPokemonById(request, response) + + expect(stubbedPokemonsFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Forms }, { model: models.Types }] + }) + expect(stubbedStatus).to.have.been.calledWith(200) + expect(stubbedStatusDotSend).to.have.been.calledWith(singlePokemonWithAltForm) + }) + + it('returns a 404 status and a message when no pokemon is found matching the id provided by the user.', async () => { + stubbedPokemonsFindOne.returns(null) + const request = { params: { id: 'ratata' } } + + await getPokemonById(request, response) + + expect(stubbedPokemonsFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Forms }, { model: models.Types }] + }) + expect(stubbedStatus).to.have.been.calledWith(404) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not find the pokemon ratata.') + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedPokemonsFindOne.throws('ERROR!') + + await getPokemonById({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve the pokemon, please try again.') + }) + }) + + describe('getPokemonByGenerationId', () => { + it('retrieves all the pokemon in the user specified id.', async () => { + stubbedPokemonsFindAll.returns(pokemonList) + + const request = { params: { id: '1' } } + + + await getPokemonByGenerationId(request, response) + + expect(stubbedPokemonsFindAll).to.have.been.calledWith({ where: { generationNumber: request.params.id } }) + expect(stubbedSend).to.have.been.calledWith(pokemonList) + }) + + it('returns a 404 error when a user searches for a generation thats not in the database.', async () => { + stubbedPokemonsFindAll.returns('') + const request = { params: { id: 4 } } + + await getPokemonByGenerationId(request, response) + + expect(stubbedPokemonsFindAll).to.be.calledWith({ where: { generationNumber: request.params.id } }) + expect(stubbedStatus).to.have.been.calledWith(404) + expect(stubbedStatusDotSend).to.have.been.calledWith(`No generation ${request.params.id} pokemon currently exists.`) + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedPokemonsFindAll.throws('ERROR!') + + await getPokemonByGenerationId({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve the pokemon by the sepcified generation, please try again.') + }) + }) + + describe('saveNewPokemon', () => { + it('either finds a pokemon matching the name provided or creates a new pokemon based on the by the user inputs.', async () => { + stubbedPokemonsFindOrCreate.onCall(0).returns([newPokemon, false]) + stubbedTypesFindOrCreate.onCall(1).returns(7) + stubbedTypesFindOrCreate.onCall(2).returns(8) + stubbedPokemonTypesFindOrCreate.onCall(3).returns({ PokemonPokedexNumber: 154, typeId: 7 }) + stubbedPokemonTypesFindOrCreate.onCall(4).returns({ PokemonPokedexNumber: 154, typeId: 8 }) + + const request = { + body: { + name: 'Leafeon', + generationNumber: 1, + fromId: null, + types: ['Fire', 'Flying'] + } + } + + await saveNewPokemon(request, response) + + expect(stubbedStatus).to.have.been.calledWith(201) + expect(stubbedStatusDotSend).to.have.been.calledWith(newPokemon) + }) + + it('returns a 400 status and a message when no pokemon is found matching the id provided by the user.', async () => { + stubbedPokemonsFindOne.returns(null) + const request = { body: { name: 'ratata' } } + + await saveNewPokemon(request, response) + + expect(stubbedStatus).to.have.been.calledWith(400) + expect(stubbedStatusDotSend).to.have.been.calledWith('At least one of the following attributes is missing: pokedexNumber, name, or generationNumber') + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedPokemonsFindOne.throws('ERROR!') + + await saveNewPokemon({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not reach the database, please try again.') + }) + }) + + describe('deletePokemon', () => { + it('deletes a user named pokemon from the database as long as its not protected.', async () => { + stubbedPokemonsFindOne.returns(unprotectedPokemon) + + const request = { params: { name: 'Jolion' } } + + await deletePokemon(request, response) + + expect(stubbedPokemonTypesDestroy).to.have.callCount(1) + expect(stubbedPokemonsDestroy).to.have.callCount(1) + expect(stubbedSend).to.have.been.calledWith(`Successfully deleted the pokemon: ${request.params.name}.`) + }) + + it('returns a 404 status and a message when no pokemon is found matching the id provided by the user.', async () => { + stubbedPokemonsFindOne.returns(null) + + const request = { params: { name: 'Fakemon' } } + + await deletePokemon(request, response) + + expect(stubbedPokemonsDestroy).to.have.callCount(0) + expect(stubbedStatus).to.have.been.calledWith(404) + expect(stubbedStatusDotSend).to.have.been.calledWith(`No pokemon matching the name: ${request.params.name}`) + }) + + it('returns a 409 status and a message when trying to delete a protected pokemon.', async () => { + stubbedPokemonsFindOne.returns(protectedPokemon) + + const request = { params: { name: 'Fakemon' } } + + await deletePokemon(request, response) + + expect(stubbedPokemonsDestroy).to.have.callCount(0) + expect(stubbedStatus).to.have.been.calledWith(409) + expect(stubbedStatusDotSend).to.have.been.calledWith('Cannot delete protected pokemon') + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedPokemonsFindOne.throws('ERROR!') + + await deletePokemon({}, response) + + expect(stubbedPokemonsDestroy).to.have.callCount(0) + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Unknown error while deleting pokemon, please try again.') + }) + }) + }) + + describe('Controllers - Forms', () => { + describe('getAllForms', () => { + it('retrieves a list of all form names.', async () => { + stubbedFormsFindAll.returns(formsList) + + await getAllForms({}, response) + + expect(stubbedFormsFindAll).to.have.been.calledWith() + expect(stubbedSend).to.have.been.calledWith(formsList) + }) + + it('returns a 500 error with an error message when the database call throws an error.', async () => { + stubbedFormsFindAll.throws('ERROR!') + + await getAllForms({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve all the forms, please try again.') + }) + }) + + describe('getFormById', () => { + it('retrieves the form associated with the id passed by the user with the pokemon that have that form and responds with a 200 status and sends the list of pokemon back.', async () => { + stubbedFormsFindOne.returns(singleAltFormWithPokemon) + const request = { params: { id: 'alolan' } } + + await getFormById(request, response) + + expect(stubbedFormsFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Pokemons }] + }) + expect(stubbedStatus).to.have.been.calledWith(200) + expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) + }) + + it('returns a 404 status and a message when no form is found matching the id provided by the user.', async () => { + stubbedFormsFindOne.returns(null) + const request = { params: { id: 'pikachu' } } + + await getFormById(request, response) + + expect(stubbedFormsFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Pokemons }] + }) + expect(stubbedStatus).to.have.been.calledWith(404) + expect(stubbedStatusDotSend).to.have.been.calledWith('It appears there is no form called \'pikachu\' does not exist.') + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedFormsFindOne.throws('ERROR!') + + await getFormById({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Unable to retrieve the form, please try again.') + }) + }) + }) + + describe('Controllers - Types', () => { + describe('getAllTypes', () => { + it('retrieves a list of all alternate form names.', async () => { + stubbedTypesFindAll.returns(pokemonList) + + await getAllTypes({}, response) + + expect(stubbedTypesFindAll).to.have.been.calledWith() + expect(stubbedSend).to.have.been.calledWith(pokemonList) + }) + + it('returns a 500 error with an error message when the database call throws an error.', async () => { + stubbedTypesFindAll.throws('ERROR!') + + await getAllTypes({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve all the types, please try again.') + }) + }) + + describe('getTypeById', () => { + it('retrieves the alternate form associated with the id passed by the user with the pokemon that have that alternate form and responds with a 200 status and sends the list of pokemon back.', async () => { + stubbedTypesFindOne.returns(singleAltFormWithPokemon) + const request = { params: { id: 'alolan' } } + + await getTypeById(request, response) + + expect(stubbedTypesFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Pokemons }] + }) + expect(stubbedStatus).to.have.been.calledWith(200) + expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) + }) + + it('returns a 404 status and a message when no alternate form is found matching the id provided by the user.', async () => { + stubbedTypesFindOne.returns(null) + const request = { params: { id: 'shadow' } } + + await getTypeById(request, response) + + expect(stubbedTypesFindOne).to.be.calledWith({ + where: { name: request.params.id }, + include: [{ model: models.Pokemons }] + }) + expect(stubbedStatus).to.have.been.calledWith(404) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not find the type: shadow.') + }) + + it('returns a 500 status with a message when the database call throws an error.', async () => { + stubbedTypesFindOne.throws('ERROR!') + + await getTypeById({}, response) + + expect(stubbedStatus).to.have.been.calledWith(500) + expect(stubbedStatusDotSend).to.have.been.calledWith('Could not retrieve the specified type, please try again.') + }) + }) + }) +}) diff --git a/tests/mocks/pokemonData.js b/tests/mocks/pokemonData.js index 0dc0209..e47fa60 100644 --- a/tests/mocks/pokemonData.js +++ b/tests/mocks/pokemonData.js @@ -3,7 +3,7 @@ const pokemonList = [{ name: 'Bulbasaur', generationNumber: 1, fromId: null, - protected: 1, + isProtected: 1, createdAt: '2020-05-23T11:42:42.000Z', updatedAt: '2020-05-23T11:42:42.000Z' }, { @@ -11,7 +11,7 @@ const pokemonList = [{ name: 'Bulbasaur', generationNumber: 1, fromId: null, - protected: 1, + isProtected: 1, createdAt: '2020-05-23T11:42:42.000Z', updatedAt: '2020-05-23T11:42:42.000Z' }] @@ -35,7 +35,7 @@ const singlePokemonWithAltForm = { name: 'Grimer', generationNumber: 1, fromId: null, - protected: 1, + isProtected: 1, createdAt: '2020-05-23T11:42:42.000Z', updatedAt: '2020-05-23T11:42:42.000Z', 'AlternateForms': [ @@ -79,7 +79,7 @@ const singleAltFormWithPokemon = { name: 'Rattata', generationNumber: 1, fromId: null, - protected: 1, + isProtected: 1, createdAt: '2020-05-23T11:42:42.000Z', updatedAt: '2020-05-23T11:42:42.000Z', PokemonAlternateForms: { @@ -103,7 +103,7 @@ const singleTypeWithPokemon = { name: 'Caterpie', generationNumber: 1, fromId: null, - protected: 1, + isProtected: 1, createdAt: '2020-05-23T11:42:42.000Z', updatedAt: '2020-05-23T11:42:42.000Z', PokemonTypes: { @@ -116,6 +116,37 @@ const singleTypeWithPokemon = { ] } +const newPokemon = { + pokedexNumber: 154, + generationNumber: 1, + fromId: null, + isisProtected: 0, + name: 'Leafeon', + updatedAt: '2020-05-24T16:42:32.743Z', + createdAt: '2020-05-24T16:42:32.743Z' +} + +const unprotectedPokemon = { + pokedexNumber: 88, + generationNumber: 1, + fromId: null, + isisProtected: 0, + name: 'Jolion', + updatedAt: '2020-05-24T16:42:32.743Z', + createdAt: '2020-05-24T16:42:32.743Z' +} + +const protectedPokemon = { + pokedexNumber: 1, + name: 'Fakemon', + generationNumber: 1, + fromId: null, + isProtected: 1, + createdAt: '2020-05-23T11:42:42.000Z', + updatedAt: '2020-05-23T11:42:42.000Z', + deletedAt: null, +} + module.exports = { pokemonList, @@ -123,5 +154,8 @@ module.exports = { typesList, singlePokemonWithAltForm, singleAltFormWithPokemon, - singleTypeWithPokemon + singleTypeWithPokemon, + newPokemon, + unprotectedPokemon, + protectedPokemon } From 249f674e4a7d7e3520b7dfa9a2192c4a4c6fd612 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sun, 24 May 2020 19:53:43 -0400 Subject: [PATCH 18/26] Created migrations for creating the tables and for loading the tables. Changed the password and username for the datbse no one could ue the info from previous commits of the setup.sql file. --- .env-sample | 5 + .gitignore | 3 +- configs/sequelize.js | 9 + .../20200524223604-initial-table-creation.js | 108 ++++ .../20200524230810-initial-data-load.js | 510 ++++++++++++++++++ models/PokemonForms.js | 2 +- models/PokemonTypes.js | 2 +- package-lock.json | 465 +++++++++++++--- package.json | 9 +- 9 files changed, 1042 insertions(+), 71 deletions(-) create mode 100644 .env-sample create mode 100644 configs/sequelize.js create mode 100644 migrations/20200524223604-initial-table-creation.js create mode 100644 migrations/20200524230810-initial-data-load.js diff --git a/.env-sample b/.env-sample new file mode 100644 index 0000000..edeb2de --- /dev/null +++ b/.env-sample @@ -0,0 +1,5 @@ +DB_USERNAME='DB_USERNAME' +DB_PASSWORD='DB_PASSWORD' +DB_DATABASE='DB_DATABASE' +DB_HOST='DB_HOST' +DB_DIALECT='DB_DIALECT' \ No newline at end of file diff --git a/.gitignore b/.gitignore index 560a1f1..79cf6ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -setup.sql \ No newline at end of file +setup.sql +.env diff --git a/configs/sequelize.js b/configs/sequelize.js new file mode 100644 index 0000000..e3b2585 --- /dev/null +++ b/configs/sequelize.js @@ -0,0 +1,9 @@ +module.exports = { + development: { + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + database: process.env.DB_DATABASE, + host: process.env.DB_HOST, + dialect: process.env.DB_DIALECT, + } +} diff --git a/migrations/20200524223604-initial-table-creation.js b/migrations/20200524223604-initial-table-creation.js new file mode 100644 index 0000000..d8d2fa0 --- /dev/null +++ b/migrations/20200524223604-initial-table-creation.js @@ -0,0 +1,108 @@ +module.exports = { + up: async (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + + await queryInterface.createTable('Pokemons', { + pokedexNumber: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, + name: { type: Sequelize.STRING, allowNull: false }, + generationNumber: { type: Sequelize.INTEGER, allowNull: false }, + fromId: { type: Sequelize.INTEGER, allowNull: true }, + isProtected: { type: Sequelize.TINYINT, default: 0 }, + createdAt: { type: Sequelize.DATE, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, + updatedAt: { + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP') + }, + deletedAt: { type: Sequelize.DATE }, + }) + + await queryInterface.createTable('Forms', { + id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, + name: { type: Sequelize.STRING, allowNull: false }, + createdAt: { type: Sequelize.DATE, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, + updatedAt: { + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP') + }, + deletedAt: { type: Sequelize.DATE }, + }) + + await queryInterface.createTable('Types', { + id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, + name: { type: Sequelize.STRING, allowNull: false }, + createdAt: { type: Sequelize.DATE, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, + updatedAt: { + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP') + }, + deletedAt: { type: Sequelize.DATE }, + }) + + await queryInterface.createTable('PokemonTypes', { + PokemonPokedexNumber: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + references: { model: 'Pokemons', key: 'pokedexNumber' } + }, + TypeId: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + references: { model: 'Types', key: 'id' } + }, + createdAt: { type: Sequelize.DATE, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, + updatedAt: { + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP') + }, + deletedAt: { type: Sequelize.DATE }, + }) + + return queryInterface.createTable('PokemonForms', { + PokemonPokedexNumber: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + references: { model: 'Pokemons', key: 'pokedexNumber' } + }, + FormId: { + type: Sequelize.INTEGER, + allowNull: false, + primaryKey: true, + references: { model: 'Forms', key: 'id' } + }, + createdAt: { type: Sequelize.DATE, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, + updatedAt: { + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP') + }, + deletedAt: { type: Sequelize.DATE }, + }) + }, + + down: async (queryInterface) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + Example: + return queryInterface.dropTable('users'); + */ + + await queryInterface.dropTable('PokemonForms') + + await queryInterface.dropTable('Forms') + + await queryInterface.dropTable('PokemonTypes') + + await queryInterface.dropTable('Types') + + return queryInterface.dropTable('Pokemons') + } +} diff --git a/migrations/20200524230810-initial-data-load.js b/migrations/20200524230810-initial-data-load.js new file mode 100644 index 0000000..22d8699 --- /dev/null +++ b/migrations/20200524230810-initial-data-load.js @@ -0,0 +1,510 @@ +module.exports = { + up: async (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + + await queryInterface.bulkInsert('Pokemons', [ + { name: 'Bulbasaur', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Ivysaur', generationNumber: 1, fromId: 1, isProtected: 1 }, + { name: 'Venusaur', generationNumber: 1, fromId: 2, isProtected: 1 }, + { name: 'Charmander', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Charmeleon', generationNumber: 1, fromId: 4, isProtected: 1 }, + { name: 'Charizard', generationNumber: 1, fromId: 5, isProtected: 1 }, + { name: 'Squirtle', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Wartortle', generationNumber: 1, fromId: 7, isProtected: 1 }, + { name: 'Blastoise', generationNumber: 1, fromId: 8, isProtected: 1 }, + { name: 'Caterpie', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Metapod', generationNumber: 1, fromId: 10, isProtected: 1 }, + { name: 'Butterfree', generationNumber: 1, fromId: 11, isProtected: 1 }, + { name: 'Weedle', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Kakuna', generationNumber: 1, fromId: 13, isProtected: 1 }, + { name: 'Beedrill', generationNumber: 1, fromId: 14, isProtected: 1 }, + { name: 'Pidgey', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Pidgeotto', generationNumber: 1, fromId: 16, isProtected: 1 }, + { name: 'Pidgeot', generationNumber: 1, fromId: 17, isProtected: 1 }, + { name: 'Rattata', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Raticate', generationNumber: 1, fromId: 19, isProtected: 1 }, + { name: 'Spearow', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Fearow', generationNumber: 1, fromId: 21, isProtected: 1 }, + { name: 'Ekans', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Arbok', generationNumber: 1, fromId: 23, isProtected: 1 }, + { name: 'Pikachu', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Raichu', generationNumber: 1, fromId: 25, isProtected: 1 }, + { name: 'Sandshrew', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Sandslash', generationNumber: 1, fromId: 27, isProtected: 1 }, + { name: 'Nidoran♀', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Nidorina', generationNumber: 1, fromId: 29, isProtected: 1 }, + { name: 'Nidoqueen', generationNumber: 1, fromId: 30, isProtected: 1 }, + { name: 'Nidoran♂', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Nidorino', generationNumber: 1, fromId: 32, isProtected: 1 }, + { name: 'Nidoking', generationNumber: 1, fromId: 33, isProtected: 1 }, + { name: 'Clefairy', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Clefable', generationNumber: 1, fromId: 35, isProtected: 1 }, + { name: 'Vulpix', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Ninetales', generationNumber: 1, fromId: 37, isProtected: 1 }, + { name: 'Jigglypuff', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Wigglytuff', generationNumber: 1, fromId: 39, isProtected: 1 }, + { name: 'Zubat', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Golbat', generationNumber: 1, fromId: 41, isProtected: 1 }, + { name: 'Oddish', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Gloom', generationNumber: 1, fromId: 43, isProtected: 1 }, + { name: 'Vileplume', generationNumber: 1, fromId: 44, isProtected: 1 }, + { name: 'Paras', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Parasect', generationNumber: 1, fromId: 46, isProtected: 1 }, + { name: 'Venonat', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Venomoth', generationNumber: 1, fromId: 48, isProtected: 1 }, + { name: 'Diglett', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Dugtrio', generationNumber: 1, fromId: 50, isProtected: 1 }, + { name: 'Meowth', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Persian', generationNumber: 1, fromId: 52, isProtected: 1 }, + { name: 'Psyduck', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Golduck', generationNumber: 1, fromId: 55, isProtected: 1 }, + { name: 'Mankey', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Primeape', generationNumber: 1, fromId: 56, isProtected: 1 }, + { name: 'Growlithe', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Arcanine', generationNumber: 1, fromId: 58, isProtected: 1 }, + { name: 'Poliwag', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Poliwhirl', generationNumber: 1, fromId: 60, isProtected: 1 }, + { name: 'Poliwrath', generationNumber: 1, fromId: 61, isProtected: 1 }, + { name: 'Abra', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Kadabra', generationNumber: 1, fromId: 63, isProtected: 1 }, + { name: 'Alakazam', generationNumber: 1, fromId: 64, isProtected: 1 }, + { name: 'Machop', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Machoke', generationNumber: 1, fromId: 66, isProtected: 1 }, + { name: 'Machamp', generationNumber: 1, fromId: 67, isProtected: 1 }, + { name: 'Bellsprout', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Weepinbell', generationNumber: 1, fromId: 69, isProtected: 1 }, + { name: 'Victreebel', generationNumber: 1, fromId: 70, isProtected: 1 }, + { name: 'Tentacool', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Tentacruel', generationNumber: 1, fromId: 72, isProtected: 1 }, + { name: 'Geodude', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Graveler', generationNumber: 1, fromId: 74, isProtected: 1 }, + { name: 'Golem', generationNumber: 1, fromId: 75, isProtected: 1 }, + { name: 'Ponyta', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Rapidash', generationNumber: 1, fromId: 77, isProtected: 1 }, + { name: 'Slowpoke', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Slowbro', generationNumber: 1, fromId: 79, isProtected: 1 }, + { name: 'Magnemite', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Magneton', generationNumber: 1, fromId: 81, isProtected: 1 }, + { name: 'Farfetch\'d', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Doduo', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Dodrio', generationNumber: 1, fromId: 84, isProtected: 1 }, + { name: 'Seel', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Dewgong', generationNumber: 1, fromId: 86, isProtected: 1 }, + { name: 'Grimer', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Muk', generationNumber: 1, fromId: 88, isProtected: 1 }, + { name: 'Shellder', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Cloyster', generationNumber: 1, fromId: 90, isProtected: 1 }, + { name: 'Gastly', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Haunter', generationNumber: 1, fromId: 92, isProtected: 1 }, + { name: 'Gengar', generationNumber: 1, fromId: 93, isProtected: 1 }, + { name: 'Onix', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Drowzee', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Hypno', generationNumber: 1, fromId: 96, isProtected: 1 }, + { name: 'Krabby', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Kingler', generationNumber: 1, fromId: 98, isProtected: 1 }, + { name: 'Voltorb', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Electrode', generationNumber: 1, fromId: 100, isProtected: 1 }, + { name: 'Exeggcute', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Exeggutor', generationNumber: 1, fromId: 102, isProtected: 1 }, + { name: 'Cubone', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Marowak', generationNumber: 1, fromId: 104, isProtected: 1 }, + { name: 'Hitmonlee', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Hitmonchan', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Lickitung', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Koffing', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Weezing', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Rhyhorn', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Rhydon', generationNumber: 1, fromId: 111, isProtected: 1 }, + { name: 'Chansey', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Tangela', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Kangaskhan', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Horsea', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Seadra', generationNumber: 1, fromId: 116, isProtected: 1 }, + { name: 'Goldeen', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Seaking', generationNumber: 1, fromId: 118, isProtected: 1 }, + { name: 'Staryu', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Starmie', generationNumber: 1, fromId: 120, isProtected: 1 }, + { name: 'Mr. Mime', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Scyther', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Jynx', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Electabuzz', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Magmar', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Pinsir', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Tauros', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Magikarp', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Gyrados', generationNumber: 1, fromId: 129, isProtected: 1 }, + { name: 'Lapras', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Ditto', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Eevee', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Vaporeon', generationNumber: 1, fromId: 133, isProtected: 1 }, + { name: 'Jolteon', generationNumber: 1, fromId: 133, isProtected: 1 }, + { name: 'Flareon', generationNumber: 1, fromId: 133, isProtected: 1 }, + { name: 'Porygon', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Omanyte', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Omastar', generationNumber: 1, fromId: 138, isProtected: 1 }, + { name: 'Kabuto', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Kabutops', generationNumber: 1, fromId: 140, isProtected: 1 }, + { name: 'Aerodactyl', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Snorlax', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Articuno', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Zapdos', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Moltres', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Dratini', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Dragonair', generationNumber: 1, fromId: 147, isProtected: 1 }, + { name: 'Dragonite', generationNumber: 1, fromId: 148, isProtected: 1 }, + { name: 'Mewtwo', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Mew', generationNumber: 1, fromId: null, isProtected: 1 }, + ]) + + await queryInterface.bulkInsert('Types', [ + { name: 'Bug' }, + { name: 'Dark' }, + { name: 'Dragon' }, + { name: 'Electric' }, + { name: 'Fairy' }, + { name: 'Fighting' }, + { name: 'Fire' }, + { name: 'Flying' }, + { name: 'Ghost' }, + { name: 'Grass' }, + { name: 'Ground' }, + { name: 'Ice' }, + { name: 'Normal' }, + { name: 'Poison' }, + { name: 'Psychic' }, + { name: 'Rock' }, + { name: 'Steel' }, + { name: 'Water' } + ]) + + await queryInterface.bulkInsert('Forms', [ + { name: 'Gender' }, + { name: 'Alternate' }, + { name: 'Mega' }, + { name: 'Alolan' }, + { name: 'Galarian' }, + { name: 'Gigantamax' } + ]) + + await queryInterface.bulkInsert('PokemonTypes', [ + { PokemonPokedexNumber: 1, typeId: 10 }, + { PokemonPokedexNumber: 1, typeId: 14 }, + { PokemonPokedexNumber: 2, typeId: 10 }, + { PokemonPokedexNumber: 2, typeId: 14 }, + { PokemonPokedexNumber: 3, typeId: 10 }, + { PokemonPokedexNumber: 3, typeId: 14 }, + { PokemonPokedexNumber: 4, typeId: 7 }, + { PokemonPokedexNumber: 5, typeId: 7 }, + { PokemonPokedexNumber: 6, typeId: 7 }, + { PokemonPokedexNumber: 6, typeId: 8 }, + { PokemonPokedexNumber: 7, typeId: 18 }, + { PokemonPokedexNumber: 8, typeId: 18 }, + { PokemonPokedexNumber: 9, typeId: 18 }, + { PokemonPokedexNumber: 10, typeId: 1 }, + { PokemonPokedexNumber: 11, typeId: 1 }, + { PokemonPokedexNumber: 12, typeId: 1 }, + { PokemonPokedexNumber: 12, typeId: 8 }, + { PokemonPokedexNumber: 13, typeId: 1 }, + { PokemonPokedexNumber: 13, typeId: 14 }, + { PokemonPokedexNumber: 14, typeId: 1 }, + { PokemonPokedexNumber: 14, typeId: 14 }, + { PokemonPokedexNumber: 15, typeId: 1 }, + { PokemonPokedexNumber: 15, typeId: 14 }, + { PokemonPokedexNumber: 16, typeId: 13 }, + { PokemonPokedexNumber: 16, typeId: 8 }, + { PokemonPokedexNumber: 17, typeId: 13 }, + { PokemonPokedexNumber: 17, typeId: 8 }, + { PokemonPokedexNumber: 18, typeId: 13 }, + { PokemonPokedexNumber: 18, typeId: 8 }, + { PokemonPokedexNumber: 19, typeId: 13 }, + { PokemonPokedexNumber: 20, typeId: 13 }, + { PokemonPokedexNumber: 21, typeId: 13 }, + { PokemonPokedexNumber: 21, typeId: 8 }, + { PokemonPokedexNumber: 22, typeId: 13 }, + { PokemonPokedexNumber: 22, typeId: 8 }, + { PokemonPokedexNumber: 23, typeId: 14 }, + { PokemonPokedexNumber: 24, typeId: 14 }, + { PokemonPokedexNumber: 25, typeId: 4 }, + { PokemonPokedexNumber: 26, typeId: 4 }, + { PokemonPokedexNumber: 27, typeId: 11 }, + { PokemonPokedexNumber: 28, typeId: 11 }, + { PokemonPokedexNumber: 29, typeId: 14 }, + { PokemonPokedexNumber: 30, typeId: 14 }, + { PokemonPokedexNumber: 31, typeId: 14 }, + { PokemonPokedexNumber: 31, typeId: 11 }, + { PokemonPokedexNumber: 32, typeId: 14 }, + { PokemonPokedexNumber: 33, typeId: 14 }, + { PokemonPokedexNumber: 34, typeId: 14 }, + { PokemonPokedexNumber: 34, typeId: 11 }, + { PokemonPokedexNumber: 35, typeId: 5 }, + { PokemonPokedexNumber: 36, typeId: 5 }, + { PokemonPokedexNumber: 37, typeId: 7 }, + { PokemonPokedexNumber: 38, typeId: 7 }, + { PokemonPokedexNumber: 39, typeId: 13 }, + { PokemonPokedexNumber: 39, typeId: 5 }, + { PokemonPokedexNumber: 40, typeId: 13 }, + { PokemonPokedexNumber: 40, typeId: 5 }, + { PokemonPokedexNumber: 41, typeId: 14 }, + { PokemonPokedexNumber: 41, typeId: 8 }, + { PokemonPokedexNumber: 42, typeId: 14 }, + { PokemonPokedexNumber: 42, typeId: 8 }, + { PokemonPokedexNumber: 43, typeId: 10 }, + { PokemonPokedexNumber: 43, typeId: 14 }, + { PokemonPokedexNumber: 44, typeId: 10 }, + { PokemonPokedexNumber: 44, typeId: 14 }, + { PokemonPokedexNumber: 45, typeId: 10 }, + { PokemonPokedexNumber: 45, typeId: 14 }, + { PokemonPokedexNumber: 46, typeId: 1 }, + { PokemonPokedexNumber: 46, typeId: 10 }, + { PokemonPokedexNumber: 47, typeId: 1 }, + { PokemonPokedexNumber: 47, typeId: 10 }, + { PokemonPokedexNumber: 48, typeId: 1 }, + { PokemonPokedexNumber: 48, typeId: 14 }, + { PokemonPokedexNumber: 49, typeId: 1 }, + { PokemonPokedexNumber: 49, typeId: 14 }, + { PokemonPokedexNumber: 50, typeId: 11 }, + { PokemonPokedexNumber: 51, typeId: 11 }, + { PokemonPokedexNumber: 52, typeId: 13 }, + { PokemonPokedexNumber: 53, typeId: 13 }, + { PokemonPokedexNumber: 54, typeId: 18 }, + { PokemonPokedexNumber: 55, typeId: 18 }, + { PokemonPokedexNumber: 56, typeId: 6 }, + { PokemonPokedexNumber: 57, typeId: 6 }, + { PokemonPokedexNumber: 58, typeId: 7 }, + { PokemonPokedexNumber: 59, typeId: 7 }, + { PokemonPokedexNumber: 60, typeId: 18 }, + { PokemonPokedexNumber: 61, typeId: 18 }, + { PokemonPokedexNumber: 62, typeId: 18 }, + { PokemonPokedexNumber: 62, typeId: 6 }, + { PokemonPokedexNumber: 63, typeId: 15 }, + { PokemonPokedexNumber: 64, typeId: 15 }, + { PokemonPokedexNumber: 65, typeId: 15 }, + { PokemonPokedexNumber: 66, typeId: 6 }, + { PokemonPokedexNumber: 67, typeId: 6 }, + { PokemonPokedexNumber: 68, typeId: 6 }, + { PokemonPokedexNumber: 69, typeId: 10 }, + { PokemonPokedexNumber: 69, typeId: 14 }, + { PokemonPokedexNumber: 70, typeId: 10 }, + { PokemonPokedexNumber: 70, typeId: 14 }, + { PokemonPokedexNumber: 71, typeId: 10 }, + { PokemonPokedexNumber: 71, typeId: 14 }, + { PokemonPokedexNumber: 72, typeId: 18 }, + { PokemonPokedexNumber: 72, typeId: 14 }, + { PokemonPokedexNumber: 73, typeId: 18 }, + { PokemonPokedexNumber: 73, typeId: 14 }, + { PokemonPokedexNumber: 74, typeId: 16 }, + { PokemonPokedexNumber: 74, typeId: 11 }, + { PokemonPokedexNumber: 75, typeId: 16 }, + { PokemonPokedexNumber: 75, typeId: 11 }, + { PokemonPokedexNumber: 76, typeId: 16 }, + { PokemonPokedexNumber: 76, typeId: 11 }, + { PokemonPokedexNumber: 77, typeId: 7 }, + { PokemonPokedexNumber: 78, typeId: 7 }, + { PokemonPokedexNumber: 79, typeId: 18 }, + { PokemonPokedexNumber: 79, typeId: 15 }, + { PokemonPokedexNumber: 80, typeId: 18 }, + { PokemonPokedexNumber: 80, typeId: 15 }, + { PokemonPokedexNumber: 81, typeId: 4 }, + { PokemonPokedexNumber: 81, typeId: 17 }, + { PokemonPokedexNumber: 82, typeId: 4 }, + { PokemonPokedexNumber: 82, typeId: 17 }, + { PokemonPokedexNumber: 83, typeId: 13 }, + { PokemonPokedexNumber: 83, typeId: 8 }, + { PokemonPokedexNumber: 84, typeId: 13 }, + { PokemonPokedexNumber: 84, typeId: 8 }, + { PokemonPokedexNumber: 85, typeId: 13 }, + { PokemonPokedexNumber: 85, typeId: 8 }, + { PokemonPokedexNumber: 86, typeId: 18 }, + { PokemonPokedexNumber: 87, typeId: 18 }, + { PokemonPokedexNumber: 87, typeId: 12 }, + { PokemonPokedexNumber: 88, typeId: 14 }, + { PokemonPokedexNumber: 89, typeId: 14 }, + { PokemonPokedexNumber: 90, typeId: 18 }, + { PokemonPokedexNumber: 91, typeId: 18 }, + { PokemonPokedexNumber: 91, typeId: 12 }, + { PokemonPokedexNumber: 92, typeId: 9 }, + { PokemonPokedexNumber: 92, typeId: 14 }, + { PokemonPokedexNumber: 93, typeId: 9 }, + { PokemonPokedexNumber: 93, typeId: 14 }, + { PokemonPokedexNumber: 94, typeId: 9 }, + { PokemonPokedexNumber: 94, typeId: 14 }, + { PokemonPokedexNumber: 95, typeId: 16 }, + { PokemonPokedexNumber: 95, typeId: 11 }, + { PokemonPokedexNumber: 96, typeId: 15 }, + { PokemonPokedexNumber: 97, typeId: 15 }, + { PokemonPokedexNumber: 98, typeId: 18 }, + { PokemonPokedexNumber: 99, typeId: 18 }, + { PokemonPokedexNumber: 100, typeId: 4 }, + { PokemonPokedexNumber: 101, typeId: 4 }, + { PokemonPokedexNumber: 102, typeId: 10 }, + { PokemonPokedexNumber: 102, typeId: 15 }, + { PokemonPokedexNumber: 103, typeId: 10 }, + { PokemonPokedexNumber: 103, typeId: 15 }, + { PokemonPokedexNumber: 104, typeId: 11 }, + { PokemonPokedexNumber: 105, typeId: 11 }, + { PokemonPokedexNumber: 106, typeId: 6 }, + { PokemonPokedexNumber: 107, typeId: 6 }, + { PokemonPokedexNumber: 108, typeId: 13 }, + { PokemonPokedexNumber: 109, typeId: 14 }, + { PokemonPokedexNumber: 110, typeId: 14 }, + { PokemonPokedexNumber: 111, typeId: 11 }, + { PokemonPokedexNumber: 111, typeId: 16 }, + { PokemonPokedexNumber: 112, typeId: 11 }, + { PokemonPokedexNumber: 112, typeId: 16 }, + { PokemonPokedexNumber: 113, typeId: 13 }, + { PokemonPokedexNumber: 114, typeId: 10 }, + { PokemonPokedexNumber: 115, typeId: 13 }, + { PokemonPokedexNumber: 116, typeId: 18 }, + { PokemonPokedexNumber: 117, typeId: 18 }, + { PokemonPokedexNumber: 118, typeId: 18 }, + { PokemonPokedexNumber: 119, typeId: 18 }, + { PokemonPokedexNumber: 120, typeId: 18 }, + { PokemonPokedexNumber: 121, typeId: 18 }, + { PokemonPokedexNumber: 121, typeId: 15 }, + { PokemonPokedexNumber: 122, typeId: 15 }, + { PokemonPokedexNumber: 122, typeId: 5 }, + { PokemonPokedexNumber: 123, typeId: 1 }, + { PokemonPokedexNumber: 123, typeId: 8 }, + { PokemonPokedexNumber: 124, typeId: 12 }, + { PokemonPokedexNumber: 124, typeId: 15 }, + { PokemonPokedexNumber: 125, typeId: 4 }, + { PokemonPokedexNumber: 126, typeId: 7 }, + { PokemonPokedexNumber: 127, typeId: 1 }, + { PokemonPokedexNumber: 128, typeId: 13 }, + { PokemonPokedexNumber: 129, typeId: 18 }, + { PokemonPokedexNumber: 130, typeId: 18 }, + { PokemonPokedexNumber: 130, typeId: 8 }, + { PokemonPokedexNumber: 131, typeId: 18 }, + { PokemonPokedexNumber: 131, typeId: 12 }, + { PokemonPokedexNumber: 132, typeId: 13 }, + { PokemonPokedexNumber: 133, typeId: 13 }, + { PokemonPokedexNumber: 134, typeId: 18 }, + { PokemonPokedexNumber: 135, typeId: 4 }, + { PokemonPokedexNumber: 136, typeId: 7 }, + { PokemonPokedexNumber: 137, typeId: 13 }, + { PokemonPokedexNumber: 138, typeId: 16 }, + { PokemonPokedexNumber: 138, typeId: 18 }, + { PokemonPokedexNumber: 139, typeId: 16 }, + { PokemonPokedexNumber: 139, typeId: 18 }, + { PokemonPokedexNumber: 140, typeId: 16 }, + { PokemonPokedexNumber: 140, typeId: 18 }, + { PokemonPokedexNumber: 141, typeId: 16 }, + { PokemonPokedexNumber: 141, typeId: 18 }, + { PokemonPokedexNumber: 142, typeId: 16 }, + { PokemonPokedexNumber: 142, typeId: 8 }, + { PokemonPokedexNumber: 143, typeId: 13 }, + { PokemonPokedexNumber: 144, typeId: 12 }, + { PokemonPokedexNumber: 144, typeId: 8 }, + { PokemonPokedexNumber: 145, typeId: 4 }, + { PokemonPokedexNumber: 145, typeId: 8 }, + { PokemonPokedexNumber: 146, typeId: 7 }, + { PokemonPokedexNumber: 146, typeId: 8 }, + { PokemonPokedexNumber: 147, typeId: 3 }, + { PokemonPokedexNumber: 148, typeId: 3 }, + { PokemonPokedexNumber: 149, typeId: 3 }, + { PokemonPokedexNumber: 149, typeId: 8 }, + { PokemonPokedexNumber: 150, typeId: 15 }, + { PokemonPokedexNumber: 151, typeId: 15 }, + ]) + + return queryInterface.bulkInsert('PokemonForms', [ + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Rattata\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Raticate\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Raichu\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Sandshrew\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Sandslash\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Ninetales\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Vulpix\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Diglett\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Dugtrio\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Meowth\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Persian\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Geodude\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Graveler\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Golem\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Grimer\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Muk\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Exeggutor\')'), + FormId: 4 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Marowak\')'), + FormId: 4 + }, + ]) + }, + + down: async (queryInterface) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.dropTable('users'); + */ + await queryInterface.bulkDelete('PokemonTypes') + + await queryInterface.bulkDelete('PokemonForms') + + await queryInterface.bulkDelete('Forms') + + await queryInterface.bulkDelete('Types') + + return queryInterface.bulkDelete('Pokemons') + } +} diff --git a/models/PokemonForms.js b/models/PokemonForms.js index 7f8dcff..b640061 100644 --- a/models/PokemonForms.js +++ b/models/PokemonForms.js @@ -7,7 +7,7 @@ const PokemonForms = (connection, Sequelize, Forms, Pokemons) => { references: { model: Pokemons, key: 'pokedexNumber' } }, FormId: { - type: Sequelize.STRING, + type: Sequelize.INTEGER, allowNull: false, primaryKey: true, references: { model: Forms, key: 'id' } diff --git a/models/PokemonTypes.js b/models/PokemonTypes.js index baca4b7..a1cdba0 100644 --- a/models/PokemonTypes.js +++ b/models/PokemonTypes.js @@ -6,7 +6,7 @@ const PokemonTypes = (connection, Sequelize, Pokemons, Types) => { primaryKey: true, references: { model: Pokemons, key: 'pokedexNumber' } }, - TypeId: { type: Sequelize.STRING, allowNull: false, primaryKey: true, references: { model: Types, key: 'id' } } + TypeId: { type: Sequelize.INTEGER, allowNull: false, primaryKey: true, references: { model: Types, key: 'id' } } }, { defaultScope: { attributes: { exclude: ['deletedAt'] } diff --git a/package-lock.json b/package-lock.json index ed9e42e..0cb017f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -117,8 +117,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { "version": "1.3.7", @@ -246,7 +245,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -330,8 +328,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "binary-extensions": { "version": "2.0.0", @@ -448,7 +445,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -515,8 +511,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "cardinal": { "version": "2.1.1", @@ -617,6 +612,26 @@ "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", "dev": true }, + "cli-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -664,7 +679,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -672,20 +686,26 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } }, "configstore": { "version": "5.0.1", @@ -773,6 +793,15 @@ "integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g==", "dev": true }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -886,6 +915,38 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -911,6 +972,58 @@ "once": "^1.4.0" } }, + "env-cmd": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", + "integrity": "sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==", + "requires": { + "commander": "^4.0.0", + "cross-spawn": "^7.0.0" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + }, + "cross-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", + "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "es-abstract": { "version": "1.17.5", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", @@ -941,6 +1054,46 @@ "is-symbol": "^1.0.2" } }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escape-goat": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", @@ -1086,6 +1239,15 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -1138,6 +1300,21 @@ } } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==" + } + } + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -1233,7 +1410,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -1282,11 +1458,20 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.1.2", @@ -1317,8 +1502,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-func-name": { "version": "2.0.0", @@ -1339,7 +1523,6 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1398,8 +1581,7 @@ "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, "growl": { "version": "1.10.5", @@ -1515,7 +1697,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -1524,14 +1705,12 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { "version": "7.1.0", @@ -1779,8 +1958,35 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "js-beautify": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.11.0.tgz", + "integrity": "sha512-a26B+Cx7USQGSWnz9YxgJNMmML/QG2nqIaL7VVYPCXbqiKz8PN0waSNvroMtvAK6tY7g/wPdNWGEP+JTNIBr6A==", + "requires": { + "config-chain": "^1.1.12", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "mkdirp": "~1.0.3", + "nopt": "^4.0.3" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + } + } }, "js-stringify": { "version": "1.0.2", @@ -1821,6 +2027,14 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jstransformer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", @@ -1881,7 +2095,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -1931,6 +2144,14 @@ "yallist": "^3.0.2" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "~0.10.2" + } + }, "make-dir": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", @@ -1945,6 +2166,21 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -1989,7 +2225,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2249,6 +2484,11 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -2404,7 +2644,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -2438,11 +2677,24 @@ "word-wrap": "~1.2.3" } }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "p-cancelable": { "version": "1.1.0", @@ -2454,7 +2706,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -2463,7 +2714,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -2471,8 +2721,7 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "package-json": { "version": "6.5.0", @@ -2503,14 +2752,12 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "2.0.1", @@ -2566,6 +2813,11 @@ "asap": "~2.0.3" } }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -2855,14 +3107,12 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { "version": "1.16.1", @@ -3033,6 +3283,70 @@ "wkx": "^0.4.8" } }, + "sequelize-cli": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-5.5.1.tgz", + "integrity": "sha512-ZM4kUZvY3y14y+Rq3cYxGH7YDJz11jWHcN2p2x7rhAIemouu4CEXr5ebw30lzTBtyXV4j2kTO+nUjZOqzG7k+Q==", + "requires": { + "bluebird": "^3.5.3", + "cli-color": "^1.4.0", + "fs-extra": "^7.0.1", + "js-beautify": "^1.8.8", + "lodash": "^4.17.5", + "resolve": "^1.5.0", + "umzug": "^2.1.0", + "yargs": "^13.1.0" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + } + } + }, "sequelize-pool": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", @@ -3052,8 +3366,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setprototypeof": { "version": "1.1.1", @@ -3080,6 +3393,11 @@ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -3238,7 +3556,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" }, @@ -3246,8 +3563,7 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" } } }, @@ -3321,6 +3637,15 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -3380,6 +3705,11 @@ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", "dev": true }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -3442,6 +3772,14 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "optional": true }, + "umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "requires": { + "bluebird": "^3.7.2" + } + }, "undefsafe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", @@ -3477,6 +3815,11 @@ "crypto-random-string": "^2.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -3616,8 +3959,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "wide-align": { "version": "1.1.3", @@ -3714,7 +4056,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -3724,20 +4065,17 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -3749,8 +4087,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", @@ -3782,8 +4119,7 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "3.1.1", @@ -3812,7 +4148,6 @@ "version": "13.1.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/package.json b/package.json index d43a5ca..b86b08a 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,13 @@ "description": "", "main": ".eslintrc.js", "scripts": { - "dev": "./node_modules/.bin/nodemon index.js", + "dev": "./node_modules/.bin/env-cmd ./node_modules/.bin/nodemon index.js", + "dev:migrate": "./node_modules/.bin/env-cmd ./node_modules/.bin/sequelize db:migrate --env development --config ./configs/sequelize.js", "lint": "npm run lint:pug && npm run lint:eslint", "lint:eslint": "./node_modules/.bin/eslint --format codeframe .", "lint:esfix": "./node_modules/.bin/eslint --fix --format codeframe .", "lint:pug": "./node_modules/.bin/pug-lint .", - "test": "./node_modules/.bin/mocha tests/**/*.tests.js" + "test": "./node_modules/.bin/env-cmd ./node_modules/.bin/mocha tests/**/*.tests.js" }, "repository": { "type": "git", @@ -24,6 +25,7 @@ "devDependencies": { "chai": "^4.2.0", "eslint": "^6.8.0", + "env-cmd": "^10.1.0", "mocha": "^7.1.2", "nodemon": "^2.0.3", "pug-lint": "^2.6.0", @@ -35,6 +37,7 @@ "express": "^4.17.1", "mysql2": "^2.1.0", "pug": "^2.0.4", - "sequelize": "^5.21.8" + "sequelize": "^5.21.8", + "sequelize-cli": "^5.5.1" } } \ No newline at end of file From 58c27a2455863f3a4745cb6808097e297bade303 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Sun, 24 May 2020 23:48:06 -0400 Subject: [PATCH 19/26] Fixed coopy pastas in the describe and it desriptions. --- tests/controllers/api.tests.js | 26 +++++++++++++------------- tests/mocks/pokemonData.js | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/controllers/api.tests.js b/tests/controllers/api.tests.js index bfa2863..49ae62c 100644 --- a/tests/controllers/api.tests.js +++ b/tests/controllers/api.tests.js @@ -107,7 +107,7 @@ describe('Controllers - API', () => { expect(stubbedSend).to.have.been.calledWith(pokemonList) }) - it('returns a 500 error with an error message when the database call throws an error.', async () => { + it('returns a 500 error with a message when the database call throws an error.', async () => { stubbedPokemonsFindAll.throws('ERROR!') await getAllPokemon({}, response) @@ -118,7 +118,7 @@ describe('Controllers - API', () => { }) describe('getPokemonById', () => { - it('retrieves the pokemon associated with the id passed by the user with the pokemon\'s alternate formm and types and responds with a 200 status and sends the list of pokemon back.', async () => { + it('retrieves the pokemon associated with the id passed by the user with the pokemon\'s alternate form and types and responds with a 200 status and sends the list of pokemon back.', async () => { stubbedPokemonsFindOne.returns(singlePokemonWithAltForm) const request = { params: { id: 'Grimer' } } @@ -132,7 +132,7 @@ describe('Controllers - API', () => { expect(stubbedStatusDotSend).to.have.been.calledWith(singlePokemonWithAltForm) }) - it('returns a 404 status and a message when no pokemon is found matching the id provided by the user.', async () => { + it('returns a 404 status with a message when no pokemon is found matching the id provided by the user.', async () => { stubbedPokemonsFindOne.returns(null) const request = { params: { id: 'ratata' } } @@ -157,7 +157,7 @@ describe('Controllers - API', () => { }) describe('getPokemonByGenerationId', () => { - it('retrieves all the pokemon in the user specified id.', async () => { + it('retrieves all the pokemon in a generation provided by the user specified id.', async () => { stubbedPokemonsFindAll.returns(pokemonList) const request = { params: { id: '1' } } @@ -169,7 +169,7 @@ describe('Controllers - API', () => { expect(stubbedSend).to.have.been.calledWith(pokemonList) }) - it('returns a 404 error when a user searches for a generation thats not in the database.', async () => { + it('returns a 404 error when a user searches for a generation that does not exist in the database.', async () => { stubbedPokemonsFindAll.returns('') const request = { params: { id: 4 } } @@ -191,8 +191,8 @@ describe('Controllers - API', () => { }) describe('saveNewPokemon', () => { - it('either finds a pokemon matching the name provided or creates a new pokemon based on the by the user inputs.', async () => { - stubbedPokemonsFindOrCreate.onCall(0).returns([newPokemon, false]) + it('either finds a pokemon matching the name provided or creates a new pokemon based on the id input by user.', async () => { + stubbedPokemonsFindOrCreate.returns([newPokemon, false]) stubbedTypesFindOrCreate.onCall(1).returns(7) stubbedTypesFindOrCreate.onCall(2).returns(8) stubbedPokemonTypesFindOrCreate.onCall(3).returns({ PokemonPokedexNumber: 154, typeId: 7 }) @@ -284,7 +284,7 @@ describe('Controllers - API', () => { describe('Controllers - Forms', () => { describe('getAllForms', () => { - it('retrieves a list of all form names.', async () => { + it('retrieves a list of all form names.', async () => { stubbedFormsFindAll.returns(formsList) await getAllForms({}, response) @@ -304,7 +304,7 @@ describe('Controllers - API', () => { }) describe('getFormById', () => { - it('retrieves the form associated with the id passed by the user with the pokemon that have that form and responds with a 200 status and sends the list of pokemon back.', async () => { + it('retrieves a form and the associated pokemon to the form and responds with a 200 status and sends the list of pokemon back.', async () => { stubbedFormsFindOne.returns(singleAltFormWithPokemon) const request = { params: { id: 'alolan' } } @@ -318,7 +318,7 @@ describe('Controllers - API', () => { expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) }) - it('returns a 404 status and a message when no form is found matching the id provided by the user.', async () => { + it('returns a 404 status and a message when no form is found matching the id provided by the user.', async () => { stubbedFormsFindOne.returns(null) const request = { params: { id: 'pikachu' } } @@ -345,7 +345,7 @@ describe('Controllers - API', () => { describe('Controllers - Types', () => { describe('getAllTypes', () => { - it('retrieves a list of all alternate form names.', async () => { + it('retrieves a list of all types.', async () => { stubbedTypesFindAll.returns(pokemonList) await getAllTypes({}, response) @@ -365,7 +365,7 @@ describe('Controllers - API', () => { }) describe('getTypeById', () => { - it('retrieves the alternate form associated with the id passed by the user with the pokemon that have that alternate form and responds with a 200 status and sends the list of pokemon back.', async () => { + it('retrieves all the pokemon under a user specified type and responds with a 200 status and sends the list of pokemon back.', async () => { stubbedTypesFindOne.returns(singleAltFormWithPokemon) const request = { params: { id: 'alolan' } } @@ -379,7 +379,7 @@ describe('Controllers - API', () => { expect(stubbedStatusDotSend).to.have.been.calledWith(singleAltFormWithPokemon) }) - it('returns a 404 status and a message when no alternate form is found matching the id provided by the user.', async () => { + it('returns a 404 status and a message when no type is found matching the id provided by the user.', async () => { stubbedTypesFindOne.returns(null) const request = { params: { id: 'shadow' } } diff --git a/tests/mocks/pokemonData.js b/tests/mocks/pokemonData.js index e47fa60..8a0c0ee 100644 --- a/tests/mocks/pokemonData.js +++ b/tests/mocks/pokemonData.js @@ -120,7 +120,7 @@ const newPokemon = { pokedexNumber: 154, generationNumber: 1, fromId: null, - isisProtected: 0, + isProtected: 0, name: 'Leafeon', updatedAt: '2020-05-24T16:42:32.743Z', createdAt: '2020-05-24T16:42:32.743Z' From ea24f5fbab492f8281e3d5563b6fd4da89223e98 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Mon, 25 May 2020 17:03:49 -0400 Subject: [PATCH 20/26] Changed the connection parameters to use environment variables instead, in ./models/index.js --- models/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/models/index.js b/models/index.js index e686fb3..cf57598 100644 --- a/models/index.js +++ b/models/index.js @@ -4,9 +4,13 @@ const FormsModel = require('./Forms') const TypesModel = require('./Types') const PokemonFormsModel = require('./PokemonForms') const PokemonTypesModel = require('./PokemonTypes') +const allConfigs = require('../configs/sequelize') -const connection = new Sequelize('pokemonApi', 'ash', 'P1k4chU', { - host: 'localhost', dialect: 'mysql' +const environment = process.env.NODE_ENV || 'development' +const config = allConfigs[environment] + +const connection = new Sequelize(config.database, config.username, config.password, { + host: config.host, dialect: config.dialect }) const Pokemons = PokemonsModel(connection, Sequelize) From 857089f598e7b0ed697488ec6606928160bd9fb1 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Mon, 25 May 2020 18:22:50 -0400 Subject: [PATCH 21/26] Worked on the documentation page: restyled, corrected routes to be better named, and added in more get path documentation. --- public/css/styles.css | 15 ++- views/index.pug | 2 +- views/partials/leftSideDocumentation.pug | 23 +++- views/partials/rightSideDocumentaion.pug | 129 +++++++++++++++-------- 4 files changed, 117 insertions(+), 52 deletions(-) diff --git a/public/css/styles.css b/public/css/styles.css index 7738eea..56aa35e 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -2,14 +2,19 @@ body{ margin-top: 150px; } -h2{ +h1{ text-align: center; } -h3{ +h2{ margin-bottom: 5px; } +span{ + font-size: 0.9em; + font-weight: bold; +} + .delete{ color: crimson; font-weight: bold; @@ -36,9 +41,9 @@ h3{ .highlighted:after { bottom: 0; - border-bottom: 15px solid transparent; + border-bottom: 14px solid transparent; border-left: 15px solid lightgray; - border-top: 15px solid transparent; + border-top: 14px solid transparent; content: ""; position: absolute; right: -15px; @@ -62,7 +67,7 @@ h3{ } .right-container{ - margin: 0px 20px; + margin: 80px 20px; position: relative; width: 440px; } diff --git a/views/index.pug b/views/index.pug index 972ff05..2f59885 100644 --- a/views/index.pug +++ b/views/index.pug @@ -5,7 +5,7 @@ html script(src="/javascripts/indexPugInteraction.js") body - h2 Welcome to the Pokemon API + h1 Welcome to the Pokemon API div(class="main-container") include partials/leftSideDocumentation.pug diff --git a/views/partials/leftSideDocumentation.pug b/views/partials/leftSideDocumentation.pug index 12c5c5c..80d7393 100644 --- a/views/partials/leftSideDocumentation.pug +++ b/views/partials/leftSideDocumentation.pug @@ -2,13 +2,30 @@ div(class="left-container") div(class="tabs highlighted" id="getAll" onclick="updateSelected('getAll')") span(class="get") GET span /pokemon + + div(class="tabs" id="getPokemonById" onclick="updateSelected('getPokemonById')") + span(class="get") GET + span /pokemon/{name} + div(class="tabs" id="getGeneration" onclick="updateSelected('getGeneration')") span(class="get") GET span /generation/{genId} - div(class="tabs" id="getPokemonById" onclick="updateSelected('getPokemonById')") + div(class="tabs" id="getTypes" onclick="updateSelected('getTypes')") + span(class="get") GET + span /types/ + + div(class="tabs" id="getTypesById" onclick="updateSelected('getTypesById')") + span(class="get") GET + span /types/{name} + + div(class="tabs" id="getForms" onclick="updateSelected('getForms')") + span(class="get") GET + span /forms/ + + div(class="tabs" id="getFormsById" onclick="updateSelected('getFormsById')") span(class="get") GET - span /pokemon/{pokemonId} + span /forms/{name} div(class="tabs" id="postPokemon" onclick="updateSelected('postPokemon')") span(class="post") POST @@ -16,4 +33,4 @@ div(class="left-container") div(class="tabs" id="deletePokemonById" onclick="updateSelected('deletePokemonById')") span(class="delete") DELETE - span /pokemon/{pokemonId} + span /pokemon/{name} diff --git a/views/partials/rightSideDocumentaion.pug b/views/partials/rightSideDocumentaion.pug index c94b405..6204a45 100644 --- a/views/partials/rightSideDocumentaion.pug +++ b/views/partials/rightSideDocumentaion.pug @@ -1,52 +1,95 @@ div(class="right-container") div(class="method" id="getAll") - h3 Method - div(class="get spacing") GET - h3 Route - div(class="spacing") http://localhost:1337/pokemon - h3 Headers - div(class="spacing") None needed - h3 Decription - div(class="spacing") Returns a list all of the pokemon in the database. + h2 Method + h3(class="get spacing") GET + h2 Route + h3(class="spacing") http://localhost:1337/pokemon + h2 Headers + h3(class="spacing") None needed + h2 Decription + h3(class="spacing") Returns a list all of the pokemon in the database. + + div(class="method hidden" id="getPokemonById") + h2 Method + h3(class="spacing get") GET + h2 Route + h3(class="spacing") http://localhost:1337/pokemon/{name} + h2 Headers + h3(class="spacing") None needed + h2 Decription + h3(class="spacing") Returns the pokemon associated with the {name}. div(class="method hidden" id="getGeneration") - h3 Method - div(class="spacing get") GET - h3 Route - div(class="spacing") http://localhost:1337/pokemon/generations/{genId} - h3 Headers - div(class="spacing") None needed - h3 Decription - div(class="spacing") Returns the generation list of all pokemon associated with {genId}. + h2 Method + h3(class="spacing get") GET + h2 Route + h3(class="spacing") http://localhost:1337/pokemon/generation/{genId} + h2 Headers + h3(class="spacing") None needed + h2 Decription + h3(class="spacing") Returns the list of pokemon from gemeration passed with {genId}. - div(class="method hidden" id="getPokemonById") - h3 Method - div(class="spacing get") GET - h3 Route - div(class="spacing") http://localhost:1337/pokemon/{pokemonId} - h3 Headers - div(class="spacing") None needed - h3 Decription - div(class="spacing") Returns the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). + div(class="method hidden" id="getTypes") + h2 Method + h3(class="spacing get") GET + h2 Route + h3(class="spacing") http://localhost:1337/types/ + h2 Headers + h3(class="spacing") None needed + h2 Decription + h3(class="spacing") Returns a list of all the types. + + div(class="method hidden" id="getTypesById") + h2 Method + h3(class="spacing get") GET + h2 Route + h3(class="spacing") http://localhost:1337/types/{name} + h2 Headers + h3(class="spacing") None needed + h2 Decription + h3(class="spacing") Returns the type and all pokemon associated with the type {name} provided. + + div(class="method hidden" id="getForms") + h2 Method + h3(class="spacing get") GET + h2 Route + h3(class="spacing") http://localhost:1337/forms/ + h2 Headers + h3(class="spacing") None needed + h2 Decription + h3(class="spacing") Returns a list of all the forms. + + div(class="method hidden" id="getFormsById") + h2 Method + h3(class="spacing get") GET + h2 Route + h3(class="spacing") http://localhost:1337/forms/{name} + h2 Headers + h3(class="spacing") None needed + h2 Decription + h3(class="spacing") Returns the form and all pokemon associated with the form {name} provided. div(class="method hidden" id="postPokemon") - h3 Method - div(class="spacing post") POST - h3 Route - div(class="spacing") http://localhost:1337/pokemon - h3 Headers - div(class="spacing") Content-Type: application/json - h3 Body - div(class="spacing") { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']" } - h3 Decription - div(class="spacing") Saves a new pokemon to the database. + h2 Method + h3(class="spacing post") POST + h2 Route + h3(class="spacing") http://localhost:1337/pokemon + h2 Headers + h3(class="spacing") Content-Type: application/json + h2 Body + h3(class="spacing") { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']", "fromId": "null" } + h2 Decription + h3(class="spacing") + | Saves a new pokemon to the database. (Note: the fromId is if the pokemon is an evolution of + | another pokemon Bulbasuar has 'fromId: null' as its a base evolution where as Ivysaur has + | 'fromId: 1' as it evolves from Bulbasaur) div(class="method hidden" id="deletePokemonById") - h3 Method - div(class="spacing delete") DELETE - h3 Route - div(class="spacing") http://localhost:1337/pokemon/{pokemonId} - h3 Headers - div(class="spacing") None needed - h3 Decription - div(class="spacing") Deletes the pokemon associated with the {id} (Id's are also the pokemon's pokedex number). + h2 Method + h3(class="spacing delete") DELETE + h2 Route + h3(class="spacing") http://localhost:1337/pokemon/{name} + h2 Headers + h3(class="spacing") None needed + h2 Decription + h3(class="spacing") Deletes the pokemon associated with the {name}. From e5811940950b55e1e22de15f6f2e6d0fccd60f5b Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Mon, 25 May 2020 18:29:50 -0400 Subject: [PATCH 22/26] Got a a little OCD over the higlightinf flag now lining up correctly. --- public/css/styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/css/styles.css b/public/css/styles.css index 56aa35e..eacee55 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -41,7 +41,7 @@ span{ .highlighted:after { bottom: 0; - border-bottom: 14px solid transparent; + border-bottom: 15px solid transparent; border-left: 15px solid lightgray; border-top: 14px solid transparent; content: ""; From 4a8469de37d4f5121698826a7633303472ff195c Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Thu, 28 May 2020 00:02:28 -0400 Subject: [PATCH 23/26] Fixed a test to be ore specific, added data to migrations, fixed PokemonForms to have an id column to allow for duplicate entries (because pokemon need to be overly complicated). Also fixed an error where a column was set to auto increment but wasn't supposed to have that. --- .../20200524223604-initial-table-creation.js | 4 +- ...0524230810-initial-data-load-first-gen.js} | 506 +++++++++++++++++- models/PokemonForms.js | 4 +- tests/controllers/api.tests.js | 5 +- 4 files changed, 500 insertions(+), 19 deletions(-) rename migrations/{20200524230810-initial-data-load.js => 20200524230810-initial-data-load-first-gen.js} (51%) diff --git a/migrations/20200524223604-initial-table-creation.js b/migrations/20200524223604-initial-table-creation.js index d8d2fa0..a1c4162 100644 --- a/migrations/20200524223604-initial-table-creation.js +++ b/migrations/20200524223604-initial-table-creation.js @@ -66,16 +66,14 @@ module.exports = { }) return queryInterface.createTable('PokemonForms', { + id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, PokemonPokedexNumber: { type: Sequelize.INTEGER, - autoIncrement: true, - primaryKey: true, references: { model: 'Pokemons', key: 'pokedexNumber' } }, FormId: { type: Sequelize.INTEGER, allowNull: false, - primaryKey: true, references: { model: 'Forms', key: 'id' } }, createdAt: { type: Sequelize.DATE, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, diff --git a/migrations/20200524230810-initial-data-load.js b/migrations/20200524230810-initial-data-load-first-gen.js similarity index 51% rename from migrations/20200524230810-initial-data-load.js rename to migrations/20200524230810-initial-data-load-first-gen.js index 22d8699..b501aa6 100644 --- a/migrations/20200524230810-initial-data-load.js +++ b/migrations/20200524230810-initial-data-load-first-gen.js @@ -33,7 +33,7 @@ module.exports = { { name: 'Fearow', generationNumber: 1, fromId: 21, isProtected: 1 }, { name: 'Ekans', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Arbok', generationNumber: 1, fromId: 23, isProtected: 1 }, - { name: 'Pikachu', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Pikachu', generationNumber: 1, fromId: 172, isProtected: 1 }, { name: 'Raichu', generationNumber: 1, fromId: 25, isProtected: 1 }, { name: 'Sandshrew', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Sandslash', generationNumber: 1, fromId: 27, isProtected: 1 }, @@ -43,11 +43,11 @@ module.exports = { { name: 'Nidoran♂', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Nidorino', generationNumber: 1, fromId: 32, isProtected: 1 }, { name: 'Nidoking', generationNumber: 1, fromId: 33, isProtected: 1 }, - { name: 'Clefairy', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Clefairy', generationNumber: 1, fromId: 173, isProtected: 1 }, { name: 'Clefable', generationNumber: 1, fromId: 35, isProtected: 1 }, { name: 'Vulpix', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Ninetales', generationNumber: 1, fromId: 37, isProtected: 1 }, - { name: 'Jigglypuff', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Jigglypuff', generationNumber: 1, fromId: 174, isProtected: 1 }, { name: 'Wigglytuff', generationNumber: 1, fromId: 39, isProtected: 1 }, { name: 'Zubat', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Golbat', generationNumber: 1, fromId: 41, isProtected: 1 }, @@ -114,14 +114,14 @@ module.exports = { { name: 'Exeggutor', generationNumber: 1, fromId: 102, isProtected: 1 }, { name: 'Cubone', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Marowak', generationNumber: 1, fromId: 104, isProtected: 1 }, - { name: 'Hitmonlee', generationNumber: 1, fromId: null, isProtected: 1 }, - { name: 'Hitmonchan', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Hitmonlee', generationNumber: 1, fromId: 236, isProtected: 1 }, + { name: 'Hitmonchan', generationNumber: 1, fromId: 236, isProtected: 1 }, { name: 'Lickitung', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Koffing', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Weezing', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Rhyhorn', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Rhydon', generationNumber: 1, fromId: 111, isProtected: 1 }, - { name: 'Chansey', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Chansey', generationNumber: 1, fromId: 440, isProtected: 1 }, { name: 'Tangela', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Kangaskhan', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Horsea', generationNumber: 1, fromId: null, isProtected: 1 }, @@ -130,11 +130,11 @@ module.exports = { { name: 'Seaking', generationNumber: 1, fromId: 118, isProtected: 1 }, { name: 'Staryu', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Starmie', generationNumber: 1, fromId: 120, isProtected: 1 }, - { name: 'Mr. Mime', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Mr. Mime', generationNumber: 1, fromId: 439, isProtected: 1 }, { name: 'Scyther', generationNumber: 1, fromId: null, isProtected: 1 }, - { name: 'Jynx', generationNumber: 1, fromId: null, isProtected: 1 }, - { name: 'Electabuzz', generationNumber: 1, fromId: null, isProtected: 1 }, - { name: 'Magmar', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Jynx', generationNumber: 1, fromId: 238, isProtected: 1 }, + { name: 'Electabuzz', generationNumber: 1, fromId: 239, isProtected: 1 }, + { name: 'Magmar', generationNumber: 1, fromId: 240, isProtected: 1 }, { name: 'Pinsir', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Tauros', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Magikarp', generationNumber: 1, fromId: null, isProtected: 1 }, @@ -151,7 +151,7 @@ module.exports = { { name: 'Kabuto', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Kabutops', generationNumber: 1, fromId: 140, isProtected: 1 }, { name: 'Aerodactyl', generationNumber: 1, fromId: null, isProtected: 1 }, - { name: 'Snorlax', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Snorlax', generationNumber: 1, fromId: 446, isProtected: 1 }, { name: 'Articuno', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Zapdos', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Moltres', generationNumber: 1, fromId: null, isProtected: 1 }, @@ -160,6 +160,106 @@ module.exports = { { name: 'Dragonite', generationNumber: 1, fromId: 148, isProtected: 1 }, { name: 'Mewtwo', generationNumber: 1, fromId: null, isProtected: 1 }, { name: 'Mew', generationNumber: 1, fromId: null, isProtected: 1 }, + { name: 'Chikorita', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Bayleef', generationNumber: 2, fromId: 153, isProtected: 1 }, + { name: 'Meganium', generationNumber: 2, fromId: 154, isProtected: 1 }, + { name: 'Cyndaquil', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Quilava', generationNumber: 2, fromId: 155, isProtected: 1 }, + { name: 'Typhlosion', generationNumber: 2, fromId: 156, isProtected: 1 }, + { name: 'Totodile', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Croconaw', generationNumber: 2, fromId: 158, isProtected: 1 }, + { name: 'Feraligatr', generationNumber: 2, fromId: 159, isProtected: 1 }, + { name: 'Sentret', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Furret', generationNumber: 2, fromId: 161, isProtected: 1 }, + { name: 'Hoothoot', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Noctowl', generationNumber: 2, fromId: 163, isProtected: 1 }, + { name: 'Ledyba', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Ledian', generationNumber: 2, fromId: 165, isProtected: 1 }, + { name: 'Spinarak', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Ariados', generationNumber: 2, fromId: 167, isProtected: 1 }, + { name: 'Crobat', generationNumber: 2, fromId: 42, isProtected: 1 }, + { name: 'Chinchou', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Lanturn', generationNumber: 2, fromId: 170, isProtected: 1 }, + { name: 'Pichu', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Cleffa', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Igglybuff', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Togepi', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Togetic', generationNumber: 2, fromId: 175, isProtected: 1 }, + { name: 'Natu', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Xatu', generationNumber: 2, fromId: 177, isProtected: 1 }, + { name: 'Mareep', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Flaaffy', generationNumber: 2, fromId: 179, isProtected: 1 }, + { name: 'Ampharos', generationNumber: 2, fromId: 180, isProtected: 1 }, + { name: 'Bellossom', generationNumber: 2, fromId: 44, isProtected: 1 }, + { name: 'Marill', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Azumarill', generationNumber: 2, fromId: 183, isProtected: 1 }, + { name: 'Sudowoodo', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Politoed', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Hoppip', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Skiploom', generationNumber: 2, fromId: 187, isProtected: 1 }, + { name: 'Jumpluff', generationNumber: 2, fromId: 188, isProtected: 1 }, + { name: 'Aipom', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Sunkern', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Sunflora', generationNumber: 2, fromId: 191, isProtected: 1 }, + { name: 'Yanma', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Wooper', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Quagsire', generationNumber: 2, fromId: 194, isProtected: 1 }, + { name: 'Espeon', generationNumber: 2, fromId: 133, isProtected: 1 }, + { name: 'Umbreon', generationNumber: 2, fromId: 133, isProtected: 1 }, + { name: 'Murkrow', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Slowking', generationNumber: 2, fromId: 79, isProtected: 1 }, + { name: 'Misdreavus', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Unown', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Wobbuffet', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Girafarig', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Pineco', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Forretress', generationNumber: 2, fromId: 204, isProtected: 1 }, + { name: 'Dunsparce', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Gligar', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Steelix', generationNumber: 2, fromId: 95, isProtected: 1 }, + { name: 'Snubbull', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Granbull', generationNumber: 2, fromId: 209, isProtected: 1 }, + { name: 'Qwilfish', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Scizor', generationNumber: 2, fromId: 12, isProtected: 1 }, + { name: 'Shuckle', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Heracross', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Sneasel', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Teddiursa', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Ursaring', generationNumber: 2, fromId: 216, isProtected: 1 }, + { name: 'Slugma', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Magcargo', generationNumber: 2, fromId: 218, isProtected: 1 }, + { name: 'Swinub', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Piloswine', generationNumber: 2, fromId: 220, isProtected: 1 }, + { name: 'Corsola', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Remoraid', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Octillery', generationNumber: 2, fromId: 223, isProtected: 1 }, + { name: 'Delibird', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Mantine', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Skarmory', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Houndour', generationNumber: 2, fromId: 228, isProtected: 1 }, + { name: 'Houndoom', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Kingdra', generationNumber: 2, fromId: 117, isProtected: 1 }, + { name: 'Phanpy', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Donphan', generationNumber: 2, fromId: 231, isProtected: 1 }, + { name: 'Porygon2', generationNumber: 2, fromId: 137, isProtected: 1 }, + { name: 'Stantler', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Smeargle', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Tyrogue', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Hitmontop', generationNumber: 2, fromId: 236, isProtected: 1 }, + { name: 'Smoochum', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Elekid', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Magby', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Miltank', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Blissey', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Raikou', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Entei', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Suicune', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Larvitar', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Pupitar', generationNumber: 2, fromId: 246, isProtected: 1 }, + { name: 'Tyranitar', generationNumber: 2, fromId: 247, isProtected: 1 }, + { name: 'Lugia', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Ho-Oh', generationNumber: 2, fromId: null, isProtected: 1 }, + { name: 'Celebi', generationNumber: 2, fromId: null, isProtected: 1 }, ]) await queryInterface.bulkInsert('Types', [ @@ -411,9 +511,318 @@ module.exports = { { PokemonPokedexNumber: 149, typeId: 8 }, { PokemonPokedexNumber: 150, typeId: 15 }, { PokemonPokedexNumber: 151, typeId: 15 }, + { PokemonPokedexNumber: 152, typeId: 10 }, + { PokemonPokedexNumber: 153, typeId: 10 }, + { PokemonPokedexNumber: 154, typeId: 10 }, + { PokemonPokedexNumber: 155, typeId: 7 }, + { PokemonPokedexNumber: 156, typeId: 7 }, + { PokemonPokedexNumber: 157, typeId: 7 }, + { PokemonPokedexNumber: 158, typeId: 18 }, + { PokemonPokedexNumber: 159, typeId: 18 }, + { PokemonPokedexNumber: 160, typeId: 18 }, + { PokemonPokedexNumber: 161, typeId: 13 }, + { PokemonPokedexNumber: 162, typeId: 13 }, + { PokemonPokedexNumber: 163, typeId: 13 }, + { PokemonPokedexNumber: 163, typeId: 8 }, + { PokemonPokedexNumber: 164, typeId: 13 }, + { PokemonPokedexNumber: 164, typeId: 8 }, + { PokemonPokedexNumber: 165, typeId: 1 }, + { PokemonPokedexNumber: 165, typeId: 8 }, + { PokemonPokedexNumber: 166, typeId: 1 }, + { PokemonPokedexNumber: 166, typeId: 8 }, + { PokemonPokedexNumber: 167, typeId: 1 }, + { PokemonPokedexNumber: 167, typeId: 14 }, + { PokemonPokedexNumber: 168, typeId: 1 }, + { PokemonPokedexNumber: 168, typeId: 14 }, + { PokemonPokedexNumber: 169, typeId: 14 }, + { PokemonPokedexNumber: 169, typeId: 8 }, + { PokemonPokedexNumber: 170, typeId: 18 }, + { PokemonPokedexNumber: 170, typeId: 4 }, + { PokemonPokedexNumber: 171, typeId: 18 }, + { PokemonPokedexNumber: 171, typeId: 4 }, + { PokemonPokedexNumber: 172, typeId: 4 }, + { PokemonPokedexNumber: 173, typeId: 5 }, + { PokemonPokedexNumber: 174, typeId: 13 }, + { PokemonPokedexNumber: 174, typeId: 5 }, + { PokemonPokedexNumber: 175, typeId: 5 }, + { PokemonPokedexNumber: 176, typeId: 5 }, + { PokemonPokedexNumber: 176, typeId: 8 }, + { PokemonPokedexNumber: 177, typeId: 15 }, + { PokemonPokedexNumber: 177, typeId: 8 }, + { PokemonPokedexNumber: 178, typeId: 15 }, + { PokemonPokedexNumber: 178, typeId: 8 }, + { PokemonPokedexNumber: 179, typeId: 4 }, + { PokemonPokedexNumber: 180, typeId: 4 }, + { PokemonPokedexNumber: 181, typeId: 4 }, + { PokemonPokedexNumber: 182, typeId: 10 }, + { PokemonPokedexNumber: 183, typeId: 18 }, + { PokemonPokedexNumber: 183, typeId: 5 }, + { PokemonPokedexNumber: 184, typeId: 18 }, + { PokemonPokedexNumber: 184, typeId: 5 }, + { PokemonPokedexNumber: 185, typeId: 16 }, + { PokemonPokedexNumber: 186, typeId: 18 }, + { PokemonPokedexNumber: 187, typeId: 10 }, + { PokemonPokedexNumber: 187, typeId: 8 }, + { PokemonPokedexNumber: 188, typeId: 10 }, + { PokemonPokedexNumber: 188, typeId: 8 }, + { PokemonPokedexNumber: 189, typeId: 10 }, + { PokemonPokedexNumber: 189, typeId: 8 }, + { PokemonPokedexNumber: 190, typeId: 13 }, + { PokemonPokedexNumber: 191, typeId: 10 }, + { PokemonPokedexNumber: 192, typeId: 10 }, + { PokemonPokedexNumber: 193, typeId: 1 }, + { PokemonPokedexNumber: 193, typeId: 8 }, + { PokemonPokedexNumber: 194, typeId: 18 }, + { PokemonPokedexNumber: 194, typeId: 11 }, + { PokemonPokedexNumber: 195, typeId: 18 }, + { PokemonPokedexNumber: 195, typeId: 11 }, + { PokemonPokedexNumber: 196, typeId: 15 }, + { PokemonPokedexNumber: 197, typeId: 2 }, + { PokemonPokedexNumber: 198, typeId: 2 }, + { PokemonPokedexNumber: 198, typeId: 8 }, + { PokemonPokedexNumber: 199, typeId: 18 }, + { PokemonPokedexNumber: 199, typeId: 15 }, + { PokemonPokedexNumber: 200, typeId: 9 }, + { PokemonPokedexNumber: 201, typeId: 15 }, + { PokemonPokedexNumber: 202, typeId: 15 }, + { PokemonPokedexNumber: 203, typeId: 13 }, + { PokemonPokedexNumber: 203, typeId: 15 }, + { PokemonPokedexNumber: 204, typeId: 1 }, + { PokemonPokedexNumber: 205, typeId: 1 }, + { PokemonPokedexNumber: 205, typeId: 17 }, + { PokemonPokedexNumber: 206, typeId: 13 }, + { PokemonPokedexNumber: 207, typeId: 11 }, + { PokemonPokedexNumber: 207, typeId: 8 }, + { PokemonPokedexNumber: 208, typeId: 17 }, + { PokemonPokedexNumber: 208, typeId: 11 }, + { PokemonPokedexNumber: 209, typeId: 5 }, + { PokemonPokedexNumber: 210, typeId: 5 }, + { PokemonPokedexNumber: 211, typeId: 18 }, + { PokemonPokedexNumber: 211, typeId: 14 }, + { PokemonPokedexNumber: 212, typeId: 1 }, + { PokemonPokedexNumber: 212, typeId: 17 }, + { PokemonPokedexNumber: 213, typeId: 16 }, + { PokemonPokedexNumber: 214, typeId: 1 }, + { PokemonPokedexNumber: 214, typeId: 16 }, + { PokemonPokedexNumber: 215, typeId: 1 }, + { PokemonPokedexNumber: 215, typeId: 6 }, + { PokemonPokedexNumber: 216, typeId: 13 }, + { PokemonPokedexNumber: 217, typeId: 13 }, + { PokemonPokedexNumber: 218, typeId: 7 }, + { PokemonPokedexNumber: 219, typeId: 7 }, + { PokemonPokedexNumber: 219, typeId: 16 }, + { PokemonPokedexNumber: 220, typeId: 12 }, + { PokemonPokedexNumber: 220, typeId: 11 }, + { PokemonPokedexNumber: 221, typeId: 12 }, + { PokemonPokedexNumber: 221, typeId: 11 }, + { PokemonPokedexNumber: 222, typeId: 18 }, + { PokemonPokedexNumber: 222, typeId: 16 }, + { PokemonPokedexNumber: 223, typeId: 18 }, + { PokemonPokedexNumber: 224, typeId: 18 }, + { PokemonPokedexNumber: 225, typeId: 12 }, + { PokemonPokedexNumber: 225, typeId: 8 }, + { PokemonPokedexNumber: 226, typeId: 18 }, + { PokemonPokedexNumber: 226, typeId: 8 }, + { PokemonPokedexNumber: 227, typeId: 17 }, + { PokemonPokedexNumber: 227, typeId: 8 }, + { PokemonPokedexNumber: 228, typeId: 2 }, + { PokemonPokedexNumber: 228, typeId: 7 }, + { PokemonPokedexNumber: 229, typeId: 2 }, + { PokemonPokedexNumber: 229, typeId: 7 }, + { PokemonPokedexNumber: 230, typeId: 18 }, + { PokemonPokedexNumber: 230, typeId: 3 }, + { PokemonPokedexNumber: 231, typeId: 11 }, + { PokemonPokedexNumber: 232, typeId: 11 }, + { PokemonPokedexNumber: 233, typeId: 13 }, + { PokemonPokedexNumber: 234, typeId: 13 }, + { PokemonPokedexNumber: 235, typeId: 13 }, + { PokemonPokedexNumber: 236, typeId: 6 }, + { PokemonPokedexNumber: 237, typeId: 6 }, + { PokemonPokedexNumber: 238, typeId: 12 }, + { PokemonPokedexNumber: 238, typeId: 15 }, + { PokemonPokedexNumber: 239, typeId: 4 }, + { PokemonPokedexNumber: 240, typeId: 7 }, + { PokemonPokedexNumber: 241, typeId: 13 }, + { PokemonPokedexNumber: 242, typeId: 13 }, + { PokemonPokedexNumber: 243, typeId: 4 }, + { PokemonPokedexNumber: 244, typeId: 7 }, + { PokemonPokedexNumber: 245, typeId: 18 }, + { PokemonPokedexNumber: 246, typeId: 16 }, + { PokemonPokedexNumber: 246, typeId: 11 }, + { PokemonPokedexNumber: 247, typeId: 16 }, + { PokemonPokedexNumber: 247, typeId: 11 }, + { PokemonPokedexNumber: 248, typeId: 16 }, + { PokemonPokedexNumber: 248, typeId: 2 }, + { PokemonPokedexNumber: 249, typeId: 15 }, + { PokemonPokedexNumber: 249, typeId: 8 }, + { PokemonPokedexNumber: 250, typeId: 7 }, + { PokemonPokedexNumber: 250, typeId: 8 }, + { PokemonPokedexNumber: 251, typeId: 15 }, + { PokemonPokedexNumber: 251, typeId: 10 }, ]) return queryInterface.bulkInsert('PokemonForms', [ + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Venusaur\')'), + FormId: 1 + }, + + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Butterfree\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Rattata\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Raticate\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Pickachu\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Raichu\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Nidoran♀\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Nidoran♂\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Zubat\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Golbat\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Gloom\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Vileplume\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Kadabra\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Alakazam\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Doduo\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Dodrio\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Hypno\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Rhyhorn\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Rhydon\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Goldeen\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Seaking\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Scyther\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Magikarp\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Gyarados\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Eevee\')'), + FormId: 1 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Venusaur\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Charizard\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Charizard\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Blastoise\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Alakazam\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Gengar\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Kangaskhan\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Pinsir\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Gyarados\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Aerodactyl\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Mewtwo\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Mewtwo\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Beedrill\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Pidgeot\')'), + FormId: 3 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Slowbro\')'), + FormId: 3 + }, { PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Rattata\')'), FormId: 4 @@ -486,6 +895,81 @@ module.exports = { PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Marowak\')'), FormId: 4 }, + + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Meowth\')'), + FormId: 5 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Ponyta\')'), + FormId: 5 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Rapidash\')'), + FormId: 5 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Slowpoke\')'), + FormId: 5 + }, + { PokemonPokedexNumber: 83, FormId: 5 }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Weezing\')'), + FormId: 5 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Mr. Mime\')'), + FormId: 5 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Venusaur\')'), + FormId: 6 + }, + + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Charizard\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Blastoise\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Butterfree\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Pikachu\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Meowth\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Machamp\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Gengar\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Kingler\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Lapras\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Eevee\')'), + FormId: 6 + }, + { + PokemonPokedexNumber: Sequelize.literal('(SELECT pokedexNumber FROM Pokemons WHERE name = \'Snorlax\')'), + FormId: 6 + }, ]) }, diff --git a/models/PokemonForms.js b/models/PokemonForms.js index b640061..2a3e008 100644 --- a/models/PokemonForms.js +++ b/models/PokemonForms.js @@ -1,15 +1,13 @@ const PokemonForms = (connection, Sequelize, Forms, Pokemons) => { return connection.define('PokemonForms', { + id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true }, PokemonPokedexNumber: { type: Sequelize.INTEGER, - autoIncrement: true, - primaryKey: true, references: { model: Pokemons, key: 'pokedexNumber' } }, FormId: { type: Sequelize.INTEGER, allowNull: false, - primaryKey: true, references: { model: Forms, key: 'id' } } }, { diff --git a/tests/controllers/api.tests.js b/tests/controllers/api.tests.js index 49ae62c..563596b 100644 --- a/tests/controllers/api.tests.js +++ b/tests/controllers/api.tests.js @@ -237,12 +237,13 @@ describe('Controllers - API', () => { it('deletes a user named pokemon from the database as long as its not protected.', async () => { stubbedPokemonsFindOne.returns(unprotectedPokemon) + const request = { params: { name: 'Jolion' } } await deletePokemon(request, response) - expect(stubbedPokemonTypesDestroy).to.have.callCount(1) - expect(stubbedPokemonsDestroy).to.have.callCount(1) + expect(stubbedPokemonTypesDestroy).to.have.calledWith({ where: { PokemonPokedexNumber: unprotectedPokemon.pokedexNumber } }) + expect(stubbedPokemonsDestroy).to.have.calledWith({ where: { name: request.params.name } }) expect(stubbedSend).to.have.been.calledWith(`Successfully deleted the pokemon: ${request.params.name}.`) }) From db68dad104eea4529bfa8d288b7379f4a15cbc09 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Thu, 28 May 2020 14:52:31 -0400 Subject: [PATCH 24/26] Updated the ERD image file. --- Pokemon-API-ERD.png | Bin 96383 -> 111656 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Pokemon-API-ERD.png b/Pokemon-API-ERD.png index c8952247ab3b022b8c1f82ceaea291cc12076d14..978893995a4b34ad2482fa0e5eefb4a706dcf819 100644 GIT binary patch literal 111656 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 DypW1h literal 96383 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
^Q_L8-{Zx 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⁡g5#Fujn4;uC}A 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 Z@c;S+v$yqI;ss)?pLhI}sA+lZzW_L3KBE8t From 788fc2814db40ebb7116e09376a71753b7a1f41a Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Thu, 11 Jun 2020 15:59:11 -0400 Subject: [PATCH 25/26] Fixed documentation discrepencies and fixed the fromId = 'null' issue. --- controllers/Pokemons.js | 6 ++++-- views/partials/rightSideDocumentaion.pug | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/controllers/Pokemons.js b/controllers/Pokemons.js index 1849af2..373a0a2 100644 --- a/controllers/Pokemons.js +++ b/controllers/Pokemons.js @@ -47,10 +47,12 @@ const saveNewPokemon = async (request, response) => { const { name, generationNumber, - fromId, types } = request.body - const isProtected = request.body.isPortected || 0 + const isProtected = request.body.isProtected || 0 + const fromId = request.body.fromId.toLowerCase() === 'null' + ? null + : request.body.fromId if (!name || !generationNumber) { diff --git a/views/partials/rightSideDocumentaion.pug b/views/partials/rightSideDocumentaion.pug index 6204a45..c673cbc 100644 --- a/views/partials/rightSideDocumentaion.pug +++ b/views/partials/rightSideDocumentaion.pug @@ -23,7 +23,7 @@ div(class="right-container") h2 Method h3(class="spacing get") GET h2 Route - h3(class="spacing") http://localhost:1337/pokemon/generation/{genId} + h3(class="spacing") http://localhost:1337/generation/{genId} h2 Headers h3(class="spacing") None needed h2 Decription @@ -77,7 +77,7 @@ div(class="right-container") h2 Headers h3(class="spacing") Content-Type: application/json h2 Body - h3(class="spacing") { "gen": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']", "fromId": "null" } + h3(class="spacing") { "generationNumber": "1", "name": "Bulbasaur", "Types": "['grass', 'poison']", "fromId": "null" } h2 Decription h3(class="spacing") | Saves a new pokemon to the database. (Note: the fromId is if the pokemon is an evolution of From 2834e6cd9ae72560dc43b3defbb09f7228f700b4 Mon Sep 17 00:00:00 2001 From: orbitalbitmap Date: Thu, 11 Jun 2020 16:24:56 -0400 Subject: [PATCH 26/26] Fixed two broken tests from the update on the previous commit. --- tests/controllers/api.tests.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/controllers/api.tests.js b/tests/controllers/api.tests.js index 563596b..faf8d7a 100644 --- a/tests/controllers/api.tests.js +++ b/tests/controllers/api.tests.js @@ -202,7 +202,7 @@ describe('Controllers - API', () => { body: { name: 'Leafeon', generationNumber: 1, - fromId: null, + fromId: 'null', types: ['Fire', 'Flying'] } } @@ -215,7 +215,13 @@ describe('Controllers - API', () => { it('returns a 400 status and a message when no pokemon is found matching the id provided by the user.', async () => { stubbedPokemonsFindOne.returns(null) - const request = { body: { name: 'ratata' } } + const request = { + body: { + generationNumber: 1, + fromId: 'null', + types: ['Fire', 'Flying'] + } + } await saveNewPokemon(request, response)