├── .babelrc ├── .dockerignore ├── .editorconfig ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .nvmrc ├── .prettierrc ├── .vscode └── launch.json ├── CHANGELOG.md ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── README.md ├── components ├── header │ └── Header.js ├── layout │ └── Layout.js └── privateRoute │ └── PrivateRoute.js ├── config └── appConfig.js ├── flow-typed └── npm │ ├── babel-plugin-transform-async-to-generator_vx.x.x.js │ ├── babel-plugin-transform-regenerator_vx.x.x.js │ ├── babel-preset-es2015_vx.x.x.js │ ├── babel-preset-flow_vx.x.x.js │ ├── babel-preset-react_vx.x.x.js │ ├── babel-preset-stage-2_vx.x.x.js │ ├── eslint-plugin-flowtype_vx.x.x.js │ ├── eslint-plugin-react_vx.x.x.js │ ├── eslint_vx.x.x.js │ ├── flow-bin_v0.x.x.js │ └── next_vx.x.x.js ├── mock ├── fakeAPI.json └── userInfosMock.json ├── next.config.js ├── package.json ├── pages ├── _error.js ├── index.js ├── login.js ├── page1.js └── private1.js ├── preview.png ├── redux ├── middleware │ └── fetchMiddleware.js ├── modules │ ├── fakeModuleWithFetch.js │ ├── persistStore.js │ ├── reducers.js │ └── userAuth.js └── store │ ├── configureStore.dev.js │ ├── configureStore.js │ └── configureStore.prod.js ├── services ├── auth.js └── fetchTools.js ├── static ├── css │ └── bootstrap.min.css ├── favicon.ico └── robot.txt ├── typings.json └── typings ├── globals ├── axios │ ├── index.d.ts │ └── typings.json ├── localforage │ ├── index.d.ts │ └── typings.json ├── moment │ ├── index.d.ts │ └── typings.json ├── redux-thunk │ ├── index.d.ts │ └── typings.json └── redux │ ├── index.d.ts │ └── typings.json └── index.d.ts /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "next/babel", 4 | "es2015", 5 | "react", 6 | "stage-2", 7 | "flow" 8 | ], 9 | "plugins": [ 10 | "transform-regenerator", 11 | "transform-async-to-generator" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .git 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "node": true, 6 | "es6": true 7 | }, 8 | "plugins": [ 9 | "react", 10 | "flowtype" 11 | ], 12 | "extends": [ 13 | "plugin:react/recommended", 14 | "plugin:flowtype/recommended" 15 | ], 16 | "parserOptions": { 17 | "ecmaFeatures": { 18 | "arrowFunctions": true, 19 | "binaryLiterals": true, 20 | "blockBindings": true, 21 | "classes": true, 22 | "defaultParams": true, 23 | "destructuring": true, 24 | "forOf": true, 25 | "generators": true, 26 | "modules": true, 27 | "objectLiteralComputedProperties": true, 28 | "objectLiteralDuplicateProperties": true, 29 | "objectLiteralShorthandMethods": true, 30 | "objectLiteralShorthandProperties": true, 31 | "octalLiterals": true, 32 | "regexUFlag": true, 33 | "regexYFlag": true, 34 | "spread": true, 35 | "superInFunctions": true, 36 | "templateStrings": true, 37 | "unicodeCodePointEscapes": true, 38 | "globalReturn": true, 39 | "jsx": true 40 | } 41 | }, 42 | "rules": { 43 | // 44 | //Possible Errors 45 | // 46 | // The following rules point out areas where you might have made mistakes. 47 | // 48 | "comma-dangle": 2, // disallow or enforce trailing commas 49 | "no-cond-assign": 2, // disallow assignment in conditional expressions 50 | "no-console": 1, // disallow use of console (off by default in the node environment) 51 | "no-constant-condition": 2, // disallow use of constant expressions in conditions 52 | "no-control-regex": 2, // disallow control characters in regular expressions 53 | "no-debugger": 2, // disallow use of debugger 54 | "no-dupe-args": 2, // disallow duplicate arguments in functions 55 | "no-dupe-keys": 2, // disallow duplicate keys when creating object literals 56 | "no-duplicate-case": 2, // disallow a duplicate case label. 57 | "no-empty": 2, // disallow empty statements 58 | "no-empty-character-class": 2, // disallow the use of empty character classes in regular expressions 59 | "no-ex-assign": 2, // disallow assigning to the exception in a catch block 60 | "no-extra-boolean-cast": 2, // disallow double-negation boolean casts in a boolean context 61 | "no-extra-parens": 0, // disallow unnecessary parentheses (off by default) 62 | "no-extra-semi": 2, // disallow unnecessary semicolons 63 | "no-func-assign": 2, // disallow overwriting functions written as function declarations 64 | "no-inner-declarations": 2, // disallow function or variable declarations in nested blocks 65 | "no-invalid-regexp": 2, // disallow invalid regular expression strings in the RegExp constructor 66 | "no-irregular-whitespace": 2, // disallow irregular whitespace outside of strings and comments 67 | "no-negated-in-lhs": 2, // disallow negation of the left operand of an in expression 68 | "no-obj-calls": 2, // disallow the use of object properties of the global object (Math and JSON) as functions 69 | "no-regex-spaces": 2, // disallow multiple spaces in a regular expression literal 70 | "no-sparse-arrays": 2, // disallow sparse arrays 71 | "no-unreachable": 2, // disallow unreachable statements after a return, throw, continue, or break statement 72 | "use-isnan": 2, // disallow comparisons with the value NaN 73 | "valid-jsdoc": 2, // Ensure JSDoc comments are valid (off by default) 74 | "valid-typeof": 2, // Ensure that the results of typeof are compared against a valid string 75 | // 76 | // Best Practices 77 | // 78 | // These are rules designed to prevent you from making mistakes. 79 | // They either prescribe a better way of doing something or help you avoid footguns. 80 | // 81 | "prefer-const": [ 82 | "error", 83 | { 84 | "destructuring": "any", 85 | "ignoreReadBeforeAssign": false 86 | } 87 | ], 88 | "block-scoped-var": 0, // treat var statements as if they were block scoped (off by default). 0: deep destructuring is not compatible https://github.com/eslint/eslint/issues/1863 89 | "complexity": 0, // specify the maximum cyclomatic complexity allowed in a program (off by default) 90 | "consistent-return": 2, // require return statements to either always or never specify values 91 | "curly": 2, // specify curly brace conventions for all control statements 92 | "default-case": 2, // require default case in switch statements (off by default) 93 | "dot-notation": 2, // encourages use of dot notation whenever possible 94 | "eqeqeq": 2, // require the use of === and !== 95 | "guard-for-in": 2, // make sure for-in loops have an if statement (off by default) 96 | "no-alert": 2, // disallow the use of alert, confirm, and prompt 97 | "no-caller": 2, // disallow use of arguments.caller or arguments.callee 98 | "no-div-regex": 2, // disallow division operators explicitly at beginning of regular expression (off by default) 99 | //"no-else-return": 2, // disallow else after a return in an if (off by default) 100 | //"no-empty-label": 2, // disallow use of labels for anything other then loops and switches 101 | "no-eq-null": 2, // disallow comparisons to null without a type-checking operator (off by default) 102 | "no-eval": 2, // disallow use of eval() 103 | "no-extend-native": 2, // disallow adding to native types 104 | "no-extra-bind": 2, // disallow unnecessary function binding 105 | "no-fallthrough": 2, // disallow fallthrough of case statements 106 | "no-floating-decimal": 2, // disallow the use of leading or trailing decimal points in numeric literals (off by default) 107 | "no-implied-eval": 2, // disallow use of eval()-like methods 108 | "no-iterator": 2, // disallow usage of __iterator__ property 109 | "no-labels": 2, // disallow use of labeled statements 110 | "no-lone-blocks": 2, // disallow unnecessary nested blocks 111 | "no-loop-func": 2, // disallow creation of functions within loops 112 | "no-multi-spaces": 0, // disallow use of multiple spaces 113 | "no-multi-str": 2, // disallow use of multiline strings 114 | "no-native-reassign": 2, // disallow reassignments of native objects 115 | "no-new": 2, // disallow use of new operator when not part of the assignment or comparison 116 | "no-new-func": 2, // disallow use of new operator for Function object 117 | "no-new-wrappers": 2, // disallows creating new instances of String,Number, and Boolean 118 | "no-octal": 2, // disallow use of octal literals 119 | "no-octal-escape": 2, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251"; 120 | "no-param-reassign": 2, // disallow reassignment of function parameters (off by default) 121 | "no-process-env": 2, // disallow use of process.env (off by default) 122 | "no-proto": 2, // disallow usage of __proto__ property 123 | "no-redeclare": 2, // disallow declaring the same variable more then once 124 | "no-return-assign": 2, // disallow use of assignment in return statement 125 | "no-script-url": 2, // disallow use of javascript: urls. 126 | "no-self-compare": 2, // disallow comparisons where both sides are exactly the same (off by default) 127 | "no-sequences": 2, // disallow use of comma operator 128 | "no-throw-literal": 2, // restrict what can be thrown as an exception (off by default) 129 | "no-unused-expressions": 2, // disallow usage of expressions in statement position 130 | "no-void": 2, // disallow use of void operator (off by default) 131 | "no-warning-comments": [ 132 | 0, 133 | { 134 | "terms": [ 135 | "todo", 136 | "fixme" 137 | ], 138 | "location": "start" 139 | } 140 | ], // disallow usage of configurable warning terms in comments": 2, // e.g. TODO or FIXME (off by default) 141 | "no-with": 2, // disallow use of the with statement 142 | "radix": 2, // require use of the second argument for parseInt() (off by default) 143 | "vars-on-top": 2, // requires to declare all vars on top of their containing scope (off by default) 144 | "wrap-iife": 2, // require immediate function invocation to be wrapped in parentheses (off by default) 145 | "yoda": 2, // require or disallow Yoda conditions 146 | // 147 | // Strict Mode 148 | // 149 | // These rules relate to using strict mode. 150 | // 151 | "strict": 0, // controls location of Use Strict Directives. 0: required by `babel-eslint` 152 | // 153 | // Variables 154 | // 155 | // These rules have to do with variable declarations. 156 | // 157 | "no-catch-shadow": 2, // disallow the catch clause parameter name being the same as a variable in the outer scope (off by default in the node environment) 158 | "no-delete-var": 2, // disallow deletion of variables 159 | "no-label-var": 2, // disallow labels that share a name with a variable 160 | "no-shadow": 2, // disallow declaration of variables already declared in the outer scope 161 | "no-shadow-restricted-names": 2, // disallow shadowing of names such as arguments 162 | "no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block 163 | "no-undef-init": 2, // disallow use of undefined when initializing variables 164 | "no-undefined": 2, // disallow use of undefined variable (off by default) 165 | "no-unused-vars": 2, // disallow declaration of variables that are not used in the code 166 | "no-use-before-define": [ 167 | "error", 168 | { 169 | "functions": false, 170 | "classes": true 171 | } 172 | ], // disallow use of variables before they are defined 173 | // 174 | //Stylistic Issues 175 | // 176 | // These rules are purely matters of style and are quite subjective. 177 | // 178 | "indent": [ 179 | 1, 180 | 2 181 | ], // this option sets a specific tab width for your code (off by default) 182 | "brace-style": 1, // enforce one true brace style (off by default) 183 | "camelcase": 1, // require camel case names 184 | "comma-spacing": [ 185 | 1, 186 | { 187 | "before": false, 188 | "after": true 189 | } 190 | ], // enforce spacing before and after comma 191 | "comma-style": [ 192 | 1, 193 | "last" 194 | ], // enforce one true comma style (off by default) 195 | "consistent-this": [ 196 | 1, 197 | "_this" 198 | ], // enforces consistent naming when capturing the current execution context (off by default) 199 | "eol-last": 1, // enforce newline at the end of file, with no multiple empty lines 200 | "func-names": 0, // require function expressions to have a name (off by default) 201 | "func-style": 0, // enforces use of function declarations or expressions (off by default) 202 | "max-nested-callbacks": [ 203 | 1, 204 | 3 205 | ], // specify the maximum depth callbacks can be nested (off by default) 206 | "new-cap": [ 207 | 1, 208 | { 209 | "newIsCap": true, 210 | "capIsNew": false 211 | } 212 | ], // require a capital letter for constructors 213 | "new-parens": 1, // disallow the omission of parentheses when invoking a constructor with no arguments 214 | "newline-after-var": 0, // allow/disallow an empty newline after var statement (off by default) 215 | "no-array-constructor": 1, // disallow use of the Array constructor 216 | "no-inline-comments": 0, // disallow comments inline after code (off by default) 217 | "no-lonely-if": 1, // disallow if as the only statement in an else block (off by default) 218 | "no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation 219 | "no-multiple-empty-lines": [ 220 | 1, 221 | { 222 | "max": 2 223 | } 224 | ], // disallow multiple empty lines (off by default) 225 | "no-nested-ternary": 1, // disallow nested ternary expressions (off by default) 226 | "no-new-object": 1, // disallow use of the Object constructor 227 | "no-spaced-func": 1, // disallow space between function identifier and application 228 | "no-ternary": 0, // disallow the use of ternary operators (off by default) 229 | //"no-trailing-spaces": 1, // disallow trailing whitespace at the end of lines 230 | //"no-underscore-dangle": 1, // disallow dangling underscores in identifiers 231 | "one-var": [ 232 | 1, 233 | "never" 234 | ], // allow just one var statement per function (off by default) 235 | "operator-assignment": [ 236 | 1, 237 | "never" 238 | ], // require assignment operator shorthand where possible or prohibit it entirely (off by default) 239 | "padded-blocks": [ 240 | 1, 241 | "never" 242 | ], // enforce padding within blocks (off by default) 243 | "quotes": [ 244 | 1, 245 | "single" 246 | ], // specify whether double or single quotes should be used 247 | "semi": [ 248 | 1, 249 | "always" 250 | ], // require or disallow use of semicolons instead of ASI 251 | "semi-spacing": [ 252 | 1, 253 | { 254 | "before": false, 255 | "after": true 256 | } 257 | ], // enforce spacing before and after semicolons 258 | "sort-vars": 0, // sort variables within the same declaration block (off by default) 259 | // "space-after-keywords": [1, "always"], // require a space after certain keywords (off by default) 260 | "space-before-blocks": [ 261 | 1, 262 | "always" 263 | ], // require or disallow space before blocks (off by default) 264 | "space-before-function-paren": [ 265 | 1, 266 | { 267 | "anonymous": "always", 268 | "named": "never" 269 | } 270 | ], // require or disallow space before function opening parenthesis (off by default) 271 | //"space-in-brackets": [1, "never"], // require or disallow spaces inside brackets (off by default) 272 | "space-in-parens": [ 273 | 1, 274 | "never" 275 | ], // require or disallow spaces inside parentheses (off by default) 276 | "space-unary-ops": [ 277 | 1, 278 | { 279 | "words": true, 280 | "nonwords": false 281 | } 282 | ], // Require or disallow spaces before/after unary operators (words on by default, nonwords off by default) 283 | "spaced-comment": [ 284 | 1, 285 | "always" 286 | ], // require or disallow a space immediately following the // in a line comment (off by default) 287 | "wrap-regex": 0, // require regex literals to be wrapped in parentheses (off by default) 288 | // 289 | // ECMAScript 6 290 | // 291 | // These rules are only relevant to ES6 environments and are off by default. 292 | // 293 | "no-var": 2, // require let or const instead of var (off by default) 294 | "generator-star-spacing": [ 295 | 2, 296 | "before" 297 | ], // enforce the spacing around the * in generator functions (off by default) 298 | // 299 | // Legacy 300 | // 301 | // The following rules are included for compatibility with JSHint and JSLint. 302 | // While the names of the rules may not match up with the JSHint/JSLint counterpart, 303 | // the functionality is the same. 304 | // 305 | "max-depth": [ 306 | 2, 307 | 3 308 | ], // specify the maximum depth that blocks can be nested (off by default) 309 | "max-len": [ 310 | 2, 311 | 300, 312 | 2 313 | ], // specify the maximum length of a line in your program (off by default) 314 | "max-params": [ 315 | 2, 316 | 5 317 | ], // limits the number of parameters that can be used in the function declaration. (off by default) 318 | "max-statements": 0, // specify the maximum number of statement allowed in a function (off by default) 319 | "no-bitwise": 0, // disallow use of bitwise operators (off by default) 320 | "no-plusplus": 2, // disallow use of unary operators, ++ and -- (off by default) 321 | // 322 | // eslint-plugin-react 323 | // 324 | // React specific linting rules for ESLint 325 | // 326 | "react/display-name": 0, // Prevent missing displayName in a React component definition 327 | //"react/jsx-quotes": [2, "double", "avoid-escape"], // Enforce quote style for JSX attributes 328 | "jsx-quotes": [ 329 | 2, 330 | "prefer-double" 331 | ], 332 | // "react/jsx-quotes": 0, 333 | "react/jsx-no-undef": 2, // Disallow undeclared variables in JSX 334 | "react/jsx-sort-props": 0, // Enforce props alphabetical sorting 335 | "react/jsx-uses-react": 2, // Prevent React to be incorrectly marked as unused 336 | "react/jsx-uses-vars": 2, // Prevent variables used in JSX to be incorrectly marked as unused 337 | // "react/no-did-mount-set-state": [2, "allow-in-func"], // Prevent usage of setState in componentDidMount 338 | // "react/no-did-update-set-state": 2, // Prevent usage of setState in componentDidUpdate 339 | "react/no-multi-comp": 0, // Prevent multiple component definition per file 340 | "react/no-unknown-property": 2, // Prevent usage of unknown DOM property 341 | "react/prop-types": 2, // Prevent missing props validation in a React component definition 342 | "react/react-in-jsx-scope": 0, // Prevent missing React when using JSX: No more need in next js since react is global 343 | "react/self-closing-comp": 2, // Prevent extra closing tags for components without children 344 | "react/jsx-wrap-multilines": 2 // Prevent missing parentheses around multilines JSX 345 | } 346 | } 347 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [lints] 8 | 9 | [options] 10 | module.system=haste 11 | strip_root=true 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store* 3 | Icon? 4 | ._* 5 | 6 | # Windows 7 | Thumbs.db 8 | ehthumbs.db 9 | Desktop.ini 10 | 11 | # Linux 12 | .directory 13 | *~ 14 | 15 | # npm 16 | node_modules 17 | *.log 18 | *.gz 19 | 20 | # intelliJ 21 | .idea/ 22 | 23 | # Coveralls 24 | coverage 25 | 26 | # next 27 | .next/ 28 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "bracketSpacing": true, 5 | "jsxBracketSameLine": false, 6 | "singleQuote": true, 7 | "overrides": [], 8 | "printWidth": 80, 9 | "useTabs": false, 10 | "tabWidth": 2, 11 | "parser": "babylon" 12 | } 13 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Utilisez IntelliSense pour en savoir plus sur les attributs possibles. 3 | // Pointez pour afficher la description des attributs existants. 4 | // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "chrome", 9 | "request": "launch", 10 | "name": "Launch Chrome localhost:3000", 11 | "url": "http://localhost:3000", 12 | "webRoot": "${workspaceRoot}" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.3.0 (RELEASED) 2 | - add localforage 3 | 4 | ## 0.2.0 (RELEASED) 5 | - add Private component to handle private page 6 | 7 | ## 0.1.0 (RELEASED) 8 | - add redux store persistance (`redux-persist`) to maintain state accross all application. 9 | - add user authentication 10 | 11 | ## 0.0.1 (RELEASED) 12 | - first bricks of this starter 13 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Version 2 | 1.2.0 3 | 4 | ### Node JS 5 | v7.x | v8.X 6 | 7 | ### Browser 8 | Chrome 64.x | Safari 11.x 9 | 10 | ### OS version 11 | macOS | windows 10 | linux Ubuntu... 12 | 13 | ### Steps to reproduce 14 | 1. 15 | 2. 16 | 3. 17 | 18 | ### Expected behavior 19 | What should happen 20 | 21 | ### Actual behavior 22 | What is happening 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # LICENSE 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2019 Erwan DATIN 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](https://github.com/MacKentoch/react-redux-nextjs-bootstrap-starter) 2 | 3 | # Next JS + React + Redux + Redux persist + redux-devtools-extension + Bootstrap starter 4 | 5 | > A NextJS starter with redux and bootstrap 6 | 7 | 8 | 9 |  10 | 11 | 12 | 13 | [See it in action deployed with `now`](https://react-redux-nextjs-bootstrap-starter-xfdpqhzseq.now.sh/) 14 | 15 | ## Detailed Content 16 | 17 | **Front:** 18 | - Next js (4.x+ [github :link:](https://github.com/zeit/next.js)) 19 | - React JS (16.x+ - [github :link:](https://github.com/facebook/react)) 20 | - redux (*as your application grows managing state will be a serious concern, save pain with Redux*) 21 | - redux-persist (*simplifies your NextJS state share between pages* [github :link:](https://github.com/rt2zz/redux-persist)) 22 | - localforage (*for better performances than localStorage*) 23 | - react-redux (*Redux is not specific to ReactJS, you could easily use it with Angular2 for instance*) 24 | - redux-thunk (*simple and does the job*) 25 | - next-redux-wrapper 26 | - redux-devtools-extension ([github :link:](https://github.com/zalmoxisus/redux-devtools-extension#redux-devtools-extension)) 27 | - react-bootstrap ([github :link:](https://github.com/react-bootstrap/react-bootstrap)) 28 | - axios ([github :link:](https://github.com/mzabriskie/axios) *Why: simple, complete, isomorphic ...*) 29 | 30 | **Tool chain:** 31 | - Next js (4.x+ [github :link:](https://github.com/zeit/next.js)) 32 | - Flow JS types 33 | 34 | ## Usage 35 | 36 | IMPORTANT: `Next JS` when `redux` connected 37 | 38 | - **you are forced to connect each page** (*even if you don't need redux in that page*) with `withRedux` from `next-redux-wrapper` (*[see page1 as an example](https://github.com/MacKentoch/react-redux-nextjs-bootstrap-starter/blob/master/pages/page1.js)*). 39 | - **each sub component you may want to connect** should be connected by usual `connect` from `redux` (*[see Header component as an example](https://github.com/MacKentoch/react-redux-nextjs-bootstrap-starter/blob/master/components/header/Header.js)*) 40 | 41 | 42 | ### Install 43 | 44 | ```bash 45 | npm install 46 | ``` 47 | 48 | ### Scripts 49 | 50 | 51 | run dev with hot reload 52 | 53 | Clone this repository, then install dependencies: 54 | 55 | ```bash 56 | npm run start 57 | ``` 58 | 59 | 60 | 61 | 62 | build dev bundle 63 | 64 | ```bash 65 | npm run build 66 | ``` 67 | 68 | 69 | 70 | 71 | start dev (no hot reload) 72 | 73 | 74 | *NOTE: ensure you built first before starting* 75 | 76 | ```bash 77 | npm run start 78 | ``` 79 | 80 | 81 | 82 | ## LICENSE 83 | 84 | The MIT License (MIT) 85 | 86 | Copyright (c) 2017 Erwan DATIN 87 | 88 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 89 | 90 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 91 | 92 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 93 | -------------------------------------------------------------------------------- /components/header/Header.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import Link from 'next/link'; 5 | import Router from 'next/router'; 6 | import { connect } from 'react-redux'; 7 | import { bindActionCreators } from 'redux'; 8 | import * as userAuthActions from '../../redux/modules/userAuth'; 9 | import Navbar from 'react-bootstrap/lib/Navbar'; 10 | import Nav from 'react-bootstrap/lib/Nav'; 11 | import NavItem from 'react-bootstrap/lib/NavItem'; 12 | // import NavDropdown from 'react-bootstrap/lib/NavDropdown'; 13 | // import MenuItem from 'react-bootstrap/lib/MenuItem'; 14 | import { PureComponent } from 'react'; 15 | // #endregion 16 | 17 | // #region flow types 18 | type Props = { 19 | // userAuth: 20 | isAuthenticated: boolean, 21 | disconnectUser: (...any) => any, 22 | 23 | ...any 24 | }; 25 | 26 | type State = any; 27 | // #endregion 28 | 29 | class Header extends PureComponent { 30 | // #region default props 31 | static defaultProps = { 32 | isAuthenticated: false 33 | }; 34 | 35 | // #region component lifecycle methods 36 | render() { 37 | const { 38 | isAuthenticated 39 | } = this.props; 40 | 41 | return ( 42 | 47 | 48 | 49 | 52 | react-redux-next-bootstrap starter 53 | 54 | 55 | 56 | 57 | 58 | 61 | 65 | 69 | Page1 70 | 71 | 72 | 76 | 80 | Private1 81 | 82 | 83 | { 84 | isAuthenticated 85 | ? 86 | 91 | 95 | 96 | : 97 | 101 | 105 | 109 | 110 | 111 | } 112 | 113 | 114 | 115 | 116 | ); 117 | } 118 | // #endregion 119 | 120 | // #region on disconnect click 121 | HandlesDisconnectUser = ( 122 | event: SyntheticEvent<> 123 | ) => { 124 | if (event) { 125 | event.preventDefault(); 126 | } 127 | 128 | const { 129 | disconnectUser 130 | } = this.props; 131 | 132 | disconnectUser(); 133 | Router.replace('/login'); 134 | } 135 | // #endregion 136 | } 137 | 138 | 139 | // #region redux state and dispatch map to props 140 | const mapStateToProps = ( 141 | state: any 142 | ) => ({ 143 | // userAuth: 144 | isAuthenticated: state.userAuth.isAuthenticated 145 | }); 146 | 147 | const mapDispatchToProps = ( 148 | dispatch: (...any) => any 149 | ) => { 150 | return { 151 | ...bindActionCreators( 152 | { 153 | // userAuth: 154 | ...userAuthActions 155 | }, 156 | dispatch 157 | ) 158 | }; 159 | }; 160 | // #endregion 161 | 162 | export default connect( 163 | mapStateToProps, 164 | mapDispatchToProps 165 | )(Header); 166 | 167 | -------------------------------------------------------------------------------- /components/layout/Layout.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import { PureComponent } from 'react'; 5 | import Head from 'next/head'; 6 | // #endregion 7 | 8 | // #region flow types 9 | type Props = { 10 | children: ReactNode 11 | } 12 | 13 | type State = any; 14 | // #endregion 15 | 16 | class Layout extends PureComponent { 17 | // #region component lifecycle methods 18 | render() { 19 | const { children } = this.props; 20 | 21 | return ( 22 | 23 | 24 | 28 | 31 | 36 | 40 | 44 | 45 | 58 | {children} 59 | 60 | ); 61 | } 62 | // #endregion 63 | } 64 | 65 | export default Layout; 66 | -------------------------------------------------------------------------------- /components/privateRoute/PrivateRoute.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import { PureComponent } from 'react'; 5 | import Router from 'next/router'; 6 | import auth from '../../services/auth'; 7 | // #endregion 8 | 9 | // #region flow types 10 | type Props = { 11 | fromPath: string, 12 | children: ReactNode 13 | } 14 | 15 | type State = any; 16 | // #endregion 17 | 18 | class Private extends PureComponent { 19 | // #region 20 | static defaultProps = { 21 | fromPath: '/' 22 | }; 23 | 24 | // #region component lifecycle methods 25 | componentDidMount() { 26 | const { 27 | fromPath 28 | } = this.props; 29 | 30 | const userIsAuthenticated = this.isAuthenticated(); 31 | const userTokenExpired =this.isExpired(); 32 | 33 | const RoutePayload = { 34 | pathname: '/login', 35 | query: { from: fromPath } 36 | }; 37 | 38 | if (!userIsAuthenticated) { 39 | return Router.replace(RoutePayload); 40 | } 41 | 42 | if (userTokenExpired) { 43 | return Router.replace(RoutePayload); 44 | } 45 | 46 | return true; 47 | } 48 | 49 | render() { 50 | const { children } = this.props; 51 | 52 | return ( 53 | 54 | {children} 55 | 56 | ); 57 | } 58 | // #endregion 59 | 60 | // #region authentication check methods 61 | isAuthenticated(): boolean { 62 | const checkUserHasId = user => user && user.id; 63 | const user = auth.getUserInfo() ? auth.getUserInfo() : null; 64 | const isAuthenticated = auth.getToken() && checkUserHasId(user) ? true : false; 65 | return isAuthenticated; 66 | } 67 | 68 | isExpired(): boolean { 69 | /* eslint-disable no-console */ 70 | // comment me: 71 | console.log('token expires: ', auth.getTokenExpirationDate(auth.getToken())); 72 | /* eslint-enable no-console */ 73 | return auth.isExpiredToken(auth.getToken()); 74 | } 75 | // #endregion 76 | } 77 | 78 | export default Private; 79 | -------------------------------------------------------------------------------- /config/appConfig.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const AppConfig = { 4 | // flag: set fetch mock or real fetch 5 | DEV_MODE: true, 6 | 7 | // API 8 | api: { 9 | fakeEndPoint: 'api/somewhere' 10 | } 11 | }; 12 | 13 | export default AppConfig; 14 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-plugin-transform-async-to-generator_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: b566883b98bb79a75cbf392f24988c4f 2 | // flow-typed version: <>/babel-plugin-transform-async-to-generator_v^6.24.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-plugin-transform-async-to-generator' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-plugin-transform-async-to-generator' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-plugin-transform-async-to-generator/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-plugin-transform-async-to-generator/lib/index.js' { 31 | declare module.exports: $Exports<'babel-plugin-transform-async-to-generator/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 104fda36b08cda34bbac121973e64b1d 2 | // flow-typed version: <>/babel-plugin-transform-regenerator_v^6.26.0/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-plugin-transform-regenerator' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-plugin-transform-regenerator' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-plugin-transform-regenerator/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-plugin-transform-regenerator/lib/index.js' { 31 | declare module.exports: $Exports<'babel-plugin-transform-regenerator/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-es2015_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 8722dd2bea14809f8f45293872c8f6cf 2 | // flow-typed version: <>/babel-preset-es2015_v^6.24.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-es2015' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-es2015' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-es2015/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-es2015/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-es2015/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-flow_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 2f58597102bce11ff3a4482d6607d60f 2 | // flow-typed version: <>/babel-preset-flow_v^6.23.0/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-flow' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-flow' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-flow/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-flow/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-flow/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-react_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 1421db38882c7eb42bf18e8dbb388727 2 | // flow-typed version: <>/babel-preset-react_v^6.24.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-react' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-react' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-react/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-react/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-react/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-stage-2_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a801d20d6e50d29432634751cde9135d 2 | // flow-typed version: <>/babel-preset-stage-2_v^6.24.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-stage-2' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-stage-2' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-stage-2/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-stage-2/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-stage-2/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 54255bb1299438546b6f355a212368bb 2 | // flow-typed version: <>/eslint-plugin-flowtype_v^2.39.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'eslint-plugin-flowtype' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'eslint-plugin-flowtype' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'eslint-plugin-flowtype/bin/readmeAssertions' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'eslint-plugin-flowtype/dist/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'eslint-plugin-flowtype/dist/rules/booleanStyle' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'eslint-plugin-flowtype/dist/rules/defineFlowType' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'eslint-plugin-flowtype/dist/rules/delimiterDangle' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'eslint-plugin-flowtype/dist/rules/genericSpacing' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'eslint-plugin-flowtype/dist/rules/noDupeKeys' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'eslint-plugin-flowtype/dist/rules/noMutableArray' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'eslint-plugin-flowtype/dist/rules/noUnusedExpressions' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'eslint-plugin-flowtype/dist/rules/noWeakTypes' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'eslint-plugin-flowtype/dist/rules/requireVariableType' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'eslint-plugin-flowtype/dist/rules/semi' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'eslint-plugin-flowtype/dist/rules/sortKeys' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module 'eslint-plugin-flowtype/dist/rules/typeIdMatch' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module 'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module 'eslint-plugin-flowtype/dist/rules/useFlowType' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module 'eslint-plugin-flowtype/dist/rules/validSyntax' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module 'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module 'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module 'eslint-plugin-flowtype/dist/utilities/getParameterName' { 170 | declare module.exports: any; 171 | } 172 | 173 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens' { 174 | declare module.exports: any; 175 | } 176 | 177 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens' { 178 | declare module.exports: any; 179 | } 180 | 181 | declare module 'eslint-plugin-flowtype/dist/utilities/index' { 182 | declare module.exports: any; 183 | } 184 | 185 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFile' { 186 | declare module.exports: any; 187 | } 188 | 189 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation' { 190 | declare module.exports: any; 191 | } 192 | 193 | declare module 'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes' { 194 | declare module.exports: any; 195 | } 196 | 197 | declare module 'eslint-plugin-flowtype/dist/utilities/quoteName' { 198 | declare module.exports: any; 199 | } 200 | 201 | declare module 'eslint-plugin-flowtype/dist/utilities/spacingFixers' { 202 | declare module.exports: any; 203 | } 204 | 205 | // Filename aliases 206 | declare module 'eslint-plugin-flowtype/bin/readmeAssertions.js' { 207 | declare module.exports: $Exports<'eslint-plugin-flowtype/bin/readmeAssertions'>; 208 | } 209 | declare module 'eslint-plugin-flowtype/dist/index.js' { 210 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/index'>; 211 | } 212 | declare module 'eslint-plugin-flowtype/dist/rules/booleanStyle.js' { 213 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/booleanStyle'>; 214 | } 215 | declare module 'eslint-plugin-flowtype/dist/rules/defineFlowType.js' { 216 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/defineFlowType'>; 217 | } 218 | declare module 'eslint-plugin-flowtype/dist/rules/delimiterDangle.js' { 219 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/delimiterDangle'>; 220 | } 221 | declare module 'eslint-plugin-flowtype/dist/rules/genericSpacing.js' { 222 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/genericSpacing'>; 223 | } 224 | declare module 'eslint-plugin-flowtype/dist/rules/noDupeKeys.js' { 225 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noDupeKeys'>; 226 | } 227 | declare module 'eslint-plugin-flowtype/dist/rules/noMutableArray.js' { 228 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noMutableArray'>; 229 | } 230 | declare module 'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes.js' { 231 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes'>; 232 | } 233 | declare module 'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation.js' { 234 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation'>; 235 | } 236 | declare module 'eslint-plugin-flowtype/dist/rules/noUnusedExpressions.js' { 237 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noUnusedExpressions'>; 238 | } 239 | declare module 'eslint-plugin-flowtype/dist/rules/noWeakTypes.js' { 240 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noWeakTypes'>; 241 | } 242 | declare module 'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter.js' { 243 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter'>; 244 | } 245 | declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType.js' { 246 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireParameterType'>; 247 | } 248 | declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType.js' { 249 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireReturnType'>; 250 | } 251 | declare module 'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation.js' { 252 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation'>; 253 | } 254 | declare module 'eslint-plugin-flowtype/dist/rules/requireVariableType.js' { 255 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireVariableType'>; 256 | } 257 | declare module 'eslint-plugin-flowtype/dist/rules/semi.js' { 258 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/semi'>; 259 | } 260 | declare module 'eslint-plugin-flowtype/dist/rules/sortKeys.js' { 261 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/sortKeys'>; 262 | } 263 | declare module 'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon.js' { 264 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon'>; 265 | } 266 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket.js' { 267 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket'>; 268 | } 269 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon.js' { 270 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon'>; 271 | } 272 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions.js' { 273 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions'>; 274 | } 275 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer.js' { 276 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer'>; 277 | } 278 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty.js' { 279 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty'>; 280 | } 281 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType.js' { 282 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType'>; 283 | } 284 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression.js' { 285 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression'>; 286 | } 287 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical.js' { 288 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical'>; 289 | } 290 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index.js' { 291 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index'>; 292 | } 293 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter.js' { 294 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter'>; 295 | } 296 | declare module 'eslint-plugin-flowtype/dist/rules/typeIdMatch.js' { 297 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeIdMatch'>; 298 | } 299 | declare module 'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing.js' { 300 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing'>; 301 | } 302 | declare module 'eslint-plugin-flowtype/dist/rules/useFlowType.js' { 303 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/useFlowType'>; 304 | } 305 | declare module 'eslint-plugin-flowtype/dist/rules/validSyntax.js' { 306 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/validSyntax'>; 307 | } 308 | declare module 'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation.js' { 309 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation'>; 310 | } 311 | declare module 'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch.js' { 312 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch'>; 313 | } 314 | declare module 'eslint-plugin-flowtype/dist/utilities/getParameterName.js' { 315 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getParameterName'>; 316 | } 317 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens.js' { 318 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens'>; 319 | } 320 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens.js' { 321 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens'>; 322 | } 323 | declare module 'eslint-plugin-flowtype/dist/utilities/index.js' { 324 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/index'>; 325 | } 326 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFile.js' { 327 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/isFlowFile'>; 328 | } 329 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation.js' { 330 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation'>; 331 | } 332 | declare module 'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes.js' { 333 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes'>; 334 | } 335 | declare module 'eslint-plugin-flowtype/dist/utilities/quoteName.js' { 336 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/quoteName'>; 337 | } 338 | declare module 'eslint-plugin-flowtype/dist/utilities/spacingFixers.js' { 339 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/spacingFixers'>; 340 | } 341 | -------------------------------------------------------------------------------- /flow-typed/npm/eslint-plugin-react_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: ac6d689b6059ae4f32504b8eb2c6c381 2 | // flow-typed version: <>/eslint-plugin-react_v^7.4.0/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'eslint-plugin-react' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'eslint-plugin-react' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'eslint-plugin-react/lib/rules/boolean-prop-naming' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'eslint-plugin-react/lib/rules/default-props-match-prop-types' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'eslint-plugin-react/lib/rules/display-name' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'eslint-plugin-react/lib/rules/forbid-component-props' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'eslint-plugin-react/lib/rules/forbid-elements' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'eslint-plugin-react/lib/rules/forbid-foreign-prop-types' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'eslint-plugin-react/lib/rules/forbid-prop-types' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'eslint-plugin-react/lib/rules/jsx-boolean-value' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'eslint-plugin-react/lib/rules/jsx-closing-bracket-location' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'eslint-plugin-react/lib/rules/jsx-closing-tag-location' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'eslint-plugin-react/lib/rules/jsx-curly-brace-presence' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'eslint-plugin-react/lib/rules/jsx-curly-spacing' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'eslint-plugin-react/lib/rules/jsx-equals-spacing' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'eslint-plugin-react/lib/rules/jsx-filename-extension' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'eslint-plugin-react/lib/rules/jsx-first-prop-new-line' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'eslint-plugin-react/lib/rules/jsx-handler-names' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'eslint-plugin-react/lib/rules/jsx-indent-props' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'eslint-plugin-react/lib/rules/jsx-indent' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'eslint-plugin-react/lib/rules/jsx-key' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'eslint-plugin-react/lib/rules/jsx-max-props-per-line' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'eslint-plugin-react/lib/rules/jsx-no-bind' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'eslint-plugin-react/lib/rules/jsx-no-comment-textnodes' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'eslint-plugin-react/lib/rules/jsx-no-duplicate-props' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'eslint-plugin-react/lib/rules/jsx-no-literals' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'eslint-plugin-react/lib/rules/jsx-no-target-blank' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'eslint-plugin-react/lib/rules/jsx-no-undef' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'eslint-plugin-react/lib/rules/jsx-pascal-case' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'eslint-plugin-react/lib/rules/jsx-sort-props' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module 'eslint-plugin-react/lib/rules/jsx-space-before-closing' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module 'eslint-plugin-react/lib/rules/jsx-tag-spacing' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module 'eslint-plugin-react/lib/rules/jsx-uses-react' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module 'eslint-plugin-react/lib/rules/jsx-uses-vars' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module 'eslint-plugin-react/lib/rules/jsx-wrap-multilines' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module 'eslint-plugin-react/lib/rules/no-array-index-key' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module 'eslint-plugin-react/lib/rules/no-children-prop' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module 'eslint-plugin-react/lib/rules/no-danger-with-children' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module 'eslint-plugin-react/lib/rules/no-danger' { 170 | declare module.exports: any; 171 | } 172 | 173 | declare module 'eslint-plugin-react/lib/rules/no-deprecated' { 174 | declare module.exports: any; 175 | } 176 | 177 | declare module 'eslint-plugin-react/lib/rules/no-did-mount-set-state' { 178 | declare module.exports: any; 179 | } 180 | 181 | declare module 'eslint-plugin-react/lib/rules/no-did-update-set-state' { 182 | declare module.exports: any; 183 | } 184 | 185 | declare module 'eslint-plugin-react/lib/rules/no-direct-mutation-state' { 186 | declare module.exports: any; 187 | } 188 | 189 | declare module 'eslint-plugin-react/lib/rules/no-find-dom-node' { 190 | declare module.exports: any; 191 | } 192 | 193 | declare module 'eslint-plugin-react/lib/rules/no-is-mounted' { 194 | declare module.exports: any; 195 | } 196 | 197 | declare module 'eslint-plugin-react/lib/rules/no-multi-comp' { 198 | declare module.exports: any; 199 | } 200 | 201 | declare module 'eslint-plugin-react/lib/rules/no-redundant-should-component-update' { 202 | declare module.exports: any; 203 | } 204 | 205 | declare module 'eslint-plugin-react/lib/rules/no-render-return-value' { 206 | declare module.exports: any; 207 | } 208 | 209 | declare module 'eslint-plugin-react/lib/rules/no-set-state' { 210 | declare module.exports: any; 211 | } 212 | 213 | declare module 'eslint-plugin-react/lib/rules/no-string-refs' { 214 | declare module.exports: any; 215 | } 216 | 217 | declare module 'eslint-plugin-react/lib/rules/no-typos' { 218 | declare module.exports: any; 219 | } 220 | 221 | declare module 'eslint-plugin-react/lib/rules/no-unescaped-entities' { 222 | declare module.exports: any; 223 | } 224 | 225 | declare module 'eslint-plugin-react/lib/rules/no-unknown-property' { 226 | declare module.exports: any; 227 | } 228 | 229 | declare module 'eslint-plugin-react/lib/rules/no-unused-prop-types' { 230 | declare module.exports: any; 231 | } 232 | 233 | declare module 'eslint-plugin-react/lib/rules/no-unused-state' { 234 | declare module.exports: any; 235 | } 236 | 237 | declare module 'eslint-plugin-react/lib/rules/no-will-update-set-state' { 238 | declare module.exports: any; 239 | } 240 | 241 | declare module 'eslint-plugin-react/lib/rules/prefer-es6-class' { 242 | declare module.exports: any; 243 | } 244 | 245 | declare module 'eslint-plugin-react/lib/rules/prefer-stateless-function' { 246 | declare module.exports: any; 247 | } 248 | 249 | declare module 'eslint-plugin-react/lib/rules/prop-types' { 250 | declare module.exports: any; 251 | } 252 | 253 | declare module 'eslint-plugin-react/lib/rules/react-in-jsx-scope' { 254 | declare module.exports: any; 255 | } 256 | 257 | declare module 'eslint-plugin-react/lib/rules/require-default-props' { 258 | declare module.exports: any; 259 | } 260 | 261 | declare module 'eslint-plugin-react/lib/rules/require-optimization' { 262 | declare module.exports: any; 263 | } 264 | 265 | declare module 'eslint-plugin-react/lib/rules/require-render-return' { 266 | declare module.exports: any; 267 | } 268 | 269 | declare module 'eslint-plugin-react/lib/rules/self-closing-comp' { 270 | declare module.exports: any; 271 | } 272 | 273 | declare module 'eslint-plugin-react/lib/rules/sort-comp' { 274 | declare module.exports: any; 275 | } 276 | 277 | declare module 'eslint-plugin-react/lib/rules/sort-prop-types' { 278 | declare module.exports: any; 279 | } 280 | 281 | declare module 'eslint-plugin-react/lib/rules/style-prop-object' { 282 | declare module.exports: any; 283 | } 284 | 285 | declare module 'eslint-plugin-react/lib/rules/void-dom-elements-no-children' { 286 | declare module.exports: any; 287 | } 288 | 289 | declare module 'eslint-plugin-react/lib/util/annotations' { 290 | declare module.exports: any; 291 | } 292 | 293 | declare module 'eslint-plugin-react/lib/util/Components' { 294 | declare module.exports: any; 295 | } 296 | 297 | declare module 'eslint-plugin-react/lib/util/getTokenBeforeClosingBracket' { 298 | declare module.exports: any; 299 | } 300 | 301 | declare module 'eslint-plugin-react/lib/util/makeNoMethodSetStateRule' { 302 | declare module.exports: any; 303 | } 304 | 305 | declare module 'eslint-plugin-react/lib/util/pragma' { 306 | declare module.exports: any; 307 | } 308 | 309 | declare module 'eslint-plugin-react/lib/util/variable' { 310 | declare module.exports: any; 311 | } 312 | 313 | declare module 'eslint-plugin-react/lib/util/version' { 314 | declare module.exports: any; 315 | } 316 | 317 | // Filename aliases 318 | declare module 'eslint-plugin-react/index' { 319 | declare module.exports: $Exports<'eslint-plugin-react'>; 320 | } 321 | declare module 'eslint-plugin-react/index.js' { 322 | declare module.exports: $Exports<'eslint-plugin-react'>; 323 | } 324 | declare module 'eslint-plugin-react/lib/rules/boolean-prop-naming.js' { 325 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/boolean-prop-naming'>; 326 | } 327 | declare module 'eslint-plugin-react/lib/rules/default-props-match-prop-types.js' { 328 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/default-props-match-prop-types'>; 329 | } 330 | declare module 'eslint-plugin-react/lib/rules/display-name.js' { 331 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/display-name'>; 332 | } 333 | declare module 'eslint-plugin-react/lib/rules/forbid-component-props.js' { 334 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/forbid-component-props'>; 335 | } 336 | declare module 'eslint-plugin-react/lib/rules/forbid-elements.js' { 337 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/forbid-elements'>; 338 | } 339 | declare module 'eslint-plugin-react/lib/rules/forbid-foreign-prop-types.js' { 340 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/forbid-foreign-prop-types'>; 341 | } 342 | declare module 'eslint-plugin-react/lib/rules/forbid-prop-types.js' { 343 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/forbid-prop-types'>; 344 | } 345 | declare module 'eslint-plugin-react/lib/rules/jsx-boolean-value.js' { 346 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-boolean-value'>; 347 | } 348 | declare module 'eslint-plugin-react/lib/rules/jsx-closing-bracket-location.js' { 349 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-closing-bracket-location'>; 350 | } 351 | declare module 'eslint-plugin-react/lib/rules/jsx-closing-tag-location.js' { 352 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-closing-tag-location'>; 353 | } 354 | declare module 'eslint-plugin-react/lib/rules/jsx-curly-brace-presence.js' { 355 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-curly-brace-presence'>; 356 | } 357 | declare module 'eslint-plugin-react/lib/rules/jsx-curly-spacing.js' { 358 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-curly-spacing'>; 359 | } 360 | declare module 'eslint-plugin-react/lib/rules/jsx-equals-spacing.js' { 361 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-equals-spacing'>; 362 | } 363 | declare module 'eslint-plugin-react/lib/rules/jsx-filename-extension.js' { 364 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-filename-extension'>; 365 | } 366 | declare module 'eslint-plugin-react/lib/rules/jsx-first-prop-new-line.js' { 367 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-first-prop-new-line'>; 368 | } 369 | declare module 'eslint-plugin-react/lib/rules/jsx-handler-names.js' { 370 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-handler-names'>; 371 | } 372 | declare module 'eslint-plugin-react/lib/rules/jsx-indent-props.js' { 373 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-indent-props'>; 374 | } 375 | declare module 'eslint-plugin-react/lib/rules/jsx-indent.js' { 376 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-indent'>; 377 | } 378 | declare module 'eslint-plugin-react/lib/rules/jsx-key.js' { 379 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-key'>; 380 | } 381 | declare module 'eslint-plugin-react/lib/rules/jsx-max-props-per-line.js' { 382 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-max-props-per-line'>; 383 | } 384 | declare module 'eslint-plugin-react/lib/rules/jsx-no-bind.js' { 385 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-no-bind'>; 386 | } 387 | declare module 'eslint-plugin-react/lib/rules/jsx-no-comment-textnodes.js' { 388 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-no-comment-textnodes'>; 389 | } 390 | declare module 'eslint-plugin-react/lib/rules/jsx-no-duplicate-props.js' { 391 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-no-duplicate-props'>; 392 | } 393 | declare module 'eslint-plugin-react/lib/rules/jsx-no-literals.js' { 394 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-no-literals'>; 395 | } 396 | declare module 'eslint-plugin-react/lib/rules/jsx-no-target-blank.js' { 397 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-no-target-blank'>; 398 | } 399 | declare module 'eslint-plugin-react/lib/rules/jsx-no-undef.js' { 400 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-no-undef'>; 401 | } 402 | declare module 'eslint-plugin-react/lib/rules/jsx-pascal-case.js' { 403 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-pascal-case'>; 404 | } 405 | declare module 'eslint-plugin-react/lib/rules/jsx-sort-props.js' { 406 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-sort-props'>; 407 | } 408 | declare module 'eslint-plugin-react/lib/rules/jsx-space-before-closing.js' { 409 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-space-before-closing'>; 410 | } 411 | declare module 'eslint-plugin-react/lib/rules/jsx-tag-spacing.js' { 412 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-tag-spacing'>; 413 | } 414 | declare module 'eslint-plugin-react/lib/rules/jsx-uses-react.js' { 415 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-uses-react'>; 416 | } 417 | declare module 'eslint-plugin-react/lib/rules/jsx-uses-vars.js' { 418 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-uses-vars'>; 419 | } 420 | declare module 'eslint-plugin-react/lib/rules/jsx-wrap-multilines.js' { 421 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-wrap-multilines'>; 422 | } 423 | declare module 'eslint-plugin-react/lib/rules/no-array-index-key.js' { 424 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-array-index-key'>; 425 | } 426 | declare module 'eslint-plugin-react/lib/rules/no-children-prop.js' { 427 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-children-prop'>; 428 | } 429 | declare module 'eslint-plugin-react/lib/rules/no-danger-with-children.js' { 430 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-danger-with-children'>; 431 | } 432 | declare module 'eslint-plugin-react/lib/rules/no-danger.js' { 433 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-danger'>; 434 | } 435 | declare module 'eslint-plugin-react/lib/rules/no-deprecated.js' { 436 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-deprecated'>; 437 | } 438 | declare module 'eslint-plugin-react/lib/rules/no-did-mount-set-state.js' { 439 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-did-mount-set-state'>; 440 | } 441 | declare module 'eslint-plugin-react/lib/rules/no-did-update-set-state.js' { 442 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-did-update-set-state'>; 443 | } 444 | declare module 'eslint-plugin-react/lib/rules/no-direct-mutation-state.js' { 445 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-direct-mutation-state'>; 446 | } 447 | declare module 'eslint-plugin-react/lib/rules/no-find-dom-node.js' { 448 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-find-dom-node'>; 449 | } 450 | declare module 'eslint-plugin-react/lib/rules/no-is-mounted.js' { 451 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-is-mounted'>; 452 | } 453 | declare module 'eslint-plugin-react/lib/rules/no-multi-comp.js' { 454 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-multi-comp'>; 455 | } 456 | declare module 'eslint-plugin-react/lib/rules/no-redundant-should-component-update.js' { 457 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-redundant-should-component-update'>; 458 | } 459 | declare module 'eslint-plugin-react/lib/rules/no-render-return-value.js' { 460 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-render-return-value'>; 461 | } 462 | declare module 'eslint-plugin-react/lib/rules/no-set-state.js' { 463 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-set-state'>; 464 | } 465 | declare module 'eslint-plugin-react/lib/rules/no-string-refs.js' { 466 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-string-refs'>; 467 | } 468 | declare module 'eslint-plugin-react/lib/rules/no-typos.js' { 469 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-typos'>; 470 | } 471 | declare module 'eslint-plugin-react/lib/rules/no-unescaped-entities.js' { 472 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-unescaped-entities'>; 473 | } 474 | declare module 'eslint-plugin-react/lib/rules/no-unknown-property.js' { 475 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-unknown-property'>; 476 | } 477 | declare module 'eslint-plugin-react/lib/rules/no-unused-prop-types.js' { 478 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-unused-prop-types'>; 479 | } 480 | declare module 'eslint-plugin-react/lib/rules/no-unused-state.js' { 481 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-unused-state'>; 482 | } 483 | declare module 'eslint-plugin-react/lib/rules/no-will-update-set-state.js' { 484 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/no-will-update-set-state'>; 485 | } 486 | declare module 'eslint-plugin-react/lib/rules/prefer-es6-class.js' { 487 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/prefer-es6-class'>; 488 | } 489 | declare module 'eslint-plugin-react/lib/rules/prefer-stateless-function.js' { 490 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/prefer-stateless-function'>; 491 | } 492 | declare module 'eslint-plugin-react/lib/rules/prop-types.js' { 493 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/prop-types'>; 494 | } 495 | declare module 'eslint-plugin-react/lib/rules/react-in-jsx-scope.js' { 496 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/react-in-jsx-scope'>; 497 | } 498 | declare module 'eslint-plugin-react/lib/rules/require-default-props.js' { 499 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/require-default-props'>; 500 | } 501 | declare module 'eslint-plugin-react/lib/rules/require-optimization.js' { 502 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/require-optimization'>; 503 | } 504 | declare module 'eslint-plugin-react/lib/rules/require-render-return.js' { 505 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/require-render-return'>; 506 | } 507 | declare module 'eslint-plugin-react/lib/rules/self-closing-comp.js' { 508 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/self-closing-comp'>; 509 | } 510 | declare module 'eslint-plugin-react/lib/rules/sort-comp.js' { 511 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/sort-comp'>; 512 | } 513 | declare module 'eslint-plugin-react/lib/rules/sort-prop-types.js' { 514 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/sort-prop-types'>; 515 | } 516 | declare module 'eslint-plugin-react/lib/rules/style-prop-object.js' { 517 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/style-prop-object'>; 518 | } 519 | declare module 'eslint-plugin-react/lib/rules/void-dom-elements-no-children.js' { 520 | declare module.exports: $Exports<'eslint-plugin-react/lib/rules/void-dom-elements-no-children'>; 521 | } 522 | declare module 'eslint-plugin-react/lib/util/annotations.js' { 523 | declare module.exports: $Exports<'eslint-plugin-react/lib/util/annotations'>; 524 | } 525 | declare module 'eslint-plugin-react/lib/util/Components.js' { 526 | declare module.exports: $Exports<'eslint-plugin-react/lib/util/Components'>; 527 | } 528 | declare module 'eslint-plugin-react/lib/util/getTokenBeforeClosingBracket.js' { 529 | declare module.exports: $Exports<'eslint-plugin-react/lib/util/getTokenBeforeClosingBracket'>; 530 | } 531 | declare module 'eslint-plugin-react/lib/util/makeNoMethodSetStateRule.js' { 532 | declare module.exports: $Exports<'eslint-plugin-react/lib/util/makeNoMethodSetStateRule'>; 533 | } 534 | declare module 'eslint-plugin-react/lib/util/pragma.js' { 535 | declare module.exports: $Exports<'eslint-plugin-react/lib/util/pragma'>; 536 | } 537 | declare module 'eslint-plugin-react/lib/util/variable.js' { 538 | declare module.exports: $Exports<'eslint-plugin-react/lib/util/variable'>; 539 | } 540 | declare module 'eslint-plugin-react/lib/util/version.js' { 541 | declare module.exports: $Exports<'eslint-plugin-react/lib/util/version'>; 542 | } 543 | -------------------------------------------------------------------------------- /flow-typed/npm/flow-bin_v0.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6a5610678d4b01e13bbfbbc62bdaf583 2 | // flow-typed version: 3817bc6980/flow-bin_v0.x.x/flow_>=v0.25.x 3 | 4 | declare module "flow-bin" { 5 | declare module.exports: string; 6 | } 7 | -------------------------------------------------------------------------------- /flow-typed/npm/next_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a090d89ea52a4af4a03acae98696426a 2 | // flow-typed version: <>/next_v^4.0.3/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'next' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'next' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'next/babel' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'next/css' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'next/dist/client/head-manager' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'next/dist/client/index' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'next/dist/client/next-dev' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'next/dist/client/next' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'next/dist/client/on-demand-entries-client' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'next/dist/client/webpack-hot-middleware-client' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'next/dist/lib/app' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'next/dist/lib/css' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'next/dist/lib/dynamic' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'next/dist/lib/error-debug' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'next/dist/lib/error' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'next/dist/lib/EventEmitter' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'next/dist/lib/head' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'next/dist/lib/link' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'next/dist/lib/p-queue' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'next/dist/lib/page-loader' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'next/dist/lib/prefetch' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'next/dist/lib/router/index' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'next/dist/lib/router/router' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'next/dist/lib/router/with-router' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'next/dist/lib/shallow-equals' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'next/dist/lib/side-effect' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'next/dist/lib/utils' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'next/dist/pages/_document' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'next/dist/pages/_error' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'next/dist/server/build/babel/find-config' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module 'next/dist/server/build/babel/plugins/handle-import' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module 'next/dist/server/build/babel/preset' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module 'next/dist/server/build/clean' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module 'next/dist/server/build/index' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module 'next/dist/server/build/loaders/emit-file-loader' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module 'next/dist/server/build/loaders/hot-self-accept-loader' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module 'next/dist/server/build/plugins/combine-assets-plugin' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module 'next/dist/server/build/plugins/dynamic-chunks-plugin' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module 'next/dist/server/build/plugins/pages-plugin' { 170 | declare module.exports: any; 171 | } 172 | 173 | declare module 'next/dist/server/build/plugins/unlink-file-plugin' { 174 | declare module.exports: any; 175 | } 176 | 177 | declare module 'next/dist/server/build/plugins/watch-pages-plugin' { 178 | declare module.exports: any; 179 | } 180 | 181 | declare module 'next/dist/server/build/replace' { 182 | declare module.exports: any; 183 | } 184 | 185 | declare module 'next/dist/server/build/root-module-relative-path' { 186 | declare module.exports: any; 187 | } 188 | 189 | declare module 'next/dist/server/build/webpack' { 190 | declare module.exports: any; 191 | } 192 | 193 | declare module 'next/dist/server/config' { 194 | declare module.exports: any; 195 | } 196 | 197 | declare module 'next/dist/server/document' { 198 | declare module.exports: any; 199 | } 200 | 201 | declare module 'next/dist/server/export' { 202 | declare module.exports: any; 203 | } 204 | 205 | declare module 'next/dist/server/hot-reloader' { 206 | declare module.exports: any; 207 | } 208 | 209 | declare module 'next/dist/server/index' { 210 | declare module.exports: any; 211 | } 212 | 213 | declare module 'next/dist/server/next' { 214 | declare module.exports: any; 215 | } 216 | 217 | declare module 'next/dist/server/on-demand-entry-handler' { 218 | declare module.exports: any; 219 | } 220 | 221 | declare module 'next/dist/server/render' { 222 | declare module.exports: any; 223 | } 224 | 225 | declare module 'next/dist/server/require' { 226 | declare module.exports: any; 227 | } 228 | 229 | declare module 'next/dist/server/resolve' { 230 | declare module.exports: any; 231 | } 232 | 233 | declare module 'next/dist/server/router' { 234 | declare module.exports: any; 235 | } 236 | 237 | declare module 'next/dist/server/utils' { 238 | declare module.exports: any; 239 | } 240 | 241 | declare module 'next/document' { 242 | declare module.exports: any; 243 | } 244 | 245 | declare module 'next/dynamic' { 246 | declare module.exports: any; 247 | } 248 | 249 | declare module 'next/error' { 250 | declare module.exports: any; 251 | } 252 | 253 | declare module 'next/head' { 254 | declare module.exports: any; 255 | } 256 | 257 | declare module 'next/link' { 258 | declare module.exports: any; 259 | } 260 | 261 | declare module 'next/prefetch' { 262 | declare module.exports: any; 263 | } 264 | 265 | declare module 'next/router' { 266 | declare module.exports: any; 267 | } 268 | 269 | // Filename aliases 270 | declare module 'next/babel.js' { 271 | declare module.exports: $Exports<'next/babel'>; 272 | } 273 | declare module 'next/css.js' { 274 | declare module.exports: $Exports<'next/css'>; 275 | } 276 | declare module 'next/dist/client/head-manager.js' { 277 | declare module.exports: $Exports<'next/dist/client/head-manager'>; 278 | } 279 | declare module 'next/dist/client/index.js' { 280 | declare module.exports: $Exports<'next/dist/client/index'>; 281 | } 282 | declare module 'next/dist/client/next-dev.js' { 283 | declare module.exports: $Exports<'next/dist/client/next-dev'>; 284 | } 285 | declare module 'next/dist/client/next.js' { 286 | declare module.exports: $Exports<'next/dist/client/next'>; 287 | } 288 | declare module 'next/dist/client/on-demand-entries-client.js' { 289 | declare module.exports: $Exports<'next/dist/client/on-demand-entries-client'>; 290 | } 291 | declare module 'next/dist/client/webpack-hot-middleware-client.js' { 292 | declare module.exports: $Exports<'next/dist/client/webpack-hot-middleware-client'>; 293 | } 294 | declare module 'next/dist/lib/app.js' { 295 | declare module.exports: $Exports<'next/dist/lib/app'>; 296 | } 297 | declare module 'next/dist/lib/css.js' { 298 | declare module.exports: $Exports<'next/dist/lib/css'>; 299 | } 300 | declare module 'next/dist/lib/dynamic.js' { 301 | declare module.exports: $Exports<'next/dist/lib/dynamic'>; 302 | } 303 | declare module 'next/dist/lib/error-debug.js' { 304 | declare module.exports: $Exports<'next/dist/lib/error-debug'>; 305 | } 306 | declare module 'next/dist/lib/error.js' { 307 | declare module.exports: $Exports<'next/dist/lib/error'>; 308 | } 309 | declare module 'next/dist/lib/EventEmitter.js' { 310 | declare module.exports: $Exports<'next/dist/lib/EventEmitter'>; 311 | } 312 | declare module 'next/dist/lib/head.js' { 313 | declare module.exports: $Exports<'next/dist/lib/head'>; 314 | } 315 | declare module 'next/dist/lib/link.js' { 316 | declare module.exports: $Exports<'next/dist/lib/link'>; 317 | } 318 | declare module 'next/dist/lib/p-queue.js' { 319 | declare module.exports: $Exports<'next/dist/lib/p-queue'>; 320 | } 321 | declare module 'next/dist/lib/page-loader.js' { 322 | declare module.exports: $Exports<'next/dist/lib/page-loader'>; 323 | } 324 | declare module 'next/dist/lib/prefetch.js' { 325 | declare module.exports: $Exports<'next/dist/lib/prefetch'>; 326 | } 327 | declare module 'next/dist/lib/router/index.js' { 328 | declare module.exports: $Exports<'next/dist/lib/router/index'>; 329 | } 330 | declare module 'next/dist/lib/router/router.js' { 331 | declare module.exports: $Exports<'next/dist/lib/router/router'>; 332 | } 333 | declare module 'next/dist/lib/router/with-router.js' { 334 | declare module.exports: $Exports<'next/dist/lib/router/with-router'>; 335 | } 336 | declare module 'next/dist/lib/shallow-equals.js' { 337 | declare module.exports: $Exports<'next/dist/lib/shallow-equals'>; 338 | } 339 | declare module 'next/dist/lib/side-effect.js' { 340 | declare module.exports: $Exports<'next/dist/lib/side-effect'>; 341 | } 342 | declare module 'next/dist/lib/utils.js' { 343 | declare module.exports: $Exports<'next/dist/lib/utils'>; 344 | } 345 | declare module 'next/dist/pages/_document.js' { 346 | declare module.exports: $Exports<'next/dist/pages/_document'>; 347 | } 348 | declare module 'next/dist/pages/_error.js' { 349 | declare module.exports: $Exports<'next/dist/pages/_error'>; 350 | } 351 | declare module 'next/dist/server/build/babel/find-config.js' { 352 | declare module.exports: $Exports<'next/dist/server/build/babel/find-config'>; 353 | } 354 | declare module 'next/dist/server/build/babel/plugins/handle-import.js' { 355 | declare module.exports: $Exports<'next/dist/server/build/babel/plugins/handle-import'>; 356 | } 357 | declare module 'next/dist/server/build/babel/preset.js' { 358 | declare module.exports: $Exports<'next/dist/server/build/babel/preset'>; 359 | } 360 | declare module 'next/dist/server/build/clean.js' { 361 | declare module.exports: $Exports<'next/dist/server/build/clean'>; 362 | } 363 | declare module 'next/dist/server/build/index.js' { 364 | declare module.exports: $Exports<'next/dist/server/build/index'>; 365 | } 366 | declare module 'next/dist/server/build/loaders/emit-file-loader.js' { 367 | declare module.exports: $Exports<'next/dist/server/build/loaders/emit-file-loader'>; 368 | } 369 | declare module 'next/dist/server/build/loaders/hot-self-accept-loader.js' { 370 | declare module.exports: $Exports<'next/dist/server/build/loaders/hot-self-accept-loader'>; 371 | } 372 | declare module 'next/dist/server/build/plugins/combine-assets-plugin.js' { 373 | declare module.exports: $Exports<'next/dist/server/build/plugins/combine-assets-plugin'>; 374 | } 375 | declare module 'next/dist/server/build/plugins/dynamic-chunks-plugin.js' { 376 | declare module.exports: $Exports<'next/dist/server/build/plugins/dynamic-chunks-plugin'>; 377 | } 378 | declare module 'next/dist/server/build/plugins/pages-plugin.js' { 379 | declare module.exports: $Exports<'next/dist/server/build/plugins/pages-plugin'>; 380 | } 381 | declare module 'next/dist/server/build/plugins/unlink-file-plugin.js' { 382 | declare module.exports: $Exports<'next/dist/server/build/plugins/unlink-file-plugin'>; 383 | } 384 | declare module 'next/dist/server/build/plugins/watch-pages-plugin.js' { 385 | declare module.exports: $Exports<'next/dist/server/build/plugins/watch-pages-plugin'>; 386 | } 387 | declare module 'next/dist/server/build/replace.js' { 388 | declare module.exports: $Exports<'next/dist/server/build/replace'>; 389 | } 390 | declare module 'next/dist/server/build/root-module-relative-path.js' { 391 | declare module.exports: $Exports<'next/dist/server/build/root-module-relative-path'>; 392 | } 393 | declare module 'next/dist/server/build/webpack.js' { 394 | declare module.exports: $Exports<'next/dist/server/build/webpack'>; 395 | } 396 | declare module 'next/dist/server/config.js' { 397 | declare module.exports: $Exports<'next/dist/server/config'>; 398 | } 399 | declare module 'next/dist/server/document.js' { 400 | declare module.exports: $Exports<'next/dist/server/document'>; 401 | } 402 | declare module 'next/dist/server/export.js' { 403 | declare module.exports: $Exports<'next/dist/server/export'>; 404 | } 405 | declare module 'next/dist/server/hot-reloader.js' { 406 | declare module.exports: $Exports<'next/dist/server/hot-reloader'>; 407 | } 408 | declare module 'next/dist/server/index.js' { 409 | declare module.exports: $Exports<'next/dist/server/index'>; 410 | } 411 | declare module 'next/dist/server/next.js' { 412 | declare module.exports: $Exports<'next/dist/server/next'>; 413 | } 414 | declare module 'next/dist/server/on-demand-entry-handler.js' { 415 | declare module.exports: $Exports<'next/dist/server/on-demand-entry-handler'>; 416 | } 417 | declare module 'next/dist/server/render.js' { 418 | declare module.exports: $Exports<'next/dist/server/render'>; 419 | } 420 | declare module 'next/dist/server/require.js' { 421 | declare module.exports: $Exports<'next/dist/server/require'>; 422 | } 423 | declare module 'next/dist/server/resolve.js' { 424 | declare module.exports: $Exports<'next/dist/server/resolve'>; 425 | } 426 | declare module 'next/dist/server/router.js' { 427 | declare module.exports: $Exports<'next/dist/server/router'>; 428 | } 429 | declare module 'next/dist/server/utils.js' { 430 | declare module.exports: $Exports<'next/dist/server/utils'>; 431 | } 432 | declare module 'next/document.js' { 433 | declare module.exports: $Exports<'next/document'>; 434 | } 435 | declare module 'next/dynamic.js' { 436 | declare module.exports: $Exports<'next/dynamic'>; 437 | } 438 | declare module 'next/error.js' { 439 | declare module.exports: $Exports<'next/error'>; 440 | } 441 | declare module 'next/head.js' { 442 | declare module.exports: $Exports<'next/head'>; 443 | } 444 | declare module 'next/link.js' { 445 | declare module.exports: $Exports<'next/link'>; 446 | } 447 | declare module 'next/prefetch.js' { 448 | declare module.exports: $Exports<'next/prefetch'>; 449 | } 450 | declare module 'next/router.js' { 451 | declare module.exports: $Exports<'next/router'>; 452 | } 453 | -------------------------------------------------------------------------------- /mock/fakeAPI.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "label": "item 1" 5 | }, 6 | { 7 | "id": 2, 8 | "label": "item 2" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /mock/userInfosMock.json: -------------------------------------------------------------------------------- 1 | { 2 | "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJkZW1vIiwiaWF0IjoxNTAyMzA3MzU0LCJleHAiOjE3MjMyMzIxNTQsImF1ZCI6ImRlbW8tZGVtbyIsInN1YiI6ImRlbW8iLCJHaXZlbk5hbWUiOiJKb2huIiwiU3VybmFtZSI6IkRvZSIsIkVtYWlsIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJSb2xlIjpbIlN1cGVyIGNvb2wgZGV2IiwibWFnaWMgbWFrZXIiXX0.6FjgLCypaqmRp4tDjg_idVKIzQw16e-z_rjA3R94IqQ", 3 | "user": { 4 | "id": 111, 5 | "login": "john.doe@fake.mail", 6 | "firstname": "John", 7 | "lastname": "Doe", 8 | "isAdmin": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | // next.config.js 2 | module.exports = { 3 | /* config options here */ 4 | }; 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-redux-nextjs-bootstrap-starter", 3 | "version": "0.3.0", 4 | "description": "react + redux + next js + bootstrap starter", 5 | "author": "Erwan DATIN (http://www.erwan-datin.com)", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/MacKentoch/react-redux-nextjs-bootstrap-starter.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/MacKentoch/react-redux-nextjs-bootstrap-starter/issues" 13 | }, 14 | "keywords": [ 15 | "react", 16 | "next", 17 | "zeit", 18 | "next.js", 19 | "next js", 20 | "now", 21 | "redux", 22 | "react-redux", 23 | "ES6", 24 | "ES7", 25 | "ES8", 26 | "ES2015", 27 | "ES2016", 28 | "ES2017", 29 | "bootstrap", 30 | "starter", 31 | "persist", 32 | "redux-persist", 33 | "hot-reload" 34 | ], 35 | "engines": { 36 | "node": ">=8.6.0", 37 | "npm": ">=5.4.2" 38 | }, 39 | "main": "index.js", 40 | "scripts": { 41 | "dev": "next", 42 | "build": "next build", 43 | "start": "next start", 44 | "deploy": "now --public" 45 | }, 46 | "dependencies": { 47 | "axios": "^0.16.2", 48 | "jwt-decode": "^2.2.0", 49 | "localforage": "^1.5.2", 50 | "moment": "^2.19.1", 51 | "next": "^4.0.3", 52 | "next-redux-wrapper": "^1.3.4", 53 | "normalize.css": "^7.0.0", 54 | "react": "^16.0.0", 55 | "react-bootstrap": "^0.31.3", 56 | "react-dom": "^16.0.0", 57 | "react-redux": "^5.0.6", 58 | "redux": "^3.7.2", 59 | "redux-persist": "^4.10.1", 60 | "redux-thunk": "^2.2.0" 61 | }, 62 | "devDependencies": { 63 | "@types/axios": "^0.14.0", 64 | "@types/jwt-decode": "^2.2.1", 65 | "@types/moment": "^2.13.0", 66 | "@types/next": "^2.4.3", 67 | "@types/next-redux-wrapper": "^1.3.3", 68 | "@types/react": "^16.0.10", 69 | "@types/react-bootstrap": "^0.31.4", 70 | "@types/react-dom": "^16.0.1", 71 | "@types/react-redux": "^5.0.10", 72 | "@types/redux": "^3.6.0", 73 | "@types/redux-persist": "^4.3.1", 74 | "@types/redux-thunk": "^2.1.0", 75 | "babel-eslint": "^8.0.1", 76 | "babel-plugin-transform-async-to-generator": "^6.24.1", 77 | "babel-plugin-transform-regenerator": "^6.26.0", 78 | "babel-preset-es2015": "^6.24.1", 79 | "babel-preset-flow": "^6.23.0", 80 | "babel-preset-react": "^6.24.1", 81 | "babel-preset-stage-2": "^6.24.1", 82 | "eslint": "^4.8.0", 83 | "eslint-plugin-flowtype": "^2.39.1", 84 | "eslint-plugin-react": "^7.4.0", 85 | "flow-bin": "^0.57.2", 86 | "redux-devtools-extension": "^2.13.2", 87 | "redux-logger": "^3.0.6" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /pages/_error.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import React, { 5 | PureComponent 6 | } from 'react'; 7 | import Jumbotron from 'react-bootstrap/lib/Jumbotron'; 8 | // #endregion 9 | 10 | // #region flow types 11 | type Props = { 12 | errorCode?: number 13 | }; 14 | 15 | type State = any; 16 | 17 | type NextInitialProps = { 18 | res?: { 19 | statusCode: number 20 | }, 21 | xhr: { 22 | status: number 23 | } 24 | } 25 | // #endregion 26 | 27 | class Error extends PureComponent { 28 | // #region props initialization 29 | static getInitialProps( 30 | {res, xhr}: NextInitialProps 31 | ) { 32 | const errorCode = res ? res.statusCode : xhr.status; 33 | return { errorCode }; 34 | } 35 | // #endregion 36 | 37 | // #region component default props 38 | static defaultProps = { 39 | errorCode: null 40 | }; 41 | // #endregion 42 | 43 | // #region component lifecycle methods 44 | render() { 45 | const { 46 | errorCode 47 | } = this.props; 48 | 49 | return ( 50 | 51 | 52 | Sorry but this time... It threw an error... 53 | 54 | 55 | Error code: { errorCode ? errorCode : '--' } 56 | 57 | 58 | ); 59 | } 60 | // #endregion 61 | } 62 | 63 | export default Error; 64 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import { PureComponent } from 'react'; 5 | import { bindActionCreators } from 'redux'; 6 | import withRedux from 'next-redux-wrapper'; 7 | import configureStore from '../redux/store/configureStore'; 8 | import * as fakeFetchActions from '../redux/modules/fakeModuleWithFetch'; 9 | import * as userAuthActions from '../redux/modules/userAuth'; 10 | import Layout from '../components/layout/Layout'; 11 | import Header from '../components/header/Header'; 12 | import Jumbotron from 'react-bootstrap/lib/Jumbotron'; 13 | import Button from 'react-bootstrap/lib/Button'; 14 | import Router from 'next/router'; 15 | // #endregion 16 | 17 | // #region flow types 18 | type Props = { 19 | // fakeModuleWithFetch: 20 | isFetching: boolean; 21 | fakeData: any, 22 | fakeFetchIfNeeded: () => Promise, 23 | // userAuth: 24 | isAuthenticated: boolean, 25 | disconnectUser: () => any, 26 | ...any 27 | }; 28 | 29 | type State = any; 30 | 31 | type InitialProps = { 32 | req: any, 33 | res: any, 34 | pathname: string, 35 | query: any, 36 | asPath: string, 37 | isServer: boolean, 38 | store?: any, 39 | ...any 40 | } 41 | // #endregion 42 | 43 | class Index extends PureComponent { 44 | // #region props initialization 45 | static async getInitialProps({ 46 | isServer, 47 | store 48 | }: InitialProps) { 49 | const SIDE = isServer ? 'SERVER SIDE' : 'FRONT SIDE'; 50 | 51 | try { 52 | const response = await store.dispatch(fakeFetchActions.fakeFetchIfNeeded()); 53 | const { 54 | payload: { 55 | data 56 | } 57 | } = response; 58 | // NOTE: you will see this log in your server console (where you `npm run dev`): 59 | /* eslint-disable no-console */ 60 | console.log(`getInitialProps - ${SIDE} - fake fetch result: `, data); 61 | } catch (error) { 62 | console.error(`getInitialProps - ${SIDE} - fake fetch failed: `, error); 63 | /* eslint-enable no-console */ 64 | } 65 | }; 66 | // #endregion 67 | 68 | // #region component lifecycle methods 69 | async componentDidMount() { 70 | const { 71 | fakeFetchIfNeeded 72 | } = this.props; 73 | 74 | try { 75 | const response = await fakeFetchIfNeeded(); 76 | const { 77 | payload: { 78 | data 79 | } 80 | } = response; 81 | // NOTE: you will see this log in your browser console: 82 | /* eslint-disable no-console */ 83 | console.log('componentDidMount - FRONT SIDE - fake fetch result: ', data); 84 | } catch (error) { 85 | console.error('componentDidMount - FRONT SIDE - fake fetch failed: ', error); 86 | /* eslint-enable no-console */ 87 | } 88 | } 89 | 90 | render() { 91 | return ( 92 | 93 | 94 | 97 | 98 | 99 | Next JS + React + Redux + Bootstrap STARTER 100 | 101 | 105 | login 106 | 107 | 108 | 109 | 110 | ); 111 | } 112 | // #endregion 113 | 114 | // # region go login click 115 | goLogin = ( 116 | event: SyntheticEvent<> 117 | ) => { 118 | if (event) { 119 | event.preventDefault(); 120 | Router.push('/login'); 121 | } 122 | } 123 | // #endregion 124 | } 125 | 126 | // #region redux state and dispatch map to props 127 | const mapStateToProps = ( 128 | state: any 129 | ) => ({ 130 | // fakeModuleWithFetch: 131 | isFetching: state.fakeModuleWithFetch.isFetching, 132 | fakeData: state.fakeModuleWithFetch.data, 133 | // userAuth: 134 | isAuthenticated: state.userAuth.isAuthenticated 135 | }); 136 | 137 | const mapDispatchToProps = ( 138 | dispatch: (...any) => any 139 | ) => { 140 | return { 141 | ...bindActionCreators( 142 | { 143 | // fakeModuleWithFetch: 144 | ...fakeFetchActions, 145 | // userAuth: 146 | ...userAuthActions 147 | }, 148 | dispatch) 149 | }; 150 | }; 151 | // #endregion 152 | 153 | export default withRedux( 154 | configureStore, 155 | mapStateToProps, 156 | mapDispatchToProps 157 | )(Index); 158 | -------------------------------------------------------------------------------- /pages/login.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import { PureComponent } from 'react'; 5 | import { bindActionCreators } from 'redux'; 6 | import withRedux from 'next-redux-wrapper'; 7 | import configureStore from '../redux/store/configureStore'; 8 | import * as userAuthActions from '../redux/modules/userAuth'; 9 | import Router from 'next/router'; 10 | import Layout from '../components/layout/Layout'; 11 | import Button from 'react-bootstrap/lib/Button'; 12 | import Row from 'react-bootstrap/lib/Row'; 13 | import Col from 'react-bootstrap/lib/Col'; 14 | import auth from '../services/auth'; 15 | // #endregion 16 | 17 | // #region flow types 18 | type Props = { 19 | // next/route: 20 | url: { 21 | // query.from sent by Private component when user auth failed 22 | query?: { 23 | from?: string 24 | } 25 | }, 26 | 27 | // userAuth: 28 | isAuthenticated: boolean, 29 | isFetching: boolean, 30 | isLogging: boolean, 31 | disconnectUser: () => string, 32 | logUserIfNeeded: (user: string) => any, 33 | 34 | ...any 35 | }; 36 | 37 | type State = { 38 | email: string, 39 | password: string 40 | } 41 | // #endregion 42 | 43 | class Login extends PureComponent { 44 | // #region default PropTypes 45 | static defaultProps = { 46 | isFetching: false, 47 | isLogging: false 48 | } 49 | // #endregion 50 | 51 | // #region state initialization 52 | state = { 53 | email: '', 54 | password: '' 55 | }; 56 | // #endregion 57 | 58 | // #region component lifeculcle methods 59 | componentDidMount() { 60 | const { 61 | disconnectUser 62 | } = this.props; 63 | 64 | disconnectUser(); // diconnect user: remove token and user info 65 | } 66 | 67 | render() { 68 | const { 69 | email, 70 | password 71 | } = this.state; 72 | 73 | const { 74 | isLogging 75 | } = this.props; 76 | 77 | return ( 78 | 79 | 91 | 92 | 93 | 99 | 103 | 104 | 105 | Login 106 | 107 | 108 | 109 | 113 | Email 114 | 115 | 116 | 124 | 125 | 126 | 127 | 128 | 132 | Password 133 | 134 | 135 | 143 | 144 | 145 | 146 | 150 | 156 | { 157 | isLogging 158 | ? 159 | 160 | login in... 161 | 162 | 165 | 166 | : 167 | 168 | Login 169 | 170 | } 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 185 | 189 | back to home 190 | 191 | 192 | 193 | 194 | 195 | ); 196 | } 197 | // #endregion 198 | 199 | // #region input change methods 200 | handlesOnEmailChange = (event: SyntheticEvent<>) => { 201 | if (event) { 202 | event.preventDefault(); 203 | // should add some validator before setState in real use cases 204 | this.setState({ email: event.target.value.trim() }); 205 | } 206 | } 207 | 208 | handlesOnPasswordChange = (event: SyntheticEvent<>) => { 209 | if (event) { 210 | event.preventDefault(); 211 | // should add some validator before setState in real use cases 212 | this.setState({ password: event.target.value.trim() }); 213 | } 214 | } 215 | // #endregion 216 | 217 | // #region on login click 218 | handlesOnLogin = async (event: SyntheticEvent<>) => { 219 | if (event) { 220 | event.preventDefault(); 221 | } 222 | 223 | const { 224 | logUserIfNeeded, 225 | url: { 226 | query 227 | } 228 | } = this.props; 229 | 230 | const { 231 | email, 232 | password 233 | } = this.state; 234 | 235 | const userLogin = { 236 | login: email, 237 | password: password 238 | }; 239 | 240 | try { 241 | const response = await logUserIfNeeded(userLogin); 242 | const { 243 | data: { 244 | token, 245 | user 246 | } 247 | } = response.payload; 248 | 249 | auth.setToken(token); 250 | auth.setUserInfo(user); 251 | 252 | // test if we were redirected to login from a private page, redirect back to where we were: 253 | if (query.from) { 254 | return Router.push({ pathname: query.from }); // back to Home 255 | } 256 | 257 | // redirect to home otherwise: 258 | Router.push({ pathname: '/' }); // back to Home 259 | } catch (error) { 260 | /* eslint-disable no-console */ 261 | console.error('login went wrong..., error: ', error); 262 | /* eslint-enable no-console */ 263 | } 264 | } 265 | // #endregion 266 | 267 | // #region on go back home click 268 | goHome = (event: SyntheticEvent<>) => { 269 | if (event) { 270 | event.preventDefault(); 271 | } 272 | 273 | Router.push({ pathname: '/' }); 274 | } 275 | // #endregion 276 | } 277 | 278 | 279 | // #region redux state and dispatch map to props 280 | const mapStateToProps = ( 281 | state: any 282 | ) => ({ 283 | // userAuth: 284 | isAuthenticated: state.userAuth.isAuthenticated, 285 | isFetching: state.userAuth.isFetching, 286 | isLogging: state.userAuth.isLogging 287 | }); 288 | 289 | const mapDispatchToProps = ( 290 | dispatch: (...any) => any 291 | ) => { 292 | return { 293 | ...bindActionCreators( 294 | { 295 | // userAuth: 296 | ...userAuthActions 297 | }, 298 | dispatch) 299 | }; 300 | }; 301 | // #endregion 302 | 303 | export default withRedux( 304 | configureStore, 305 | mapStateToProps, 306 | mapDispatchToProps 307 | )(Login); 308 | 309 | -------------------------------------------------------------------------------- /pages/page1.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import { PureComponent } from 'react'; 5 | import { bindActionCreators } from 'redux'; 6 | import withRedux from 'next-redux-wrapper'; 7 | import configureStore from '../redux/store/configureStore'; 8 | import * as userAuthActions from '../redux/modules/userAuth'; 9 | import Layout from '../components/layout/Layout'; 10 | import Header from '../components/header/Header'; 11 | import Button from 'react-bootstrap/lib/Button'; 12 | import Router from 'next/router'; 13 | // #endregion 14 | 15 | // #region flow types 16 | type Props = { 17 | // userAuth: 18 | isAuthenticated: boolean, 19 | disconnectUser: () => any, 20 | ...any 21 | }; 22 | 23 | type State = any; 24 | // #endregion 25 | 26 | class Page1 extends PureComponent { 27 | // #region component lifecycle methods 28 | render() { 29 | return ( 30 | 31 | 32 | 33 | Page1 here 34 | 35 | 39 | go back home 40 | 41 | 42 | ); 43 | } 44 | // #endregion 45 | 46 | // html elements events 47 | goBackHome = ( 48 | event: SyntheticEvent<> 49 | ): void => { 50 | if (event) { 51 | event.preventDefault(); 52 | } 53 | 54 | Router.push('/'); 55 | } 56 | // #endregion 57 | } 58 | 59 | 60 | // #region redux state and dispatch map to props 61 | const mapStateToProps = ( 62 | state: any 63 | ) => ({ 64 | // userAuth: 65 | isAuthenticated: state.userAuth.isAuthenticated 66 | }); 67 | 68 | const mapDispatchToProps = ( 69 | dispatch: (...any) => any 70 | ) => { 71 | return { 72 | ...bindActionCreators( 73 | { 74 | // userAuth: 75 | ...userAuthActions 76 | }, 77 | dispatch) 78 | }; 79 | }; 80 | // #endregion 81 | 82 | export default withRedux( 83 | configureStore, 84 | mapStateToProps, 85 | mapDispatchToProps 86 | )(Page1); 87 | -------------------------------------------------------------------------------- /pages/private1.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import { PureComponent } from 'react'; 5 | import { bindActionCreators } from 'redux'; 6 | import withRedux from 'next-redux-wrapper'; 7 | import configureStore from '../redux/store/configureStore'; 8 | import * as userAuthActions from '../redux/modules/userAuth'; 9 | import Layout from '../components/layout/Layout'; 10 | import Header from '../components/header/Header'; 11 | import Button from 'react-bootstrap/lib/Button'; 12 | import Router from 'next/router'; 13 | import Private from '../components/privateRoute/PrivateRoute'; 14 | // #endregion 15 | 16 | // #region flow types 17 | type Props = { 18 | // from next/Router: 19 | url: { 20 | asPath: string, 21 | pathname: string, 22 | ...any 23 | }, 24 | 25 | // userAuth: 26 | isAuthenticated: boolean, 27 | disconnectUser: () => any, 28 | ...any 29 | }; 30 | 31 | type State = any; 32 | // #endregion 33 | 34 | class Private1 extends PureComponent { 35 | // #region component lifecycle methods 36 | render() { 37 | const { 38 | url: { 39 | pathname 40 | } 41 | } = this.props; 42 | 43 | return ( 44 | 47 | 48 | 49 | 50 | Private1 here 51 | 52 | 56 | go back home 57 | 58 | 59 | 60 | ); 61 | } 62 | // #endregion 63 | 64 | // #region html elements events 65 | goBackHome = ( 66 | event: SyntheticEvent<> 67 | ): void => { 68 | if (event) { 69 | event.preventDefault(); 70 | } 71 | 72 | Router.push('/'); 73 | } 74 | // #endregion 75 | } 76 | 77 | 78 | // #region redux state and dispatch map to props 79 | const mapStateToProps = ( 80 | state: any 81 | ) => ({ 82 | // userAuth: 83 | isAuthenticated: state.userAuth.isAuthenticated 84 | }); 85 | 86 | const mapDispatchToProps = ( 87 | dispatch: (...any) => any 88 | ) => { 89 | return { 90 | ...bindActionCreators( 91 | { 92 | // userAuth: 93 | ...userAuthActions 94 | }, 95 | dispatch) 96 | }; 97 | }; 98 | // #endregion 99 | 100 | export default withRedux( 101 | configureStore, 102 | mapStateToProps, 103 | mapDispatchToProps 104 | )(Private1); 105 | -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacKentoch/react-redux-nextjs-bootstrap-starter/724b559554e157b8b665e5484e3baff3140cdc96/preview.png -------------------------------------------------------------------------------- /redux/middleware/fetchMiddleware.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import axios from 'axios'; 5 | // #endregion 6 | 7 | // #region constants 8 | export const FETCH_MOCK = 'FETCH_MOCK'; 9 | export const FETCH = 'FETCH'; 10 | // #endregion 11 | 12 | // #region flow type 13 | type Fetch = { 14 | // real and mock fetch properties: 15 | type: 'FETCH_MOCK' | 'FETCH', // choose between real fetch or just mock fetch (will return mockResult in thta case) 16 | actionTypes: { 17 | request: string, // action for request fetch 18 | success: string, // action for successul fetch 19 | fail: string // action for failed fetch 20 | }, 21 | 22 | // real fetch properties: 23 | url?: string, // real fetch url 24 | method?: 'get' | 'post' | 'put' | 'delete', // verb 25 | headers?: any, // OPTIONAL CONTENT like: data: { someprop: 'value ...} 26 | options?: { 27 | credentials?: string, // ex: 'same-origin 28 | data?: any // payload 29 | }, // OPTIONAL CONTENT like: Authorization: 'Bearer _A_TOKEN_' 30 | 31 | // mock fetch propperties: 32 | mockResult?: any, // payload returned when type === 'FETCH_MOCK' 33 | }; 34 | 35 | type Action = { 36 | fetch?: Fetch, // fetch middleware payload 37 | ...any 38 | }; 39 | // #endregion 40 | 41 | // ////////////////////////////// 42 | // ###### HOW TO USE 43 | // ////////////////////////////// 44 | // CASE: FETCH_MOCK mode 45 | // in any action just add fetch object like: 46 | // { 47 | // fetch: { 48 | // type: 'FETCH_MOCK', 49 | // actionTypes: { 50 | // request: 'TYPE_FOR_REQUEST', 51 | // success: 'TYPE_FOR_RECEIVED', 52 | // fail: 'TYPE_FOR_ERROR', 53 | // }, 54 | // mockResult: any 55 | // } 56 | // } 57 | // 58 | // --------------------------- 59 | // CASE: FETCH mode 60 | // in any action just add fetch object like: 61 | // { 62 | // fetch: { 63 | // type: 'FETCH', 64 | // actionTypes: { 65 | // request: 'TYPE_FOR_REQUEST', 66 | // success: 'TYPE_FOR_RECEIVED', 67 | // fail: 'TYPE_FOR_ERROR', 68 | // }, 69 | // url: 'an url', 70 | // method: 'get', // lower case, one of 'get', 'post'... 71 | // headers: {} // OPTIONAL CONTENT like: data: { someprop: 'value ...} 72 | // options: {} // OPTIONAL CONTENT like: Authorization: 'Bearer _A_TOKEN_' 73 | // } 74 | // } 75 | // 76 | 77 | // #region middleware function 78 | const fetchMiddleware = store => next => (action: Action) => { 79 | if (!action.fetch) { 80 | return next(action); 81 | } 82 | 83 | if (!action.fetch.type || 84 | !action.fetch.type === FETCH_MOCK || 85 | !action.fetch.type === FETCH) { 86 | return next(action); 87 | } 88 | 89 | if (!action.fetch.actionTypes) { 90 | return next(action); 91 | } 92 | 93 | /** 94 | * fetch mock 95 | * @type {[type]} 96 | */ 97 | if (action.fetch.type === FETCH_MOCK) { 98 | if (!action.fetch.mockResult) { 99 | throw new Error('Fetch middleware require a mockResult payload when type is "FETCH_MOCK"'); 100 | } 101 | 102 | const { 103 | actionTypes: {request, success}, 104 | mockResult 105 | } = action.fetch; 106 | 107 | // request 108 | store.dispatch({ type: request }); 109 | 110 | // received successful for mock 111 | return Promise.resolve( 112 | store.dispatch({ 113 | type: success, 114 | payload: { 115 | status: 200, 116 | data: mockResult 117 | } 118 | }) 119 | ); 120 | } 121 | 122 | if (action.fetch.type === FETCH) { 123 | const { 124 | actionTypes: {request, success, fail}, 125 | url, 126 | method, 127 | headers, 128 | options 129 | } = action.fetch; 130 | 131 | // request 132 | store.dispatch({ type: request }); 133 | 134 | // fetch server (success or fail) 135 | // returns a Promise 136 | return axios.request({ 137 | method, 138 | url, 139 | withCredentials: true, 140 | headers: { 141 | 'Accept': 'application/json', 142 | 'Content-Type': 'application/json', 143 | 'Acces-Control-Allow-Origin': '*', 144 | ...headers 145 | }, 146 | ...options 147 | }) 148 | .then(data => store.dispatch({type: success, payload: data})) 149 | .catch( 150 | err => { 151 | store.dispatch({type: fail, error: err.response}); 152 | return Promise.reject(err.response); 153 | } 154 | ); 155 | } 156 | return next(action); 157 | }; 158 | // #endregion 159 | 160 | export default fetchMiddleware; 161 | -------------------------------------------------------------------------------- /redux/modules/fakeModuleWithFetch.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import moment from 'moment'; 5 | import fakeData from '../../mock/fakeAPI.json'; 6 | import AppConfig from '../../config/appConfig'; 7 | import { getLocationOrigin } from '../../services/fetchTools'; 8 | // #endregion 9 | 10 | // #region CONSTANTS 11 | const REQUEST_FAKE_FETCH = 'REQUEST_FAKE_FETCH'; 12 | const RECEIVED_FAKE_FETCH = 'RECEIVED_FAKE_FETCH'; 13 | const ERROR_FAKE_FETCH = 'ERROR_FAKE_FETCH'; 14 | // #endregion 15 | 16 | // #region REDUCER 17 | const initialState = { 18 | isFetching: false, 19 | actionTime: '', 20 | data: [], 21 | error: {} 22 | }; 23 | 24 | export default function (state = initialState, action) { 25 | const currentTime = moment().format(); 26 | 27 | switch (action.type) { 28 | case REQUEST_FAKE_FETCH: 29 | return { 30 | ...state, 31 | actionTime: currentTime, 32 | isFetching: true 33 | }; 34 | 35 | case RECEIVED_FAKE_FETCH: 36 | return { 37 | ...state, 38 | actionTime: currentTime, 39 | isFetching: false, 40 | data: [...action.payload] 41 | }; 42 | 43 | case ERROR_FAKE_FETCH: 44 | return { 45 | ...state, 46 | actionTime: currentTime, 47 | isFetching: false, 48 | error: action.error ? { ...action.error } : {} 49 | }; 50 | 51 | default: 52 | return state; 53 | } 54 | } 55 | // #endregion 56 | 57 | // #region ACTIONS CREATORS 58 | function fakeFetch() { 59 | return dispatch => { 60 | const shouldFetchMock = AppConfig.DEV_MODE; 61 | const fetchType = shouldFetchMock ? 'FETCH_MOCK': 'FETCH'; 62 | const mockResult = fakeData; 63 | 64 | const url = `${getLocationOrigin()}/${AppConfig.api.fakeEndPoint}`; 65 | const method = 'get'; 66 | const options = {}; 67 | 68 | // fetch middleware 69 | // -> you handles pure front or with back-end asyncs just by disaptching a single object 70 | // -> just change config: AppConfig.DEV_MODE 71 | return Promise.resolve( 72 | dispatch({ 73 | // type name is not important here since fetchMiddleware will intercept this action: 74 | type: 'FETCH_MIDDLEWARE', 75 | // here are fetch middleware props: 76 | fetch: { 77 | type: fetchType, 78 | actionTypes: { 79 | request: REQUEST_FAKE_FETCH, 80 | success: RECEIVED_FAKE_FETCH, 81 | fail: ERROR_FAKE_FETCH 82 | }, 83 | // props only used when type = FETCH_MOCK: 84 | mockResult, 85 | // props only used when type = FETCH: 86 | url, 87 | method, 88 | options 89 | } 90 | }) 91 | ); 92 | }; 93 | } 94 | 95 | export function fakeFetchIfNeeded() { 96 | return (dispatch, getState) => { 97 | if (shouldFakeFetch(getState())) { 98 | return dispatch(fakeFetch()); 99 | } 100 | return Promise.resolve(); 101 | }; 102 | } 103 | 104 | function shouldFakeFetch(state) { 105 | const isFetching = state.fakeModuleWithFetch.isFetching; 106 | // prevents fetching twice while already fetching: 107 | if (isFetching) { 108 | return false; 109 | } 110 | return true; 111 | } 112 | // #endregion 113 | -------------------------------------------------------------------------------- /redux/modules/persistStore.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import { REHYDRATE } from 'redux-persist/constants'; 5 | // #endregion 6 | 7 | const initialState = {}; 8 | 9 | /** 10 | * redux-persist reducer rehydration logic 11 | * 12 | * NOTE: you need to write on your own!!! 13 | * 14 | * @export 15 | * @param {any} [state=initialState] state 16 | * @param {any} action action 17 | * @returns {any} state 18 | */ 19 | export default function (state = initialState, action) { 20 | switch (action.type) { 21 | case REHYDRATE: { 22 | const incoming = action.payload.myReducer; 23 | if (incoming) { 24 | return { 25 | ...state, 26 | ...incoming 27 | // specialKey: processSpecial(incoming.specialKey) 28 | }; 29 | } 30 | return state; 31 | } 32 | 33 | default: 34 | return state; 35 | } 36 | } 37 | // #endregion 38 | -------------------------------------------------------------------------------- /redux/modules/reducers.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import { combineReducers } from 'redux'; 4 | import fakeModuleWithFetch from './fakeModuleWithFetch'; 5 | import userAuth from './userAuth'; 6 | import persistStore from './persistStore'; 7 | 8 | export const reducers = { 9 | fakeModuleWithFetch, 10 | userAuth, 11 | persistStore 12 | }; 13 | 14 | export default combineReducers({ 15 | ...reducers 16 | }); 17 | -------------------------------------------------------------------------------- /redux/modules/userAuth.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import moment from 'moment'; 5 | import AppConfig from '../../config/appConfig'; 6 | import userInfosMockData from '../../mock/userInfosMock.json'; 7 | import { getLocationOrigin } from '../../services/fetchTools'; 8 | import auth from '../../services/auth'; 9 | // #endregion 10 | 11 | // #region CONSTANTS 12 | const REQUEST_USER_INFOS_DATA: string = 'REQUEST_USER_INFOS_DATA'; 13 | const RECEIVED_USER_INFOS_DATA: string = 'RECEIVED_USER_INFOS_DATA'; 14 | const ERROR_USER_INFOS_DATA: string = 'ERROR_USER_INFOS_DATA'; 15 | 16 | const REQUEST_LOG_USER: string = 'REQUEST_LOG_USER'; 17 | const RECEIVED_LOG_USER: string = 'RECEIVED_LOG_USER'; 18 | const ERROR_LOG_USER: string = 'ERROR_LOG_USER'; 19 | 20 | const CHECK_IF_USER_IS_AUTHENTICATED = 'CHECK_IF_USER_IS_AUTHENTICATED'; 21 | 22 | const DISCONNECT_USER = 'DISCONNECT_USER'; 23 | // #endregion 24 | 25 | // #region REDUCER 26 | 27 | const initialState = { 28 | // actions details 29 | isFetching: false, 30 | isLogging: false, 31 | time: '', 32 | 33 | // userInfos 34 | id: '', 35 | login: '', 36 | firstname: '', 37 | lastname: '', 38 | 39 | token: null, 40 | isAuthenticated: false // authentication status (token based auth) 41 | }; 42 | 43 | export default function ( 44 | state = initialState, 45 | action 46 | ) { 47 | const currentTime = moment().format(); 48 | 49 | switch (action.type) { 50 | case CHECK_IF_USER_IS_AUTHENTICATED: 51 | return { 52 | ...state, 53 | actionTime: currentTime, 54 | isAuthenticated: action.isAuthenticated, 55 | token: action.token || initialState.token, 56 | id: action.user && action.user.id ? action.user.id: initialState.id, 57 | login: action.user && action.user.login ? action.user.login: initialState.login, 58 | firstname: action.user && action.user.firstname ? action.user.firstname: initialState.firstname, 59 | lastname: action.user && action.user.lastname ? action.user.lastname: initialState.firstname 60 | }; 61 | 62 | case DISCONNECT_USER: 63 | return { 64 | ...state, 65 | actionTime: currentTime, 66 | isAuthenticated: false, 67 | token: initialState.token, 68 | id: initialState.id, 69 | login: initialState.login, 70 | firstname: initialState.firstname, 71 | lastname: initialState.lastname 72 | }; 73 | 74 | // user login (get token and userInfo) 75 | case REQUEST_LOG_USER: 76 | return { 77 | ...state, 78 | actionTime: currentTime, 79 | isLogging: true 80 | }; 81 | 82 | case RECEIVED_LOG_USER: 83 | const userLogged = action.payload.data; 84 | 85 | return { 86 | ...state, 87 | actionTime: currentTime, 88 | isAuthenticated: true, 89 | token: userLogged.token, 90 | id: userLogged.id, 91 | login: userLogged.login, 92 | firstname: userLogged.firstname, 93 | lastname: userLogged.lastname, 94 | isLogging: false 95 | }; 96 | 97 | case ERROR_LOG_USER: 98 | return { 99 | ...state, 100 | actionTime: currentTime, 101 | isAuthenticated: false, 102 | isLogging: false 103 | }; 104 | 105 | // not used right now: 106 | case REQUEST_USER_INFOS_DATA: 107 | return { 108 | ...state, 109 | actionTime: currentTime, 110 | isFetching: true 111 | }; 112 | 113 | case RECEIVED_USER_INFOS_DATA: 114 | const userInfos = action.payload.data; 115 | 116 | return { 117 | ...state, 118 | actionTime: currentTime, 119 | isFetching: false, 120 | id: userInfos.id, 121 | login: userInfos.login, 122 | firstname: userInfos.firstname, 123 | lastname: userInfos.lastname 124 | }; 125 | 126 | case ERROR_USER_INFOS_DATA: 127 | return { 128 | ...state, 129 | actionTime: currentTime, 130 | isFetching: false 131 | }; 132 | 133 | default: 134 | return state; 135 | } 136 | } 137 | // #endregion 138 | 139 | // #region ACTIONS CREATORS 140 | 141 | /** 142 | * 143 | * set user isAuthenticated to false and clear all app localstorage: 144 | * 145 | * @export 146 | * @returns {action} action 147 | */ 148 | export function disconnectUser() { 149 | auth.clearAllAppStorage(); 150 | return { type: DISCONNECT_USER }; 151 | } 152 | 153 | /** 154 | * 155 | * check if user is connected by looking at locally stored 156 | * - token 157 | * - user fonrmation 158 | * 159 | * @export 160 | * @returns {action} action 161 | */ 162 | export function checkUserIsConnected() { 163 | const token = auth.getToken(); 164 | const user = auth.getUserInfo(); 165 | const checkUserHasId = obj => obj && obj._id; 166 | const isAuthenticated = (token && checkUserHasId(user)) ? true : false; 167 | 168 | return { 169 | type: CHECK_IF_USER_IS_AUTHENTICATED, 170 | token, 171 | ...user, 172 | isAuthenticated 173 | }; 174 | } 175 | 176 | /** 177 | * 178 | * user login 179 | * 180 | * @param {string} login user login 181 | * @param {string} password usepasswordr 182 | * @returns {Promise} promised action 183 | */ 184 | function logUser( 185 | login: string, 186 | password: string 187 | ) { 188 | return async (dispatch) => { 189 | const FETCH_TYPE = AppConfig.DEV_MODE ? 'FETCH_MOCK' : 'FETCH'; 190 | const __SOME_LOGIN_API__ = 'login'; 191 | 192 | const mockResult = userInfosMockData; // will be fetch_mock data returned (in case FETCH_TYPE = 'FETCH_MOCK', otherwise cata come from server) 193 | const url = `${getLocationOrigin()}/${__SOME_LOGIN_API__}`; 194 | const method = 'post'; 195 | const headers = {}; 196 | const options = { 197 | credentials: 'same-origin', 198 | data: { 199 | login, 200 | password 201 | } 202 | }; 203 | 204 | // fetchMiddleware (does: fetch mock, real fetch, dispatch 3 actions... for a minimum code on action creator!) 205 | return dispatch({ 206 | type: 'FETCH_MIDDLEWARE', 207 | fetch: { 208 | // common props: 209 | type: FETCH_TYPE, 210 | actionTypes: { 211 | request: REQUEST_LOG_USER, 212 | success: RECEIVED_LOG_USER, 213 | fail: ERROR_LOG_USER 214 | }, 215 | // mock fetch props: 216 | mockResult, 217 | // real fetch props: 218 | url, 219 | method, 220 | headers, 221 | options 222 | } 223 | }); 224 | }; 225 | } 226 | export function logUserIfNeeded( 227 | email: string, 228 | password: string 229 | ): (...any) => Promise { 230 | return ( 231 | dispatch: (any) => any, 232 | getState: () => boolean 233 | ): any => { 234 | if (shouldLogUser(getState())) { 235 | return dispatch(logUser(email, password)); 236 | } 237 | return Promise.resolve(); 238 | }; 239 | } 240 | function shouldLogUser( 241 | state: any 242 | ): boolean { 243 | const isLogging = state.userAuth.isLogging; 244 | if (isLogging) { 245 | return false; 246 | } 247 | return true; 248 | } 249 | 250 | /** 251 | * fetch user info 252 | * 253 | * NOTE: this shows a use-case of fetchMiddleware 254 | *@param {string} [id=''] user id 255 | * @returns {Promise} returns fetch promise 256 | */ 257 | function fetchUserInfosData(id = '') { 258 | return dispatch => { 259 | const token = auth.getToken(); 260 | const FETCH_TYPE = AppConfig.DEV_MODE ? 'FETCH_MOCK' : 'FETCH'; 261 | 262 | const mockResult = userInfosMockData; // will be fetch_mock data returned (in case FETCH_TYPE = 'FETCH_MOCK', otherwise cata come from server) 263 | const url = `${getLocationOrigin()}/${AppConfig.API.users}/${id}`; 264 | const method = 'get'; 265 | const headers = { authorization: `Bearer ${token}` }; 266 | const options = { credentials: 'same-origin' }; // put options here (see axios options) 267 | 268 | return dispatch({ 269 | type: 'FETCH_MIDDLEWARE', 270 | fetch: { 271 | // common props: 272 | type: FETCH_TYPE, 273 | actionTypes: { 274 | request: REQUEST_USER_INFOS_DATA, 275 | success: RECEIVED_USER_INFOS_DATA, 276 | fail: ERROR_USER_INFOS_DATA 277 | }, 278 | // mock fetch props: 279 | mockResult, 280 | // real fetch props: 281 | url, 282 | method, 283 | headers, 284 | options 285 | } 286 | }); 287 | }; 288 | } 289 | 290 | export function fetchUserInfoDataIfNeeded( 291 | id: string = '' 292 | ) { 293 | return ( 294 | dispatch, 295 | getState 296 | ) => { 297 | if (shouldFetchUserInfoData(getState())) { 298 | return dispatch(fetchUserInfosData(id)); 299 | } 300 | return Promise.resolve(); 301 | }; 302 | } 303 | 304 | /** 305 | * 306 | * determine wether fetching should occur 307 | * 308 | * rules: 309 | * - should not fetch twice when already fetching 310 | * - ...more rules can be added 311 | * 312 | * @param {Object} state all redux state 313 | * @returns {boolean} flag 314 | */ 315 | function shouldFetchUserInfoData(state): boolean { 316 | const userInfos = state.userAuth; 317 | if (userInfos.isFetching) { 318 | return false; 319 | } 320 | return true; 321 | } 322 | 323 | // #endregion 324 | -------------------------------------------------------------------------------- /redux/store/configureStore.dev.js: -------------------------------------------------------------------------------- 1 | // @flow weak 2 | 3 | import { 4 | createStore, 5 | applyMiddleware 6 | } from 'redux'; 7 | import { createLogger } from 'redux-logger'; 8 | import thunkMiddleware from 'redux-thunk'; 9 | import { 10 | persistStore, 11 | autoRehydrate 12 | } from 'redux-persist'; 13 | import localForage from 'localforage'; 14 | import { composeWithDevTools } from 'redux-devtools-extension'; 15 | import reducer from '../modules/reducers'; 16 | import fetchMiddleware from '../middleware/fetchMiddleware'; 17 | 18 | // #region configure logger middleware 19 | const loggerMiddleware = createLogger({ 20 | level: 'info', 21 | collapsed: true 22 | }); 23 | // #endregion 24 | 25 | // #region createStore : enhancer 26 | const enhancer = composeWithDevTools( 27 | applyMiddleware( 28 | thunkMiddleware, 29 | fetchMiddleware, 30 | loggerMiddleware, 31 | ), 32 | autoRehydrate() 33 | ); 34 | // #endregion 35 | 36 | // #region store initialization 37 | export default function configureStore(initialState) { 38 | const store = createStore(reducer, initialState, enhancer); 39 | 40 | // begin periodically persisting the store 41 | persistStore(store, {storage: localForage}); 42 | 43 | // OPTIONAL: you can blacklist reducers to avoid them to persist, so call 44 | // persistStore( 45 | // store, 46 | // {blacklist: ['someTransientReducer']}, 47 | // () => { 48 | // console.log('rehydration complete') 49 | // } 50 | // ); 51 | 52 | return store; 53 | } 54 | // #endregion 55 | -------------------------------------------------------------------------------- /redux/store/configureStore.js: -------------------------------------------------------------------------------- 1 | /* eslint no-process-env:0 */ 2 | 3 | if (process.env.NODE_ENV === 'production') { 4 | module.exports = require('./configureStore.prod'); 5 | } else { 6 | module.exports = require('./configureStore.dev'); 7 | } 8 | -------------------------------------------------------------------------------- /redux/store/configureStore.prod.js: -------------------------------------------------------------------------------- 1 | // @flow weak 2 | 3 | import { 4 | createStore, 5 | compose, 6 | applyMiddleware 7 | } from 'redux'; 8 | import thunkMiddleware from 'redux-thunk'; 9 | import { 10 | persistStore, 11 | autoRehydrate 12 | } from 'redux-persist'; 13 | import localForage from 'localforage'; 14 | import reducer from '../modules/reducers'; 15 | import fetchMiddleware from '../middleware/fetchMiddleware'; 16 | 17 | // #region createStore : enhancer 18 | const enhancer = compose( 19 | applyMiddleware( 20 | thunkMiddleware, 21 | fetchMiddleware 22 | ), 23 | autoRehydrate() 24 | ); 25 | // #endregion 26 | 27 | // #region store initialization 28 | export default function configureStore(initialState) { 29 | const store = createStore(reducer, initialState, enhancer); 30 | 31 | // begin periodically persisting the store 32 | persistStore(store, {storage: localForage}); 33 | 34 | // OPTIONAL: you can blacklist reducers to avoid them to persist, so call 35 | // persistStore( 36 | // store, 37 | // {blacklist: ['someTransientReducer']}, 38 | // () => { 39 | // console.log('rehydration complete') 40 | // } 41 | // ); 42 | 43 | return store; 44 | } 45 | // #endregion 46 | -------------------------------------------------------------------------------- /services/auth.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import decode from 'jwt-decode'; 5 | import moment from 'moment'; 6 | // #endregion 7 | 8 | // #region flow types 9 | type STORES_TYPES = 10 | | 'localStorage' 11 | | 'sessionStorage'; 12 | 13 | type Storage = STORES_TYPES 14 | type TokenKey = string; 15 | type UserInfoKey = string; 16 | // #endregion 17 | 18 | // #region constants 19 | const TOKEN_KEY = 'token'; 20 | const USER_INFO = 'userInfo'; 21 | 22 | const APP_PERSIST_STORES_TYPES: Array = [ 23 | 'localStorage', 24 | 'sessionStorage' 25 | ]; 26 | 27 | const parse = JSON.parse; 28 | const stringify = JSON.stringify; 29 | // #endregion 30 | 31 | /** 32 | * auth object 33 | * 34 | * -> store "TOKEN_KEY" 35 | * - default storage is "localStorage" 36 | * - default token key is 'token' 37 | */ 38 | export const auth = { 39 | // ///////////////////////////////////////////////////////////// 40 | // TOKEN 41 | // ///////////////////////////////////////////////////////////// 42 | 43 | /** 44 | * get token from localstorage 45 | * 46 | * @param {'localStorage' | 'sessionStorage'} [fromStorage='localStorage'] specify storage 47 | * @param {any} [tokenKey=TOKEN_KEY] optionnal parameter to specify a token key 48 | * @returns {string} token value 49 | */ 50 | getToken( 51 | fromStorage: Storage = APP_PERSIST_STORES_TYPES[0], 52 | tokenKey: TokenKey = TOKEN_KEY 53 | ): ?string { 54 | // localStorage: 55 | if (fromStorage === APP_PERSIST_STORES_TYPES[0]) { 56 | return (localStorage && localStorage.getItem(tokenKey)) || null; 57 | } 58 | // sessionStorage: 59 | if (fromStorage === APP_PERSIST_STORES_TYPES[1]) { 60 | return (sessionStorage && sessionStorage.getItem(tokenKey)) || null; 61 | } 62 | // default: 63 | return null; 64 | }, 65 | 66 | /** 67 | * set the token value into localstorage (managed by localforage) 68 | * 69 | * @param {string} [value=''] token value 70 | * @param {'localStorage' | 'sessionStorage'} [toStorage='localStorage'] specify storage 71 | * @param {any} [tokenKey='token'] token key 72 | * @returns {boolean} success/failure flag 73 | */ 74 | setToken( 75 | value: string = '', 76 | toStorage: Storage = APP_PERSIST_STORES_TYPES[0], 77 | tokenKey: TokenKey = TOKEN_KEY 78 | ): ?string { 79 | if (!value || value.length <= 0) { 80 | return; 81 | } 82 | // localStorage: 83 | if (toStorage === APP_PERSIST_STORES_TYPES[0]) { 84 | if (localStorage) { 85 | localStorage.setItem(tokenKey, value); 86 | } 87 | } 88 | // sessionStorage: 89 | if (toStorage === APP_PERSIST_STORES_TYPES[1]) { 90 | if (sessionStorage) { 91 | sessionStorage.setItem(tokenKey, value); 92 | } 93 | } 94 | }, 95 | 96 | 97 | /** 98 | * check 99 | * - if token key contains a valid token value (defined and not an empty value) 100 | * - if the token expiration date is passed 101 | * 102 | * 103 | * Note: 'isAuthenticated' just checks 'tokenKey' on store (localStorage by default or sessionStorage) 104 | * 105 | * You may think: 'ok I just put an empty token key and I have access to protected routes?'' 106 | * -> answer is: YES^^ 107 | * BUT 108 | * -> : your backend will not recognize a wrong token so private data or safe and you protected view could be a bit ugly without any data. 109 | * 110 | * => ON CONCLUSION: this aim of 'isAuthenticated' 111 | * -> is to help for a better "user experience" (= better than displaying a view with no data since server did not accept the user). 112 | * -> it is not a security purpose (security comes from backend, since frontend is easily hackable => user has access to all your frontend) 113 | * 114 | * @param {'localStorage' | 'sessionStorage'} [fromStorage='localStorage'] specify storage 115 | * @param {any} [tokenKey=TOKEN_KEY] token key 116 | * @returns {bool} is authenticed response 117 | */ 118 | isAuthenticated( 119 | fromStorage: Storage = APP_PERSIST_STORES_TYPES[0], 120 | tokenKey: TokenKey = TOKEN_KEY 121 | ): boolean { 122 | // localStorage: 123 | if (fromStorage === APP_PERSIST_STORES_TYPES[0]) { 124 | if ((localStorage && localStorage.getItem(tokenKey))) { 125 | return true; 126 | } else { 127 | return false; 128 | } 129 | } 130 | // sessionStorage: 131 | if (fromStorage === APP_PERSIST_STORES_TYPES[1]) { 132 | if ((sessionStorage && sessionStorage.getItem(tokenKey))) { 133 | return true; 134 | } else { 135 | return false; 136 | } 137 | } 138 | // default: 139 | return false; 140 | }, 141 | 142 | /** 143 | * delete token 144 | * 145 | * @param {any} [storage=APP_PERSIST_STORES_TYPES[0]] token key 146 | * @param {any} [tokenKey='token'] token key 147 | * @returns {bool} success/failure flag 148 | */ 149 | clearToken( 150 | storage: Storage = APP_PERSIST_STORES_TYPES[0], 151 | tokenKey: TokenKey = TOKEN_KEY 152 | ): boolean { 153 | // localStorage: 154 | if (storage === APP_PERSIST_STORES_TYPES[0]) { 155 | localStorage.removeItem(tokenKey); 156 | return true; 157 | } 158 | // sessionStorage: 159 | if (storage === APP_PERSIST_STORES_TYPES[1]) { 160 | sessionStorage.removeItem(tokenKey); 161 | return true; 162 | } 163 | return false; 164 | }, 165 | 166 | /** 167 | * return expiration date from token 168 | * 169 | * @param {string} encodedToken - base 64 token received from server and stored in local storage 170 | * @returns {date | null} returns expiration date or null id expired props not found in decoded token 171 | */ 172 | getTokenExpirationDate( 173 | encodedToken: any 174 | ): Date { 175 | if (!encodedToken) { 176 | return new Date(0); // is expired 177 | } 178 | 179 | const token = decode(encodedToken); 180 | if (!token.exp) { 181 | return new Date(0); // is expired 182 | } 183 | 184 | const expirationDate = new Date(token.exp*1000); 185 | return expirationDate; 186 | }, 187 | 188 | /** 189 | * tell is token is expired (compared to now) 190 | * 191 | * @param {string} encodedToken - base 64 token received from server and stored in local storage 192 | * @returns {bool} returns true if expired else false 193 | */ 194 | isExpiredToken( 195 | encodedToken: any 196 | ): boolean { 197 | const expirationDate = this.getTokenExpirationDate(encodedToken); 198 | const rightNow = moment(); 199 | const isExpiredToken = moment(rightNow).isAfter(moment(expirationDate)); 200 | 201 | return isExpiredToken; 202 | }, 203 | 204 | // ///////////////////////////////////////////////////////////// 205 | // USER_INFO 206 | // ///////////////////////////////////////////////////////////// 207 | /** 208 | * get user info from localstorage 209 | * 210 | * @param {'localStorage' | 'sessionStorage'} [fromStorage='localStorage'] specify storage 211 | * @param {any} [userInfoKey='userInfo'] optionnal parameter to specify a token key 212 | * @returns {string} token value 213 | */ 214 | getUserInfo( 215 | fromStorage: Storage = APP_PERSIST_STORES_TYPES[0], 216 | userInfoKey: UserInfoKey = USER_INFO 217 | ): ?string { 218 | // localStorage: 219 | if (fromStorage === APP_PERSIST_STORES_TYPES[0]) { 220 | return (localStorage && parse(localStorage.getItem(userInfoKey))) || null; 221 | } 222 | // sessionStorage: 223 | if (fromStorage === APP_PERSIST_STORES_TYPES[1]) { 224 | return (sessionStorage && parse(sessionStorage.getItem(userInfoKey))) || null; 225 | } 226 | // default: 227 | return null; 228 | }, 229 | 230 | /** 231 | * set the userInfo value into localstorage 232 | * 233 | * @param {object} [value=''] token value 234 | * @param {'localStorage' | 'sessionStorage'} [toStorage='localStorage'] specify storage 235 | * @param {any} [userInfoKey='userInfo'] token key 236 | * @returns {boolean} success/failure flag 237 | */ 238 | setUserInfo( 239 | value: string = '', 240 | toStorage: Storage = APP_PERSIST_STORES_TYPES[0], 241 | userInfoKey: UserInfoKey = USER_INFO 242 | ): any { 243 | if (!value || value.length <= 0) { 244 | return; 245 | } 246 | // localStorage: 247 | if (toStorage === APP_PERSIST_STORES_TYPES[0]) { 248 | if (localStorage) { 249 | localStorage.setItem(userInfoKey, stringify(value)); 250 | } 251 | } 252 | // sessionStorage: 253 | if (toStorage === APP_PERSIST_STORES_TYPES[1]) { 254 | if (sessionStorage) { 255 | sessionStorage.setItem(userInfoKey, stringify(value)); 256 | } 257 | } 258 | }, 259 | 260 | /** 261 | * delete userInfo 262 | * 263 | * @param {string} [userInfoKey='userInfo'] token key 264 | * @returns {bool} success/failure flag 265 | */ 266 | clearUserInfo( 267 | userInfoKey: UserInfoKey = USER_INFO 268 | ): any { 269 | // localStorage: 270 | if (localStorage && localStorage[userInfoKey]) { 271 | localStorage.removeItem(userInfoKey); 272 | } 273 | // sessionStorage: 274 | if (sessionStorage && sessionStorage[userInfoKey]) { 275 | sessionStorage.removeItem(userInfoKey); 276 | } 277 | }, 278 | 279 | 280 | // ///////////////////////////////////////////////////////////// 281 | // COMMON 282 | // ///////////////////////////////////////////////////////////// 283 | 284 | /** 285 | * forget me method: clear all 286 | * @returns {bool} success/failure flag 287 | */ 288 | clearAllAppStorage(): any { 289 | if (localStorage) { 290 | localStorage.clear(); 291 | } 292 | if (sessionStorage) { 293 | sessionStorage.clear(); 294 | } 295 | } 296 | }; 297 | 298 | export default auth; 299 | -------------------------------------------------------------------------------- /services/fetchTools.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | /** 4 | * getLocationOrigin returns dynamically base url 5 | * 6 | * @export 7 | * @returns {string} location origin 8 | */ 9 | export function getLocationOrigin(): string { 10 | if (typeof window === 'undefined') { 11 | return ''; 12 | } 13 | 14 | if (!window.location.origin) { 15 | window.location.origin = `${window.location.protocol}//${window.location.hostname}${window.location.port ? ':' + window.location.port : ''}`; 16 | } 17 | 18 | return window.location.origin; 19 | } 20 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MacKentoch/react-redux-nextjs-bootstrap-starter/724b559554e157b8b665e5484e3baff3140cdc96/static/favicon.ico -------------------------------------------------------------------------------- /static/robot.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDevDependencies": {}, 3 | "globalDependencies": { 4 | "axios": "registry:dt/axios#0.9.1+20161016142654", 5 | "localforage": "registry:dt/localforage#0.0.0+20161102134758", 6 | "moment": "registry:dt/moment#2.11.1+20161010105546", 7 | "redux": "registry:dt/redux#3.5.2+20160703092728", 8 | "redux-thunk": "registry:dt/redux-thunk#2.1.0+20160703120921" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /typings/globals/axios/index.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by typings 2 | // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/e6215d4444ef44a38cd760817e955ce19b522032/axios/axios.d.ts 3 | declare namespace Axios { 4 | 5 | interface IThenable { 6 | then(onFulfilled?: (value: R) => U | IThenable, onRejected?: (error: any) => U | IThenable): IThenable; 7 | then(onFulfilled?: (value: R) => U | IThenable, onRejected?: (error: any) => void): IThenable; 8 | } 9 | 10 | interface IPromise extends IThenable { 11 | then(onFulfilled?: (value: R) => U | IThenable, onRejected?: (error: any) => U | IThenable): IPromise; 12 | then(onFulfilled?: (value: R) => U | IThenable, onRejected?: (error: any) => void): IPromise; 13 | catch(onRejected?: (error: any) => U | IThenable): IPromise; 14 | } 15 | 16 | /** 17 | * HTTP Basic auth details 18 | */ 19 | interface AxiosHttpBasicAuth { 20 | username: string; 21 | password: string; 22 | } 23 | 24 | /** 25 | * Common axios XHR config interface 26 | * - request body data type 27 | */ 28 | interface AxiosXHRConfigBase { 29 | /** 30 | * will be prepended to `url` unless `url` is absolute. 31 | * It can be convenient to set `baseURL` for an instance 32 | * of axios to pass relative URLs to methods of that instance. 33 | */ 34 | baseURL?: string; 35 | 36 | /** 37 | * custom headers to be sent 38 | */ 39 | headers?: {[key: string]: any}; 40 | 41 | /** 42 | * URL parameters to be sent with the request 43 | */ 44 | params?: Object; 45 | 46 | /** 47 | * optional function in charge of serializing `params` 48 | * (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/) 49 | */ 50 | paramsSerializer?: (params: Object) => string; 51 | 52 | /** 53 | * specifies the number of milliseconds before the request times out. 54 | * If the request takes longer than `timeout`, the request will be aborted. 55 | */ 56 | timeout?: number; 57 | 58 | /** 59 | * indicates whether or not cross-site Access-Control requests 60 | * should be made using credentials 61 | */ 62 | withCredentials?: boolean; 63 | 64 | /** 65 | * indicates that HTTP Basic auth should be used, and supplies 66 | * credentials. This will set an `Authorization` header, 67 | * overwriting any existing `Authorization` custom headers you have 68 | * set using `headers`. 69 | */ 70 | auth?: AxiosHttpBasicAuth; 71 | 72 | /** 73 | * indicates the type of data that the server will respond with 74 | * options are 'arraybuffer', 'blob', 'document', 'json', 'text' 75 | */ 76 | responseType?: string; 77 | 78 | /** 79 | * name of the cookie to use as a value for xsrf token 80 | */ 81 | xsrfCookieName?: string; 82 | 83 | /** 84 | * name of the http header that carries the xsrf token value 85 | */ 86 | xsrfHeaderName?: string; 87 | 88 | /** 89 | * Change the request data before it is sent to the server. 90 | * This is only applicable for request methods 'PUT', 'POST', and 'PATCH' 91 | * The last function in the array must return a string or an ArrayBuffer 92 | */ 93 | transformRequest?: ((data: T) => U) | [(data: T) => U]; 94 | 95 | /** 96 | * change the response data to be made before it is passed to then/catch 97 | */ 98 | transformResponse?: (data: T) => U; 99 | } 100 | 101 | /** 102 | * - request body data type 103 | */ 104 | interface AxiosXHRConfig extends AxiosXHRConfigBase { 105 | /** 106 | * server URL that will be used for the request, options are: 107 | * GET, PUT, POST, DELETE, CONNECT, HEAD, OPTIONS, TRACE, PATCH 108 | */ 109 | url: string; 110 | 111 | /** 112 | * request method to be used when making the request 113 | */ 114 | method?: string; 115 | 116 | /** 117 | * data to be sent as the request body 118 | * Only applicable for request methods 'PUT', 'POST', and 'PATCH' 119 | * When no `transformRequest` is set, must be a string, an ArrayBuffer or a hash 120 | */ 121 | data?: T; 122 | } 123 | 124 | interface AxiosXHRConfigDefaults extends AxiosXHRConfigBase { 125 | /** 126 | * custom headers to be sent 127 | */ 128 | headers: { 129 | common: {[index: string]: string}; 130 | patch: {[index: string]: string}; 131 | post: {[index: string]: string}; 132 | put: {[index: string]: string}; 133 | }; 134 | } 135 | 136 | /** 137 | * - expected response type, 138 | * - request body data type 139 | */ 140 | interface AxiosXHR { 141 | /** 142 | * Response that was provided by the server 143 | */ 144 | data: T; 145 | 146 | /** 147 | * HTTP status code from the server response 148 | */ 149 | status: number; 150 | 151 | /** 152 | * HTTP status message from the server response 153 | */ 154 | statusText: string; 155 | 156 | /** 157 | * headers that the server responded with 158 | */ 159 | headers: Object; 160 | 161 | /** 162 | * config that was provided to `axios` for the request 163 | */ 164 | config: AxiosXHRConfig; 165 | } 166 | 167 | interface Interceptor { 168 | /** 169 | * intercept request before it is sent 170 | */ 171 | request: RequestInterceptor; 172 | 173 | /** 174 | * intercept response of request when it is received. 175 | */ 176 | response: ResponseInterceptor 177 | } 178 | 179 | type InterceptorId = number; 180 | 181 | interface RequestInterceptor { 182 | /** 183 | * - request body data type 184 | */ 185 | 186 | use(fulfilledFn: (config: AxiosXHRConfig) => AxiosXHRConfig): InterceptorId; 187 | 188 | use(fulfilledFn: (config: AxiosXHRConfig) => AxiosXHRConfig, 189 | rejectedFn: (error: any) => any) 190 | : InterceptorId; 191 | 192 | eject(interceptorId: InterceptorId): void; 193 | } 194 | 195 | interface ResponseInterceptor { 196 | /** 197 | * - expected response type 198 | */ 199 | 200 | use(fulfilledFn: (config: Axios.AxiosXHR) => Axios.AxiosXHR): InterceptorId; 201 | 202 | use(fulfilledFn: (config: Axios.AxiosXHR) => Axios.AxiosXHR, 203 | rejectedFn: (error: any) => any) 204 | : InterceptorId; 205 | 206 | eject(interceptorId: InterceptorId): void; 207 | } 208 | 209 | /** 210 | * - expected response type, 211 | * - request body data type 212 | */ 213 | interface AxiosInstance { 214 | 215 | /** 216 | * Send request as configured 217 | */ 218 | (config: AxiosXHRConfig): IPromise>; 219 | 220 | /** 221 | * Send request as configured 222 | */ 223 | new (config: AxiosXHRConfig): IPromise>; 224 | 225 | /** 226 | * Send request as configured 227 | */ 228 | request(config: AxiosXHRConfig): IPromise>; 229 | 230 | /** 231 | * intercept requests or responses before they are handled by then or catch 232 | */ 233 | interceptors: Interceptor; 234 | 235 | /** 236 | * Config defaults 237 | */ 238 | defaults: AxiosXHRConfigDefaults; 239 | 240 | /** 241 | * equivalent to `Promise.all` 242 | */ 243 | all(values: [T1 | IPromise>, T2 | IPromise>, T3 | IPromise>, T4 | IPromise>, T5 | IPromise>, T6 | IPromise>, T7 | IPromise>, T8 | IPromise>, T9 | IPromise>, T10 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR]>; 244 | all(values: [T1 | IPromise>, T2 | IPromise>, T3 | IPromise>, T4 | IPromise>, T5 | IPromise>, T6 | IPromise>, T7 | IPromise>, T8 | IPromise>, T9 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR]>; 245 | all(values: [T1 | IPromise>, T2 | IPromise>, T3 | IPromise>, T4 | IPromise>, T5 | IPromise>, T6 | IPromise>, T7 | IPromise>, T8 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR]>; 246 | all(values: [T1 | IPromise>, T2 | IPromise>, T3 | IPromise>, T4 | IPromise>, T5 | IPromise>, T6 | IPromise>, T7 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR]>; 247 | all(values: [T1 | IPromise>, T2 | IPromise>, T3 | IPromise>, T4 | IPromise>, T5 | IPromise>, T6 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR]>; 248 | all(values: [T1 | IPromise>, T2 | IPromise>, T3 | IPromise>, T4 | IPromise>, T5 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR]>; 249 | all(values: [T1 | IPromise>, T2 | IPromise>, T3 | IPromise>, T4 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR, AxiosXHR, AxiosXHR]>; 250 | all(values: [T1 | IPromise>, T2 | IPromise>, T3 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR, AxiosXHR]>; 251 | all(values: [T1 | IPromise>, T2 | IPromise>]): IPromise<[AxiosXHR, AxiosXHR]>; 252 | 253 | /** 254 | * spread array parameter to `fn`. 255 | * note: alternative to `spread`, destructuring assignment. 256 | */ 257 | spread(fn: (t1: T1, t2: T2) => U): (arr: ([T1, T2])) => U; 258 | 259 | /** 260 | * convenience alias, method = GET 261 | */ 262 | get(url: string, config?: AxiosXHRConfigBase): IPromise>; 263 | 264 | 265 | /** 266 | * convenience alias, method = DELETE 267 | */ 268 | delete(url: string, config?: AxiosXHRConfigBase): IPromise>; 269 | 270 | /** 271 | * convenience alias, method = HEAD 272 | */ 273 | head(url: string, config?: AxiosXHRConfigBase): IPromise>; 274 | 275 | /** 276 | * convenience alias, method = POST 277 | */ 278 | post(url: string, data?: any, config?: AxiosXHRConfigBase): IPromise>; 279 | 280 | /** 281 | * convenience alias, method = PUT 282 | */ 283 | put(url: string, data?: any, config?: AxiosXHRConfigBase): IPromise>; 284 | 285 | /** 286 | * convenience alias, method = PATCH 287 | */ 288 | patch(url: string, data?: any, config?: AxiosXHRConfigBase): IPromise>; 289 | } 290 | 291 | /** 292 | * - expected response type, 293 | */ 294 | interface AxiosStatic extends AxiosInstance { 295 | /** 296 | * create a new instance of axios with a custom config 297 | */ 298 | create(config: AxiosXHRConfigBase): AxiosInstance; 299 | } 300 | } 301 | 302 | declare var axios: Axios.AxiosStatic; 303 | 304 | declare module "axios" { 305 | export = axios; 306 | } 307 | -------------------------------------------------------------------------------- /typings/globals/axios/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "resolution": "main", 3 | "tree": { 4 | "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/e6215d4444ef44a38cd760817e955ce19b522032/axios/axios.d.ts", 5 | "raw": "registry:dt/axios#0.9.1+20161016142654", 6 | "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/e6215d4444ef44a38cd760817e955ce19b522032/axios/axios.d.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /typings/globals/localforage/index.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by typings 2 | // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/20aff2bdb6082f4f51eac9d4e6e64a2be786e346/localForage/localForage.d.ts 3 | interface LocalForageOptions { 4 | driver?: string | LocalForageDriver | LocalForageDriver[]; 5 | 6 | name?: string; 7 | 8 | size?: number; 9 | 10 | storeName?: string; 11 | 12 | version?: number; 13 | 14 | description?: string; 15 | } 16 | 17 | interface LocalForageDbMethods { 18 | getItem(key: string): Promise; 19 | getItem(key: string, callback: (err: any, value: T) => void): void; 20 | 21 | setItem(key: string, value: T): Promise; 22 | setItem(key: string, value: T, callback: (err: any, value: T) => void): void; 23 | 24 | removeItem(key: string): Promise; 25 | removeItem(key: string, callback: (err: any) => void): void; 26 | 27 | clear(): Promise; 28 | clear(callback: (err: any) => void): void; 29 | 30 | length(): Promise; 31 | length(callback: (err: any, numberOfKeys: number) => void): void; 32 | 33 | key(keyIndex: number): Promise; 34 | key(keyIndex: number, callback: (err: any, key: string) => void): void; 35 | 36 | keys(): Promise; 37 | keys(callback: (err: any, keys: string[]) => void): void; 38 | 39 | iterate(iteratee: (value: any, key: string, iterationNumber: number) => any): Promise; 40 | iterate(iteratee: (value: any, key: string, iterationNumber: number) => any, 41 | callback: (err: any, result: any) => void): void; 42 | } 43 | 44 | interface LocalForageDriverSupportFunc { 45 | (): Promise; 46 | } 47 | 48 | interface LocalForageDriver extends LocalForageDbMethods { 49 | _driver: string; 50 | 51 | _initStorage(options: LocalForageOptions): void; 52 | 53 | _support?: boolean | LocalForageDriverSupportFunc; 54 | } 55 | 56 | interface LocalForageSerializer { 57 | serialize(value: T | ArrayBuffer | Blob, callback: (value: string, error: any) => void): void; 58 | 59 | deserialize(value: string): T | ArrayBuffer | Blob; 60 | 61 | stringToBuffer(serializedString: string): ArrayBuffer; 62 | 63 | bufferToString(buffer: ArrayBuffer): string; 64 | } 65 | 66 | interface LocalForage extends LocalForageDbMethods { 67 | LOCALSTORAGE: string; 68 | WEBSQL: string; 69 | INDEXEDDB: string; 70 | 71 | /** 72 | * Set and persist localForage options. This must be called before any other calls to localForage are made, but can be called after localForage is loaded. 73 | * If you set any config values with this method they will persist after driver changes, so you can call config() then setDriver() 74 | * @param {LocalForageOptions} options? 75 | */ 76 | config(options: LocalForageOptions): boolean; 77 | 78 | /** 79 | * Create a new instance of localForage to point to a different store. 80 | * All the configuration options used by config are supported. 81 | * @param {LocalForageOptions} options 82 | */ 83 | createInstance(options: LocalForageOptions): LocalForage; 84 | 85 | driver(): string; 86 | /** 87 | * Force usage of a particular driver or drivers, if available. 88 | * @param {string} driver 89 | */ 90 | setDriver(driver: string | string[]): Promise; 91 | setDriver(driver: string | string[], callback: () => void, errorCallback: (error: any) => void): void; 92 | defineDriver(driver: LocalForageDriver): Promise; 93 | defineDriver(driver: LocalForageDriver, callback: () => void, errorCallback: (error: any) => void): void; 94 | /** 95 | * Return a particular driver 96 | * @param {string} driver 97 | */ 98 | getDriver(driver: string): Promise; 99 | 100 | getSerializer(): Promise; 101 | getSerializer(callback: (serializer: LocalForageSerializer) => void): void; 102 | 103 | supports(driverName: string): boolean; 104 | 105 | ready(callback: () => void): void; 106 | ready(): Promise; 107 | } 108 | 109 | declare module "localforage" { 110 | let localforage: LocalForage; 111 | export = localforage; 112 | } 113 | -------------------------------------------------------------------------------- /typings/globals/localforage/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "resolution": "main", 3 | "tree": { 4 | "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/20aff2bdb6082f4f51eac9d4e6e64a2be786e346/localForage/localForage.d.ts", 5 | "raw": "registry:dt/localforage#0.0.0+20161102134758", 6 | "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/20aff2bdb6082f4f51eac9d4e6e64a2be786e346/localForage/localForage.d.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /typings/globals/moment/index.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by typings 2 | // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/637e7d6df755e785387d5269cb9287cdc51b8cb7/moment/moment.d.ts 3 | declare namespace moment { 4 | 5 | type MomentComparable = Moment | string | number | Date | number[]; 6 | 7 | interface MomentDateObject { 8 | years?: number; 9 | /* One digit */ 10 | months?: number; 11 | /* Day of the month */ 12 | date?: number; 13 | hours?: number; 14 | minutes?: number; 15 | seconds?: number; 16 | milliseconds?: number; 17 | } 18 | 19 | interface MomentInput { 20 | /** Year */ 21 | years?: number; 22 | /** Year */ 23 | year?: number; 24 | /** Year */ 25 | y?: number; 26 | 27 | /** Month */ 28 | months?: number; 29 | /** Month */ 30 | month?: number; 31 | /** Month */ 32 | M?: number; 33 | 34 | /** Week */ 35 | weeks?: number; 36 | /** Week */ 37 | week?: number; 38 | /** Week */ 39 | w?: number; 40 | 41 | /** Day/Date */ 42 | days?: number; 43 | /** Day/Date */ 44 | day?: number; 45 | /** Day/Date */ 46 | date?: number; 47 | /** Day/Date */ 48 | d?: number; 49 | 50 | /** Hour */ 51 | hours?: number; 52 | /** Hour */ 53 | hour?: number; 54 | /** Hour */ 55 | h?: number; 56 | 57 | /** Minute */ 58 | minutes?: number; 59 | /** Minute */ 60 | minute?: number; 61 | /** Minute */ 62 | m?: number; 63 | 64 | /** Second */ 65 | seconds?: number; 66 | /** Second */ 67 | second?: number; 68 | /** Second */ 69 | s?: number; 70 | 71 | /** Millisecond */ 72 | milliseconds?: number; 73 | /** Millisecond */ 74 | millisecond?: number; 75 | /** Millisecond */ 76 | ms?: number; 77 | } 78 | 79 | interface Duration { 80 | humanize(withSuffix?: boolean): string; 81 | 82 | as(units: string): number; 83 | 84 | milliseconds(): number; 85 | asMilliseconds(): number; 86 | 87 | seconds(): number; 88 | asSeconds(): number; 89 | 90 | minutes(): number; 91 | asMinutes(): number; 92 | 93 | hours(): number; 94 | asHours(): number; 95 | 96 | days(): number; 97 | asDays(): number; 98 | 99 | weeks(): number; 100 | asWeeks(): number; 101 | 102 | months(): number; 103 | asMonths(): number; 104 | 105 | years(): number; 106 | asYears(): number; 107 | 108 | add(n: number, p: string): Duration; 109 | add(n: number): Duration; 110 | add(d: Duration): Duration; 111 | 112 | subtract(n: number, p: string): Duration; 113 | subtract(n: number): Duration; 114 | subtract(d: Duration): Duration; 115 | 116 | toISOString(): string; 117 | toJSON(): string; 118 | } 119 | 120 | interface MomentLocale { 121 | ordinal(n: number): string; 122 | } 123 | 124 | interface MomentCreationData { 125 | input?: string; 126 | format?: string; 127 | locale: MomentLocale; 128 | isUTC: boolean; 129 | strict?: boolean; 130 | } 131 | 132 | interface Moment { 133 | format(format: string): string; 134 | format(): string; 135 | 136 | fromNow(withoutSuffix?: boolean): string; 137 | 138 | startOf(unitOfTime: string): Moment; 139 | endOf(unitOfTime: string): Moment; 140 | 141 | /** 142 | * Mutates the original moment by adding time. (deprecated in 2.8.0) 143 | * 144 | * @param unitOfTime the unit of time you want to add (eg "years" / "hours" etc) 145 | * @param amount the amount you want to add 146 | */ 147 | add(unitOfTime: string, amount: number): Moment; 148 | /** 149 | * Mutates the original moment by adding time. 150 | * 151 | * @param amount the amount you want to add 152 | * @param unitOfTime the unit of time you want to add (eg "years" / "hours" etc) 153 | */ 154 | add(amount: number, unitOfTime: string): Moment; 155 | /** 156 | * Mutates the original moment by adding time. Note that the order of arguments can be flipped. 157 | * 158 | * @param amount the amount you want to add 159 | * @param unitOfTime the unit of time you want to add (eg "years" / "hours" etc) 160 | */ 161 | add(amount: string, unitOfTime: string): Moment; 162 | /** 163 | * Mutates the original moment by adding time. 164 | * 165 | * @param objectLiteral an object literal that describes multiple time units {days:7,months:1} 166 | */ 167 | add(objectLiteral: MomentInput): Moment; 168 | /** 169 | * Mutates the original moment by adding time. 170 | * 171 | * @param duration a length of time 172 | */ 173 | add(duration: Duration): Moment; 174 | 175 | /** 176 | * Mutates the original moment by subtracting time. (deprecated in 2.8.0) 177 | * 178 | * @param unitOfTime the unit of time you want to subtract (eg "years" / "hours" etc) 179 | * @param amount the amount you want to subtract 180 | */ 181 | subtract(unitOfTime: string, amount: number): Moment; 182 | /** 183 | * Mutates the original moment by subtracting time. 184 | * 185 | * @param unitOfTime the unit of time you want to subtract (eg "years" / "hours" etc) 186 | * @param amount the amount you want to subtract 187 | */ 188 | subtract(amount: number, unitOfTime: string): Moment; 189 | /** 190 | * Mutates the original moment by subtracting time. Note that the order of arguments can be flipped. 191 | * 192 | * @param amount the amount you want to add 193 | * @param unitOfTime the unit of time you want to subtract (eg "years" / "hours" etc) 194 | */ 195 | subtract(amount: string, unitOfTime: string): Moment; 196 | /** 197 | * Mutates the original moment by subtracting time. 198 | * 199 | * @param objectLiteral an object literal that describes multiple time units {days:7,months:1} 200 | */ 201 | subtract(objectLiteral: MomentInput): Moment; 202 | /** 203 | * Mutates the original moment by subtracting time. 204 | * 205 | * @param duration a length of time 206 | */ 207 | subtract(duration: Duration): Moment; 208 | 209 | calendar(): string; 210 | calendar(start: Moment): string; 211 | calendar(start: Moment, formats: MomentCalendar): string; 212 | 213 | clone(): Moment; 214 | 215 | /** 216 | * @return Unix timestamp, or milliseconds since the epoch. 217 | */ 218 | valueOf(): number; 219 | 220 | local(): Moment; // current date/time in local mode 221 | 222 | utc(): Moment; // current date/time in UTC mode 223 | 224 | isValid(): boolean; 225 | invalidAt(): number; 226 | 227 | year(y: number): Moment; 228 | year(): number; 229 | quarter(): number; 230 | quarter(q: number): Moment; 231 | month(M: number): Moment; 232 | month(M: string): Moment; 233 | month(): number; 234 | day(d: number): Moment; 235 | day(d: string): Moment; 236 | day(): number; 237 | date(d: number): Moment; 238 | date(): number; 239 | hour(h: number): Moment; 240 | hour(): number; 241 | hours(h: number): Moment; 242 | hours(): number; 243 | minute(m: number): Moment; 244 | minute(): number; 245 | minutes(m: number): Moment; 246 | minutes(): number; 247 | second(s: number): Moment; 248 | second(): number; 249 | seconds(s: number): Moment; 250 | seconds(): number; 251 | millisecond(ms: number): Moment; 252 | millisecond(): number; 253 | milliseconds(ms: number): Moment; 254 | milliseconds(): number; 255 | weekday(): number; 256 | weekday(d: number): Moment; 257 | isoWeekday(): number; 258 | isoWeekday(d: number): Moment; 259 | weekYear(): number; 260 | weekYear(d: number): Moment; 261 | isoWeekYear(): number; 262 | isoWeekYear(d: number): Moment; 263 | week(): number; 264 | week(d: number): Moment; 265 | weeks(): number; 266 | weeks(d: number): Moment; 267 | isoWeek(): number; 268 | isoWeek(d: number): Moment; 269 | isoWeeks(): number; 270 | isoWeeks(d: number): Moment; 271 | weeksInYear(): number; 272 | isoWeeksInYear(): number; 273 | dayOfYear(): number; 274 | dayOfYear(d: number): Moment; 275 | 276 | from(f: MomentComparable, suffix?: boolean): string; 277 | to(f: MomentComparable, suffix?: boolean): string; 278 | toNow(withoutPrefix?: boolean): string; 279 | 280 | diff(b: MomentComparable): number; 281 | diff(b: MomentComparable, unitOfTime: string): number; 282 | diff(b: MomentComparable, unitOfTime: string, round: boolean): number; 283 | 284 | toArray(): number[]; 285 | toDate(): Date; 286 | toISOString(): string; 287 | toJSON(): string; 288 | unix(): number; 289 | 290 | isLeapYear(): boolean; 291 | zone(): number; 292 | zone(b: number): Moment; 293 | zone(b: string): Moment; 294 | utcOffset(): number; 295 | utcOffset(b: number): Moment; 296 | utcOffset(b: string): Moment; 297 | daysInMonth(): number; 298 | isDST(): boolean; 299 | 300 | isBefore(): boolean; 301 | isBefore(b: MomentComparable, granularity?: string): boolean; 302 | 303 | isAfter(): boolean; 304 | isAfter(b: MomentComparable, granularity?: string): boolean; 305 | 306 | isSame(b: MomentComparable, granularity?: string): boolean; 307 | isBetween(a: MomentComparable, b: MomentComparable, granularity?: string, inclusivity?: string): boolean; 308 | 309 | /** 310 | * @since 2.10.7+ 311 | */ 312 | isSameOrBefore(b: MomentComparable, granularity?: string): boolean; 313 | isSameOrAfter(b: MomentComparable, granularity?: string): boolean; 314 | 315 | /** 316 | * @deprecated since version 2.8.0 317 | */ 318 | lang(language: string): Moment; 319 | lang(reset: boolean): Moment; 320 | lang(): MomentLanguage; 321 | 322 | locale(language: string): Moment; 323 | locale(reset: boolean): Moment; 324 | locale(): string; 325 | 326 | /** 327 | * @since 2.12.0+ 328 | */ 329 | locales() : string[]; 330 | localeData(language: string): Moment; 331 | localeData(reset: boolean): Moment; 332 | localeData(): MomentLanguageData; 333 | 334 | /** 335 | * @deprecated since version 2.7.0 336 | */ 337 | max(date: Moment | string | number | Date | any[]): Moment; 338 | max(date: string, format: string): Moment; 339 | 340 | /** 341 | * @deprecated since version 2.7.0 342 | */ 343 | min(date: Moment | string | number | Date | any[]): Moment; 344 | min(date: string, format: string): Moment; 345 | 346 | get(unit: string): number; 347 | set(unit: string, value: number): Moment; 348 | set(objectLiteral: MomentInput): Moment; 349 | 350 | /** 351 | * This returns an object containing year, month, day-of-month, hour, minute, seconds, milliseconds. 352 | * @since 2.10.5+ 353 | */ 354 | toObject(): MomentDateObject; 355 | 356 | /** 357 | * @since 2.10.7+ 358 | */ 359 | creationData(): MomentCreationData; 360 | } 361 | 362 | type formatFunction = () => string; 363 | 364 | interface MomentCalendar { 365 | lastDay?: string | formatFunction; 366 | sameDay?: string | formatFunction; 367 | nextDay?: string | formatFunction; 368 | lastWeek?: string | formatFunction; 369 | nextWeek?: string | formatFunction; 370 | sameElse?: string | formatFunction; 371 | } 372 | 373 | interface BaseMomentLanguage { 374 | months?: any; 375 | monthsShort?: any; 376 | weekdays?: any; 377 | weekdaysShort?: any; 378 | weekdaysMin?: any; 379 | relativeTime?: MomentRelativeTime; 380 | meridiem?: (hour: number, minute: number, isLowercase: boolean) => string; 381 | calendar?: MomentCalendar; 382 | ordinal?: (num: number) => string; 383 | week?: MomentLanguageWeek; 384 | } 385 | 386 | interface MomentLanguage extends BaseMomentLanguage { 387 | longDateFormat?: MomentLongDateFormat; 388 | } 389 | 390 | interface MomentLanguageWeek { 391 | dow?: number; 392 | doy?: number; 393 | } 394 | 395 | interface MomentLanguageData { 396 | /** 397 | * Get the full localized month name of a moment object 398 | * @param {Moment} aMoment a moment object 399 | * @return {string} full month name 400 | */ 401 | months(aMoment: Moment): string; 402 | 403 | /** 404 | * Get the short localized month name of a moment object 405 | * @param {Moment} aMoment a moment object 406 | * @return {string} short month name 407 | */ 408 | monthsShort(aMoment: Moment): string; 409 | 410 | /** 411 | * Parses a month name and returns the month id (0-11) 412 | * @param {string} longOrShortMonthString string of month to parse 413 | * @return {number} month id (0 to 11) of input 414 | */ 415 | monthsParse(longOrShortMonthString: string): number; 416 | 417 | /** 418 | * Gets the full weekday name of a moment object (eg. Monday) 419 | * @param {Moment} aMoment a moment object 420 | * @return {string} full weekday name 421 | */ 422 | weekdays(aMoment: Moment): string; 423 | 424 | /** 425 | * Gets the short weekday name of a moment object (eg. Mon) 426 | * @param {Moment} aMoment a moment object 427 | * @return {string} short weekday name 428 | */ 429 | weekdaysShort(aMoment: Moment): string; 430 | 431 | /** 432 | * Gets the min weekday name of a moment object (eg. Mo) 433 | * @param {Moment} aMoment a moment object 434 | * @return {string} min weekday name 435 | */ 436 | weekdaysMin(aMoment: Moment): string; 437 | 438 | /** 439 | * Parses a weekday name and returns the weekday id (0-6) 440 | * @param {string} longOrShortMonthString string of weekday to parse 441 | * @return {number} weekday id (0 to 6) of input 442 | */ 443 | weekdaysParse(longOrShortMonthString: string): number; 444 | 445 | /** 446 | * Returns the full format of abbreviated date-time formats 447 | * @param {string} dateFormat date-time format such as LT, L, LL and so on 448 | * @return {string} full date format string 449 | */ 450 | longDateFormat(dateFormat: string): string; 451 | 452 | /** 453 | * Returns whether a string represents PM 454 | * @param {string} amPmString date string to check 455 | * @return {boolean} true if string represents PM 456 | */ 457 | isPM(amPmString: string): boolean; 458 | 459 | /** 460 | * Returns am/pm string for particular time-of-day in upper/lower case 461 | * @param {number} hour hour 462 | * @param {number} minute minute 463 | * @param {boolean} isLowercase whether to return in lowercase 464 | * @return {string} 'am' or 'pm' 465 | */ 466 | meridiem(hour: number, minute: number, isLowercase: boolean): string; 467 | 468 | /** 469 | * Returns a format that would be used for calendar representation. 470 | * @param {string} key one of 'sameDay', 'nextDay', 'lastDay', 'nextWeek', 'prevWeek', 'sameElse' 471 | * @param {Moment} aMoment a moment object 472 | * @return {string} date format string 473 | */ 474 | calendar(key: string, aMoment: Moment): string; 475 | 476 | /** 477 | * Returns relative time string (eg. a year ago) 478 | * @param {number} number the relative number 479 | * @param {boolean} withoutSuffix whether to drop the suffix 480 | * @param {string} key one of 's', 'm', 'mm', 'h', 'hh', 'd', 'dd', 'M', 'MM', 'y', 'yy'. Single letter when number is 1. 481 | * @param {boolean} isFuture whether this represents a future date 482 | * @return {string} humanized representation of relative time 483 | */ 484 | relativeTime(number: number, withoutSuffix: boolean, key: string, isFuture: boolean): string; 485 | 486 | /** 487 | * Converts relative time string to past or future string depending on difference 488 | * @param {number} diff positive or negative number 489 | * @param {string} relTime relative time string 490 | * @return {string} humanized representation of relative time 491 | */ 492 | pastFuture(diff: number, relTime: string): string; 493 | 494 | /** 495 | * Convert number to ordinal string 1 -> 1st 496 | * @param {number} number the number 497 | * @return {string} ordinal string 498 | */ 499 | ordinal(number: number): string; 500 | 501 | /** 502 | * Called before parsing every input string 503 | */ 504 | preparse(str: string): string; 505 | 506 | /** 507 | * Called after formatting on every string 508 | */ 509 | postformat(str: string): string; 510 | 511 | /** 512 | * Returns week-of-year of a moment object 513 | * @param {Moment} aMoment a moment object 514 | * @return {number} number of the week 515 | */ 516 | week(aMoment: Moment): number; 517 | 518 | /** 519 | * Returns a translation of 'Invalid date' 520 | * @return {string} translation of 'Invalid date' 521 | */ 522 | invalidDate(): string; 523 | 524 | /** 525 | * Returns the first day of the week (0-6, Sunday to Saturday) 526 | * @return {number} first day of the week 527 | */ 528 | firstDayOfWeek(): number; 529 | 530 | /** 531 | * This and the first day of week are used to determine which is 532 | * the first week of the year. dow == 1 and doy == 4 means week starts 533 | * Monday and first week that has Thursday is the first week of the 534 | * year (but doy is NOT simply Thursday). 535 | * @return {number} number between 0-15 536 | */ 537 | firstDayOfYear(): number; 538 | } 539 | 540 | interface MomentLongDateFormat { 541 | L: string; 542 | LL: string; 543 | LLL: string; 544 | LLLL: string; 545 | LT: string; 546 | LTS: string; 547 | l?: string; 548 | ll?: string; 549 | lll?: string; 550 | llll?: string; 551 | lt?: string; 552 | lts?: string; 553 | } 554 | 555 | interface MomentRelativeTime { 556 | future: any; 557 | past: any; 558 | s: any; 559 | m: any; 560 | mm: any; 561 | h: any; 562 | hh: any; 563 | d: any; 564 | dd: any; 565 | M: any; 566 | MM: any; 567 | y: any; 568 | yy: any; 569 | } 570 | 571 | interface MomentBuiltinFormat { 572 | __momentBuiltinFormatBrand: any; 573 | } 574 | 575 | type MomentFormatSpecification = string | MomentBuiltinFormat | (string | MomentBuiltinFormat)[]; 576 | 577 | interface MomentStatic { 578 | version: string; 579 | fn: Moment; 580 | 581 | (): Moment; 582 | (date: number): Moment; 583 | (date: number[]): Moment; 584 | (date: string, format?: MomentFormatSpecification, strict?: boolean): Moment; 585 | (date: string, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment; 586 | (date: Date): Moment; 587 | (date: Moment): Moment; 588 | (date: Object): Moment; 589 | 590 | utc(): Moment; 591 | utc(date: number): Moment; 592 | utc(date: number[]): Moment; 593 | utc(date: string, format?: string, strict?: boolean): Moment; 594 | utc(date: string, format?: string, language?: string, strict?: boolean): Moment; 595 | utc(date: string, formats: string[], strict?: boolean): Moment; 596 | utc(date: string, formats: string[], language?: string, strict?: boolean): Moment; 597 | utc(date: Date): Moment; 598 | utc(date: Moment): Moment; 599 | utc(date: Object): Moment; 600 | 601 | unix(timestamp: number): Moment; 602 | 603 | invalid(parsingFlags?: Object): Moment; 604 | isMoment(): boolean; 605 | isMoment(m: any): m is Moment; 606 | isDate(m: any): m is Date; 607 | isDuration(): boolean; 608 | isDuration(d: any): d is Duration; 609 | 610 | /** 611 | * @deprecated since version 2.8.0 612 | */ 613 | lang(language?: string): string; 614 | lang(language?: string, definition?: MomentLanguage): string; 615 | 616 | locale(language?: string): string; 617 | locale(language?: string[]): string; 618 | locale(language?: string, definition?: MomentLanguage): string; 619 | 620 | localeData(language?: string): MomentLanguageData; 621 | 622 | longDateFormat: any; 623 | relativeTime: any; 624 | meridiem: (hour: number, minute: number, isLowercase: boolean) => string; 625 | calendar: any; 626 | ordinal: (num: number) => string; 627 | 628 | duration(milliseconds: Number): Duration; 629 | duration(num: Number, unitOfTime: string): Duration; 630 | duration(input: MomentInput): Duration; 631 | duration(object: any): Duration; 632 | duration(): Duration; 633 | 634 | parseZone(date: string): Moment; 635 | 636 | months(): string[]; 637 | months(index: number): string; 638 | months(format: string): string[]; 639 | months(format: string, index: number): string; 640 | monthsShort(): string[]; 641 | monthsShort(index: number): string; 642 | monthsShort(format: string): string[]; 643 | monthsShort(format: string, index: number): string; 644 | 645 | weekdays(): string[]; 646 | weekdays(index: number): string; 647 | weekdays(format: string): string[]; 648 | weekdays(format: string, index: number): string; 649 | weekdaysShort(): string[]; 650 | weekdaysShort(index: number): string; 651 | weekdaysShort(format: string): string[]; 652 | weekdaysShort(format: string, index: number): string; 653 | weekdaysMin(): string[]; 654 | weekdaysMin(index: number): string; 655 | weekdaysMin(format: string): string[]; 656 | weekdaysMin(format: string, index: number): string; 657 | 658 | min(...moments: Moment[]): Moment; 659 | min(moments: Moment[]): Moment; 660 | max(...moments: Moment[]): Moment; 661 | max(moments: Moment[]): Moment; 662 | 663 | normalizeUnits(unit: string): string; 664 | relativeTimeThreshold(threshold: string): number | boolean; 665 | relativeTimeThreshold(threshold: string, limit: number): boolean; 666 | 667 | /** 668 | * @since 2.10.7+ 669 | */ 670 | now(): number; 671 | 672 | /** 673 | * Constant used to enable explicit ISO_8601 format parsing. 674 | */ 675 | ISO_8601: MomentBuiltinFormat; 676 | 677 | defaultFormat: string; 678 | } 679 | 680 | } 681 | 682 | declare module 'moment' { 683 | var moment: moment.MomentStatic; 684 | export = moment; 685 | } 686 | 687 | declare module 'moment/moment' { 688 | var moment: moment.MomentStatic; 689 | export = moment; 690 | } 691 | 692 | declare var moment: moment.MomentStatic; 693 | -------------------------------------------------------------------------------- /typings/globals/moment/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "resolution": "main", 3 | "tree": { 4 | "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/637e7d6df755e785387d5269cb9287cdc51b8cb7/moment/moment.d.ts", 5 | "raw": "registry:dt/moment#2.11.1+20161010105546", 6 | "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/637e7d6df755e785387d5269cb9287cdc51b8cb7/moment/moment.d.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /typings/globals/redux-thunk/index.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by typings 2 | // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/d417f687ab0c81ed72bffbc5dace5f643369bb70/redux-thunk/redux-thunk.d.ts 3 | declare namespace Redux { 4 | type ThunkAction = (dispatch: Dispatch, getState: () => S, extraArgument: E) => R; 5 | 6 | interface Dispatch { 7 | (asyncAction: ThunkAction): R; 8 | } 9 | } 10 | 11 | declare module "redux-thunk" { 12 | import { Middleware } from "redux"; 13 | 14 | const thunk: Middleware & { 15 | withExtraArgument(extraArgument: any): Middleware; 16 | }; 17 | 18 | export default thunk; 19 | } 20 | -------------------------------------------------------------------------------- /typings/globals/redux-thunk/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "resolution": "main", 3 | "tree": { 4 | "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/d417f687ab0c81ed72bffbc5dace5f643369bb70/redux-thunk/redux-thunk.d.ts", 5 | "raw": "registry:dt/redux-thunk#2.1.0+20160703120921", 6 | "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/d417f687ab0c81ed72bffbc5dace5f643369bb70/redux-thunk/redux-thunk.d.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /typings/globals/redux/index.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by typings 2 | // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/15ddcf312782faf9e7fdfe724a3a29382a5825d7/redux/redux.d.ts 3 | declare namespace Redux { 4 | /** 5 | * An *action* is a plain object that represents an intention to change the 6 | * state. Actions are the only way to get data into the store. Any data, 7 | * whether from UI events, network callbacks, or other sources such as 8 | * WebSockets needs to eventually be dispatched as actions. 9 | * 10 | * Actions must have a `type` field that indicates the type of action being 11 | * performed. Types can be defined as constants and imported from another 12 | * module. It’s better to use strings for `type` than Symbols because strings 13 | * are serializable. 14 | * 15 | * Other than `type`, the structure of an action object is really up to you. 16 | * If you’re interested, check out Flux Standard Action for recommendations on 17 | * how actions should be constructed. 18 | */ 19 | interface Action { 20 | type: any; 21 | } 22 | 23 | 24 | /* reducers */ 25 | 26 | /** 27 | * A *reducer* (also called a *reducing function*) is a function that accepts 28 | * an accumulation and a value and returns a new accumulation. They are used 29 | * to reduce a collection of values down to a single value 30 | * 31 | * Reducers are not unique to Redux—they are a fundamental concept in 32 | * functional programming. Even most non-functional languages, like 33 | * JavaScript, have a built-in API for reducing. In JavaScript, it's 34 | * `Array.prototype.reduce()`. 35 | * 36 | * In Redux, the accumulated value is the state object, and the values being 37 | * accumulated are actions. Reducers calculate a new state given the previous 38 | * state and an action. They must be *pure functions*—functions that return 39 | * the exact same output for given inputs. They should also be free of 40 | * side-effects. This is what enables exciting features like hot reloading and 41 | * time travel. 42 | * 43 | * Reducers are the most important concept in Redux. 44 | * 45 | * *Do not put API calls into reducers.* 46 | * 47 | * @template S State object type. 48 | */ 49 | type Reducer = (state: S, action: A) => S; 50 | 51 | /** 52 | * Object whose values correspond to different reducer functions. 53 | */ 54 | interface ReducersMapObject { 55 | [key: string]: Reducer; 56 | } 57 | 58 | /** 59 | * Turns an object whose values are different reducer functions, into a single 60 | * reducer function. It will call every child reducer, and gather their results 61 | * into a single state object, whose keys correspond to the keys of the passed 62 | * reducer functions. 63 | * 64 | * @template S Combined state object type. 65 | * 66 | * @param reducers An object whose values correspond to different reducer 67 | * functions that need to be combined into one. One handy way to obtain it 68 | * is to use ES6 `import * as reducers` syntax. The reducers may never 69 | * return undefined for any action. Instead, they should return their 70 | * initial state if the state passed to them was undefined, and the current 71 | * state for any unrecognized action. 72 | * 73 | * @returns A reducer function that invokes every reducer inside the passed 74 | * object, and builds a state object with the same shape. 75 | */ 76 | function combineReducers(reducers: ReducersMapObject): Reducer; 77 | 78 | 79 | /* store */ 80 | 81 | /** 82 | * A *dispatching function* (or simply *dispatch function*) is a function that 83 | * accepts an action or an async action; it then may or may not dispatch one 84 | * or more actions to the store. 85 | * 86 | * We must distinguish between dispatching functions in general and the base 87 | * `dispatch` function provided by the store instance without any middleware. 88 | * 89 | * The base dispatch function *always* synchronously sends an action to the 90 | * store’s reducer, along with the previous state returned by the store, to 91 | * calculate a new state. It expects actions to be plain objects ready to be 92 | * consumed by the reducer. 93 | * 94 | * Middleware wraps the base dispatch function. It allows the dispatch 95 | * function to handle async actions in addition to actions. Middleware may 96 | * transform, delay, ignore, or otherwise interpret actions or async actions 97 | * before passing them to the next middleware. 98 | */ 99 | interface Dispatch { 100 | (action: A): A; 101 | } 102 | 103 | /** 104 | * Function to remove listener added by `Store.subscribe()`. 105 | */ 106 | interface Unsubscribe { 107 | (): void; 108 | } 109 | 110 | /** 111 | * A store is an object that holds the application’s state tree. 112 | * There should only be a single store in a Redux app, as the composition 113 | * happens on the reducer level. 114 | * 115 | * @template S State object type. 116 | */ 117 | interface Store { 118 | /** 119 | * Dispatches an action. It is the only way to trigger a state change. 120 | * 121 | * The `reducer` function, used to create the store, will be called with the 122 | * current state tree and the given `action`. Its return value will be 123 | * considered the **next** state of the tree, and the change listeners will 124 | * be notified. 125 | * 126 | * The base implementation only supports plain object actions. If you want 127 | * to dispatch a Promise, an Observable, a thunk, or something else, you 128 | * need to wrap your store creating function into the corresponding 129 | * middleware. For example, see the documentation for the `redux-thunk` 130 | * package. Even the middleware will eventually dispatch plain object 131 | * actions using this method. 132 | * 133 | * @param action A plain object representing “what changed”. It is a good 134 | * idea to keep actions serializable so you can record and replay user 135 | * sessions, or use the time travelling `redux-devtools`. An action must 136 | * have a `type` property which may not be `undefined`. It is a good idea 137 | * to use string constants for action types. 138 | * 139 | * @returns For convenience, the same action object you dispatched. 140 | * 141 | * Note that, if you use a custom middleware, it may wrap `dispatch()` to 142 | * return something else (for example, a Promise you can await). 143 | */ 144 | dispatch: Dispatch
55 | Error code: { errorCode ? errorCode : '--' } 56 |