├── .eslintignore ├── test ├── environment │ ├── .eslintrc │ ├── hapi-router.spec.js │ ├── express-router.spec.js │ └── hash-router.spec.js ├── .eslintrc ├── util │ ├── throw-error.spec.js │ ├── match-cache.spec.js │ ├── validate-routes.spec.js │ ├── merge-queries.spec.js │ ├── stringify-href.spec.js │ ├── normalize-href.spec.js │ ├── create-matcher.spec.js │ └── flatten-routes.spec.js ├── .setup.js ├── test-util │ ├── fixtures │ │ └── routes.js │ └── index.js └── install.spec.js ├── .prettierignore ├── prettier.config.js ├── .eslintrc ├── .npmignore ├── config └── webpack │ ├── .eslintrc │ ├── partials │ ├── sourcemaps-inline.js │ ├── babel.js │ ├── stats.js │ ├── optimize.js │ ├── define.js │ ├── resolve.js │ └── css-modules.js │ ├── postcss.config.js │ ├── webpack.config.dev.js │ ├── demo │ ├── webpack.config.demo.dev.js │ └── webpack.config.demo.js │ └── webpack.config.js ├── demo ├── server │ ├── .eslintrc │ ├── index.hbs │ └── index.js └── client │ ├── wrap.js │ ├── .eslintrc │ ├── global.css │ ├── index.html │ ├── demo.css │ ├── app.js │ └── demo.js ├── src ├── immutable │ ├── environment │ │ ├── hapi-router.js │ │ ├── hash-router.js │ │ ├── browser-router.js │ │ └── express-router.js │ ├── install.js │ ├── components │ │ ├── fragment.js │ │ ├── props-to-js.js │ │ └── link.js │ ├── index.js │ ├── middleware.js │ ├── util │ │ └── immutable.js │ ├── enhancer.js │ └── reducer.js ├── install.js ├── util │ ├── stringify-href.js │ ├── throw-error.js │ ├── generate-id.js │ ├── merge-queries.js │ ├── match-cache.js │ ├── normalize-href.js │ ├── validate-routes.js │ ├── create-installer.js │ ├── create-matcher.js │ └── flatten-routes.js ├── .eslintrc ├── environment │ ├── hapi-router.js │ ├── hash-router.js │ ├── express-router.js │ └── browser-router.js ├── index.js ├── actions.js ├── types.js ├── middleware.js ├── enhancer.js ├── reducer.js └── components │ └── link.js ├── flow-typed └── npm │ ├── flow-bin_v0.x.x.js │ ├── normalize.css_v7.x.x.js │ ├── rimraf_v2.x.x.js │ ├── query-string_v5.x.x.js │ ├── sinon-chai_vx.x.x.js │ ├── lodash.chunk_vx.x.x.js │ ├── url-pattern_vx.x.x.js │ ├── lodash.assign_vx.x.x.js │ ├── babel-preset-react_vx.x.x.js │ ├── babel-preset-stage-2_vx.x.x.js │ ├── babel-plugin-istanbul_vx.x.x.js │ ├── compression-webpack-plugin_vx.x.x.js │ ├── babel-preset-react-hmre_vx.x.x.js │ ├── webpack-stats-plugin_vx.x.x.js │ ├── prop-types_v15.x.x.js │ ├── babel-register_vx.x.x.js │ ├── postcss-loader_vx.x.x.js │ ├── postcss-reporter_vx.x.x.js │ ├── flow-copy-source_vx.x.x.js │ ├── watch_vx.x.x.js │ ├── webpack-dev-middleware_vx.x.x.js │ ├── redux-thunk_vx.x.x.js │ ├── extract-text-webpack-plugin_vx.x.x.js │ ├── webpack-merge_vx.x.x.js │ ├── ent_vx.x.x.js │ ├── style-loader_vx.x.x.js │ ├── redux-logger_vx.x.x.js │ ├── css-modules-require-hook_vx.x.x.js │ ├── babel-loader_vx.x.x.js │ ├── babel-polyfill_vx.x.x.js │ ├── postcss-import_vx.x.x.js │ ├── eslint-config-prettier_vx.x.x.js │ ├── react-addons-test-utils_v15.x.x.js │ ├── webpack-partial_vx.x.x.js │ ├── redux_v3.x.x.js │ ├── redux-immutable_vx.x.x.js │ ├── husky_vx.x.x.js │ ├── postcss-cssnext_vx.x.x.js │ ├── react-hot-loader_vx.x.x.js │ ├── babel-eslint_vx.x.x.js │ ├── lint-staged_vx.x.x.js │ ├── eslint-plugin-filenames_vx.x.x.js │ ├── babel-preset-env_vx.x.x.js │ ├── babel-plugin-lodash_vx.x.x.js │ ├── css-loader_vx.x.x.js │ ├── prettier_vx.x.x.js │ ├── babel-cli_vx.x.x.js │ ├── builder_vx.x.x.js │ ├── nyc_vx.x.x.js │ ├── webpack-dev-server_vx.x.x.js │ ├── enzyme_v2.3.x.js │ └── react-redux_v5.x.x.js ├── .editorconfig ├── .gitignore ├── .babelrc ├── .flowconfig ├── .travis.yml ├── LICENSE.md ├── .bithoundrc └── interfaces └── history.js /.eslintignore: -------------------------------------------------------------------------------- 1 | demo/dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /test/environment/.eslintrc: -------------------------------------------------------------------------------- 1 | globals: 2 | window: false 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | lib/ 3 | es/ 4 | flow-typed/ 5 | .nyc-output/ 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 80, 3 | singleQuote: true 4 | }; 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: 3 | - "formidable" 4 | - "prettier" 5 | - "prettier/flowtype" 6 | - "prettier/react" 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /* 2 | !/dist 3 | !/lib 4 | !/es 5 | !package.json 6 | !LICENSE.md 7 | !README.md 8 | !ADVANCED.md 9 | !index.d.ts 10 | -------------------------------------------------------------------------------- /config/webpack/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: 3 | - "formidable/configurations/es6-node" 4 | - "prettier" 5 | - "prettier/flowtype" 6 | - "prettier/react" 7 | -------------------------------------------------------------------------------- /demo/server/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: 3 | - "formidable/configurations/es6-node" 4 | - "prettier" 5 | - "prettier/flowtype" 6 | - "prettier/react" 7 | -------------------------------------------------------------------------------- /demo/client/wrap.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Provider } from 'react-redux'; 3 | 4 | export default store => Root => ( 5 | 6 | 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/immutable/environment/hapi-router.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { createHapiRouter } from '../../environment/hapi-router'; 3 | import install from '../install'; 4 | 5 | export default createHapiRouter(install); 6 | -------------------------------------------------------------------------------- /src/immutable/environment/hash-router.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { createHashRouter } from '../../environment/hash-router'; 3 | import install from '../install'; 4 | 5 | export default createHashRouter(install); 6 | -------------------------------------------------------------------------------- /src/immutable/environment/browser-router.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { createBrowserRouter } from '../../environment/browser-router'; 3 | import install from '../install'; 4 | 5 | export default createBrowserRouter(install); 6 | -------------------------------------------------------------------------------- /src/immutable/environment/express-router.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { createExpressRouter } from '../../environment/express-router'; 3 | import install from '../install'; 4 | 5 | export default createExpressRouter(install); 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config/webpack/partials/sourcemaps-inline.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { smart: mergeWebpackConfig } = require('webpack-merge'); 4 | 5 | module.exports = () => config => 6 | mergeWebpackConfig(config, { 7 | devtool: 'cheap-module-source-map' 8 | }); 9 | -------------------------------------------------------------------------------- /src/install.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import reducer from './reducer'; 3 | import middleware from './middleware'; 4 | import enhancer from './enhancer'; 5 | 6 | import createInstaller from './util/create-installer'; 7 | 8 | export default createInstaller({ reducer, middleware, enhancer }); 9 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: 3 | - "formidable/configurations/es6-react-test" 4 | - "../.eslintrc" 5 | 6 | env: 7 | mocha: true 8 | 9 | globals: 10 | sandbox: true 11 | 12 | rules: 13 | no-unused-expressions: "off" 14 | react/no-multi-comp: "off" 15 | 16 | -------------------------------------------------------------------------------- /src/immutable/install.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import reducer from './reducer'; 3 | import middleware from './middleware'; 4 | import enhancer from './enhancer'; 5 | 6 | import createInstaller from '../util/create-installer'; 7 | 8 | export default createInstaller({ reducer, middleware, enhancer }); 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | max_line_length = 100 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .git 2 | 3 | .DS_Store 4 | .idea 5 | .project 6 | .vagrant 7 | bower_components 8 | node_modules 9 | npm-debug.log* 10 | package-lock.json 11 | jmeter.log 12 | yarn-error.log* 13 | 14 | # Config overrides 15 | config/local* 16 | 17 | # Build 18 | lib 19 | dist 20 | demo/stats 21 | es 22 | coverage 23 | .nyc_output 24 | -------------------------------------------------------------------------------- /config/webpack/partials/babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const loader = require('webpack-partial/loader').default; 4 | 5 | module.exports = opts => 6 | loader({ 7 | test: /\.jsx?$/, 8 | exclude: /node_modules/, 9 | include: process.cwd(), 10 | loader: require.resolve('babel-loader'), 11 | query: opts 12 | }); 13 | -------------------------------------------------------------------------------- /config/webpack/partials/stats.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const plugin = require('webpack-partial/plugin').default; 4 | const StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin; 5 | 6 | module.exports = () => 7 | plugin( 8 | new StatsWriterPlugin({ 9 | filename: '../stats/stats.json' 10 | }) 11 | ); 12 | -------------------------------------------------------------------------------- /demo/client/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: 3 | - "formidable/configurations/es6-react" 4 | - "prettier" 5 | - "prettier/flowtype" 6 | - "prettier/react" 7 | 8 | env: 9 | browser: true 10 | 11 | parser: "babel-eslint" 12 | 13 | plugins: 14 | - "babel" 15 | - "flowtype" 16 | 17 | rules: 18 | flowtype/define-flow-type: warn 19 | 20 | -------------------------------------------------------------------------------- /src/util/stringify-href.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Href } from '../types'; 3 | 4 | export default (href: Href, basename: ?string) => { 5 | if (typeof href === 'string') { 6 | return `${basename || ''}${href}`; 7 | } 8 | 9 | const { pathname, search } = href; 10 | return `${basename || ''}${pathname}${search || ''}`; 11 | }; 12 | -------------------------------------------------------------------------------- /src/util/throw-error.js: -------------------------------------------------------------------------------- 1 | export default (errorMsg?: string) => (...args: Array<*>) => { 2 | const argsString = args.reduce( 3 | (str, arg) => `${str && `${str}, `}${arg}`, 4 | '' 5 | ); 6 | throw new Error( 7 | `${errorMsg && `${errorMsg} `} ${argsString && 8 | `Was called with arguments ${argsString}.`}` 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /src/util/generate-id.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /** 3 | * Returns a psuedo-unique identifier used by fragments 4 | * to track match status within MatchCache. 5 | * @returns {String} id 6 | */ 7 | export default (): string => { 8 | const radix = 16; 9 | const length = 8; 10 | return (Math.random() * Date.now()).toString(radix).slice(0, length); 11 | }; 12 | -------------------------------------------------------------------------------- /config/webpack/postcss.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const postcssImport = require('postcss-import'); 4 | const cssnext = require('postcss-cssnext'); 5 | const reporter = require('postcss-reporter'); 6 | 7 | module.exports = { 8 | plugins: [ 9 | postcssImport, 10 | cssnext(), 11 | reporter({ 12 | throwError: true 13 | }) 14 | ] 15 | }; 16 | -------------------------------------------------------------------------------- /flow-typed/npm/normalize.css_v7.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: b0a8c8851219a1c2a933509d842e0bc8 2 | // flow-typed version: 4a2d036a51/normalize.css_v7.x.x/flow_>=v0.34.x 3 | 4 | // normalize.css may be imported for side-effects, 5 | // e.g. to force webpack to bundle it alongside CSS modules 6 | 7 | declare module "normalize.css" { 8 | declare export default empty 9 | } 10 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["env", { "modules": false }], "react", "stage-2"], 3 | "plugins": [ 4 | ["lodash", { "id": ["lodash", "recompose"] }] 5 | ], 6 | "env": { 7 | "commonjs": { 8 | "presets": ["env", "react", "stage-2"] 9 | }, 10 | "coverage": { 11 | "presets": ["env", "react", "stage-2"], 12 | "plugins": [ [ "istanbul", { "ignore": "test" } ] ] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: 3 | - "formidable/configurations/es6-react" 4 | - "prettier" 5 | - "prettier/flowtype" 6 | - "prettier/react" 7 | 8 | parser: "babel-eslint" 9 | 10 | env: 11 | browser: true 12 | 13 | plugins: 14 | - "babel" 15 | - "flowtype" 16 | 17 | rules: 18 | react/prop-types: [2, { skipUndeclared: true }] 19 | flowtype/define-flow-type: warn 20 | react/no-multi-comp: "off" 21 | 22 | -------------------------------------------------------------------------------- /demo/client/global.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | background: #218380; 7 | } 8 | 9 | h1, 10 | h2, 11 | h3, 12 | h4, 13 | h5, 14 | h6 { 15 | color: #fff; 16 | font-family: 'Source Code Pro', monospace; 17 | } 18 | 19 | p { 20 | color: #fff; 21 | font-family: 'Work Sans', sans-serif; 22 | line-height: 1.4; 23 | } 24 | 25 | a { 26 | font-family: 'Source Code Pro', monospace; 27 | } 28 | -------------------------------------------------------------------------------- /src/util/merge-queries.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Location, Query } from '../types'; 3 | 4 | import qs from 'query-string'; 5 | 6 | export default (oldQuery: ?Query, newQuery: ?Query): Location => { 7 | const mergedQuery = { 8 | ...oldQuery, 9 | ...newQuery 10 | }; 11 | const search: string = `?${qs.stringify(mergedQuery)}`; 12 | 13 | return { 14 | query: mergedQuery, 15 | search 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /config/webpack/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const webpack = require('webpack'); 4 | const config = require('./webpack.config'); 5 | 6 | // **WARNING**: Mutates base configuration. 7 | // We do this because lodash isn't available in `production` mode. 8 | config.output.filename = config.output.filename.replace(/\.min\.js$/, '.js'); 9 | config.plugins = [new webpack.SourceMapDevToolPlugin('[file].map')]; 10 | 11 | // Export mutated base. 12 | module.exports = config; 13 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | dist/ 3 | lib/ 4 | es/ 5 | .*/node_modules/fbjs/.* 6 | .*/node_modules/systemjs-builder/.* 7 | .*/__tests__/.* 8 | .*/__mocks__/.* 9 | .*/node_modules/flow-typed/src/.* 10 | .*/node_modules/immutable/.* 11 | 12 | [include] 13 | src/ 14 | 15 | [libs] 16 | interfaces/ 17 | 18 | [options] 19 | module.name_mapper='history\(.*\)' -> 'history' 20 | esproposal.class_static_fields=enable 21 | esproposal.class_instance_fields=enable 22 | suppress_comment= \\(.\\|\n\\)*\\$FlowIssue 23 | suppress_comment= \\(.\\|\n\\)*\\$FlowFixMe 24 | -------------------------------------------------------------------------------- /src/util/match-cache.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | const ROUTE_FALLBACK = '@ROUTE_FALLBACK'; 3 | 4 | export class MatchCache { 5 | _data: { [parentId: string]: string }; 6 | constructor() { 7 | this._data = {}; 8 | } 9 | 10 | add(parentId: string, route: ?string): void { 11 | this._data[parentId] = route || ROUTE_FALLBACK; 12 | } 13 | 14 | get(parentId: string): null | string { 15 | return this._data[parentId] || null; 16 | } 17 | 18 | clear(): void { 19 | this._data = {}; 20 | } 21 | } 22 | 23 | export default new MatchCache(); 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "4" 5 | - "6" 6 | - "8" 7 | 8 | # Use container-based Travis infrastructure. 9 | sudo: false 10 | 11 | branches: 12 | only: 13 | - master 14 | - /^greenkeeper-.*$/ 15 | 16 | before_install: 17 | # GUI for real browsers. 18 | - export DISPLAY=:99.0 19 | - sh -e /etc/init.d/xvfb start 20 | 21 | script: 22 | - yarn run check-cov 23 | - node_modules/.bin/nyc report --reporter=text-lcov > coverage.lcov && node_modules/.bin/codecov || echo "Codecov upload failed" 24 | 25 | - yarn run build 26 | -------------------------------------------------------------------------------- /src/immutable/components/fragment.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { MapStateToProps } from 'react-redux'; 3 | import { connect } from 'react-redux'; 4 | import { compose } from 'recompose'; 5 | 6 | import { FragmentComponent, withIdAndContext } from '../../components/fragment'; 7 | import propsToJS from './props-to-js'; 8 | 9 | const mapStateToProps: MapStateToProps<*, *, *> = state => ({ 10 | location: state.get('router') 11 | }); 12 | 13 | // $FlowFixMe 14 | export default compose(connect(mapStateToProps), withIdAndContext, propsToJS)( 15 | FragmentComponent 16 | ); 17 | -------------------------------------------------------------------------------- /config/webpack/partials/optimize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { flow } = require('lodash'); 4 | const CompressionPlugin = require('compression-webpack-plugin'); 5 | const plugin = require('webpack-partial/plugin').default; 6 | const optimize = require('webpack').optimize; 7 | 8 | module.exports = () => 9 | flow( 10 | plugin(new optimize.UglifyJsPlugin()), 11 | plugin( 12 | new CompressionPlugin({ 13 | asset: '[path].gz[query]', 14 | test: /\.js$|\.css$/, 15 | algorithm: 'gzip', 16 | threshold: 1500 17 | }) 18 | ) 19 | ); 20 | -------------------------------------------------------------------------------- /flow-typed/npm/rimraf_v2.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 1dff23447d5e18f5ac2b05aaec7cfb74 2 | // flow-typed version: a453e98ea2/rimraf_v2.x.x/flow_>=v0.25.0 3 | 4 | declare module 'rimraf' { 5 | declare type Options = { 6 | maxBusyTries?: number, 7 | emfileWait?: number, 8 | glob?: boolean, 9 | disableGlob?: boolean 10 | }; 11 | 12 | declare type Callback = (err: ?Error, path: ?string) => void; 13 | 14 | declare module.exports: { 15 | (f: string, opts?: Options | Callback, callback?: Callback): void; 16 | sync(path: string, opts?: Options): void; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /src/immutable/components/props-to-js.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Component } from 'react'; 3 | 4 | import React from 'react'; 5 | import { isImmutable } from '../util/immutable'; 6 | 7 | export default (WrappedComponent: Class>) => ( 8 | wrappedProps: P 9 | ) => { 10 | const propsJS = Object.keys(wrappedProps).reduce( 11 | (props, key) => ({ 12 | ...props, 13 | [key]: isImmutable(wrappedProps[key]) 14 | ? wrappedProps[key].toJS() 15 | : wrappedProps[key] 16 | }), 17 | {} 18 | ); 19 | 20 | return ; 21 | }; 22 | -------------------------------------------------------------------------------- /config/webpack/partials/define.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const _ = require('lodash'); 4 | const plugin = require('webpack-partial/plugin').default; 5 | const DefinePlugin = require('webpack').DefinePlugin; 6 | 7 | module.exports = function(opts) { 8 | opts = _.defaults(opts, { 9 | 'process.env.NODE_ENV': JSON.stringify( 10 | process.env.NODE_ENV || 'development' 11 | ) 12 | }); 13 | 14 | const define = _.reduce( 15 | opts, 16 | (accumulator, value, key) => { 17 | return _.set(accumulator, key, JSON.stringify(value)); 18 | }, 19 | {} 20 | ); 21 | 22 | return plugin(new DefinePlugin(define)); 23 | }; 24 | -------------------------------------------------------------------------------- /test/util/throw-error.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import throwError from '../../src/util/throw-error'; 3 | 4 | describe('throwError', () => { 5 | it('throws an error', () => { 6 | expect(throwError()).to.throw(); 7 | }); 8 | 9 | it('throws an error with an error message', () => { 10 | const throwWeirdError = throwError('There was a weird error.'); 11 | expect(throwWeirdError).to.throw('There was a weird error.'); 12 | }); 13 | 14 | it('lists the arguments passed in', () => { 15 | expect(throwError().bind(null, 1, 'two')).to.throw( 16 | 'Was called with arguments 1, two.' 17 | ); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /flow-typed/npm/query-string_v5.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 2389e99bd2259b7242a44127a9c2d620 2 | // flow-typed version: 576c24ae7e/query-string_v5.x.x/flow_>=v0.32.x 3 | 4 | declare module "query-string" { 5 | declare type ArrayFormat = "none" | "bracket" | "index"; 6 | declare type ParseOptions = {| 7 | arrayFormat?: ArrayFormat 8 | |}; 9 | 10 | declare type StringifyOptions = {| 11 | arrayFormat?: ArrayFormat, 12 | encode?: boolean, 13 | strict?: boolean 14 | |}; 15 | 16 | declare module.exports: { 17 | extract(str: string): string, 18 | parse(str: string, opts?: ParseOptions): Object, 19 | stringify(obj: Object, opts?: StringifyOptions): string 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /config/webpack/partials/resolve.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { smart: mergeWebpackConfig } = require('webpack-merge'); 4 | const path = require('path'); 5 | 6 | module.exports = () => config => 7 | mergeWebpackConfig(config, { 8 | resolve: { 9 | // Alias `react` to copy in this repo's `node_modules`. 10 | // Solves an issue where Webpack includes multiple versions of React when using 11 | // npm link to install a package that also includes React as a dependency. 12 | // 13 | // http://www.justincarmony.com/blog/2015/04/02/webpack-react-multiple-versions-issues/ 14 | alias: { 15 | react: path.dirname(require.resolve('react/package.json')) 16 | } 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /test/util/match-cache.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { MatchCache } from '../../src/util/match-cache'; 3 | 4 | let cache; 5 | 6 | describe('MatchCache', () => { 7 | beforeEach(() => { 8 | cache = new MatchCache(); 9 | }); 10 | 11 | it('allows items to be set', () => { 12 | cache.add('foo', 'bar'); 13 | expect(cache._data).to.deep.equal({ foo: 'bar' }); 14 | }); 15 | 16 | it('allows items to be retrieved', () => { 17 | cache.add('foo', 'bar'); 18 | const foo = cache.get('foo'); 19 | expect(foo).to.equal('bar'); 20 | }); 21 | 22 | it('is clearable', () => { 23 | cache.add('foo', 'bar'); 24 | cache.clear(); 25 | expect(cache._data).to.deep.equal({}); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/immutable/components/link.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { connect } from 'react-redux'; 3 | 4 | import { 5 | LinkComponent, 6 | PersistentQueryLinkComponent, 7 | mapDispatchToProps 8 | } from '../../components/link'; 9 | import propsToJS from './props-to-js'; 10 | 11 | const mapStateToProps = state => ({ location: state.get('router') }); 12 | 13 | const withLocation = connect(mapStateToProps, mapDispatchToProps); 14 | 15 | const LinkWithLocation = withLocation(propsToJS(LinkComponent)); 16 | const PersistentQueryLinkWithLocation = withLocation( 17 | propsToJS(PersistentQueryLinkComponent) 18 | ); 19 | 20 | export { 21 | LinkWithLocation as ImmutableLink, 22 | PersistentQueryLinkWithLocation as ImmutablePersistentQueryLink 23 | }; 24 | -------------------------------------------------------------------------------- /src/immutable/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import immutableRouterForBrowser from './environment/browser-router'; 3 | import immutableRouterForExpress from './environment/express-router'; 4 | import immutableRouterForHash from './environment/hash-router'; 5 | import immutableRouterForHapi from './environment/hapi-router'; 6 | 7 | import { ImmutableLink, ImmutablePersistentQueryLink } from './components/link'; 8 | import ImmutableFragment from './components/fragment'; 9 | 10 | export { 11 | // High-level Redux API 12 | immutableRouterForBrowser, 13 | immutableRouterForExpress, 14 | immutableRouterForHapi, 15 | immutableRouterForHash, 16 | // React API 17 | ImmutableLink, 18 | ImmutablePersistentQueryLink, 19 | ImmutableFragment 20 | }; 21 | -------------------------------------------------------------------------------- /test/.setup.js: -------------------------------------------------------------------------------- 1 | require('babel-register')(); 2 | 3 | var jsdom = require('jsdom').jsdom; 4 | var sinon = require('sinon'); 5 | 6 | var exposedProperties = ['window', 'navigator', 'document']; 7 | 8 | global.document = jsdom(''); 9 | global.window = document.defaultView; 10 | Object.keys(document.defaultView).forEach(property => { 11 | if (typeof global[property] === 'undefined') { 12 | exposedProperties.push(property); 13 | global[property] = document.defaultView[property]; 14 | } 15 | }); 16 | 17 | global.navigator = { 18 | userAgent: 'node.js' 19 | }; 20 | 21 | documentRef = document; 22 | 23 | beforeEach(function() { 24 | global.sandbox = sinon.sandbox.create(); 25 | }); 26 | 27 | afterEach(function() { 28 | global.sandbox.restore(); 29 | }); 30 | -------------------------------------------------------------------------------- /demo/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | Demo 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/util/normalize-href.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Href, Location } from '../types'; 3 | 4 | import { parsePath } from 'history/PathUtils'; 5 | import qs from 'query-string'; 6 | 7 | export default (href: Href): Location => { 8 | if (typeof href === 'string') { 9 | const { search = '', ...other } = parsePath(href); 10 | const query = search && qs.parse(search); 11 | 12 | return query ? { ...other, query, search } : { ...other }; 13 | } 14 | 15 | const { search, query } = href; 16 | 17 | const resolvedSearch = 18 | search || 19 | (query && Object.keys(query).length && `?${qs.stringify(query)}`) || 20 | ''; 21 | const resolvedQuery = query || qs.parse(search || ''); 22 | 23 | return { 24 | ...href, 25 | search: resolvedSearch, 26 | query: resolvedQuery 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /config/webpack/demo/webpack.config.demo.dev.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const compose = require('lodash/fp/compose'); 5 | 6 | const babel = require('../partials/babel'); 7 | const cssModules = require('../partials/css-modules'); 8 | const sourceMaps = require('../partials/sourcemaps-inline'); 9 | 10 | const extendConfig = compose(babel(), cssModules(), sourceMaps()); 11 | 12 | module.exports = extendConfig({ 13 | devServer: { 14 | contentBase: './demo/client', 15 | noInfo: false, 16 | historyApiFallback: true 17 | }, 18 | 19 | output: { 20 | path: path.resolve('demo/client'), 21 | filename: 'main.js', 22 | publicPath: '/assets/' 23 | }, 24 | 25 | cache: true, 26 | entry: { 27 | app: ['./demo/client/app.js'] 28 | }, 29 | stats: { 30 | colors: true, 31 | reasons: true 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /demo/server/index.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Demo 7 | 8 | 9 | {{#each css}} 10 | 11 | {{/each}} 12 | 13 | 14 | 15 |
{{#if content}}{{{content}}}{{/if}}
16 | {{#if initialState}} 17 | 20 | {{/if}} 21 | {{#each js}} 22 | 23 | {{/each}} 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/immutable/middleware.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Store, Dispatch } from 'redux'; 3 | import type { Map } from 'immutable'; 4 | 5 | import type { RouterAction, State } from '../types'; 6 | import type { MiddlewareArgs } from '../middleware'; 7 | 8 | import { isNavigationAction } from '../types'; 9 | import { handleNavigationAction } from '../middleware'; 10 | 11 | type ImmutableState = $Shape>; 12 | 13 | export default ({ history }: MiddlewareArgs) => ({ 14 | getState 15 | }: Store) => (next: Dispatch<*>) => ( 16 | action: RouterAction 17 | ) => { 18 | const query = getState().getIn(['router', 'query']); 19 | return isNavigationAction(action) 20 | ? handleNavigationAction({ 21 | next, 22 | action, 23 | history, 24 | query: query && query.toJS() 25 | }) 26 | : next(action); 27 | }; 28 | -------------------------------------------------------------------------------- /src/immutable/util/immutable.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /* eslint-disable import/no-mutable-exports, no-empty */ 3 | import throwError from '../../util/throw-error'; 4 | 5 | const throwImmutableError = throwError( 6 | 'immutable.js was not imported. Make sure you have it installed.' 7 | ); 8 | 9 | let immutable; 10 | let Map = throwImmutableError; 11 | let List = throwImmutableError; 12 | let fromJS = throwImmutableError; 13 | let isImmutable = throwImmutableError; 14 | 15 | try { 16 | immutable = require('immutable'); 17 | Map = immutable.Map; 18 | List = immutable.List; 19 | fromJS = immutable.fromJS; 20 | // To account for immutable versions 3.8.x -> 4.x.x 21 | isImmutable = immutable.isImmutable 22 | ? immutable.isImmutable 23 | : immutable.Iterable.isIterable; 24 | } catch (e) {} 25 | 26 | export { Map, List, fromJS, isImmutable }; 27 | 28 | export default immutable; 29 | -------------------------------------------------------------------------------- /src/util/validate-routes.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import throwError from './throw-error'; 3 | 4 | export const README_MESSAGE = ` 5 | See the README for more information: 6 | https://github.com/FormidableLabs/redux-little-router#wiring-up-the-boilerplate 7 | `; 8 | 9 | export default (routes: Object) => { 10 | if (!routes) { 11 | throwError(` 12 | Missing route configuration. You must define your routes as 13 | an object where the keys are routes and the values are any 14 | route-specific data. 15 | 16 | ${README_MESSAGE} 17 | `)(); 18 | } 19 | 20 | // eslint-disable-next-line no-magic-numbers 21 | if (!Object.keys(routes).every(route => route.indexOf('/') === 0)) { 22 | throwError(` 23 | The route configuration you provided is malformed. Make sure 24 | that all of your routes start with a slash. 25 | 26 | ${README_MESSAGE} 27 | `)(); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/environment/hapi-router.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { MemoryHistoryOptions } from 'history'; 3 | 4 | import createMemoryHistory from 'history/createMemoryHistory'; 5 | 6 | import normalizeHref from '../util/normalize-href'; 7 | import install from '../install'; 8 | 9 | type ServerRouterArgs = { 10 | routes: Object, 11 | request: { 12 | path: string, 13 | url: string, 14 | query: { [key: string]: string } 15 | }, 16 | historyOptions: MemoryHistoryOptions 17 | }; 18 | 19 | export const createHapiRouter = (installer: Function) => ({ 20 | routes, 21 | request, 22 | historyOptions = {} 23 | }: ServerRouterArgs) => { 24 | const history = createMemoryHistory(historyOptions); 25 | 26 | const location = normalizeHref({ 27 | pathname: request.path, 28 | query: request.query 29 | }); 30 | 31 | return installer({ routes, history, location }); 32 | }; 33 | 34 | export default createHapiRouter(install); 35 | -------------------------------------------------------------------------------- /test/util/validate-routes.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import validateRoutes, { README_MESSAGE } from '../../src/util/validate-routes'; 3 | 4 | describe('validateRoute', () => { 5 | it('throws an error if no routes object is passed in', () => { 6 | expect(validateRoutes).to.throw(` 7 | Missing route configuration. You must define your routes as 8 | an object where the keys are routes and the values are any 9 | route-specific data. 10 | 11 | ${README_MESSAGE} 12 | `); 13 | }); 14 | 15 | it('throws an error if a route does not begin with a slash', () => { 16 | const routes = { 17 | '/': {}, 18 | cat: {}, 19 | '/dog': {} 20 | }; 21 | expect(validateRoutes.bind(null, routes)).to.throw(` 22 | The route configuration you provided is malformed. Make sure 23 | that all of your routes start with a slash. 24 | 25 | ${README_MESSAGE} 26 | `); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /src/environment/hash-router.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { History, HashHistoryOptions } from 'history'; 3 | import createHashHistory from 'history/createHashHistory'; 4 | 5 | import normalizeHref from '../util/normalize-href'; 6 | import install from '../install'; 7 | 8 | type HashRouterArgs = { 9 | routes: Object, 10 | basename: string, 11 | hashType: string, 12 | historyOptions: HashHistoryOptions, 13 | history: History 14 | }; 15 | 16 | export const createHashRouter = (installer: Function) => ({ 17 | routes, 18 | basename, 19 | hashType = 'slash', 20 | historyOptions, 21 | history = createHashHistory({ basename, hashType, ...historyOptions }) 22 | }: HashRouterArgs) => { 23 | const descriptor = basename 24 | ? { basename, ...history.location } 25 | : history.location; 26 | 27 | const location = normalizeHref(descriptor); 28 | 29 | return installer({ routes, history, location }); 30 | }; 31 | 32 | export default createHashRouter(install); 33 | -------------------------------------------------------------------------------- /config/webpack/demo/webpack.config.demo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const compose = require('lodash/fp/compose'); 5 | 6 | const babelConfig = require('../partials/babel'); 7 | const cssConfig = require('../partials/css-modules'); 8 | const defineConfig = require('../partials/define'); 9 | const optimizeConfig = require('../partials/optimize'); 10 | const resolveConfig = require('../partials/resolve'); 11 | const statsConfig = require('../partials/stats'); 12 | 13 | const extendConfig = compose( 14 | babelConfig(), 15 | cssConfig({ production: true }), 16 | defineConfig({ 'process.env.NODE_ENV': 'production' }), 17 | optimizeConfig(), 18 | resolveConfig(), 19 | statsConfig() 20 | ); 21 | 22 | module.exports = extendConfig({ 23 | cache: true, 24 | context: path.resolve('demo/client'), 25 | entry: './app.js', 26 | output: { 27 | path: path.resolve('demo/dist'), 28 | publicPath: '/', 29 | filename: '[name].[hash].js' 30 | } 31 | }); 32 | -------------------------------------------------------------------------------- /flow-typed/npm/sinon-chai_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6de989383946ee619fbba4e68ee0ff77 2 | // flow-typed version: <>/sinon-chai_v^2.9.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'sinon-chai' 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 'sinon-chai' { 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 'sinon-chai/lib/sinon-chai' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'sinon-chai/lib/sinon-chai.js' { 31 | declare module.exports: $Exports<'sinon-chai/lib/sinon-chai'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/lodash.chunk_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 4f646fbd1d7014223b5874f853bf3e58 2 | // flow-typed version: <>/lodash.chunk_v^4.2.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'lodash.chunk' 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 'lodash.chunk' { 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 | 26 | 27 | // Filename aliases 28 | declare module 'lodash.chunk/index' { 29 | declare module.exports: $Exports<'lodash.chunk'>; 30 | } 31 | declare module 'lodash.chunk/index.js' { 32 | declare module.exports: $Exports<'lodash.chunk'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/url-pattern_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: f705cf0b6fcaf999a2e62f804ad103d8 2 | // flow-typed version: <>/url-pattern_v^1.0.3/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'url-pattern' 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 'url-pattern' { 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 'url-pattern/lib/url-pattern' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'url-pattern/lib/url-pattern.js' { 31 | declare module.exports: $Exports<'url-pattern/lib/url-pattern'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/lodash.assign_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 47f2cde191583d172722f988e0989cd3 2 | // flow-typed version: <>/lodash.assign_v^4.2.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'lodash.assign' 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 'lodash.assign' { 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 | 26 | 27 | // Filename aliases 28 | declare module 'lodash.assign/index' { 29 | declare module.exports: $Exports<'lodash.assign'>; 30 | } 31 | declare module 'lodash.assign/index.js' { 32 | declare module.exports: $Exports<'lodash.assign'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-react_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: f0cc921dbd843e87753e6ea1eabe428a 2 | // flow-typed version: <>/babel-preset-react_v^6.23.0/flow_v0.64.0 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: a4b22fd2c18369c715c6f11b7232e400 2 | // flow-typed version: <>/babel-preset-stage-2_v^6.11.0/flow_v0.64.0 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 | -------------------------------------------------------------------------------- /demo/client/demo.css: -------------------------------------------------------------------------------- 1 | .container { 2 | max-width: 1024px; 3 | display: block; 4 | margin-left: auto; 5 | margin-right: auto; 6 | padding: 20px; 7 | } 8 | 9 | .tagline { 10 | text-align: center; 11 | } 12 | 13 | .primary { 14 | font-size: 36px; 15 | } 16 | 17 | .secondary { 18 | font-size: 16px; 19 | } 20 | 21 | .nav { 22 | display: flex; 23 | justify-content: center; 24 | padding-bottom: 20px; 25 | } 26 | 27 | .nav a { 28 | color: #fff; 29 | margin: 0 16px; 30 | position: relative; 31 | text-decoration: none; 32 | } 33 | 34 | .nav a::after { 35 | position: absolute; 36 | content: ''; 37 | right: 0px; 38 | bottom: -6px; 39 | left: 0px; 40 | height: 2px; 41 | background: #fbb13c; 42 | } 43 | 44 | .gallery { 45 | display: flex; 46 | flex-direction: row; 47 | padding-top: 20px; 48 | } 49 | 50 | .column { 51 | display: flex; 52 | flex-basis: 50%; 53 | flex-direction: column; 54 | flex-wrap: wrap; 55 | font-size: 0; 56 | } 57 | 58 | .image { 59 | width: 100%; 60 | } 61 | 62 | .noMatchImage { 63 | max-width: 100%; 64 | } 65 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-plugin-istanbul_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 54858348bcd822387143d50612970140 2 | // flow-typed version: <>/babel-plugin-istanbul_v^4.1.1/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-plugin-istanbul' 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-istanbul' { 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-istanbul/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-plugin-istanbul/lib/index.js' { 31 | declare module.exports: $Exports<'babel-plugin-istanbul/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /test/util/merge-queries.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import mergeQueries from '../../src/util/merge-queries'; 3 | 4 | describe('mergeQueries', () => { 5 | it('merges two query objects and adds a merged search string', () => { 6 | const query1 = { 7 | cool: 'jeans', 8 | iced: 'tea' 9 | }; 10 | 11 | const query2 = { 12 | iced: 'joose' 13 | }; 14 | 15 | expect(mergeQueries(query1, query2)).to.deep.equal({ 16 | query: { 17 | cool: 'jeans', 18 | iced: 'joose' 19 | }, 20 | search: '?cool=jeans&iced=joose' 21 | }); 22 | }); 23 | 24 | it('allows either query to be undefined', () => { 25 | const query1 = { 26 | cool: 'jeans', 27 | iced: 'tea' 28 | }; 29 | 30 | const query2 = void 0; 31 | 32 | expect(mergeQueries(query1, query2)).to.deep.equal({ 33 | query: query1, 34 | search: '?cool=jeans&iced=tea' 35 | }); 36 | 37 | expect(mergeQueries(query2, query1)).to.deep.equal({ 38 | query: query1, 39 | search: '?cool=jeans&iced=tea' 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /flow-typed/npm/compression-webpack-plugin_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 4eb1c56c254201dcda6e52ae23b96fd7 2 | // flow-typed version: <>/compression-webpack-plugin_v^0.4.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'compression-webpack-plugin' 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 'compression-webpack-plugin' { 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 | 26 | 27 | // Filename aliases 28 | declare module 'compression-webpack-plugin/index' { 29 | declare module.exports: $Exports<'compression-webpack-plugin'>; 30 | } 31 | declare module 'compression-webpack-plugin/index.js' { 32 | declare module.exports: $Exports<'compression-webpack-plugin'>; 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 Formidable 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/util/stringify-href.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import stringifyHref from '../../src/util/stringify-href'; 3 | 4 | describe('stringifyHref', () => { 5 | it('leaves string hrefs without a basename intact', () => { 6 | expect(stringifyHref('/boop')).to.equal('/boop'); 7 | }); 8 | 9 | it('appends the basename to a string href', () => { 10 | expect(stringifyHref('/boop', '/base')).to.equal('/base/boop'); 11 | }); 12 | 13 | it('creates a string representation of an object href', () => { 14 | expect( 15 | stringifyHref({ 16 | pathname: '/wat' 17 | }) 18 | ).to.equal('/wat'); 19 | 20 | expect( 21 | stringifyHref( 22 | { 23 | pathname: '/wat' 24 | }, 25 | '/say' 26 | ) 27 | ).to.equal('/say/wat'); 28 | 29 | expect( 30 | stringifyHref({ 31 | pathname: '/wat', 32 | search: '?as=af' 33 | }) 34 | ).to.equal('/wat?as=af'); 35 | 36 | expect( 37 | stringifyHref({ 38 | pathname: '/say/wat', 39 | search: '?as=af' 40 | }) 41 | ).to.equal('/say/wat?as=af'); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /src/environment/express-router.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { MemoryHistoryOptions } from 'history'; 3 | 4 | import createMemoryHistory from 'history/createMemoryHistory'; 5 | 6 | import normalizeHref from '../util/normalize-href'; 7 | import install from '../install'; 8 | 9 | type ServerRouterArgs = { 10 | routes: Object, 11 | request: { 12 | path: string, 13 | baseUrl: string, 14 | url: string, 15 | query: { [key: string]: string } 16 | }, 17 | historyOptions: MemoryHistoryOptions 18 | }; 19 | 20 | const locationForRequest = request => { 21 | const { path: pathname, baseUrl: basename, query } = request; 22 | const descriptor = basename 23 | ? { pathname, basename, query } 24 | : { pathname, query }; 25 | return normalizeHref(descriptor); 26 | }; 27 | 28 | export const createExpressRouter = (installer: Function) => ({ 29 | routes, 30 | request, 31 | historyOptions = {} 32 | }: ServerRouterArgs) => { 33 | const history = createMemoryHistory(historyOptions); 34 | const location = locationForRequest(request); 35 | 36 | return installer({ routes, history, location }); 37 | }; 38 | 39 | export default createExpressRouter(install); 40 | -------------------------------------------------------------------------------- /src/util/create-installer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { History } from 'history'; 3 | import type { Location } from '../types'; 4 | 5 | import { default as matcherFactory } from '../util/create-matcher'; 6 | import validateRoutes from '../util/validate-routes'; 7 | import flattenRoutes from '../util/flatten-routes'; 8 | 9 | type CreateInstallArgs = {| 10 | reducer: Function, 11 | middleware: Function, 12 | enhancer: Function 13 | |}; 14 | 15 | type InstallArgs = {| 16 | routes: Object, 17 | history: History, 18 | location: Location, 19 | createMatcher?: Function 20 | |}; 21 | 22 | export default ({ reducer, middleware, enhancer }: CreateInstallArgs) => ({ 23 | routes: nestedRoutes, 24 | history, 25 | location, 26 | createMatcher = matcherFactory 27 | }: InstallArgs) => { 28 | validateRoutes(nestedRoutes); 29 | const routes = flattenRoutes(nestedRoutes); 30 | const matchRoute = createMatcher(routes); 31 | 32 | return { 33 | reducer: reducer({ 34 | routes, 35 | initialLocation: { 36 | ...location, 37 | ...matchRoute(location.pathname) 38 | } 39 | }), 40 | middleware: middleware({ history }), 41 | enhancer: enhancer({ 42 | history, 43 | matchRoute, 44 | createMatcher 45 | }) 46 | }; 47 | }; 48 | -------------------------------------------------------------------------------- /src/util/create-matcher.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import UrlPattern from 'url-pattern'; 3 | 4 | type RouteCache = { 5 | route: string, 6 | pattern: UrlPattern, 7 | result: Object 8 | }; 9 | 10 | const hasTrailingSlash = /\w+\/$/; 11 | 12 | const eagerMatcher = (routeList: Array) => ( 13 | incomingUrl: string 14 | ) => { 15 | // Discard query strings 16 | const pathname = incomingUrl 17 | .split('?')[0] 18 | .replace(hasTrailingSlash, path => path.slice(0, path.length - 1)); 19 | 20 | // Find the route that matches the URL 21 | for (let i = 0; i < routeList.length; i++) { 22 | const storedRoute = routeList[i]; 23 | const match = storedRoute.pattern.match(pathname); 24 | 25 | if (match) { 26 | // Return the matched params and user-defined result object 27 | return { 28 | route: storedRoute.route, 29 | params: match, 30 | result: storedRoute.result 31 | }; 32 | } 33 | } 34 | 35 | return null; 36 | }; 37 | 38 | export default (routes: Object) => { 39 | const routeList = Object.keys(routes) 40 | .sort() 41 | .reverse() 42 | .map(route => ({ 43 | route, 44 | pattern: new UrlPattern(route), 45 | result: routes[route] 46 | })); 47 | 48 | return eagerMatcher(routeList); 49 | }; 50 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-react-hmre_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 9cd573655b382b42ed8bdcc95037f53f 2 | // flow-typed version: <>/babel-preset-react-hmre_v^1.1.1/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-react-hmre' 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-hmre' { 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-hmre/test/Test' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-react-hmre/index' { 31 | declare module.exports: $Exports<'babel-preset-react-hmre'>; 32 | } 33 | declare module 'babel-preset-react-hmre/index.js' { 34 | declare module.exports: $Exports<'babel-preset-react-hmre'>; 35 | } 36 | declare module 'babel-preset-react-hmre/test/Test.js' { 37 | declare module.exports: $Exports<'babel-preset-react-hmre/test/Test'>; 38 | } 39 | -------------------------------------------------------------------------------- /src/environment/browser-router.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { History, BrowserHistoryOptions } from 'history'; 3 | 4 | import createBrowserHistory from 'history/createBrowserHistory'; 5 | 6 | import normalizeHref from '../util/normalize-href'; 7 | import install from '../install'; 8 | 9 | type BrowserRouterArgs = { 10 | routes: Object, 11 | basename?: string, 12 | historyOptions?: BrowserHistoryOptions, 13 | history?: History 14 | }; 15 | 16 | export const createBrowserRouter = (installer: Function) => ({ 17 | routes, 18 | basename, 19 | historyOptions = {}, 20 | history = createBrowserHistory({ basename, ...historyOptions }) 21 | }: BrowserRouterArgs) => { 22 | const { 23 | pathname: fullPathname, 24 | search, 25 | hash, 26 | state: { key, state } = {} 27 | } = history.location; 28 | 29 | // Strip the basename from the initial pathname 30 | const pathname = 31 | basename && fullPathname.indexOf(basename) === 0 32 | ? fullPathname.slice(basename.length) 33 | : fullPathname; 34 | 35 | const descriptor = basename 36 | ? { pathname, basename, search, hash, key, state } 37 | : { pathname, search, hash, key, state }; 38 | 39 | const location = normalizeHref(descriptor); 40 | 41 | return installer({ routes, history, location }); 42 | }; 43 | 44 | export default createBrowserRouter(install); 45 | -------------------------------------------------------------------------------- /flow-typed/npm/webpack-stats-plugin_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: b26e7dd1b1a908e693bec0c41366495a 2 | // flow-typed version: <>/webpack-stats-plugin_v^0.1.4/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'webpack-stats-plugin' 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 'webpack-stats-plugin' { 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 'webpack-stats-plugin/lib/stats-writer-plugin' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'webpack-stats-plugin/index' { 31 | declare module.exports: $Exports<'webpack-stats-plugin'>; 32 | } 33 | declare module 'webpack-stats-plugin/index.js' { 34 | declare module.exports: $Exports<'webpack-stats-plugin'>; 35 | } 36 | declare module 'webpack-stats-plugin/lib/stats-writer-plugin.js' { 37 | declare module.exports: $Exports<'webpack-stats-plugin/lib/stats-writer-plugin'>; 38 | } 39 | -------------------------------------------------------------------------------- /test/util/normalize-href.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import normalizeHref from '../../src/util/normalize-href'; 3 | 4 | describe('normalizeHref', () => { 5 | it('appends empty query and search properties', () => { 6 | const descriptor = { pathname: 'object' }; 7 | expect(normalizeHref(descriptor)).to.deep.equal({ 8 | pathname: 'object', 9 | search: '', 10 | query: {} 11 | }); 12 | }); 13 | 14 | it('converts a string href into an object with parsed search and query', () => { 15 | expect(normalizeHref('/string')).to.deep.equal({ 16 | pathname: '/string', 17 | hash: '' 18 | }); 19 | 20 | expect(normalizeHref('/string?things=stuff')).to.deep.equal({ 21 | pathname: '/string', 22 | search: '?things=stuff', 23 | hash: '', 24 | query: { 25 | things: 'stuff' 26 | } 27 | }); 28 | 29 | expect(normalizeHref('/string?things=stuff#anchor')).to.deep.equal({ 30 | pathname: '/string', 31 | search: '?things=stuff', 32 | hash: '#anchor', 33 | query: { 34 | things: 'stuff' 35 | } 36 | }); 37 | }); 38 | 39 | it('ignores empty query objects', () => { 40 | const result = normalizeHref({ 41 | pathname: '/', 42 | query: {} 43 | }); 44 | 45 | expect(result).to.have.property('search', ''); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /.bithoundrc: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | "flow-typed/**", 4 | "**/deps/**", 5 | "**/node_modules/**", 6 | "**/thirdparty/**", 7 | "**/third_party/**", 8 | "**/vendor/**", 9 | "**/**-min-**", 10 | "**/**-min.**", 11 | "**/**.min.**", 12 | "**/**jquery.?(ui|effects)-*.*.?(*).?(cs|j)s", 13 | "**/**jquery-*.*.?(*).?(cs|j)s", 14 | "**/prototype?(*).js", 15 | "**/mootools*.*.*.js", 16 | "**/dojo.js", 17 | "**/MochiKit.js", 18 | "**/yahoo-*.js", 19 | "**/yui*.js", 20 | "**/ckeditor*.js", 21 | "**/tiny_mce*.js", 22 | "**/tiny_mce/?(langs|plugins|themes|utils)/**", 23 | "**/MathJax/**", 24 | "**/shBrush*.js", 25 | "**/shCore.js", 26 | "**/shLegacy.js", 27 | "**/modernizr.custom.?(*).js", 28 | "**/knockout-*.*.*.debug.js", 29 | "**/extjs/*.js", 30 | "**/extjs/*.xml", 31 | "**/extjs/*.txt", 32 | "**/extjs/*.html", 33 | "**/extjs/*.properties", 34 | "**/extjs/.sencha", 35 | "**/extjs/docs/**", 36 | "**/extjs/builds/**", 37 | "**/extjs/cmd/**", 38 | "**/extjs/examples/**", 39 | "**/extjs/locale/**", 40 | "**/extjs/packages/**", 41 | "**/extjs/plugins/**", 42 | "**/extjs/resources/**", 43 | "**/extjs/src/**", 44 | "**/extjs/welcome/**", 45 | "bower_components/**" 46 | ], 47 | "test": [ 48 | "**/test/**", 49 | "**/tests/**", 50 | "**/spec/**", 51 | "**/specs/**" 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /src/immutable/enhancer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { StoreCreator, Reducer, StoreEnhancer } from 'redux'; 3 | import type { Map } from 'immutable'; 4 | 5 | import type { State } from '../types'; 6 | import type { EnhancerArgs } from '../enhancer'; 7 | 8 | import { subscribeToStoreAndHistory } from '../enhancer'; 9 | 10 | type ImmutableState = $Shape>; 11 | 12 | export default ({ history, matchRoute, createMatcher }: EnhancerArgs) => ( 13 | createStore: StoreCreator<*, *> 14 | ) => ( 15 | userReducer: Reducer<*, *>, 16 | initialState: ImmutableState, 17 | enhancer: StoreEnhancer<*, *> 18 | ) => { 19 | const store = createStore(userReducer, initialState, enhancer); 20 | const { dispatch, subscribe: subscribeToStore } = store; 21 | const { listen: subscribeToHistory } = history; 22 | 23 | const getState = () => { 24 | const routerState = store.getState().get('router'); 25 | return { 26 | routes: routerState.get('routes'), 27 | pathname: routerState.get('pathname'), 28 | search: routerState.get('search'), 29 | hash: routerState.get('hash'), 30 | updateRoutes: routerState.getIn(['options', 'updateRoutes']) 31 | }; 32 | }; 33 | 34 | subscribeToStoreAndHistory({ 35 | getState, 36 | dispatch, 37 | createMatcher, 38 | matchRoute, 39 | subscribeToStore, 40 | subscribeToHistory 41 | }); 42 | 43 | return { 44 | ...store, 45 | matchRoute 46 | }; 47 | }; 48 | -------------------------------------------------------------------------------- /src/util/flatten-routes.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import assign from 'lodash.assign'; 3 | 4 | const filterObject = (target, predicate) => 5 | Object.keys(target).reduce((acc, key) => { 6 | return predicate(key) ? { ...acc, [key]: target[key] } : acc; 7 | }, {}); 8 | 9 | const mapObject = (target, transformKey, transformValue) => 10 | Object.keys(target).reduce((acc, key) => { 11 | const newKey = transformKey ? transformKey(key) : key; 12 | const newValue = transformValue ? transformValue(target[key]) : target[key]; 13 | return { ...acc, [newKey]: newValue }; 14 | }, {}); 15 | 16 | const onlyRoutes = routes => 17 | filterObject(routes, key => key.indexOf('/') === 0); 18 | 19 | const withoutRoutes = routes => 20 | filterObject(routes, key => key.indexOf('/') !== 0); 21 | 22 | const flattenRoutes = (routes: Object, acc: Object = {}) => { 23 | Object.keys(routes).forEach(key => { 24 | const baseRoute = key === '/' ? '' : key; 25 | flattenRoutes( 26 | mapObject( 27 | onlyRoutes(routes[key]), 28 | routeKey => `${baseRoute}${routeKey}`, 29 | routeValue => ({ 30 | ...routeValue, 31 | parent: { 32 | ...withoutRoutes(routes[key]), 33 | route: key 34 | } 35 | }) 36 | ), 37 | acc 38 | ); 39 | }); 40 | 41 | assign(acc, mapObject(routes, null, withoutRoutes)); 42 | 43 | return acc; 44 | }; 45 | 46 | export default flattenRoutes; 47 | -------------------------------------------------------------------------------- /test/test-util/fixtures/routes.js: -------------------------------------------------------------------------------- 1 | import flattenRoutes from '../../../src/util/flatten-routes'; 2 | 3 | export default flattenRoutes({ 4 | '/home': { 5 | name: 'home' 6 | }, 7 | '/home/messages': { 8 | name: 'messages' 9 | }, 10 | '/home/messages/:team': { 11 | name: 'team' 12 | }, 13 | '/home/messages/:team/:channel': { 14 | name: 'channel' 15 | }, 16 | '/home/:spookyparam': { 17 | name: '3spooky5me' 18 | }, 19 | '/': { 20 | '/oh': { 21 | name: 'oh', 22 | '/hai': { 23 | name: 'hai', 24 | '/:mark': { 25 | '/mark': { 26 | name: 'mark' 27 | } 28 | } 29 | } 30 | }, 31 | '/this': { 32 | name: 'this', 33 | '/is': { 34 | name: 'is', 35 | '/nested': { 36 | name: 'nested', 37 | '/:times': { 38 | '/times': { 39 | name: 'times' 40 | } 41 | } 42 | } 43 | } 44 | }, 45 | '/cheese': { 46 | '/gifs': {}, 47 | '/:type': {} 48 | }, 49 | '/dog': { 50 | '/gifs': {}, 51 | '/:type': {} 52 | }, 53 | '/cat': { 54 | '/gifs': {}, 55 | '/:type': {} 56 | }, 57 | '/hipster': { 58 | '/gifs': {}, 59 | '/:type': {} 60 | }, 61 | '/foo': { 62 | '/bar': { 63 | '/you': { 64 | '/again': {} 65 | }, 66 | '/me': {} 67 | } 68 | } 69 | } 70 | }); 71 | -------------------------------------------------------------------------------- /flow-typed/npm/prop-types_v15.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 3eaa1f24c7397b78a7481992d2cddcb2 2 | // flow-typed version: a1a20d4928/prop-types_v15.x.x/flow_>=v0.41.x 3 | 4 | type $npm$propTypes$ReactPropsCheckType = ( 5 | props: any, 6 | propName: string, 7 | componentName: string, 8 | href?: string) => ?Error; 9 | 10 | declare module 'prop-types' { 11 | declare var array: React$PropType$Primitive>; 12 | declare var bool: React$PropType$Primitive; 13 | declare var func: React$PropType$Primitive; 14 | declare var number: React$PropType$Primitive; 15 | declare var object: React$PropType$Primitive; 16 | declare var string: React$PropType$Primitive; 17 | declare var any: React$PropType$Primitive; 18 | declare var arrayOf: React$PropType$ArrayOf; 19 | declare var element: React$PropType$Primitive; /* TODO */ 20 | declare var instanceOf: React$PropType$InstanceOf; 21 | declare var node: React$PropType$Primitive; /* TODO */ 22 | declare var objectOf: React$PropType$ObjectOf; 23 | declare var oneOf: React$PropType$OneOf; 24 | declare var oneOfType: React$PropType$OneOfType; 25 | declare var shape: React$PropType$Shape; 26 | 27 | declare function checkPropTypes( 28 | propTypes: $Subtype<{[_: $Keys]: $npm$propTypes$ReactPropsCheckType}>, 29 | values: V, 30 | location: string, 31 | componentName: string, 32 | getStack: ?(() => ?string) 33 | ) : void; 34 | } 35 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-register_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6c92f3e751c3ea9af5b7dcf7fde34d46 2 | // flow-typed version: <>/babel-register_v^6.14.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-register' 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-register' { 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-register/lib/browser' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'babel-register/lib/cache' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'babel-register/lib/node' { 34 | declare module.exports: any; 35 | } 36 | 37 | // Filename aliases 38 | declare module 'babel-register/lib/browser.js' { 39 | declare module.exports: $Exports<'babel-register/lib/browser'>; 40 | } 41 | declare module 'babel-register/lib/cache.js' { 42 | declare module.exports: $Exports<'babel-register/lib/cache'>; 43 | } 44 | declare module 'babel-register/lib/node.js' { 45 | declare module.exports: $Exports<'babel-register/lib/node'>; 46 | } 47 | -------------------------------------------------------------------------------- /flow-typed/npm/postcss-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: d5f64c5c4cf99e729755e903701c1c51 2 | // flow-typed version: <>/postcss-loader_v^2.0.6/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'postcss-loader' 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 'postcss-loader' { 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 'postcss-loader/lib/Error' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'postcss-loader/lib/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'postcss-loader/lib/options' { 34 | declare module.exports: any; 35 | } 36 | 37 | // Filename aliases 38 | declare module 'postcss-loader/lib/Error.js' { 39 | declare module.exports: $Exports<'postcss-loader/lib/Error'>; 40 | } 41 | declare module 'postcss-loader/lib/index.js' { 42 | declare module.exports: $Exports<'postcss-loader/lib/index'>; 43 | } 44 | declare module 'postcss-loader/lib/options.js' { 45 | declare module.exports: $Exports<'postcss-loader/lib/options'>; 46 | } 47 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { 3 | LOCATION_CHANGED, 4 | PUSH, 5 | REPLACE, 6 | GO, 7 | GO_BACK, 8 | GO_FORWARD, 9 | POP, 10 | BLOCK, 11 | UNBLOCK, 12 | REPLACE_ROUTES, 13 | DID_REPLACE_ROUTES 14 | } from './types'; 15 | 16 | import { 17 | push, 18 | replace, 19 | go, 20 | goBack, 21 | goForward, 22 | block, 23 | unblock, 24 | replaceRoutes, 25 | initializeCurrentLocation 26 | } from './actions'; 27 | 28 | import routerForBrowser from './environment/browser-router'; 29 | import routerForHash from './environment/hash-router'; 30 | import routerForExpress from './environment/express-router'; 31 | import routerForHapi from './environment/hapi-router'; 32 | 33 | import { Link, PersistentQueryLink } from './components/link'; 34 | import Fragment from './components/fragment'; 35 | 36 | export { 37 | // High-level Redux API 38 | routerForBrowser, 39 | routerForExpress, 40 | routerForHapi, 41 | routerForHash, 42 | initializeCurrentLocation, 43 | // React API 44 | Link, 45 | PersistentQueryLink, 46 | Fragment, 47 | // Public action creators 48 | push, 49 | replace, 50 | go, 51 | goBack, 52 | goForward, 53 | block, 54 | unblock, 55 | replaceRoutes, 56 | // Public action types 57 | LOCATION_CHANGED, 58 | PUSH, 59 | REPLACE, 60 | GO, 61 | GO_FORWARD, 62 | GO_BACK, 63 | POP, 64 | BLOCK, 65 | UNBLOCK, 66 | REPLACE_ROUTES, 67 | DID_REPLACE_ROUTES 68 | }; 69 | 70 | export type { 71 | Query, 72 | Params, 73 | LocationOptions, 74 | Location, 75 | State, 76 | Href, 77 | BareAction, 78 | IndexedAction, 79 | LocationAction, 80 | RouterAction 81 | } from './types'; 82 | -------------------------------------------------------------------------------- /flow-typed/npm/postcss-reporter_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 91299911860ad8ee2024b8c931b26877 2 | // flow-typed version: <>/postcss-reporter_v^4.0.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'postcss-reporter' 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 'postcss-reporter' { 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 'postcss-reporter/lib/formatter' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'postcss-reporter/lib/reporter' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'postcss-reporter/lib/util' { 34 | declare module.exports: any; 35 | } 36 | 37 | // Filename aliases 38 | declare module 'postcss-reporter/index' { 39 | declare module.exports: $Exports<'postcss-reporter'>; 40 | } 41 | declare module 'postcss-reporter/index.js' { 42 | declare module.exports: $Exports<'postcss-reporter'>; 43 | } 44 | declare module 'postcss-reporter/lib/formatter.js' { 45 | declare module.exports: $Exports<'postcss-reporter/lib/formatter'>; 46 | } 47 | declare module 'postcss-reporter/lib/reporter.js' { 48 | declare module.exports: $Exports<'postcss-reporter/lib/reporter'>; 49 | } 50 | declare module 'postcss-reporter/lib/util.js' { 51 | declare module.exports: $Exports<'postcss-reporter/lib/util'>; 52 | } 53 | -------------------------------------------------------------------------------- /src/actions.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { BlockCallback } from 'history'; 3 | import type { Location, LocationOptions, Href } from './types'; 4 | 5 | import { 6 | PUSH, 7 | REPLACE, 8 | GO, 9 | GO_BACK, 10 | GO_FORWARD, 11 | BLOCK, 12 | UNBLOCK, 13 | LOCATION_CHANGED, 14 | REPLACE_ROUTES, 15 | DID_REPLACE_ROUTES 16 | } from './types'; 17 | 18 | import normalizeHref from './util/normalize-href'; 19 | import flattenRoutes from './util/flatten-routes'; 20 | 21 | export const push = (href: Href, options: LocationOptions = {}) => ({ 22 | type: PUSH, 23 | payload: { ...normalizeHref(href), options } 24 | }); 25 | 26 | export const replace = (href: Href, options: LocationOptions = {}) => ({ 27 | type: REPLACE, 28 | payload: { ...normalizeHref(href), options } 29 | }); 30 | 31 | export const go = (index: number) => ({ 32 | type: GO, 33 | payload: index 34 | }); 35 | 36 | export const goBack = () => ({ type: GO_BACK }); 37 | export const goForward = () => ({ type: GO_FORWARD }); 38 | 39 | export const block = (historyShouldBlock: BlockCallback) => ({ 40 | type: BLOCK, 41 | payload: historyShouldBlock 42 | }); 43 | 44 | export const unblock = () => ({ type: UNBLOCK }); 45 | 46 | export const locationDidChange = (location: Location) => ({ 47 | type: LOCATION_CHANGED, 48 | payload: location 49 | }); 50 | 51 | export const initializeCurrentLocation = (location: Location) => ({ 52 | type: LOCATION_CHANGED, 53 | payload: location 54 | }); 55 | 56 | export const replaceRoutes = (routes: Object) => ({ 57 | type: REPLACE_ROUTES, 58 | payload: { 59 | routes: flattenRoutes(routes), 60 | options: { 61 | updateRoutes: true 62 | } 63 | } 64 | }); 65 | 66 | export const didReplaceRoutes = () => ({ 67 | type: DID_REPLACE_ROUTES 68 | }); 69 | -------------------------------------------------------------------------------- /flow-typed/npm/flow-copy-source_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 4b2652e2d41df508719d668712a0bd66 2 | // flow-typed version: <>/flow-copy-source_v^1.2.1/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'flow-copy-source' 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 'flow-copy-source' { 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 'flow-copy-source/bin/flow-copy-source' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'flow-copy-source/src/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'flow-copy-source/src/kefir-copy-file' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'flow-copy-source/src/kefir-glob' { 38 | declare module.exports: any; 39 | } 40 | 41 | // Filename aliases 42 | declare module 'flow-copy-source/bin/flow-copy-source.js' { 43 | declare module.exports: $Exports<'flow-copy-source/bin/flow-copy-source'>; 44 | } 45 | declare module 'flow-copy-source/src/index.js' { 46 | declare module.exports: $Exports<'flow-copy-source/src/index'>; 47 | } 48 | declare module 'flow-copy-source/src/kefir-copy-file.js' { 49 | declare module.exports: $Exports<'flow-copy-source/src/kefir-copy-file'>; 50 | } 51 | declare module 'flow-copy-source/src/kefir-glob.js' { 52 | declare module.exports: $Exports<'flow-copy-source/src/kefir-glob'>; 53 | } 54 | -------------------------------------------------------------------------------- /flow-typed/npm/watch_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a9d9d851c89ef870d2a8067dda9b1400 2 | // flow-typed version: <>/watch_v^1.0.2/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'watch' 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 'watch' { 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 'watch/cli' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'watch/main' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'watch/test/test_monitor' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'watch/test/test_monitorRootDirectory' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'watch/test/test_watchTree' { 42 | declare module.exports: any; 43 | } 44 | 45 | // Filename aliases 46 | declare module 'watch/cli.js' { 47 | declare module.exports: $Exports<'watch/cli'>; 48 | } 49 | declare module 'watch/main.js' { 50 | declare module.exports: $Exports<'watch/main'>; 51 | } 52 | declare module 'watch/test/test_monitor.js' { 53 | declare module.exports: $Exports<'watch/test/test_monitor'>; 54 | } 55 | declare module 'watch/test/test_monitorRootDirectory.js' { 56 | declare module.exports: $Exports<'watch/test/test_monitorRootDirectory'>; 57 | } 58 | declare module 'watch/test/test_watchTree.js' { 59 | declare module.exports: $Exports<'watch/test/test_watchTree'>; 60 | } 61 | -------------------------------------------------------------------------------- /flow-typed/npm/webpack-dev-middleware_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 790c8e138337bda7913661972a6e5acf 2 | // flow-typed version: <>/webpack-dev-middleware_v^1.7.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'webpack-dev-middleware' 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 'webpack-dev-middleware' { 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 'webpack-dev-middleware/lib/GetFilenameFromUrl' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'webpack-dev-middleware/lib/PathJoin' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'webpack-dev-middleware/lib/Shared' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'webpack-dev-middleware/middleware' { 38 | declare module.exports: any; 39 | } 40 | 41 | // Filename aliases 42 | declare module 'webpack-dev-middleware/lib/GetFilenameFromUrl.js' { 43 | declare module.exports: $Exports<'webpack-dev-middleware/lib/GetFilenameFromUrl'>; 44 | } 45 | declare module 'webpack-dev-middleware/lib/PathJoin.js' { 46 | declare module.exports: $Exports<'webpack-dev-middleware/lib/PathJoin'>; 47 | } 48 | declare module 'webpack-dev-middleware/lib/Shared.js' { 49 | declare module.exports: $Exports<'webpack-dev-middleware/lib/Shared'>; 50 | } 51 | declare module 'webpack-dev-middleware/middleware.js' { 52 | declare module.exports: $Exports<'webpack-dev-middleware/middleware'>; 53 | } 54 | -------------------------------------------------------------------------------- /config/webpack/partials/css-modules.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const _ = require('lodash'); 4 | const path = require('path'); 5 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 6 | const loader = require('webpack-partial/loader').default; 7 | const plugin = require('webpack-partial/plugin').default; 8 | 9 | module.exports = function(opts) { 10 | opts = _.defaults(opts, { 11 | production: false, 12 | cssOpts: {} 13 | }); 14 | 15 | return _.flow( 16 | loader({ 17 | test: /\.(css)$/, 18 | use: ExtractTextPlugin.extract({ 19 | fallback: require.resolve('style-loader'), 20 | use: [ 21 | { 22 | loader: require.resolve('css-loader'), 23 | options: _.assign( 24 | { 25 | autoprefixer: false, 26 | mergeRules: false, // disable or keyframes break 27 | modules: true, 28 | sourceMap: true, 29 | importLoaders: 1, 30 | localIdentName: '[local]___[hash:base64:5]', 31 | context: 'src' 32 | }, 33 | opts.cssOpts 34 | ) 35 | }, 36 | { 37 | loader: require.resolve('postcss-loader'), 38 | options: { 39 | sourceMap: true, 40 | config: { 41 | path: path.resolve(__dirname, '../postcss.config.js') 42 | } 43 | } 44 | } 45 | ] 46 | }) 47 | }), 48 | plugin( 49 | // Hashes in CSS file names make the dev server choke. 50 | // Only enable hashes in production! 51 | new ExtractTextPlugin( 52 | _.assign( 53 | { 54 | filename: `[name]${opts.production ? '.[hash]' : ''}.css` 55 | }, 56 | opts.extractTextPlugin 57 | ) 58 | ) 59 | ) 60 | ); 61 | }; 62 | -------------------------------------------------------------------------------- /flow-typed/npm/redux-thunk_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: e2ddd43355d9ec399ffd62338f31d282 2 | // flow-typed version: <>/redux-thunk_v^2.2.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'redux-thunk' 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 'redux-thunk' { 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 'redux-thunk/dist/redux-thunk' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'redux-thunk/dist/redux-thunk.min' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'redux-thunk/es/index' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'redux-thunk/lib/index' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'redux-thunk/src/index' { 42 | declare module.exports: any; 43 | } 44 | 45 | // Filename aliases 46 | declare module 'redux-thunk/dist/redux-thunk.js' { 47 | declare module.exports: $Exports<'redux-thunk/dist/redux-thunk'>; 48 | } 49 | declare module 'redux-thunk/dist/redux-thunk.min.js' { 50 | declare module.exports: $Exports<'redux-thunk/dist/redux-thunk.min'>; 51 | } 52 | declare module 'redux-thunk/es/index.js' { 53 | declare module.exports: $Exports<'redux-thunk/es/index'>; 54 | } 55 | declare module 'redux-thunk/lib/index.js' { 56 | declare module.exports: $Exports<'redux-thunk/lib/index'>; 57 | } 58 | declare module 'redux-thunk/src/index.js' { 59 | declare module.exports: $Exports<'redux-thunk/src/index'>; 60 | } 61 | -------------------------------------------------------------------------------- /flow-typed/npm/extract-text-webpack-plugin_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6b27d1cd87c9eafff1f79afca75589b9 2 | // flow-typed version: <>/extract-text-webpack-plugin_v^2.1.2/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'extract-text-webpack-plugin' 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 'extract-text-webpack-plugin' { 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 'extract-text-webpack-plugin/ExtractedModule' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'extract-text-webpack-plugin/loader' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'extract-text-webpack-plugin/OrderUndefinedError' { 34 | declare module.exports: any; 35 | } 36 | 37 | // Filename aliases 38 | declare module 'extract-text-webpack-plugin/ExtractedModule.js' { 39 | declare module.exports: $Exports<'extract-text-webpack-plugin/ExtractedModule'>; 40 | } 41 | declare module 'extract-text-webpack-plugin/index' { 42 | declare module.exports: $Exports<'extract-text-webpack-plugin'>; 43 | } 44 | declare module 'extract-text-webpack-plugin/index.js' { 45 | declare module.exports: $Exports<'extract-text-webpack-plugin'>; 46 | } 47 | declare module 'extract-text-webpack-plugin/loader.js' { 48 | declare module.exports: $Exports<'extract-text-webpack-plugin/loader'>; 49 | } 50 | declare module 'extract-text-webpack-plugin/OrderUndefinedError.js' { 51 | declare module.exports: $Exports<'extract-text-webpack-plugin/OrderUndefinedError'>; 52 | } 53 | -------------------------------------------------------------------------------- /flow-typed/npm/webpack-merge_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 2bbec8c988e23fff93e67ee8bc87eb6b 2 | // flow-typed version: <>/webpack-merge_v^4.1.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'webpack-merge' 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 'webpack-merge' { 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 'webpack-merge/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'webpack-merge/lib/join-arrays-smart' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'webpack-merge/lib/join-arrays' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'webpack-merge/lib/unique' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'webpack-merge/lib/unite-rules' { 42 | declare module.exports: any; 43 | } 44 | 45 | // Filename aliases 46 | declare module 'webpack-merge/lib/index.js' { 47 | declare module.exports: $Exports<'webpack-merge/lib/index'>; 48 | } 49 | declare module 'webpack-merge/lib/join-arrays-smart.js' { 50 | declare module.exports: $Exports<'webpack-merge/lib/join-arrays-smart'>; 51 | } 52 | declare module 'webpack-merge/lib/join-arrays.js' { 53 | declare module.exports: $Exports<'webpack-merge/lib/join-arrays'>; 54 | } 55 | declare module 'webpack-merge/lib/unique.js' { 56 | declare module.exports: $Exports<'webpack-merge/lib/unique'>; 57 | } 58 | declare module 'webpack-merge/lib/unite-rules.js' { 59 | declare module.exports: $Exports<'webpack-merge/lib/unite-rules'>; 60 | } 61 | -------------------------------------------------------------------------------- /test/util/create-matcher.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import createMatcher from '../../src/util/create-matcher'; 3 | 4 | import routes from '../test-util/fixtures/routes'; 5 | describe('createMatcher', () => { 6 | it('matches URLs and returns both their params and their value in the route hash', () => { 7 | const matchRoute = createMatcher(routes); 8 | 9 | expect(matchRoute('/home')).to.deep.equal({ 10 | route: '/home', 11 | params: {}, 12 | result: { 13 | name: 'home' 14 | } 15 | }); 16 | 17 | expect(matchRoute('/home/messages')).to.deep.equal({ 18 | route: '/home/messages', 19 | params: {}, 20 | result: { 21 | name: 'messages' 22 | } 23 | }); 24 | 25 | expect(matchRoute('/home/messages/')).to.deep.equal({ 26 | route: '/home/messages', 27 | params: {}, 28 | result: { 29 | name: 'messages' 30 | } 31 | }); 32 | 33 | expect(matchRoute('/home/messages/a-team')).to.deep.equal({ 34 | route: '/home/messages/:team', 35 | params: { 36 | team: 'a-team' 37 | }, 38 | result: { 39 | name: 'team' 40 | } 41 | }); 42 | 43 | expect(matchRoute('/home/messages/a-team/')).to.deep.equal({ 44 | route: '/home/messages/:team', 45 | params: { 46 | team: 'a-team' 47 | }, 48 | result: { 49 | name: 'team' 50 | } 51 | }); 52 | 53 | expect(matchRoute('/home/messages/a-team/the-wat-channel')).to.deep.equal({ 54 | route: '/home/messages/:team/:channel', 55 | params: { 56 | team: 'a-team', 57 | channel: 'the-wat-channel' 58 | }, 59 | result: { 60 | name: 'channel' 61 | } 62 | }); 63 | 64 | expect(matchRoute('/home/doot')).to.deep.equal({ 65 | route: '/home/:spookyparam', 66 | params: { 67 | spookyparam: 'doot' 68 | }, 69 | result: { 70 | name: '3spooky5me' 71 | } 72 | }); 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /test/environment/hapi-router.spec.js: -------------------------------------------------------------------------------- 1 | import chai, { expect } from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | import { fromJS } from 'immutable'; 5 | import { combineReducers as combineReduxReducers } from 'redux'; 6 | import { combineReducers as combineImmutableReducers } from 'redux-immutable'; 7 | 8 | import routerForHapi from '../../src/environment/hapi-router'; 9 | import immutableRouterForHapi from '../../src/immutable/environment/hapi-router'; 10 | 11 | import { setupStoreForEnv } from '../test-util'; 12 | import routes from '../test-util/fixtures/routes'; 13 | 14 | chai.use(sinonChai); 15 | 16 | const hapiRouterTest = { 17 | router: routerForHapi, 18 | combineReducers: combineReduxReducers, 19 | toState: state => state, 20 | readState: state => state, 21 | testLabel: 'hapi router' 22 | }; 23 | const immutableHapiRouterTest = { 24 | router: immutableRouterForHapi, 25 | combineReducers: combineImmutableReducers, 26 | toState: state => fromJS(state), 27 | readState: state => state.toJS(), 28 | testLabel: 'immutable hapi router' 29 | }; 30 | 31 | [hapiRouterTest, immutableHapiRouterTest].forEach( 32 | ({ router, combineReducers, toState, readState, testLabel }) => { 33 | describe(`${testLabel}`, () => { 34 | const setupHapiStore = setupStoreForEnv( 35 | router, 36 | combineReducers, 37 | toState({}) 38 | ); 39 | 40 | it('creates a server store enhancer using Hapi request object', () => { 41 | const store = setupHapiStore({ 42 | routes, 43 | request: { 44 | path: '/home', 45 | query: { get: 'schwifty' } 46 | } 47 | }); 48 | 49 | const state = readState(store.getState()); 50 | expect(state).to.have.nested.property('router.pathname', '/home'); 51 | expect(state).to.have.nested.property('router.search', '?get=schwifty'); 52 | expect(state) 53 | .to.have.nested.property('router.query') 54 | .that.deep.equals({ get: 'schwifty' }); 55 | }); 56 | }); 57 | } 58 | ); 59 | -------------------------------------------------------------------------------- /flow-typed/npm/ent_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 29f853d03c6356162e24fec4559b6a87 2 | // flow-typed version: <>/ent_v^2.2.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'ent' 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 'ent' { 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 'ent/decode' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'ent/encode' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'ent/examples/simple' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'ent/test/codes' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'ent/test/hex' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'ent/test/num' { 46 | declare module.exports: any; 47 | } 48 | 49 | // Filename aliases 50 | declare module 'ent/decode.js' { 51 | declare module.exports: $Exports<'ent/decode'>; 52 | } 53 | declare module 'ent/encode.js' { 54 | declare module.exports: $Exports<'ent/encode'>; 55 | } 56 | declare module 'ent/examples/simple.js' { 57 | declare module.exports: $Exports<'ent/examples/simple'>; 58 | } 59 | declare module 'ent/index' { 60 | declare module.exports: $Exports<'ent'>; 61 | } 62 | declare module 'ent/index.js' { 63 | declare module.exports: $Exports<'ent'>; 64 | } 65 | declare module 'ent/test/codes.js' { 66 | declare module.exports: $Exports<'ent/test/codes'>; 67 | } 68 | declare module 'ent/test/hex.js' { 69 | declare module.exports: $Exports<'ent/test/hex'>; 70 | } 71 | declare module 'ent/test/num.js' { 72 | declare module.exports: $Exports<'ent/test/num'>; 73 | } 74 | -------------------------------------------------------------------------------- /flow-typed/npm/style-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 485f2251ae60c8c27bf0e32ab4ec727d 2 | // flow-typed version: <>/style-loader_v^0.18.2/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'style-loader' 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 'style-loader' { 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 'style-loader/lib/addStyles' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'style-loader/lib/addStyleUrl' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'style-loader/lib/urls' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'style-loader/url' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'style-loader/useable' { 42 | declare module.exports: any; 43 | } 44 | 45 | // Filename aliases 46 | declare module 'style-loader/index' { 47 | declare module.exports: $Exports<'style-loader'>; 48 | } 49 | declare module 'style-loader/index.js' { 50 | declare module.exports: $Exports<'style-loader'>; 51 | } 52 | declare module 'style-loader/lib/addStyles.js' { 53 | declare module.exports: $Exports<'style-loader/lib/addStyles'>; 54 | } 55 | declare module 'style-loader/lib/addStyleUrl.js' { 56 | declare module.exports: $Exports<'style-loader/lib/addStyleUrl'>; 57 | } 58 | declare module 'style-loader/lib/urls.js' { 59 | declare module.exports: $Exports<'style-loader/lib/urls'>; 60 | } 61 | declare module 'style-loader/url.js' { 62 | declare module.exports: $Exports<'style-loader/url'>; 63 | } 64 | declare module 'style-loader/useable.js' { 65 | declare module.exports: $Exports<'style-loader/useable'>; 66 | } 67 | -------------------------------------------------------------------------------- /flow-typed/npm/redux-logger_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 9630f344c33a3364828599e53267cefa 2 | // flow-typed version: <>/redux-logger_v^3.0.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'redux-logger' 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 'redux-logger' { 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 'redux-logger/dist/redux-logger' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'redux-logger/src/core' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'redux-logger/src/defaults' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'redux-logger/src/diff' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'redux-logger/src/helpers' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'redux-logger/src/index' { 46 | declare module.exports: any; 47 | } 48 | 49 | // Filename aliases 50 | declare module 'redux-logger/dist/redux-logger.js' { 51 | declare module.exports: $Exports<'redux-logger/dist/redux-logger'>; 52 | } 53 | declare module 'redux-logger/src/core.js' { 54 | declare module.exports: $Exports<'redux-logger/src/core'>; 55 | } 56 | declare module 'redux-logger/src/defaults.js' { 57 | declare module.exports: $Exports<'redux-logger/src/defaults'>; 58 | } 59 | declare module 'redux-logger/src/diff.js' { 60 | declare module.exports: $Exports<'redux-logger/src/diff'>; 61 | } 62 | declare module 'redux-logger/src/helpers.js' { 63 | declare module.exports: $Exports<'redux-logger/src/helpers'>; 64 | } 65 | declare module 'redux-logger/src/index.js' { 66 | declare module.exports: $Exports<'redux-logger/src/index'>; 67 | } 68 | -------------------------------------------------------------------------------- /flow-typed/npm/css-modules-require-hook_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 59381860bad5d963bf94297d26649617 2 | // flow-typed version: <>/css-modules-require-hook_v^4.0.2/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'css-modules-require-hook' 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 'css-modules-require-hook' { 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 'css-modules-require-hook/lib/attachHook' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'css-modules-require-hook/lib/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'css-modules-require-hook/lib/transformTokens' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'css-modules-require-hook/lib/validate' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'css-modules-require-hook/preset' { 42 | declare module.exports: any; 43 | } 44 | 45 | // Filename aliases 46 | declare module 'css-modules-require-hook/lib/attachHook.js' { 47 | declare module.exports: $Exports<'css-modules-require-hook/lib/attachHook'>; 48 | } 49 | declare module 'css-modules-require-hook/lib/index.js' { 50 | declare module.exports: $Exports<'css-modules-require-hook/lib/index'>; 51 | } 52 | declare module 'css-modules-require-hook/lib/transformTokens.js' { 53 | declare module.exports: $Exports<'css-modules-require-hook/lib/transformTokens'>; 54 | } 55 | declare module 'css-modules-require-hook/lib/validate.js' { 56 | declare module.exports: $Exports<'css-modules-require-hook/lib/validate'>; 57 | } 58 | declare module 'css-modules-require-hook/preset.js' { 59 | declare module.exports: $Exports<'css-modules-require-hook/preset'>; 60 | } 61 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a6ba447e55dd9fd99301b3ef2bbc42bc 2 | // flow-typed version: <>/babel-loader_v^7.1.1/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-loader' 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-loader' { 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-loader/lib/fs-cache' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'babel-loader/lib/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'babel-loader/lib/resolve-rc' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'babel-loader/lib/utils/exists' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'babel-loader/lib/utils/read' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'babel-loader/lib/utils/relative' { 46 | declare module.exports: any; 47 | } 48 | 49 | // Filename aliases 50 | declare module 'babel-loader/lib/fs-cache.js' { 51 | declare module.exports: $Exports<'babel-loader/lib/fs-cache'>; 52 | } 53 | declare module 'babel-loader/lib/index.js' { 54 | declare module.exports: $Exports<'babel-loader/lib/index'>; 55 | } 56 | declare module 'babel-loader/lib/resolve-rc.js' { 57 | declare module.exports: $Exports<'babel-loader/lib/resolve-rc'>; 58 | } 59 | declare module 'babel-loader/lib/utils/exists.js' { 60 | declare module.exports: $Exports<'babel-loader/lib/utils/exists'>; 61 | } 62 | declare module 'babel-loader/lib/utils/read.js' { 63 | declare module.exports: $Exports<'babel-loader/lib/utils/read'>; 64 | } 65 | declare module 'babel-loader/lib/utils/relative.js' { 66 | declare module.exports: $Exports<'babel-loader/lib/utils/relative'>; 67 | } 68 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-polyfill_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 8644411ce2efd413a83482df63ae608a 2 | // flow-typed version: <>/babel-polyfill_v^6.23.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-polyfill' 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-polyfill' { 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-polyfill/browser' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'babel-polyfill/dist/polyfill' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'babel-polyfill/dist/polyfill.min' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'babel-polyfill/lib/index' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'babel-polyfill/scripts/postpublish' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'babel-polyfill/scripts/prepublish' { 46 | declare module.exports: any; 47 | } 48 | 49 | // Filename aliases 50 | declare module 'babel-polyfill/browser.js' { 51 | declare module.exports: $Exports<'babel-polyfill/browser'>; 52 | } 53 | declare module 'babel-polyfill/dist/polyfill.js' { 54 | declare module.exports: $Exports<'babel-polyfill/dist/polyfill'>; 55 | } 56 | declare module 'babel-polyfill/dist/polyfill.min.js' { 57 | declare module.exports: $Exports<'babel-polyfill/dist/polyfill.min'>; 58 | } 59 | declare module 'babel-polyfill/lib/index.js' { 60 | declare module.exports: $Exports<'babel-polyfill/lib/index'>; 61 | } 62 | declare module 'babel-polyfill/scripts/postpublish.js' { 63 | declare module.exports: $Exports<'babel-polyfill/scripts/postpublish'>; 64 | } 65 | declare module 'babel-polyfill/scripts/prepublish.js' { 66 | declare module.exports: $Exports<'babel-polyfill/scripts/prepublish'>; 67 | } 68 | -------------------------------------------------------------------------------- /demo/client/app.js: -------------------------------------------------------------------------------- 1 | import 'normalize.css/normalize.css'; 2 | import './global.css'; 3 | 4 | import { render } from 'react-dom'; 5 | 6 | /* Invert comments for immutable */ 7 | import { createStore, combineReducers, compose, applyMiddleware } from 'redux'; 8 | import { 9 | routerForBrowser, 10 | initializeCurrentLocation, 11 | block, 12 | unblock 13 | } from '../../src'; 14 | // import { createStore, compose, applyMiddleware } from 'redux'; 15 | // import { combineReducers } from 'redux-immutable'; 16 | // import { Map, fromJS } from 'immutable'; 17 | // import { immutableRouterForBrowser } from '../../src/immutable'; 18 | // import { initializeCurrentLocation } from '../../src'; 19 | 20 | import routes from './routes'; 21 | import wrap from './wrap'; 22 | import Demo from './demo'; 23 | 24 | const UNBLOCK_DELAY = 10000; 25 | 26 | /* Invert comments for immutable */ 27 | const { reducer, enhancer, middleware } = routerForBrowser({ routes }); 28 | const initialState = window.__INITIAL_STATE || {}; 29 | // const { reducer, enhancer, middleware } = immutableRouterForBrowser({ routes }); 30 | // const initialState = window.__INITIAL_STATE ? fromJS(window.__INITIAL_STATE) : Map(); 31 | 32 | const store = createStore( 33 | combineReducers({ router: reducer }), 34 | // If this is a server render, we grab the 35 | // initial state the hbs template inserted 36 | initialState, 37 | compose( 38 | enhancer, 39 | applyMiddleware(middleware), 40 | window.devToolsExtension ? window.devToolsExtension() : f => f 41 | ) 42 | ); 43 | 44 | /* Invert comments for immutable */ 45 | const initialLocation = store.getState().router; 46 | // const initialLocation = store.getState().get('router').toJS(); 47 | 48 | store.dispatch( 49 | // eslint-disable-next-line consistent-return 50 | block(() => { 51 | if (location.pathname.indexOf('cheese') !== -1) { 52 | return `Are you sure you want to see other pages? It's really all downhill from here.`; 53 | } 54 | }) 55 | ); 56 | 57 | setTimeout(() => store.dispatch(unblock()), UNBLOCK_DELAY); 58 | 59 | if (initialLocation) { 60 | store.dispatch(initializeCurrentLocation(initialLocation)); 61 | } 62 | 63 | render(wrap(store)(Demo), document.getElementById('content')); 64 | -------------------------------------------------------------------------------- /flow-typed/npm/postcss-import_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a9cfb7eb1dd1f49843b05312aed1c490 2 | // flow-typed version: <>/postcss-import_v^10.0.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'postcss-import' 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 'postcss-import' { 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 'postcss-import/lib/join-media' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'postcss-import/lib/load-content' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'postcss-import/lib/parse-statements' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'postcss-import/lib/process-content' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'postcss-import/lib/resolve-id' { 42 | declare module.exports: any; 43 | } 44 | 45 | // Filename aliases 46 | declare module 'postcss-import/index' { 47 | declare module.exports: $Exports<'postcss-import'>; 48 | } 49 | declare module 'postcss-import/index.js' { 50 | declare module.exports: $Exports<'postcss-import'>; 51 | } 52 | declare module 'postcss-import/lib/join-media.js' { 53 | declare module.exports: $Exports<'postcss-import/lib/join-media'>; 54 | } 55 | declare module 'postcss-import/lib/load-content.js' { 56 | declare module.exports: $Exports<'postcss-import/lib/load-content'>; 57 | } 58 | declare module 'postcss-import/lib/parse-statements.js' { 59 | declare module.exports: $Exports<'postcss-import/lib/parse-statements'>; 60 | } 61 | declare module 'postcss-import/lib/process-content.js' { 62 | declare module.exports: $Exports<'postcss-import/lib/process-content'>; 63 | } 64 | declare module 'postcss-import/lib/resolve-id.js' { 65 | declare module.exports: $Exports<'postcss-import/lib/resolve-id'>; 66 | } 67 | -------------------------------------------------------------------------------- /test/install.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-nested-callbacks */ 2 | import { expect } from 'chai'; 3 | 4 | import installRouter from '../src/install'; 5 | import immutableInstall from '../src/immutable/install'; 6 | 7 | const installTest = { 8 | install: installRouter, 9 | readState: state => state, 10 | testLabel: 'router installer' 11 | }; 12 | const immutableInstallTest = { 13 | install: immutableInstall, 14 | readState: state => state.toJS(), 15 | testLabel: 'immutable router installer' 16 | }; 17 | 18 | [installTest, immutableInstallTest].forEach( 19 | ({ install, readState, testLabel }) => { 20 | describe(`${testLabel}`, () => { 21 | it('appends the match result to the location passed to the reducer factory', () => { 22 | const { reducer } = install({ 23 | routes: { 24 | '/:thing': { 25 | congratulations: 'you played yourself' 26 | } 27 | }, 28 | history: {}, 29 | location: { pathname: '/stuff' } 30 | }); 31 | const state = readState(reducer(undefined, {})); 32 | 33 | expect(state).to.deep.equal({ 34 | pathname: '/stuff', 35 | params: { 36 | thing: 'stuff' 37 | }, 38 | route: '/:thing', 39 | routes: { 40 | '/:thing': { 41 | congratulations: 'you played yourself' 42 | } 43 | }, 44 | result: { 45 | congratulations: 'you played yourself' 46 | }, 47 | queue: [] 48 | }); 49 | }); 50 | 51 | it('throws if no routes are provided', () => { 52 | expect(() => 53 | install({ 54 | routes: {}, 55 | history: {}, 56 | location: {} 57 | }) 58 | ).to.throw(Error); 59 | }); 60 | 61 | it('throws if malformed routes are provided', () => { 62 | expect(() => 63 | install({ 64 | routes: { 65 | jlshdkfjgh: {}, 66 | '/real-route': {}, 67 | w: 'tf' 68 | }, 69 | history: {}, 70 | location: {} 71 | }) 72 | ).to.throw(Error); 73 | }); 74 | }); 75 | } 76 | ); 77 | -------------------------------------------------------------------------------- /flow-typed/npm/eslint-config-prettier_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 929eed01664bae7c956bbf87133deac9 2 | // flow-typed version: <>/eslint-config-prettier_v^2.3.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'eslint-config-prettier' 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-config-prettier' { 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-config-prettier/bin/cli' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'eslint-config-prettier/bin/validators' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'eslint-config-prettier/flowtype' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'eslint-config-prettier/react' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'eslint-config-prettier/standard' { 42 | declare module.exports: any; 43 | } 44 | 45 | // Filename aliases 46 | declare module 'eslint-config-prettier/bin/cli.js' { 47 | declare module.exports: $Exports<'eslint-config-prettier/bin/cli'>; 48 | } 49 | declare module 'eslint-config-prettier/bin/validators.js' { 50 | declare module.exports: $Exports<'eslint-config-prettier/bin/validators'>; 51 | } 52 | declare module 'eslint-config-prettier/flowtype.js' { 53 | declare module.exports: $Exports<'eslint-config-prettier/flowtype'>; 54 | } 55 | declare module 'eslint-config-prettier/index' { 56 | declare module.exports: $Exports<'eslint-config-prettier'>; 57 | } 58 | declare module 'eslint-config-prettier/index.js' { 59 | declare module.exports: $Exports<'eslint-config-prettier'>; 60 | } 61 | declare module 'eslint-config-prettier/react.js' { 62 | declare module.exports: $Exports<'eslint-config-prettier/react'>; 63 | } 64 | declare module 'eslint-config-prettier/standard.js' { 65 | declare module.exports: $Exports<'eslint-config-prettier/standard'>; 66 | } 67 | -------------------------------------------------------------------------------- /src/types.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Location as HistoryLocation, BlockCallback } from 'history'; 3 | 4 | export type Query = { [key: string]: string }; 5 | export type Params = { [key: string]: string }; 6 | 7 | export type LocationOptions = { 8 | persistQuery?: boolean, 9 | updateRoutes?: boolean 10 | }; 11 | 12 | export type Location = $Shape< 13 | HistoryLocation & { 14 | basename?: string, 15 | options?: LocationOptions, 16 | params?: Params, 17 | previous?: Location, 18 | query?: Query, 19 | result?: Object, 20 | routes?: Object, 21 | queue?: Array 22 | } 23 | >; 24 | 25 | export type State = { 26 | router: Location 27 | }; 28 | 29 | export type Href = string | Location; 30 | 31 | export const LOCATION_CHANGED = 'ROUTER_LOCATION_CHANGED'; 32 | export const PUSH = 'ROUTER_PUSH'; 33 | export const REPLACE = 'ROUTER_REPLACE'; 34 | export const GO = 'ROUTER_GO'; 35 | export const GO_BACK = 'ROUTER_GO_BACK'; 36 | export const GO_FORWARD = 'ROUTER_GO_FORWARD'; 37 | export const POP = 'ROUTER_POP'; 38 | export const BLOCK = 'ROUTER_BLOCK'; 39 | export const UNBLOCK = 'ROUTER_UNBLOCK'; 40 | export const REPLACE_ROUTES = 'ROUTER_REPLACE_ROUTES'; 41 | export const DID_REPLACE_ROUTES = 'ROUTER_DID_REPLACE_ROUTES'; 42 | 43 | const actionsWithPayload = [PUSH, REPLACE, GO, POP]; 44 | const actions = [ 45 | ...actionsWithPayload, 46 | GO_FORWARD, 47 | GO_BACK, 48 | POP, 49 | BLOCK, 50 | UNBLOCK 51 | ]; 52 | 53 | export const isNavigationAction = (action: { type: $Subtype }) => 54 | actions.indexOf(action.type) !== -1; 55 | 56 | export const isNavigationActionWithPayload = (action: { 57 | type: $Subtype 58 | }) => actionsWithPayload.indexOf(action.type) !== -1; 59 | 60 | export type BareAction = { 61 | type: 'ROUTER_GO_BACK' | 'ROUTER_GO_FORWARD' | 'ROUTER_UNBLOCK' 62 | }; 63 | 64 | export type FunctionAction = { 65 | type: 'ROUTER_BLOCK', 66 | payload: BlockCallback 67 | }; 68 | 69 | export type IndexedAction = { 70 | type: 'ROUTER_GO', 71 | payload: number 72 | }; 73 | 74 | export type LocationAction = { 75 | type: 'ROUTER_LOCATION_CHANGED' | 'ROUTER_PUSH' | 'ROUTER_REPLACE', 76 | payload: Location 77 | }; 78 | 79 | export type RouterAction = 80 | | BareAction 81 | | FunctionAction 82 | | IndexedAction 83 | | LocationAction; 84 | -------------------------------------------------------------------------------- /flow-typed/npm/react-addons-test-utils_v15.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 7472160d3f2bbd92465a51c99d03752e 2 | // flow-typed version: da30fe6876/react-addons-test-utils_v15.x.x/flow_>=v0.25.x 3 | 4 | import React from "react"; 5 | 6 | declare module "react-addons-test-utils" { 7 | declare var Simulate: { 8 | [eventName: string]: (element: Element, eventData?: Object) => void 9 | }; 10 | declare function renderIntoDocument( 11 | instance: React.Element 12 | ): React.Component; 13 | declare function mockComponent( 14 | componentClass: React.ElementType, 15 | mockTagName?: string 16 | ): Object; 17 | declare function isElement(element: React.Element): boolean; 18 | declare function isElementOfType( 19 | element: React.Element, 20 | componentClass: React.ElementType 21 | ): boolean; 22 | declare function isDOMComponent(instance: React.Component): boolean; 23 | declare function isCompositeComponent(instance: React.Component): boolean; 24 | declare function isCompositeComponentWithType( 25 | instance: React.Component, 26 | componentClass: React.ElementType 27 | ): boolean; 28 | declare function findAllInRenderedTree( 29 | tree: React.Component, 30 | test: (child: React.Component) => boolean 31 | ): Array; 32 | declare function scryRenderedDOMComponentsWithClass( 33 | tree: React.Component, 34 | className: string 35 | ): Array; 36 | declare function findRenderedDOMComponentWithClass( 37 | tree: React.Component, 38 | className: string 39 | ): ?Element; 40 | declare function scryRenderedDOMComponentsWithTag( 41 | tree: React.Component, 42 | tagName: string 43 | ): Array; 44 | declare function findRenderedDOMComponentWithTag( 45 | tree: React.Component, 46 | tagName: string 47 | ): ?Element; 48 | declare function scryRenderedComponentsWithType( 49 | tree: React.Component, 50 | componentClass: React.ElementType 51 | ): Array; 52 | declare function findRenderedComponentWithType( 53 | tree: React.Component, 54 | componentClass: React.ElementType 55 | ): ?React.Component; 56 | declare class ReactShallowRender { 57 | render(element: React.Element): void; 58 | getRenderOutput(): React.Element; 59 | } 60 | declare function createRenderer(): ReactShallowRender; 61 | } 62 | -------------------------------------------------------------------------------- /flow-typed/npm/webpack-partial_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 96768fe1d97facd9629ef8d5b4c229f5 2 | // flow-typed version: <>/webpack-partial_v^2.1.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'webpack-partial' 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 'webpack-partial' { 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 'webpack-partial/alias' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'webpack-partial/entry' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'webpack-partial/loader' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'webpack-partial/output' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'webpack-partial/plugin' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'webpack-partial/root' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'webpack-partial/tap' { 50 | declare module.exports: any; 51 | } 52 | 53 | // Filename aliases 54 | declare module 'webpack-partial/alias.js' { 55 | declare module.exports: $Exports<'webpack-partial/alias'>; 56 | } 57 | declare module 'webpack-partial/entry.js' { 58 | declare module.exports: $Exports<'webpack-partial/entry'>; 59 | } 60 | declare module 'webpack-partial/index' { 61 | declare module.exports: $Exports<'webpack-partial'>; 62 | } 63 | declare module 'webpack-partial/index.js' { 64 | declare module.exports: $Exports<'webpack-partial'>; 65 | } 66 | declare module 'webpack-partial/loader.js' { 67 | declare module.exports: $Exports<'webpack-partial/loader'>; 68 | } 69 | declare module 'webpack-partial/output.js' { 70 | declare module.exports: $Exports<'webpack-partial/output'>; 71 | } 72 | declare module 'webpack-partial/plugin.js' { 73 | declare module.exports: $Exports<'webpack-partial/plugin'>; 74 | } 75 | declare module 'webpack-partial/root.js' { 76 | declare module.exports: $Exports<'webpack-partial/root'>; 77 | } 78 | declare module 'webpack-partial/tap.js' { 79 | declare module.exports: $Exports<'webpack-partial/tap'>; 80 | } 81 | -------------------------------------------------------------------------------- /src/middleware.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /* eslint-disable consistent-return */ 3 | import type { History } from 'history'; 4 | import type { Dispatch, Store } from 'redux'; 5 | import type { RouterAction, Query, State } from './types'; 6 | 7 | import { 8 | PUSH, 9 | REPLACE, 10 | GO, 11 | GO_BACK, 12 | GO_FORWARD, 13 | BLOCK, 14 | UNBLOCK, 15 | isNavigationAction 16 | } from './types'; 17 | 18 | import mergeQueries from './util/merge-queries'; 19 | 20 | export type MiddlewareArgs = { 21 | history: History 22 | }; 23 | 24 | type HandleNavArgs = { 25 | next: Dispatch<*>, 26 | action: RouterAction, 27 | history: History, 28 | query?: Query 29 | }; 30 | 31 | let unblock = null; 32 | 33 | const navigate = (history, action) => { 34 | switch (action.type) { 35 | case PUSH: 36 | history.push(action.payload); 37 | break; 38 | case REPLACE: 39 | history.replace(action.payload); 40 | break; 41 | case GO: 42 | history.go(action.payload); 43 | break; 44 | case GO_BACK: 45 | history.goBack(); 46 | break; 47 | case GO_FORWARD: 48 | history.goForward(); 49 | break; 50 | case BLOCK: 51 | unblock = history.block(action.payload); 52 | break; 53 | case UNBLOCK: 54 | if (unblock) { 55 | unblock(); 56 | } 57 | break; 58 | default: 59 | break; 60 | } 61 | }; 62 | 63 | export const handleNavigationAction = ({ 64 | next, 65 | action, 66 | history, 67 | query 68 | }: HandleNavArgs) => { 69 | // Synchronously dispatch the original action so that the 70 | // reducer can add it to its location queue 71 | const originalDispatch = next(action); 72 | 73 | if ( 74 | (action.type === PUSH || action.type === REPLACE) && 75 | action.payload.options && 76 | action.payload.options.persistQuery 77 | ) { 78 | navigate(history, { 79 | type: action.type, 80 | payload: { 81 | ...action.payload, 82 | ...mergeQueries(query, action.payload.query) 83 | } 84 | }); 85 | } else { 86 | navigate(history, action); 87 | } 88 | 89 | return originalDispatch; 90 | }; 91 | 92 | export default ({ history }: MiddlewareArgs) => ({ 93 | getState 94 | }: Store) => (next: Dispatch<*>) => (action: RouterAction) => { 95 | const { query } = getState().router; 96 | return isNavigationAction(action) 97 | ? handleNavigationAction({ next, action, history, query }) 98 | : next(action); 99 | }; 100 | -------------------------------------------------------------------------------- /flow-typed/npm/redux_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: ec7daead5cb4fec5ab25fedbedef29e8 2 | // flow-typed version: 2c04631d20/redux_v3.x.x/flow_>=v0.55.x 3 | 4 | declare module 'redux' { 5 | 6 | /* 7 | 8 | S = State 9 | A = Action 10 | D = Dispatch 11 | 12 | */ 13 | 14 | declare export type DispatchAPI = (action: A) => A; 15 | declare export type Dispatch }> = DispatchAPI; 16 | 17 | declare export type MiddlewareAPI> = { 18 | dispatch: D; 19 | getState(): S; 20 | }; 21 | 22 | declare export type Store> = { 23 | // rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages) 24 | dispatch: D; 25 | getState(): S; 26 | subscribe(listener: () => void): () => void; 27 | replaceReducer(nextReducer: Reducer): void 28 | }; 29 | 30 | declare export type Reducer = (state: S, action: A) => S; 31 | 32 | declare export type CombinedReducer = (state: $Shape & {} | void, action: A) => S; 33 | 34 | declare export type Middleware> = 35 | (api: MiddlewareAPI) => 36 | (next: D) => D; 37 | 38 | declare export type StoreCreator> = { 39 | (reducer: Reducer, enhancer?: StoreEnhancer): Store; 40 | (reducer: Reducer, preloadedState: S, enhancer?: StoreEnhancer): Store; 41 | }; 42 | 43 | declare export type StoreEnhancer> = (next: StoreCreator) => StoreCreator; 44 | 45 | declare export function createStore(reducer: Reducer, enhancer?: StoreEnhancer): Store; 46 | declare export function createStore(reducer: Reducer, preloadedState: S, enhancer?: StoreEnhancer): Store; 47 | 48 | declare export function applyMiddleware(...middlewares: Array>): StoreEnhancer; 49 | 50 | declare export type ActionCreator = (...args: Array) => A; 51 | declare export type ActionCreators = { [key: K]: ActionCreator }; 52 | 53 | declare export function bindActionCreators, D: DispatchAPI>(actionCreator: C, dispatch: D): C; 54 | declare export function bindActionCreators, D: DispatchAPI>(actionCreators: C, dispatch: D): C; 55 | 56 | declare export function combineReducers(reducers: O): CombinedReducer<$ObjMap(r: Reducer) => S>, A>; 57 | 58 | declare export var compose: $Compose; 59 | } -------------------------------------------------------------------------------- /interfaces/history.js: -------------------------------------------------------------------------------- 1 | declare module 'history' { 2 | declare type Action = 'PUSH' | 'REPLACE' | 'POP'; 3 | 4 | declare type Location = { 5 | pathname: string, 6 | search?: string, 7 | hash?: string, 8 | state?: Object, 9 | key?: string 10 | }; 11 | 12 | declare type ListenCallback = (location: Location, action?: Action) => void; 13 | declare type BlockCallback = (location: Location, action?: Action) => string; 14 | declare type Unsubscribe = () => void; 15 | 16 | declare class History { 17 | length: number; 18 | location: Location; 19 | 20 | action: Action; 21 | 22 | listen(callback: ListenCallback): Unsubscribe; 23 | 24 | push(path: string, state?: Object): void; 25 | push(location: Location): void; 26 | replace(path: string, state?: Object): void; 27 | replace(location: Location): void; 28 | 29 | go(n: number): void; 30 | goBack(): void; 31 | goForward(): void; 32 | 33 | block(message: string): void; 34 | block(callback: BlockCallback): Unsubscribe; 35 | } 36 | 37 | declare class MemoryHistory extends History { 38 | index: number; 39 | entries: Array; 40 | 41 | canGo(n: number): void; 42 | } 43 | 44 | declare type GetUserConfirmation = ( 45 | message: string, 46 | callback: (continueTransition: boolean) => void 47 | ) => void; 48 | 49 | declare type BrowserHistoryOptions = {| 50 | basename?: string, 51 | forceRefresh?: boolean, 52 | keyLength?: number, 53 | getUserConfirmation?: GetUserConfirmation 54 | |}; 55 | 56 | declare function createBrowserHistory( 57 | options?: BrowserHistoryOptions 58 | ): History; 59 | 60 | declare type MemoryHistoryOptions = {| 61 | initialEntries?: Array, 62 | initialIndex?: number, 63 | keyLength?: number, 64 | getUserConfirmation?: GetUserConfirmation 65 | |}; 66 | 67 | declare function createMemoryHistory( 68 | options?: MemoryHistoryOptions 69 | ): MemoryHistory; 70 | 71 | declare type HashType = 'slash' | 'noslash' | 'hashbang'; 72 | 73 | declare type HashHistoryOptions = {| 74 | basename?: string, 75 | hashType?: HashType, 76 | getUserConfirmation?: GetUserConfirmation 77 | |}; 78 | 79 | declare function createHashHistory(options?: HashHistoryOptions): History; 80 | 81 | declare function createLocation( 82 | path: string | Location, 83 | state?: any, 84 | key?: string, 85 | currentLocation?: Location 86 | ): Location; 87 | 88 | declare function locationsAreEqual(a: Location, b: Location): boolean; 89 | 90 | declare function parsePath(path: string): Location; 91 | declare function createPath(location: Location): string; 92 | } 93 | -------------------------------------------------------------------------------- /flow-typed/npm/redux-immutable_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 72bb43e680b07b10e336e3aff614ddf7 2 | // flow-typed version: <>/redux-immutable_v^4.0.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'redux-immutable' 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 'redux-immutable' { 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 'redux-immutable/benchmarks/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'redux-immutable/dist/combineReducers' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'redux-immutable/dist/index' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'redux-immutable/dist/utilities/getStateName' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'redux-immutable/dist/utilities/getUnexpectedInvocationParameterMessage' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'redux-immutable/dist/utilities/index' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'redux-immutable/dist/utilities/validateNextState' { 50 | declare module.exports: any; 51 | } 52 | 53 | // Filename aliases 54 | declare module 'redux-immutable/benchmarks/index.js' { 55 | declare module.exports: $Exports<'redux-immutable/benchmarks/index'>; 56 | } 57 | declare module 'redux-immutable/dist/combineReducers.js' { 58 | declare module.exports: $Exports<'redux-immutable/dist/combineReducers'>; 59 | } 60 | declare module 'redux-immutable/dist/index.js' { 61 | declare module.exports: $Exports<'redux-immutable/dist/index'>; 62 | } 63 | declare module 'redux-immutable/dist/utilities/getStateName.js' { 64 | declare module.exports: $Exports<'redux-immutable/dist/utilities/getStateName'>; 65 | } 66 | declare module 'redux-immutable/dist/utilities/getUnexpectedInvocationParameterMessage.js' { 67 | declare module.exports: $Exports<'redux-immutable/dist/utilities/getUnexpectedInvocationParameterMessage'>; 68 | } 69 | declare module 'redux-immutable/dist/utilities/index.js' { 70 | declare module.exports: $Exports<'redux-immutable/dist/utilities/index'>; 71 | } 72 | declare module 'redux-immutable/dist/utilities/validateNextState.js' { 73 | declare module.exports: $Exports<'redux-immutable/dist/utilities/validateNextState'>; 74 | } 75 | -------------------------------------------------------------------------------- /flow-typed/npm/husky_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a0bc9c724fb036ea84b246a232e7e175 2 | // flow-typed version: <>/husky_v^0.14.2/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'husky' 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 'husky' { 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 'husky/__tests__/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'husky/bin/install' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'husky/bin/uninstall' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'husky/src/install' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'husky/src/uninstall' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'husky/src/utils/find-hooks-dir' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'husky/src/utils/find-parent' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'husky/src/utils/get-hook-script' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'husky/src/utils/is-husky' { 58 | declare module.exports: any; 59 | } 60 | 61 | // Filename aliases 62 | declare module 'husky/__tests__/index.js' { 63 | declare module.exports: $Exports<'husky/__tests__/index'>; 64 | } 65 | declare module 'husky/bin/install.js' { 66 | declare module.exports: $Exports<'husky/bin/install'>; 67 | } 68 | declare module 'husky/bin/uninstall.js' { 69 | declare module.exports: $Exports<'husky/bin/uninstall'>; 70 | } 71 | declare module 'husky/src/install.js' { 72 | declare module.exports: $Exports<'husky/src/install'>; 73 | } 74 | declare module 'husky/src/uninstall.js' { 75 | declare module.exports: $Exports<'husky/src/uninstall'>; 76 | } 77 | declare module 'husky/src/utils/find-hooks-dir.js' { 78 | declare module.exports: $Exports<'husky/src/utils/find-hooks-dir'>; 79 | } 80 | declare module 'husky/src/utils/find-parent.js' { 81 | declare module.exports: $Exports<'husky/src/utils/find-parent'>; 82 | } 83 | declare module 'husky/src/utils/get-hook-script.js' { 84 | declare module.exports: $Exports<'husky/src/utils/get-hook-script'>; 85 | } 86 | declare module 'husky/src/utils/is-husky.js' { 87 | declare module.exports: $Exports<'husky/src/utils/is-husky'>; 88 | } 89 | -------------------------------------------------------------------------------- /flow-typed/npm/postcss-cssnext_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 88153953ebb671a614b4a35e0a069d24 2 | // flow-typed version: <>/postcss-cssnext_v^2.11.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'postcss-cssnext' 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 'postcss-cssnext' { 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 'postcss-cssnext/lib/features-activation-map' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'postcss-cssnext/lib/features' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'postcss-cssnext/lib/index' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'postcss-cssnext/lib/warn-for-duplicates' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'postcss-cssnext/src/features-activation-map' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'postcss-cssnext/src/features' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'postcss-cssnext/src/index' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'postcss-cssnext/src/warn-for-duplicates' { 54 | declare module.exports: any; 55 | } 56 | 57 | // Filename aliases 58 | declare module 'postcss-cssnext/lib/features-activation-map.js' { 59 | declare module.exports: $Exports<'postcss-cssnext/lib/features-activation-map'>; 60 | } 61 | declare module 'postcss-cssnext/lib/features.js' { 62 | declare module.exports: $Exports<'postcss-cssnext/lib/features'>; 63 | } 64 | declare module 'postcss-cssnext/lib/index.js' { 65 | declare module.exports: $Exports<'postcss-cssnext/lib/index'>; 66 | } 67 | declare module 'postcss-cssnext/lib/warn-for-duplicates.js' { 68 | declare module.exports: $Exports<'postcss-cssnext/lib/warn-for-duplicates'>; 69 | } 70 | declare module 'postcss-cssnext/src/features-activation-map.js' { 71 | declare module.exports: $Exports<'postcss-cssnext/src/features-activation-map'>; 72 | } 73 | declare module 'postcss-cssnext/src/features.js' { 74 | declare module.exports: $Exports<'postcss-cssnext/src/features'>; 75 | } 76 | declare module 'postcss-cssnext/src/index.js' { 77 | declare module.exports: $Exports<'postcss-cssnext/src/index'>; 78 | } 79 | declare module 'postcss-cssnext/src/warn-for-duplicates.js' { 80 | declare module.exports: $Exports<'postcss-cssnext/src/warn-for-duplicates'>; 81 | } 82 | -------------------------------------------------------------------------------- /flow-typed/npm/react-hot-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: fc6f583ed55602121ae573a275da10fe 2 | // flow-typed version: <>/react-hot-loader_v^1.3.1/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'react-hot-loader' 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 'react-hot-loader' { 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 'react-hot-loader/getRootInstancesFromReactMount' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'react-hot-loader/Injection' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'react-hot-loader/isReactClassish' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'react-hot-loader/isReactElementish' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'react-hot-loader/makeExportsHot' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'react-hot-loader/makeIdentitySourceMap' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'react-hot-loader/RootInstanceProvider' { 50 | declare module.exports: any; 51 | } 52 | 53 | // Filename aliases 54 | declare module 'react-hot-loader/getRootInstancesFromReactMount.js' { 55 | declare module.exports: $Exports<'react-hot-loader/getRootInstancesFromReactMount'>; 56 | } 57 | declare module 'react-hot-loader/index' { 58 | declare module.exports: $Exports<'react-hot-loader'>; 59 | } 60 | declare module 'react-hot-loader/index.js' { 61 | declare module.exports: $Exports<'react-hot-loader'>; 62 | } 63 | declare module 'react-hot-loader/Injection.js' { 64 | declare module.exports: $Exports<'react-hot-loader/Injection'>; 65 | } 66 | declare module 'react-hot-loader/isReactClassish.js' { 67 | declare module.exports: $Exports<'react-hot-loader/isReactClassish'>; 68 | } 69 | declare module 'react-hot-loader/isReactElementish.js' { 70 | declare module.exports: $Exports<'react-hot-loader/isReactElementish'>; 71 | } 72 | declare module 'react-hot-loader/makeExportsHot.js' { 73 | declare module.exports: $Exports<'react-hot-loader/makeExportsHot'>; 74 | } 75 | declare module 'react-hot-loader/makeIdentitySourceMap.js' { 76 | declare module.exports: $Exports<'react-hot-loader/makeIdentitySourceMap'>; 77 | } 78 | declare module 'react-hot-loader/RootInstanceProvider.js' { 79 | declare module.exports: $Exports<'react-hot-loader/RootInstanceProvider'>; 80 | } 81 | -------------------------------------------------------------------------------- /test/test-util/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable new-cap */ 2 | import createMemoryHistory from 'history/createMemoryHistory'; 3 | import { fromJS } from 'immutable'; 4 | import { applyMiddleware, createStore, compose } from 'redux'; 5 | 6 | import createMatcher from '../../src/util/create-matcher'; 7 | 8 | import defaultRoutes from '../test-util/fixtures/routes'; 9 | 10 | export const captureErrors = (done, assertions) => { 11 | try { 12 | assertions(); 13 | done(); 14 | } catch (e) { 15 | done(e); 16 | } 17 | }; 18 | 19 | export const fakeStore = ({ 20 | assertion, 21 | basename, 22 | pathname = '/home/messages/b-team', 23 | query = { test: 'ing' }, 24 | route = '/home/messages/:team', 25 | routes = defaultRoutes, 26 | immutable = false 27 | } = {}) => { 28 | const history = createMemoryHistory(); 29 | const state = { 30 | router: { 31 | basename, 32 | pathname, 33 | query, 34 | search: '?test=ing', 35 | action: 'POP', 36 | route 37 | } 38 | }; 39 | 40 | return { 41 | subscribe() {}, 42 | getState() { 43 | return immutable ? fromJS(state) : state; 44 | }, 45 | dispatch(action) { 46 | assertion && assertion(action); 47 | }, 48 | routes, 49 | history, 50 | matchRoute: createMatcher(routes), 51 | matchWildcardRoute: createMatcher(routes, true) 52 | }; 53 | }; 54 | 55 | export const fakeContext = ({ 56 | assertion, 57 | basename, 58 | pathname = '/home/messages/b-team', 59 | route = '/home/messages/:team', 60 | query = { test: 'ing' } 61 | } = {}) => ({ 62 | context: { 63 | store: fakeStore({ 64 | assertion, 65 | basename, 66 | pathname, 67 | query, 68 | route 69 | }) 70 | } 71 | }); 72 | 73 | export const fakeImmutableContext = ({ 74 | assertion, 75 | basename, 76 | pathname = '/home/messages/b-team', 77 | route = '/home/messages/:team', 78 | query = { test: 'ing' } 79 | } = {}) => ({ 80 | context: { 81 | store: fakeStore({ 82 | assertion, 83 | basename, 84 | pathname, 85 | query, 86 | route, 87 | immutable: true 88 | }) 89 | } 90 | }); 91 | 92 | export const standardClickEvent = { 93 | button: 0, 94 | shiftKey: false, 95 | altKey: false, 96 | metaKey: false, 97 | ctrlKey: false, 98 | preventDefault() {} 99 | }; 100 | 101 | export const setupStoreForEnv = ( 102 | routerForEnv, 103 | combineReducers, 104 | initialState 105 | ) => routerArg => { 106 | const { reducer, middleware, enhancer } = routerForEnv(routerArg); 107 | return createStore( 108 | combineReducers({ router: reducer }), 109 | initialState, 110 | compose(enhancer, applyMiddleware(middleware)) 111 | ); 112 | }; 113 | -------------------------------------------------------------------------------- /config/webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | 6 | // Replace with `__dirname` if using in project root. 7 | const ROOT = process.cwd(); 8 | const SRC = path.join(ROOT, 'src'); 9 | const CLIENT = path.join(ROOT, 'test'); 10 | 11 | // **Little Hacky**: Infer the filename and library name from the package name. 12 | // 13 | // Assumptions: 14 | // - `package.json`'s `name` field is name of dist files. 15 | // - PascalCased version of that name is exported class name. 16 | const PKG = require(path.join(ROOT, 'package.json')); 17 | const libPath = (PKG.name || '').toLowerCase(); 18 | if (!libPath) { 19 | throw new Error('Need package.json:name field'); 20 | } 21 | // PascalCase (with first character capitalized). 22 | const libName = libPath 23 | .replace(/^\s+|\s+$/g, '') 24 | .replace(/(^|[-_ ])+(.)/g, (match, first, second) => { 25 | // Second match group is the character we want to change. Throw away first. 26 | return second.toUpperCase(); 27 | }); 28 | 29 | module.exports = { 30 | cache: true, 31 | context: SRC, 32 | entry: './index.js', 33 | externals: [ 34 | { 35 | react: { 36 | root: 'React', 37 | commonjs2: 'react', 38 | commonjs: 'react', 39 | amd: 'react' 40 | } 41 | }, 42 | { 43 | radium: { 44 | root: 'Radium', 45 | commonjs2: 'radium', 46 | commonjs: 'radium', 47 | amd: 'radium' 48 | } 49 | } 50 | ], 51 | output: { 52 | path: path.join(ROOT, 'dist'), 53 | filename: `${libPath}.min.js`, 54 | library: libName, 55 | libraryTarget: 'umd' 56 | }, 57 | resolve: { 58 | extensions: ['.js', '.jsx'] 59 | }, 60 | module: { 61 | rules: [ 62 | { 63 | test: /\.jsx?$/, 64 | // Use include specifically of our sources. 65 | // Do _not_ use an `exclude` here. 66 | include: [SRC, CLIENT], 67 | // **Note**: Cannot use shorthand `'babel-loader'` or `'babel'` when 68 | // we are playing around with `NODE_PATH` in builder. Manually 69 | // resolve path. 70 | use: require.resolve('babel-loader') 71 | } 72 | ] 73 | }, 74 | plugins: [ 75 | new webpack.optimize.UglifyJsPlugin({ 76 | compress: { 77 | warnings: false 78 | }, 79 | 80 | sourceMap: true 81 | }), 82 | new webpack.DefinePlugin({ 83 | // Signal production, so that webpack removes non-production code that 84 | // is in condtionals like: `if (process.env.NODE_ENV === 'production')` 85 | 'process.env.NODE_ENV': JSON.stringify('production') 86 | }), 87 | new webpack.SourceMapDevToolPlugin({ 88 | filename: '[file].map' 89 | }), 90 | new webpack.LoaderOptionsPlugin({ 91 | minimize: true 92 | }) 93 | ] 94 | }; 95 | -------------------------------------------------------------------------------- /src/immutable/reducer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /* eslint-disable new-cap */ 3 | import type { Map as MapType } from 'immutable'; 4 | 5 | import type { ReducerArgs } from '../reducer'; 6 | import type { Location, LocationAction } from '../types'; 7 | 8 | import { List, Map, fromJS } from './util/immutable'; 9 | 10 | import { 11 | LOCATION_CHANGED, 12 | REPLACE_ROUTES, 13 | DID_REPLACE_ROUTES, 14 | isNavigationActionWithPayload 15 | } from '../types'; 16 | import { resolveLocation } from '../reducer'; 17 | 18 | type ImmutableLocation = $Shape>; 19 | 20 | const locationChangeReducer = (state, action) => { 21 | // No-op the initial route action 22 | const queue = state.get('queue', List()); 23 | if ( 24 | state.get('pathname') === action.payload.pathname && 25 | state.get('search') === action.payload.search && 26 | state.get('hash') === action.payload.hash && 27 | !queue.size 28 | ) { 29 | return state; 30 | } 31 | 32 | const queuedLocation = queue.get(0, Map()); 33 | const newQueue = queue.rest(); 34 | 35 | // Extract the previous state, but dump the 36 | // previous state's previous state so that the 37 | // state tree doesn't keep growing indefinitely 38 | // eslint-disable-next-line no-unused-vars 39 | const oldLocation: Location = state 40 | .withMutations(routerState => { 41 | routerState.delete('previous').delete('routes'); 42 | }) 43 | .toJS(); 44 | const options = queuedLocation.get('options', Map()).toJS(); 45 | const query = queuedLocation.get('query', Map()).toJS(); 46 | const newLocation: Location = { ...action.payload, query }; 47 | 48 | const { newLocation: resolvedNewLocation } = resolveLocation({ 49 | oldLocation, 50 | newLocation, 51 | options 52 | }); 53 | 54 | return fromJS(resolvedNewLocation).merge({ 55 | routes: state.get('routes', Map()), 56 | queue: newQueue 57 | }); 58 | }; 59 | 60 | export default ({ routes = {}, initialLocation }: ReducerArgs = {}) => ( 61 | state: ImmutableLocation = fromJS({ ...initialLocation, routes, queue: [] }), 62 | action: LocationAction 63 | ) => { 64 | if (isNavigationActionWithPayload(action)) { 65 | const payload = fromJS(action.payload); 66 | return state.update('queue', List(), queue => queue.push(payload)); 67 | } 68 | 69 | if (action.type === REPLACE_ROUTES) { 70 | const { routes: currentRoutes, options } = action.payload; 71 | return state.withMutations(routerState => { 72 | routerState 73 | .set('routes', fromJS(currentRoutes)) 74 | .set('options', fromJS(options)); 75 | }); 76 | } 77 | 78 | if (action.type === DID_REPLACE_ROUTES) { 79 | return state.set('options', Map()); 80 | } 81 | 82 | if (action.type === LOCATION_CHANGED) { 83 | return locationChangeReducer(state, action); 84 | } 85 | 86 | return state; 87 | }; 88 | -------------------------------------------------------------------------------- /test/environment/express-router.spec.js: -------------------------------------------------------------------------------- 1 | import chai, { expect } from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | import { fromJS } from 'immutable'; 5 | import { combineReducers as combineReduxReducers } from 'redux'; 6 | import { combineReducers as combineImmutableReducers } from 'redux-immutable'; 7 | 8 | import routerForExpress from '../../src/environment/express-router'; 9 | import immutableRouterForExpress from '../../src/immutable/environment/express-router'; 10 | 11 | import { setupStoreForEnv } from '../test-util'; 12 | import routes from '../test-util/fixtures/routes'; 13 | 14 | chai.use(sinonChai); 15 | 16 | const expressRouterTest = { 17 | router: routerForExpress, 18 | combineReducers: combineReduxReducers, 19 | toState: state => state, 20 | readState: state => state, 21 | testLabel: 'express router' 22 | }; 23 | const immutableExpressRouterTest = { 24 | router: immutableRouterForExpress, 25 | combineReducers: combineImmutableReducers, 26 | toState: state => fromJS(state), 27 | readState: state => state.toJS(), 28 | testLabel: 'immutable express router' 29 | }; 30 | 31 | [expressRouterTest, immutableExpressRouterTest].forEach( 32 | ({ router, combineReducers, toState, readState, testLabel }) => { 33 | describe(`${testLabel}`, () => { 34 | const setupExpressStore = setupStoreForEnv( 35 | router, 36 | combineReducers, 37 | toState({}) 38 | ); 39 | 40 | it('creates a server store enhancer using Express request object', () => { 41 | const store = setupExpressStore({ 42 | routes, 43 | request: { 44 | path: '/home', 45 | query: { get: 'schwifty' } 46 | } 47 | }); 48 | 49 | const state = readState(store.getState()); 50 | expect(state).to.have.nested.property('router.pathname', '/home'); 51 | expect(state).to.have.nested.property('router.search', '?get=schwifty'); 52 | expect(state) 53 | .to.have.nested.property('router.query') 54 | .that.deep.equals({ get: 'schwifty' }); 55 | }); 56 | 57 | it('supports basenames', () => { 58 | const store = setupExpressStore({ 59 | routes, 60 | request: { 61 | baseUrl: '/cob-planet', 62 | path: '/home', 63 | query: { get: 'schwifty' } 64 | } 65 | }); 66 | 67 | const state = readState(store.getState()); 68 | expect(state).to.have.nested.property('router.basename', '/cob-planet'); 69 | expect(state).to.have.nested.property('router.pathname', '/home'); 70 | expect(state).to.have.nested.property('router.search', '?get=schwifty'); 71 | expect(state) 72 | .to.have.nested.property('router.query') 73 | .that.deep.equals({ get: 'schwifty' }); 74 | }); 75 | }); 76 | } 77 | ); 78 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-eslint_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a7225c6adfc0da686a04f1ce07c87ce2 2 | // flow-typed version: <>/babel-eslint_v^7.2.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-eslint' 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-eslint' { 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-eslint/babylon-to-espree/attachComments' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'babel-eslint/babylon-to-espree/convertComments' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'babel-eslint/babylon-to-espree/convertTemplateType' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'babel-eslint/babylon-to-espree/index' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'babel-eslint/babylon-to-espree/toAST' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'babel-eslint/babylon-to-espree/toToken' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'babel-eslint/babylon-to-espree/toTokens' { 50 | declare module.exports: any; 51 | } 52 | 53 | // Filename aliases 54 | declare module 'babel-eslint/babylon-to-espree/attachComments.js' { 55 | declare module.exports: $Exports<'babel-eslint/babylon-to-espree/attachComments'>; 56 | } 57 | declare module 'babel-eslint/babylon-to-espree/convertComments.js' { 58 | declare module.exports: $Exports<'babel-eslint/babylon-to-espree/convertComments'>; 59 | } 60 | declare module 'babel-eslint/babylon-to-espree/convertTemplateType.js' { 61 | declare module.exports: $Exports<'babel-eslint/babylon-to-espree/convertTemplateType'>; 62 | } 63 | declare module 'babel-eslint/babylon-to-espree/index.js' { 64 | declare module.exports: $Exports<'babel-eslint/babylon-to-espree/index'>; 65 | } 66 | declare module 'babel-eslint/babylon-to-espree/toAST.js' { 67 | declare module.exports: $Exports<'babel-eslint/babylon-to-espree/toAST'>; 68 | } 69 | declare module 'babel-eslint/babylon-to-espree/toToken.js' { 70 | declare module.exports: $Exports<'babel-eslint/babylon-to-espree/toToken'>; 71 | } 72 | declare module 'babel-eslint/babylon-to-espree/toTokens.js' { 73 | declare module.exports: $Exports<'babel-eslint/babylon-to-espree/toTokens'>; 74 | } 75 | declare module 'babel-eslint/index' { 76 | declare module.exports: $Exports<'babel-eslint'>; 77 | } 78 | declare module 'babel-eslint/index.js' { 79 | declare module.exports: $Exports<'babel-eslint'>; 80 | } 81 | -------------------------------------------------------------------------------- /flow-typed/npm/lint-staged_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 0b3fe792940be762664961e777b3b413 2 | // flow-typed version: <>/lint-staged_v^4.0.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'lint-staged' 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 'lint-staged' { 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 'lint-staged/src/calcChunkSize' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'lint-staged/src/findBin' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'lint-staged/src/generateTasks' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'lint-staged/src/getConfig' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'lint-staged/src/index' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'lint-staged/src/printErrors' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'lint-staged/src/resolveGitDir' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'lint-staged/src/runAll' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'lint-staged/src/runScript' { 58 | declare module.exports: any; 59 | } 60 | 61 | // Filename aliases 62 | declare module 'lint-staged/index' { 63 | declare module.exports: $Exports<'lint-staged'>; 64 | } 65 | declare module 'lint-staged/index.js' { 66 | declare module.exports: $Exports<'lint-staged'>; 67 | } 68 | declare module 'lint-staged/src/calcChunkSize.js' { 69 | declare module.exports: $Exports<'lint-staged/src/calcChunkSize'>; 70 | } 71 | declare module 'lint-staged/src/findBin.js' { 72 | declare module.exports: $Exports<'lint-staged/src/findBin'>; 73 | } 74 | declare module 'lint-staged/src/generateTasks.js' { 75 | declare module.exports: $Exports<'lint-staged/src/generateTasks'>; 76 | } 77 | declare module 'lint-staged/src/getConfig.js' { 78 | declare module.exports: $Exports<'lint-staged/src/getConfig'>; 79 | } 80 | declare module 'lint-staged/src/index.js' { 81 | declare module.exports: $Exports<'lint-staged/src/index'>; 82 | } 83 | declare module 'lint-staged/src/printErrors.js' { 84 | declare module.exports: $Exports<'lint-staged/src/printErrors'>; 85 | } 86 | declare module 'lint-staged/src/resolveGitDir.js' { 87 | declare module.exports: $Exports<'lint-staged/src/resolveGitDir'>; 88 | } 89 | declare module 'lint-staged/src/runAll.js' { 90 | declare module.exports: $Exports<'lint-staged/src/runAll'>; 91 | } 92 | declare module 'lint-staged/src/runScript.js' { 93 | declare module.exports: $Exports<'lint-staged/src/runScript'>; 94 | } 95 | -------------------------------------------------------------------------------- /flow-typed/npm/eslint-plugin-filenames_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 49d67b17449909ab6e0e7dc4dabb401f 2 | // flow-typed version: <>/eslint-plugin-filenames_v^1.1.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'eslint-plugin-filenames' 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-filenames' { 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-filenames/lib/common/getExportedName' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'eslint-plugin-filenames/lib/common/isIgnoredFilename' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'eslint-plugin-filenames/lib/common/isIndexFile' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'eslint-plugin-filenames/lib/common/parseFilename' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'eslint-plugin-filenames/lib/rules/match-exported' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'eslint-plugin-filenames/lib/rules/match-regex' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'eslint-plugin-filenames/lib/rules/no-index' { 50 | declare module.exports: any; 51 | } 52 | 53 | // Filename aliases 54 | declare module 'eslint-plugin-filenames/index' { 55 | declare module.exports: $Exports<'eslint-plugin-filenames'>; 56 | } 57 | declare module 'eslint-plugin-filenames/index.js' { 58 | declare module.exports: $Exports<'eslint-plugin-filenames'>; 59 | } 60 | declare module 'eslint-plugin-filenames/lib/common/getExportedName.js' { 61 | declare module.exports: $Exports<'eslint-plugin-filenames/lib/common/getExportedName'>; 62 | } 63 | declare module 'eslint-plugin-filenames/lib/common/isIgnoredFilename.js' { 64 | declare module.exports: $Exports<'eslint-plugin-filenames/lib/common/isIgnoredFilename'>; 65 | } 66 | declare module 'eslint-plugin-filenames/lib/common/isIndexFile.js' { 67 | declare module.exports: $Exports<'eslint-plugin-filenames/lib/common/isIndexFile'>; 68 | } 69 | declare module 'eslint-plugin-filenames/lib/common/parseFilename.js' { 70 | declare module.exports: $Exports<'eslint-plugin-filenames/lib/common/parseFilename'>; 71 | } 72 | declare module 'eslint-plugin-filenames/lib/rules/match-exported.js' { 73 | declare module.exports: $Exports<'eslint-plugin-filenames/lib/rules/match-exported'>; 74 | } 75 | declare module 'eslint-plugin-filenames/lib/rules/match-regex.js' { 76 | declare module.exports: $Exports<'eslint-plugin-filenames/lib/rules/match-regex'>; 77 | } 78 | declare module 'eslint-plugin-filenames/lib/rules/no-index.js' { 79 | declare module.exports: $Exports<'eslint-plugin-filenames/lib/rules/no-index'>; 80 | } 81 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-env_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: ef2d9bfec8329a2eb219a3b6492893fa 2 | // flow-typed version: <>/babel-preset-env_v^1.6.1/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-env' 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-env' { 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-env/data/built-in-features' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'babel-preset-env/data/plugin-features' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'babel-preset-env/lib/default-includes' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'babel-preset-env/lib/index' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'babel-preset-env/lib/module-transformations' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'babel-preset-env/lib/normalize-options' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'babel-preset-env/lib/targets-parser' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'babel-preset-env/lib/transform-polyfill-require-plugin' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'babel-preset-env/lib/utils' { 58 | declare module.exports: any; 59 | } 60 | 61 | // Filename aliases 62 | declare module 'babel-preset-env/data/built-in-features.js' { 63 | declare module.exports: $Exports<'babel-preset-env/data/built-in-features'>; 64 | } 65 | declare module 'babel-preset-env/data/plugin-features.js' { 66 | declare module.exports: $Exports<'babel-preset-env/data/plugin-features'>; 67 | } 68 | declare module 'babel-preset-env/lib/default-includes.js' { 69 | declare module.exports: $Exports<'babel-preset-env/lib/default-includes'>; 70 | } 71 | declare module 'babel-preset-env/lib/index.js' { 72 | declare module.exports: $Exports<'babel-preset-env/lib/index'>; 73 | } 74 | declare module 'babel-preset-env/lib/module-transformations.js' { 75 | declare module.exports: $Exports<'babel-preset-env/lib/module-transformations'>; 76 | } 77 | declare module 'babel-preset-env/lib/normalize-options.js' { 78 | declare module.exports: $Exports<'babel-preset-env/lib/normalize-options'>; 79 | } 80 | declare module 'babel-preset-env/lib/targets-parser.js' { 81 | declare module.exports: $Exports<'babel-preset-env/lib/targets-parser'>; 82 | } 83 | declare module 'babel-preset-env/lib/transform-polyfill-require-plugin.js' { 84 | declare module.exports: $Exports<'babel-preset-env/lib/transform-polyfill-require-plugin'>; 85 | } 86 | declare module 'babel-preset-env/lib/utils.js' { 87 | declare module.exports: $Exports<'babel-preset-env/lib/utils'>; 88 | } 89 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-plugin-lodash_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: fafce7d2a214316a2c4ba8175edefa73 2 | // flow-typed version: <>/babel-plugin-lodash_v^3.2.11/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-plugin-lodash' 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-lodash' { 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-lodash/lib/config' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'babel-plugin-lodash/lib/importModule' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'babel-plugin-lodash/lib/index' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'babel-plugin-lodash/lib/Map' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'babel-plugin-lodash/lib/MapCache' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'babel-plugin-lodash/lib/mapping' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'babel-plugin-lodash/lib/ModuleCache' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'babel-plugin-lodash/lib/Package' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'babel-plugin-lodash/lib/Store' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'babel-plugin-lodash/lib/util' { 62 | declare module.exports: any; 63 | } 64 | 65 | // Filename aliases 66 | declare module 'babel-plugin-lodash/lib/config.js' { 67 | declare module.exports: $Exports<'babel-plugin-lodash/lib/config'>; 68 | } 69 | declare module 'babel-plugin-lodash/lib/importModule.js' { 70 | declare module.exports: $Exports<'babel-plugin-lodash/lib/importModule'>; 71 | } 72 | declare module 'babel-plugin-lodash/lib/index.js' { 73 | declare module.exports: $Exports<'babel-plugin-lodash/lib/index'>; 74 | } 75 | declare module 'babel-plugin-lodash/lib/Map.js' { 76 | declare module.exports: $Exports<'babel-plugin-lodash/lib/Map'>; 77 | } 78 | declare module 'babel-plugin-lodash/lib/MapCache.js' { 79 | declare module.exports: $Exports<'babel-plugin-lodash/lib/MapCache'>; 80 | } 81 | declare module 'babel-plugin-lodash/lib/mapping.js' { 82 | declare module.exports: $Exports<'babel-plugin-lodash/lib/mapping'>; 83 | } 84 | declare module 'babel-plugin-lodash/lib/ModuleCache.js' { 85 | declare module.exports: $Exports<'babel-plugin-lodash/lib/ModuleCache'>; 86 | } 87 | declare module 'babel-plugin-lodash/lib/Package.js' { 88 | declare module.exports: $Exports<'babel-plugin-lodash/lib/Package'>; 89 | } 90 | declare module 'babel-plugin-lodash/lib/Store.js' { 91 | declare module.exports: $Exports<'babel-plugin-lodash/lib/Store'>; 92 | } 93 | declare module 'babel-plugin-lodash/lib/util.js' { 94 | declare module.exports: $Exports<'babel-plugin-lodash/lib/util'>; 95 | } 96 | -------------------------------------------------------------------------------- /flow-typed/npm/css-loader_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 30d3534c61e83c843ca757a09385aea3 2 | // flow-typed version: <>/css-loader_v^0.28.4/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'css-loader' 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 'css-loader' { 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 'css-loader/lib/compile-exports' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'css-loader/lib/createResolver' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'css-loader/lib/css-base' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'css-loader/lib/getImportPrefix' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'css-loader/lib/getLocalIdent' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'css-loader/lib/loader' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'css-loader/lib/localsLoader' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'css-loader/lib/processCss' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'css-loader/lib/url/escape' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'css-loader/locals' { 62 | declare module.exports: any; 63 | } 64 | 65 | // Filename aliases 66 | declare module 'css-loader/index' { 67 | declare module.exports: $Exports<'css-loader'>; 68 | } 69 | declare module 'css-loader/index.js' { 70 | declare module.exports: $Exports<'css-loader'>; 71 | } 72 | declare module 'css-loader/lib/compile-exports.js' { 73 | declare module.exports: $Exports<'css-loader/lib/compile-exports'>; 74 | } 75 | declare module 'css-loader/lib/createResolver.js' { 76 | declare module.exports: $Exports<'css-loader/lib/createResolver'>; 77 | } 78 | declare module 'css-loader/lib/css-base.js' { 79 | declare module.exports: $Exports<'css-loader/lib/css-base'>; 80 | } 81 | declare module 'css-loader/lib/getImportPrefix.js' { 82 | declare module.exports: $Exports<'css-loader/lib/getImportPrefix'>; 83 | } 84 | declare module 'css-loader/lib/getLocalIdent.js' { 85 | declare module.exports: $Exports<'css-loader/lib/getLocalIdent'>; 86 | } 87 | declare module 'css-loader/lib/loader.js' { 88 | declare module.exports: $Exports<'css-loader/lib/loader'>; 89 | } 90 | declare module 'css-loader/lib/localsLoader.js' { 91 | declare module.exports: $Exports<'css-loader/lib/localsLoader'>; 92 | } 93 | declare module 'css-loader/lib/processCss.js' { 94 | declare module.exports: $Exports<'css-loader/lib/processCss'>; 95 | } 96 | declare module 'css-loader/lib/url/escape.js' { 97 | declare module.exports: $Exports<'css-loader/lib/url/escape'>; 98 | } 99 | declare module 'css-loader/locals.js' { 100 | declare module.exports: $Exports<'css-loader/locals'>; 101 | } 102 | -------------------------------------------------------------------------------- /flow-typed/npm/prettier_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 74453c411039b669bfd1618bbf1e7dd7 2 | // flow-typed version: <>/prettier_v^1.10.2/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'prettier' 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 'prettier' { 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 'prettier/bin-prettier' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'prettier/parser-babylon' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'prettier/parser-flow' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'prettier/parser-glimmer' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'prettier/parser-graphql' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'prettier/parser-markdown' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'prettier/parser-parse5' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'prettier/parser-postcss' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'prettier/parser-typescript' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'prettier/parser-vue' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'prettier/third-party' { 66 | declare module.exports: any; 67 | } 68 | 69 | // Filename aliases 70 | declare module 'prettier/bin-prettier.js' { 71 | declare module.exports: $Exports<'prettier/bin-prettier'>; 72 | } 73 | declare module 'prettier/index' { 74 | declare module.exports: $Exports<'prettier'>; 75 | } 76 | declare module 'prettier/index.js' { 77 | declare module.exports: $Exports<'prettier'>; 78 | } 79 | declare module 'prettier/parser-babylon.js' { 80 | declare module.exports: $Exports<'prettier/parser-babylon'>; 81 | } 82 | declare module 'prettier/parser-flow.js' { 83 | declare module.exports: $Exports<'prettier/parser-flow'>; 84 | } 85 | declare module 'prettier/parser-glimmer.js' { 86 | declare module.exports: $Exports<'prettier/parser-glimmer'>; 87 | } 88 | declare module 'prettier/parser-graphql.js' { 89 | declare module.exports: $Exports<'prettier/parser-graphql'>; 90 | } 91 | declare module 'prettier/parser-markdown.js' { 92 | declare module.exports: $Exports<'prettier/parser-markdown'>; 93 | } 94 | declare module 'prettier/parser-parse5.js' { 95 | declare module.exports: $Exports<'prettier/parser-parse5'>; 96 | } 97 | declare module 'prettier/parser-postcss.js' { 98 | declare module.exports: $Exports<'prettier/parser-postcss'>; 99 | } 100 | declare module 'prettier/parser-typescript.js' { 101 | declare module.exports: $Exports<'prettier/parser-typescript'>; 102 | } 103 | declare module 'prettier/parser-vue.js' { 104 | declare module.exports: $Exports<'prettier/parser-vue'>; 105 | } 106 | declare module 'prettier/third-party.js' { 107 | declare module.exports: $Exports<'prettier/third-party'>; 108 | } 109 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-cli_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 548fce8a03bea76ea99ac07c87118aee 2 | // flow-typed version: <>/babel-cli_v^6.24.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-cli' 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-cli' { 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-cli/bin/babel-doctor' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'babel-cli/bin/babel-external-helpers' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'babel-cli/bin/babel-node' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'babel-cli/bin/babel' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'babel-cli/lib/_babel-node' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'babel-cli/lib/babel-external-helpers' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'babel-cli/lib/babel-node' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'babel-cli/lib/babel/dir' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'babel-cli/lib/babel/file' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'babel-cli/lib/babel/index' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'babel-cli/lib/babel/util' { 66 | declare module.exports: any; 67 | } 68 | 69 | // Filename aliases 70 | declare module 'babel-cli/bin/babel-doctor.js' { 71 | declare module.exports: $Exports<'babel-cli/bin/babel-doctor'>; 72 | } 73 | declare module 'babel-cli/bin/babel-external-helpers.js' { 74 | declare module.exports: $Exports<'babel-cli/bin/babel-external-helpers'>; 75 | } 76 | declare module 'babel-cli/bin/babel-node.js' { 77 | declare module.exports: $Exports<'babel-cli/bin/babel-node'>; 78 | } 79 | declare module 'babel-cli/bin/babel.js' { 80 | declare module.exports: $Exports<'babel-cli/bin/babel'>; 81 | } 82 | declare module 'babel-cli/index' { 83 | declare module.exports: $Exports<'babel-cli'>; 84 | } 85 | declare module 'babel-cli/index.js' { 86 | declare module.exports: $Exports<'babel-cli'>; 87 | } 88 | declare module 'babel-cli/lib/_babel-node.js' { 89 | declare module.exports: $Exports<'babel-cli/lib/_babel-node'>; 90 | } 91 | declare module 'babel-cli/lib/babel-external-helpers.js' { 92 | declare module.exports: $Exports<'babel-cli/lib/babel-external-helpers'>; 93 | } 94 | declare module 'babel-cli/lib/babel-node.js' { 95 | declare module.exports: $Exports<'babel-cli/lib/babel-node'>; 96 | } 97 | declare module 'babel-cli/lib/babel/dir.js' { 98 | declare module.exports: $Exports<'babel-cli/lib/babel/dir'>; 99 | } 100 | declare module 'babel-cli/lib/babel/file.js' { 101 | declare module.exports: $Exports<'babel-cli/lib/babel/file'>; 102 | } 103 | declare module 'babel-cli/lib/babel/index.js' { 104 | declare module.exports: $Exports<'babel-cli/lib/babel/index'>; 105 | } 106 | declare module 'babel-cli/lib/babel/util.js' { 107 | declare module.exports: $Exports<'babel-cli/lib/babel/util'>; 108 | } 109 | -------------------------------------------------------------------------------- /flow-typed/npm/builder_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 76226e8a33c4806c4f65a99f6b758c73 2 | // flow-typed version: <>/builder_v^3.1.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'builder' 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 'builder' { 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 'builder/bin/builder-core' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'builder/bin/builder' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'builder/lib/args' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'builder/lib/config' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'builder/lib/environment' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'builder/lib/log' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'builder/lib/runner' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'builder/lib/spawn' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'builder/lib/task' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'builder/lib/utils/archetype' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'builder/lib/utils/clone' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'builder/lib/utils/json' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'builder/lib/utils/tracker' { 74 | declare module.exports: any; 75 | } 76 | 77 | // Filename aliases 78 | declare module 'builder/bin/builder-core.js' { 79 | declare module.exports: $Exports<'builder/bin/builder-core'>; 80 | } 81 | declare module 'builder/bin/builder.js' { 82 | declare module.exports: $Exports<'builder/bin/builder'>; 83 | } 84 | declare module 'builder/lib/args.js' { 85 | declare module.exports: $Exports<'builder/lib/args'>; 86 | } 87 | declare module 'builder/lib/config.js' { 88 | declare module.exports: $Exports<'builder/lib/config'>; 89 | } 90 | declare module 'builder/lib/environment.js' { 91 | declare module.exports: $Exports<'builder/lib/environment'>; 92 | } 93 | declare module 'builder/lib/log.js' { 94 | declare module.exports: $Exports<'builder/lib/log'>; 95 | } 96 | declare module 'builder/lib/runner.js' { 97 | declare module.exports: $Exports<'builder/lib/runner'>; 98 | } 99 | declare module 'builder/lib/spawn.js' { 100 | declare module.exports: $Exports<'builder/lib/spawn'>; 101 | } 102 | declare module 'builder/lib/task.js' { 103 | declare module.exports: $Exports<'builder/lib/task'>; 104 | } 105 | declare module 'builder/lib/utils/archetype.js' { 106 | declare module.exports: $Exports<'builder/lib/utils/archetype'>; 107 | } 108 | declare module 'builder/lib/utils/clone.js' { 109 | declare module.exports: $Exports<'builder/lib/utils/clone'>; 110 | } 111 | declare module 'builder/lib/utils/json.js' { 112 | declare module.exports: $Exports<'builder/lib/utils/json'>; 113 | } 114 | declare module 'builder/lib/utils/tracker.js' { 115 | declare module.exports: $Exports<'builder/lib/utils/tracker'>; 116 | } 117 | -------------------------------------------------------------------------------- /test/environment/hash-router.spec.js: -------------------------------------------------------------------------------- 1 | import chai, { expect } from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | import { fromJS } from 'immutable'; 5 | import { combineReducers as combineReduxReducers } from 'redux'; 6 | import { combineReducers as combineImmutableReducers } from 'redux-immutable'; 7 | import * as createHashHistory from 'history/createHashHistory'; 8 | 9 | import routerForHash from '../../src/environment/hash-router'; 10 | import immutableRouterForHash from '../../src/immutable/environment/hash-router'; 11 | 12 | import { setupStoreForEnv } from '../test-util'; 13 | import routes from '../test-util/fixtures/routes'; 14 | 15 | chai.use(sinonChai); 16 | 17 | const hashRouterTest = { 18 | router: routerForHash, 19 | combineReducers: combineReduxReducers, 20 | toState: state => state, 21 | readState: state => state, 22 | testLabel: 'hash router' 23 | }; 24 | const immutableHashRouterTest = { 25 | router: immutableRouterForHash, 26 | combineReducers: combineImmutableReducers, 27 | toState: state => fromJS(state), 28 | readState: state => state.toJS(), 29 | testLabel: 'immutable hash router' 30 | }; 31 | 32 | [hashRouterTest, immutableHashRouterTest].forEach( 33 | ({ router, combineReducers, toState, readState, testLabel }) => { 34 | describe(`${testLabel}`, () => { 35 | const setupHashStore = setupStoreForEnv( 36 | router, 37 | combineReducers, 38 | toState({}) 39 | ); 40 | 41 | it('creates a hash store enhancer using window.location', () => { 42 | const store = setupHashStore({ 43 | routes, 44 | history: { 45 | listen() {}, 46 | location: { 47 | pathname: '/home', 48 | search: '?get=schwifty' 49 | } 50 | } 51 | }); 52 | 53 | const state = readState(store.getState()); 54 | expect(state).to.have.nested.property('router.pathname', '/home'); 55 | expect(state).to.have.nested.property('router.search', '?get=schwifty'); 56 | expect(state) 57 | .to.have.nested.property('router.query') 58 | .that.deep.equals({ get: 'schwifty' }); 59 | }); 60 | 61 | it('supports basenames', () => { 62 | const store = setupHashStore({ 63 | routes, 64 | history: { 65 | listen() {}, 66 | location: { 67 | pathname: '/home', 68 | search: '?get=schwifty' 69 | } 70 | }, 71 | basename: '/cob-planet' 72 | }); 73 | 74 | const state = readState(store.getState()); 75 | expect(state).to.have.nested.property('router.basename', '/cob-planet'); 76 | expect(state).to.have.nested.property('router.pathname', '/home'); 77 | expect(state).to.have.nested.property('router.search', '?get=schwifty'); 78 | expect(state) 79 | .to.have.nested.property('router.query') 80 | .that.deep.equals({ get: 'schwifty' }); 81 | }); 82 | 83 | it('calls createHashHistory when history is not provided', () => { 84 | sandbox.stub(createHashHistory, 'default').returns({ 85 | listen() {}, 86 | location: { 87 | pathname: '/home', 88 | search: '?get=schwifty' 89 | } 90 | }); 91 | setupHashStore({ 92 | routes, 93 | basename: '/cob-planet' 94 | }); 95 | expect(createHashHistory.default).to.be.calledWith({ 96 | basename: '/cob-planet', 97 | hashType: 'slash' 98 | }); 99 | }); 100 | }); 101 | } 102 | ); 103 | -------------------------------------------------------------------------------- /demo/server/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const hook = require('css-modules-require-hook'); 5 | 6 | hook({ 7 | generateScopedName: '[local]___[hash:base64:5]', 8 | rootDir: path.resolve('src') 9 | }); 10 | 11 | require('babel-register')(); 12 | 13 | const fs = require('fs'); 14 | const express = require('express'); 15 | const app = express(); 16 | 17 | const webpackDevMiddleware = require('webpack-dev-middleware'); 18 | const webpack = require('webpack'); 19 | const config = require('../../config/webpack/demo/webpack.config.demo.dev.js'); 20 | 21 | const Handlebars = require('handlebars'); 22 | 23 | const encode = require('ent/encode'); 24 | 25 | const renderToString = require('react-dom/server').renderToString; 26 | 27 | const redux = require('redux'); 28 | 29 | /* Invert comments for immutable */ 30 | const routerForExpress = require('../../src').routerForExpress; 31 | const combineReducers = redux.combineReducers; 32 | // const routerForExpress = require('../../src/immutable').immutableRouterForExpress; 33 | // const Map = require('immutable').Map; 34 | // const combineReducers = require('redux-immutable').combineReducers; 35 | 36 | const routes = require('../client/routes').default; 37 | const wrap = require('../client/wrap').default; 38 | const Root = require('../client/demo').default; 39 | 40 | const createStore = redux.createStore; 41 | const compose = redux.compose; 42 | const applyMiddleware = redux.applyMiddleware; 43 | 44 | const PORT = 4567; 45 | const DISABLE_SSR = process.env.DISABLE_SSR; 46 | 47 | const templateFile = fs.readFileSync(path.join(__dirname, 'index.hbs')); 48 | const template = Handlebars.compile(templateFile.toString()); 49 | 50 | const compiler = webpack(config); 51 | 52 | app.use(express.static('public')); 53 | 54 | app.use( 55 | webpackDevMiddleware(compiler, { 56 | contentBase: './demo', 57 | headers: { 58 | 'Access-Control-Allow-Origin': '*' 59 | }, 60 | serverSideRender: true, 61 | stats: { 62 | chunks: false, 63 | children: false, 64 | colors: true, 65 | hash: false 66 | } 67 | }) 68 | ); 69 | 70 | app.use('/favicon.ico', (req, res) => res.end()); 71 | 72 | app.get('/*', (req, res) => { 73 | const assets = res.locals.webpackStats.toJson().assetsByChunkName.app; 74 | const css = assets.filter(asset => path.extname(asset) === '.css'); 75 | const js = assets.filter(asset => path.extname(asset) === '.js'); 76 | 77 | if (DISABLE_SSR) { 78 | // eslint-disable-next-line no-console 79 | console.info('SSR DISABLED'); 80 | return res.send(template({ css, js })); 81 | } 82 | 83 | /* Invert comments for immutable */ 84 | const initialState = {}; 85 | const initialStateJSON = encode(JSON.stringify(initialState)); 86 | // const initialState = Map(); 87 | // const initialStateJSON = JSON.stringify(initialState.toJSON()); 88 | 89 | const router = routerForExpress({ routes, request: req }); 90 | const store = createStore( 91 | combineReducers({ router: router.reducer }), 92 | initialState, 93 | compose(router.enhancer, applyMiddleware(router.middleware)) 94 | ); 95 | 96 | const content = renderToString(wrap(store)(Root)); 97 | 98 | return res.send( 99 | template({ 100 | initialState: initialStateJSON, 101 | css, 102 | js, 103 | content 104 | }) 105 | ); 106 | }); 107 | 108 | app.listen(PORT, error => { 109 | if (error) { 110 | // eslint-disable-next-line no-console 111 | console.error(error); 112 | } else { 113 | // eslint-disable-next-line no-console 114 | console.info(`Listening on port ${PORT}`); 115 | } 116 | }); 117 | -------------------------------------------------------------------------------- /src/enhancer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { 3 | StoreCreator, 4 | Reducer, 5 | StoreEnhancer, 6 | Dispatch, 7 | Store 8 | } from 'redux'; 9 | import type { History, Action, Location as HistoryLocation } from 'history'; 10 | 11 | import type { State } from './types'; 12 | 13 | import qs from 'query-string'; 14 | 15 | import { POP } from './types'; 16 | import { locationDidChange, didReplaceRoutes, replace } from './actions'; 17 | 18 | import matchCache from './util/match-cache'; 19 | 20 | type SubscribeArgs = { 21 | getState: Function, 22 | dispatch: Dispatch<*>, 23 | createMatcher: Function, 24 | matchRoute: Function, 25 | subscribeToStore: $PropertyType, 'subscribe'>, 26 | subscribeToHistory: $PropertyType 27 | }; 28 | 29 | export type EnhancerArgs = {| 30 | history: History, 31 | matchRoute: Function, 32 | createMatcher: Function 33 | |}; 34 | 35 | export const createStoreSubscriber = ( 36 | getState: Function, 37 | dispatch: Dispatch<*>, 38 | createMatcher: Function 39 | ) => (currentMatcher: Function) => { 40 | const { routes, pathname, search, hash, updateRoutes } = getState(); 41 | 42 | if (updateRoutes) { 43 | currentMatcher = createMatcher(routes); 44 | dispatch(didReplaceRoutes()); 45 | dispatch(replace({ pathname, search, hash })); 46 | } 47 | 48 | return currentMatcher; 49 | }; 50 | 51 | export const createHistoryListener = (dispatch: Dispatch<*>) => ( 52 | currentMatcher: Function, 53 | location: HistoryLocation, 54 | action?: Action 55 | ) => { 56 | matchCache.clear(); 57 | 58 | const match = currentMatcher(location.pathname); 59 | const payload = { 60 | ...location, 61 | ...match, 62 | query: qs.parse(location.search || '') 63 | }; 64 | 65 | // Other actions come from the user, so they already have a 66 | // corresponding queued navigation action. 67 | if (action === 'POP') { 68 | dispatch({ 69 | type: POP, 70 | payload 71 | }); 72 | } 73 | 74 | dispatch(locationDidChange(payload)); 75 | }; 76 | 77 | export const subscribeToStoreAndHistory = ({ 78 | getState, 79 | dispatch, 80 | createMatcher, 81 | matchRoute, 82 | subscribeToStore, 83 | subscribeToHistory 84 | }: SubscribeArgs) => { 85 | const storeSubscriber = createStoreSubscriber( 86 | getState, 87 | dispatch, 88 | createMatcher 89 | ); 90 | const historyListener = createHistoryListener(dispatch); 91 | 92 | let currentMatcher = matchRoute; 93 | 94 | // Replace the matcher when replacing routes 95 | subscribeToStore(() => { 96 | currentMatcher = storeSubscriber(currentMatcher); 97 | }); 98 | 99 | subscribeToHistory((location, action) => 100 | historyListener(currentMatcher, location, action) 101 | ); 102 | }; 103 | 104 | export default ({ history, matchRoute, createMatcher }: EnhancerArgs) => ( 105 | createStore: StoreCreator<*, *> 106 | ) => ( 107 | userReducer: Reducer<*, *>, 108 | initialState: State, 109 | enhancer: StoreEnhancer<*, *> 110 | ) => { 111 | const store = createStore(userReducer, initialState, enhancer); 112 | const { dispatch, subscribe: subscribeToStore } = store; 113 | const { listen: subscribeToHistory } = history; 114 | 115 | const getState = () => { 116 | const routerState = store.getState().router; 117 | const { options: { updateRoutes } = {} } = routerState; 118 | return { ...routerState, updateRoutes }; 119 | }; 120 | 121 | subscribeToStoreAndHistory({ 122 | getState, 123 | dispatch, 124 | createMatcher, 125 | matchRoute, 126 | subscribeToStore, 127 | subscribeToHistory 128 | }); 129 | 130 | return { 131 | ...store, 132 | matchRoute 133 | }; 134 | }; 135 | -------------------------------------------------------------------------------- /flow-typed/npm/nyc_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6bf2d783bd157994ecd8821905341791 2 | // flow-typed version: <>/nyc_v^11.0.3/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'nyc' 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 'nyc' { 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 'nyc/bin/nyc' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'nyc/bin/wrap' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'nyc/lib/commands/check-coverage' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'nyc/lib/commands/instrument' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'nyc/lib/commands/report' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'nyc/lib/config-util' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'nyc/lib/hash' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'nyc/lib/instrumenters/istanbul' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'nyc/lib/instrumenters/noop' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'nyc/lib/process-args' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'nyc/lib/process' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'nyc/lib/self-coverage-helper' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'nyc/lib/source-maps' { 74 | declare module.exports: any; 75 | } 76 | 77 | // Filename aliases 78 | declare module 'nyc/bin/nyc.js' { 79 | declare module.exports: $Exports<'nyc/bin/nyc'>; 80 | } 81 | declare module 'nyc/bin/wrap.js' { 82 | declare module.exports: $Exports<'nyc/bin/wrap'>; 83 | } 84 | declare module 'nyc/index' { 85 | declare module.exports: $Exports<'nyc'>; 86 | } 87 | declare module 'nyc/index.js' { 88 | declare module.exports: $Exports<'nyc'>; 89 | } 90 | declare module 'nyc/lib/commands/check-coverage.js' { 91 | declare module.exports: $Exports<'nyc/lib/commands/check-coverage'>; 92 | } 93 | declare module 'nyc/lib/commands/instrument.js' { 94 | declare module.exports: $Exports<'nyc/lib/commands/instrument'>; 95 | } 96 | declare module 'nyc/lib/commands/report.js' { 97 | declare module.exports: $Exports<'nyc/lib/commands/report'>; 98 | } 99 | declare module 'nyc/lib/config-util.js' { 100 | declare module.exports: $Exports<'nyc/lib/config-util'>; 101 | } 102 | declare module 'nyc/lib/hash.js' { 103 | declare module.exports: $Exports<'nyc/lib/hash'>; 104 | } 105 | declare module 'nyc/lib/instrumenters/istanbul.js' { 106 | declare module.exports: $Exports<'nyc/lib/instrumenters/istanbul'>; 107 | } 108 | declare module 'nyc/lib/instrumenters/noop.js' { 109 | declare module.exports: $Exports<'nyc/lib/instrumenters/noop'>; 110 | } 111 | declare module 'nyc/lib/process-args.js' { 112 | declare module.exports: $Exports<'nyc/lib/process-args'>; 113 | } 114 | declare module 'nyc/lib/process.js' { 115 | declare module.exports: $Exports<'nyc/lib/process'>; 116 | } 117 | declare module 'nyc/lib/self-coverage-helper.js' { 118 | declare module.exports: $Exports<'nyc/lib/self-coverage-helper'>; 119 | } 120 | declare module 'nyc/lib/source-maps.js' { 121 | declare module.exports: $Exports<'nyc/lib/source-maps'>; 122 | } 123 | -------------------------------------------------------------------------------- /test/util/flatten-routes.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-nested-callbacks */ 2 | import { expect } from 'chai'; 3 | 4 | import flattenRoutes from '../../src/util/flatten-routes'; 5 | 6 | describe('Route flattening', () => { 7 | it('does not affect flat routes', () => { 8 | const flatRoutes = { 9 | '/': { 10 | title: 'Home' 11 | }, 12 | '/messages': { 13 | title: 'Message' 14 | }, 15 | '/messages/:user': { 16 | title: 'Message History' 17 | } 18 | }; 19 | 20 | expect(flattenRoutes(flatRoutes)).to.deep.equal(flatRoutes); 21 | }); 22 | 23 | it('flattens nested routes', () => { 24 | const nestedRoutes = { 25 | '/': { 26 | title: 'Home', 27 | '/messages': { 28 | title: 'Messages', 29 | '/:user': { 30 | title: 'Messages by User', 31 | '/:thing': { 32 | title: 'Thing' 33 | } 34 | } 35 | }, 36 | '/lmao': { 37 | title: 'lmao', 38 | '/:ayy': { 39 | title: 'lmaos with ayys' 40 | } 41 | }, 42 | '/things/stuff': { 43 | title: 'flat route!' 44 | }, 45 | '/nested': { 46 | title: 'Nested', 47 | '/a': { 48 | title: 'a', 49 | '/:f': { 50 | title: 'f' 51 | } 52 | } 53 | } 54 | } 55 | }; 56 | 57 | expect(flattenRoutes(nestedRoutes)).to.deep.equal({ 58 | '/messages/:user/:thing': { 59 | title: 'Thing', 60 | parent: { 61 | title: 'Messages by User', 62 | parent: { 63 | title: 'Messages', 64 | parent: { 65 | title: 'Home', 66 | route: '/' 67 | }, 68 | route: '/messages' 69 | }, 70 | route: '/messages/:user' 71 | } 72 | }, 73 | '/messages/:user': { 74 | title: 'Messages by User', 75 | parent: { 76 | title: 'Messages', 77 | parent: { 78 | title: 'Home', 79 | route: '/' 80 | }, 81 | route: '/messages' 82 | } 83 | }, 84 | '/lmao/:ayy': { 85 | title: 'lmaos with ayys', 86 | parent: { 87 | title: 'lmao', 88 | parent: { 89 | title: 'Home', 90 | route: '/' 91 | }, 92 | route: '/lmao' 93 | } 94 | }, 95 | '/nested/a/:f': { 96 | title: 'f', 97 | parent: { 98 | title: 'a', 99 | parent: { 100 | title: 'Nested', 101 | parent: { 102 | title: 'Home', 103 | route: '/' 104 | }, 105 | route: '/nested' 106 | }, 107 | route: '/nested/a' 108 | } 109 | }, 110 | '/nested/a': { 111 | title: 'a', 112 | parent: { 113 | title: 'Nested', 114 | parent: { 115 | title: 'Home', 116 | route: '/' 117 | }, 118 | route: '/nested' 119 | } 120 | }, 121 | '/messages': { 122 | title: 'Messages', 123 | parent: { 124 | title: 'Home', 125 | route: '/' 126 | } 127 | }, 128 | '/lmao': { 129 | title: 'lmao', 130 | parent: { 131 | title: 'Home', 132 | route: '/' 133 | } 134 | }, 135 | '/things/stuff': { 136 | title: 'flat route!', 137 | parent: { 138 | title: 'Home', 139 | route: '/' 140 | } 141 | }, 142 | '/nested': { 143 | title: 'Nested', 144 | parent: { 145 | title: 'Home', 146 | route: '/' 147 | } 148 | }, 149 | '/': { 150 | title: 'Home' 151 | } 152 | }); 153 | }); 154 | }); 155 | -------------------------------------------------------------------------------- /flow-typed/npm/webpack-dev-server_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 460665e6f93d7d337f9f1b57da4c72bb 2 | // flow-typed version: <>/webpack-dev-server_v^2.5.0/flow_v0.64.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'webpack-dev-server' 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 'webpack-dev-server' { 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 'webpack-dev-server/bin/webpack-dev-server' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'webpack-dev-server/client/index.bundle' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'webpack-dev-server/client/index' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'webpack-dev-server/client/live.bundle' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'webpack-dev-server/client/overlay' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'webpack-dev-server/client/socket' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'webpack-dev-server/client/sockjs.bundle' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'webpack-dev-server/lib/OptionsValidationError' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'webpack-dev-server/lib/polyfills' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'webpack-dev-server/lib/Server' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'webpack-dev-server/lib/util/addDevServerEntrypoints' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'webpack-dev-server/lib/util/createDomain' { 70 | declare module.exports: any; 71 | } 72 | 73 | // Filename aliases 74 | declare module 'webpack-dev-server/bin/webpack-dev-server.js' { 75 | declare module.exports: $Exports<'webpack-dev-server/bin/webpack-dev-server'>; 76 | } 77 | declare module 'webpack-dev-server/client/index.bundle.js' { 78 | declare module.exports: $Exports<'webpack-dev-server/client/index.bundle'>; 79 | } 80 | declare module 'webpack-dev-server/client/index.js' { 81 | declare module.exports: $Exports<'webpack-dev-server/client/index'>; 82 | } 83 | declare module 'webpack-dev-server/client/live.bundle.js' { 84 | declare module.exports: $Exports<'webpack-dev-server/client/live.bundle'>; 85 | } 86 | declare module 'webpack-dev-server/client/overlay.js' { 87 | declare module.exports: $Exports<'webpack-dev-server/client/overlay'>; 88 | } 89 | declare module 'webpack-dev-server/client/socket.js' { 90 | declare module.exports: $Exports<'webpack-dev-server/client/socket'>; 91 | } 92 | declare module 'webpack-dev-server/client/sockjs.bundle.js' { 93 | declare module.exports: $Exports<'webpack-dev-server/client/sockjs.bundle'>; 94 | } 95 | declare module 'webpack-dev-server/lib/OptionsValidationError.js' { 96 | declare module.exports: $Exports<'webpack-dev-server/lib/OptionsValidationError'>; 97 | } 98 | declare module 'webpack-dev-server/lib/polyfills.js' { 99 | declare module.exports: $Exports<'webpack-dev-server/lib/polyfills'>; 100 | } 101 | declare module 'webpack-dev-server/lib/Server.js' { 102 | declare module.exports: $Exports<'webpack-dev-server/lib/Server'>; 103 | } 104 | declare module 'webpack-dev-server/lib/util/addDevServerEntrypoints.js' { 105 | declare module.exports: $Exports<'webpack-dev-server/lib/util/addDevServerEntrypoints'>; 106 | } 107 | declare module 'webpack-dev-server/lib/util/createDomain.js' { 108 | declare module.exports: $Exports<'webpack-dev-server/lib/util/createDomain'>; 109 | } 110 | -------------------------------------------------------------------------------- /demo/client/demo.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-magic-numbers */ 2 | import React from 'react'; 3 | import { connect } from 'react-redux'; 4 | import PropTypes from 'prop-types'; 5 | import chunk from 'lodash.chunk'; 6 | 7 | /* Invert comments for immutable */ 8 | import { Link, Fragment } from '../../src'; 9 | // import { ImmutableLink as Link, ImmutableFragment as Fragment } from '../../src/immutable'; 10 | 11 | import styles from './demo.css'; 12 | 13 | const COLUMN_COUNT = 2; 14 | 15 | const columnize = (array, columns) => { 16 | const remainder = array.length % columns; 17 | const chunkSize = Math.floor(array.length / columns); 18 | const firstChunkSize = chunkSize + remainder; 19 | const firstChunk = array.slice(0, firstChunkSize); 20 | return [firstChunk].concat( 21 | chunk(array.slice(firstChunkSize, array.length), chunkSize) 22 | ); 23 | }; 24 | 25 | const Gallery = ({ images, columns, ...rest }) => ( 26 |
27 | {columnize(images, columns).map((column, index) => ( 28 |
29 | {column.map((image, imageIndex) => ( 30 | 31 | ))} 32 |
33 | ))} 34 |
35 | ); 36 | 37 | Gallery.propTypes = { 38 | columns: PropTypes.number, 39 | images: PropTypes.arrayOf(PropTypes.string) 40 | }; 41 | 42 | // eslint-disable-next-line react/no-multi-comp 43 | const Demo = ({ location }) => { 44 | const demoRoutes = ['/cheese', '/cat', '/dog', '/hipster']; 45 | return ( 46 |
47 | 48 |
49 |

50 | A Compendium of 51 |
52 | Ipsums and GIFs 53 |

54 | 55 |
56 | 57 | Cheese 58 | 59 | Dog 60 | Cat 61 | Hipster 62 | 70 | My Design Skills 71 | 72 |
73 | 74 |
75 | {demoRoutes.map(route => ( 76 | 77 |
78 |

{location.result && location.result.text}

79 | 83 |
84 |
85 | ))} 86 |
87 | 88 | 89 |

Pickum ipsum!

90 |
91 | 92 | 93 |
94 |

FOUR O'FOUR

95 |

Looks like you found something that doesn't exist!

96 | 100 |
101 |
102 |
103 |
104 |
105 | ); 106 | }; 107 | 108 | Demo.propTypes = { 109 | location: PropTypes.object 110 | }; 111 | 112 | const mapStateToProps = state => ({ 113 | /* Invert comments for immutable */ 114 | location: state.router 115 | // location: state.get('router').toJS() 116 | }); 117 | 118 | export default connect(mapStateToProps)(Demo); 119 | -------------------------------------------------------------------------------- /src/reducer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Location, LocationOptions, LocationAction } from './types'; 3 | 4 | import { 5 | LOCATION_CHANGED, 6 | REPLACE_ROUTES, 7 | DID_REPLACE_ROUTES, 8 | isNavigationActionWithPayload 9 | } from './types'; 10 | 11 | import mergeQueries from './util/merge-queries'; 12 | 13 | type ResolverArgs = { 14 | oldLocation: Location, 15 | newLocation: Location, 16 | options: LocationOptions 17 | }; 18 | 19 | export type ReducerArgs = {| 20 | routes: Object, 21 | initialLocation: Location 22 | |}; 23 | 24 | const flow = (...funcs: Array<*>) => 25 | funcs.reduce((prev, curr) => (...args: Array<*>) => curr(prev(...args))); 26 | 27 | const resolveQuery = ({ 28 | oldLocation, 29 | newLocation, 30 | options 31 | }: ResolverArgs): ResolverArgs => { 32 | // Merge the old and new queries if asked to persist 33 | if (options.persistQuery) { 34 | const mergedQuery = mergeQueries(oldLocation.query, newLocation.query); 35 | return { 36 | oldLocation, 37 | newLocation: { 38 | ...newLocation, 39 | ...mergedQuery 40 | }, 41 | options 42 | }; 43 | } 44 | 45 | return { 46 | oldLocation, 47 | newLocation: { 48 | ...newLocation, 49 | query: newLocation.query 50 | }, 51 | options 52 | }; 53 | }; 54 | 55 | const resolveBasename = ({ 56 | oldLocation, 57 | newLocation, 58 | options 59 | }: ResolverArgs): ResolverArgs => { 60 | const { basename } = oldLocation; 61 | if (basename) { 62 | return { 63 | oldLocation, 64 | newLocation: { basename, ...newLocation }, 65 | options 66 | }; 67 | } 68 | return { oldLocation, newLocation, options }; 69 | }; 70 | 71 | const resolvePrevious = ({ 72 | oldLocation, 73 | newLocation, 74 | options 75 | }: ResolverArgs): ResolverArgs => ({ 76 | oldLocation, 77 | newLocation: { 78 | ...newLocation, 79 | previous: oldLocation 80 | }, 81 | options 82 | }); 83 | 84 | export const resolveLocation = flow( 85 | resolveQuery, 86 | resolveBasename, 87 | resolvePrevious 88 | ); 89 | 90 | const locationChangeReducer = (state, action) => { 91 | // No-op the initial route action 92 | const { queue = [] } = state; 93 | if ( 94 | state.pathname === action.payload.pathname && 95 | state.search === action.payload.search && 96 | state.hash === action.payload.hash && 97 | !queue.length 98 | ) { 99 | return state; 100 | } 101 | 102 | const queuedLocation = queue[0] || {}; 103 | const newQueue = queue.slice(1); 104 | 105 | // Extract the previous state, but dump the 106 | // previous state's previous state so that the 107 | // state tree doesn't keep growing indefinitely 108 | // eslint-disable-next-line no-unused-vars 109 | const { previous, routes: currentRoutes = {}, ...oldLocation } = state; 110 | const { options = {}, query = {} } = queuedLocation; 111 | const newLocation = { ...action.payload, query }; 112 | 113 | const { newLocation: resolvedNewLocation } = resolveLocation({ 114 | oldLocation, 115 | newLocation, 116 | options 117 | }); 118 | 119 | return { ...resolvedNewLocation, routes: currentRoutes, queue: newQueue }; 120 | }; 121 | 122 | export default ({ routes = {}, initialLocation }: ReducerArgs = {}) => ( 123 | state: Location = { ...initialLocation, routes, queue: [] }, 124 | action: LocationAction 125 | ) => { 126 | if (isNavigationActionWithPayload(action)) { 127 | return { 128 | ...state, 129 | queue: state.queue && state.queue.concat([action.payload]) 130 | }; 131 | } 132 | 133 | if (action.type === REPLACE_ROUTES) { 134 | return { 135 | ...state, 136 | routes: action.payload.routes, 137 | options: action.payload.options 138 | }; 139 | } 140 | 141 | if (action.type === DID_REPLACE_ROUTES) { 142 | return { ...state, options: {} }; 143 | } 144 | 145 | if (action.type === LOCATION_CHANGED) { 146 | return locationChangeReducer(state, action); 147 | } 148 | 149 | return state; 150 | }; 151 | -------------------------------------------------------------------------------- /flow-typed/npm/enzyme_v2.3.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 905cf3353a9aaa3647dc2232b1cd864a 2 | // flow-typed version: 8742c67386/enzyme_v2.3.x/flow_>=v0.53.x 3 | 4 | import * as React from "react"; 5 | 6 | declare module "enzyme" { 7 | declare type PredicateFunction = ( 8 | wrapper: T, 9 | index: number 10 | ) => boolean; 11 | declare type NodeOrNodes = React.Node | Array; 12 | declare type EnzymeSelector = string | Class> | Object; 13 | 14 | // CheerioWrapper is a type alias for an actual cheerio instance 15 | // TODO: Reference correct type from cheerio's type declarations 16 | declare type CheerioWrapper = any; 17 | 18 | declare class Wrapper { 19 | find(selector: EnzymeSelector): this, 20 | findWhere(predicate: PredicateFunction): this, 21 | filter(selector: EnzymeSelector): this, 22 | filterWhere(predicate: PredicateFunction): this, 23 | contains(nodeOrNodes: NodeOrNodes): boolean, 24 | containsMatchingElement(node: React.Node): boolean, 25 | containsAllMatchingElements(nodes: NodeOrNodes): boolean, 26 | containsAnyMatchingElements(nodes: NodeOrNodes): boolean, 27 | dive(option?: { context?: Object }): this, 28 | exists(): boolean, 29 | matchesElement(node: React.Node): boolean, 30 | hasClass(className: string): boolean, 31 | is(selector: EnzymeSelector): boolean, 32 | isEmpty(): boolean, 33 | not(selector: EnzymeSelector): this, 34 | children(selector?: EnzymeSelector): this, 35 | childAt(index: number): this, 36 | parents(selector?: EnzymeSelector): this, 37 | parent(): this, 38 | closest(selector: EnzymeSelector): this, 39 | render(): CheerioWrapper, 40 | unmount(): this, 41 | text(): string, 42 | html(): string, 43 | get(index: number): React.Node, 44 | getNode(): React.Node, 45 | getNodes(): Array, 46 | getDOMNode(): HTMLElement | HTMLInputElement, 47 | at(index: number): this, 48 | first(): this, 49 | last(): this, 50 | state(key?: string): any, 51 | context(key?: string): any, 52 | props(): Object, 53 | prop(key: string): any, 54 | key(): string, 55 | simulate(event: string, ...args: Array): this, 56 | setState(state: {}, callback?: Function): this, 57 | setProps(props: {}): this, 58 | setContext(context: Object): this, 59 | instance(): React.Component<*, *>, 60 | update(): this, 61 | debug(): string, 62 | type(): string | Function | null, 63 | name(): string, 64 | forEach(fn: (node: this, index: number) => mixed): this, 65 | map(fn: (node: this, index: number) => T): Array, 66 | reduce( 67 | fn: (value: T, node: this, index: number) => T, 68 | initialValue?: T 69 | ): Array, 70 | reduceRight( 71 | fn: (value: T, node: this, index: number) => T, 72 | initialValue?: T 73 | ): Array, 74 | some(selector: EnzymeSelector): boolean, 75 | someWhere(predicate: PredicateFunction): boolean, 76 | every(selector: EnzymeSelector): boolean, 77 | everyWhere(predicate: PredicateFunction): boolean, 78 | length: number 79 | } 80 | 81 | declare export class ReactWrapper extends Wrapper { 82 | constructor(nodes: NodeOrNodes, root: any, options?: ?Object): ReactWrapper, 83 | mount(): this, 84 | ref(refName: string): this, 85 | detach(): void 86 | } 87 | 88 | declare export class ShallowWrapper extends Wrapper { 89 | constructor(nodes: NodeOrNodes, root: any, options?: ?Object): ShallowWrapper; 90 | equals(node: React.Node): boolean, 91 | shallow(options?: { context?: Object }): ShallowWrapper 92 | } 93 | 94 | declare export function shallow( 95 | node: React.Node, 96 | options?: { context?: Object } 97 | ): ShallowWrapper; 98 | declare export function mount( 99 | node: React.Node, 100 | options?: { 101 | context?: Object, 102 | attachTo?: HTMLElement, 103 | childContextTypes?: Object 104 | } 105 | ): ReactWrapper; 106 | declare export function render( 107 | node: React.Node, 108 | options?: { context?: Object } 109 | ): CheerioWrapper; 110 | } 111 | -------------------------------------------------------------------------------- /flow-typed/npm/react-redux_v5.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 59b0c4be0e1408f21e2446be96c79804 2 | // flow-typed version: 9092387fd2/react-redux_v5.x.x/flow_>=v0.54.x 3 | 4 | import type { Dispatch, Store } from "redux"; 5 | 6 | declare module "react-redux" { 7 | /* 8 | 9 | S = State 10 | A = Action 11 | OP = OwnProps 12 | SP = StateProps 13 | DP = DispatchProps 14 | 15 | */ 16 | 17 | declare type MapStateToProps = ( 18 | state: S, 19 | ownProps: OP 20 | ) => ((state: S, ownProps: OP) => SP) | SP; 21 | 22 | declare type MapDispatchToProps = 23 | | ((dispatch: Dispatch
, ownProps: OP) => DP) 24 | | DP; 25 | 26 | declare type MergeProps = ( 27 | stateProps: SP, 28 | dispatchProps: DP, 29 | ownProps: OP 30 | ) => P; 31 | 32 | declare type Context = { store: Store<*, *> }; 33 | 34 | declare type ComponentWithDefaultProps = Class< 35 | React$Component 36 | > & { defaultProps: DP }; 37 | 38 | declare class ConnectedComponentWithDefaultProps< 39 | OP, 40 | DP, 41 | CP 42 | > extends React$Component { 43 | static defaultProps: DP, // <= workaround for https://github.com/facebook/flow/issues/4644 44 | static WrappedComponent: Class>, 45 | getWrappedInstance(): React$Component, 46 | props: OP, 47 | state: void 48 | } 49 | 50 | declare class ConnectedComponent extends React$Component { 51 | static WrappedComponent: Class>, 52 | getWrappedInstance(): React$Component

, 53 | props: OP, 54 | state: void 55 | } 56 | 57 | declare type ConnectedComponentWithDefaultPropsClass = Class< 58 | ConnectedComponentWithDefaultProps 59 | >; 60 | 61 | declare type ConnectedComponentClass = Class< 62 | ConnectedComponent 63 | >; 64 | 65 | declare type Connector = (( 66 | component: ComponentWithDefaultProps 67 | ) => ConnectedComponentWithDefaultPropsClass) & 68 | ((component: React$ComponentType

) => ConnectedComponentClass); 69 | 70 | declare class Provider extends React$Component<{ 71 | store: Store, 72 | children?: any 73 | }> {} 74 | 75 | declare function createProvider( 76 | storeKey?: string, 77 | subKey?: string 78 | ): Provider<*, *>; 79 | 80 | declare type ConnectOptions = { 81 | pure?: boolean, 82 | withRef?: boolean 83 | }; 84 | 85 | declare type Null = null | void; 86 | 87 | declare function connect( 88 | ...rest: Array // <= workaround for https://github.com/facebook/flow/issues/2360 89 | ): Connector } & OP>>; 90 | 91 | declare function connect( 92 | mapStateToProps: Null, 93 | mapDispatchToProps: Null, 94 | mergeProps: Null, 95 | options: ConnectOptions 96 | ): Connector } & OP>>; 97 | 98 | declare function connect( 99 | mapStateToProps: MapStateToProps, 100 | mapDispatchToProps: Null, 101 | mergeProps: Null, 102 | options?: ConnectOptions 103 | ): Connector } & OP>>; 104 | 105 | declare function connect( 106 | mapStateToProps: Null, 107 | mapDispatchToProps: MapDispatchToProps, 108 | mergeProps: Null, 109 | options?: ConnectOptions 110 | ): Connector>; 111 | 112 | declare function connect( 113 | mapStateToProps: MapStateToProps, 114 | mapDispatchToProps: MapDispatchToProps, 115 | mergeProps: Null, 116 | options?: ConnectOptions 117 | ): Connector>; 118 | 119 | declare function connect( 120 | mapStateToProps: MapStateToProps, 121 | mapDispatchToProps: Null, 122 | mergeProps: MergeProps, 123 | options?: ConnectOptions 124 | ): Connector; 125 | 126 | declare function connect( 127 | mapStateToProps: MapStateToProps, 128 | mapDispatchToProps: MapDispatchToProps, 129 | mergeProps: MergeProps, 130 | options?: ConnectOptions 131 | ): Connector; 132 | } 133 | -------------------------------------------------------------------------------- /src/components/link.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Node } from 'react'; 3 | import type { Href, Location } from '../types'; 4 | 5 | import React, { Component } from 'react'; 6 | import { connect } from 'react-redux'; 7 | import PropTypes from 'prop-types'; 8 | 9 | import { push as pushAction, replace as replaceAction } from '../actions'; 10 | import mergeQueries from '../util/merge-queries'; 11 | import normalizeHref from '../util/normalize-href'; 12 | import stringifyHref from '../util/stringify-href'; 13 | 14 | type Props = { 15 | children: Node, 16 | className: string, 17 | href: Href, 18 | persistQuery: boolean, 19 | replaceState: boolean, 20 | target: string, 21 | onClick: EventHandler, 22 | style: Object, 23 | location: Location, 24 | push: typeof pushAction, 25 | replace: typeof replaceAction, 26 | // TODO: replace with recursive Props definition 27 | // https://github.com/yannickcr/eslint-plugin-react/issues/913 28 | activeProps: Object 29 | }; 30 | 31 | const LEFT_MOUSE_BUTTON = 0; 32 | 33 | const isNotLeftClick = e => e.button && e.button !== LEFT_MOUSE_BUTTON; 34 | 35 | const hasModifier = e => 36 | Boolean(e.shiftKey || e.altKey || e.metaKey || e.ctrlKey); 37 | 38 | const shouldIgnoreClick = ({ e, target }) => 39 | hasModifier(e) || isNotLeftClick(e) || e.defaultPrevented || target; 40 | 41 | const handleClick = ({ 42 | e, 43 | target, 44 | href, 45 | onClick, 46 | replaceState, 47 | persistQuery, 48 | push, 49 | replace 50 | }) => { 51 | if (onClick) { 52 | onClick(e); 53 | } 54 | 55 | if (shouldIgnoreClick({ e, target })) { 56 | return; 57 | } 58 | 59 | e.preventDefault(); 60 | 61 | const navigate = replaceState ? replace : push; 62 | navigate(href, { persistQuery }); 63 | }; 64 | 65 | // When persisting queries, we need to merge the persisted 66 | // query with the link's new query. 67 | const contextifyHref = (href, location, persistQuery) => { 68 | if (!persistQuery) { 69 | return href; 70 | } 71 | 72 | const mergedQuery = mergeQueries(location.query, href.query); 73 | 74 | return { 75 | ...href, 76 | ...mergedQuery 77 | }; 78 | }; 79 | 80 | class LinkComponent extends Component<*> { 81 | constructor(props: Props) { 82 | super(props); 83 | } 84 | 85 | render() { 86 | const { 87 | href: rawHref, 88 | location, 89 | children, 90 | onClick, 91 | target, 92 | activeProps, 93 | replaceState, 94 | persistQuery, 95 | push, 96 | replace, 97 | ...rest 98 | } = this.props; 99 | 100 | // Ensure the href has both a search and a query when needed 101 | const normalizedHref = normalizeHref(rawHref); 102 | const href = contextifyHref(normalizedHref, location, persistQuery); 103 | const isActive = href.pathname === location.pathname; 104 | const activeRest = (isActive && activeProps) || {}; 105 | 106 | const clickHandler = e => 107 | handleClick({ 108 | e, 109 | target, 110 | href, 111 | onClick, 112 | replaceState, 113 | persistQuery, 114 | push, 115 | replace 116 | }); 117 | 118 | return ( 119 | 126 | {children} 127 | 128 | ); 129 | } 130 | } 131 | 132 | const PersistentQueryLinkComponent = class extends Component<*> { 133 | render() { 134 | const { children, ...rest } = this.props; 135 | return ( 136 | 137 | {children} 138 | 139 | ); 140 | } 141 | }; 142 | 143 | PersistentQueryLinkComponent.propTypes = { 144 | children: PropTypes.node 145 | }; 146 | 147 | const mapStateToProps = state => ({ location: state.router }); 148 | const mapDispatchToProps = { 149 | push: pushAction, 150 | replace: replaceAction 151 | }; 152 | const withLocation = connect(mapStateToProps, mapDispatchToProps); 153 | 154 | const LinkWithLocation = withLocation(LinkComponent); 155 | const PersistentQueryLinkWithLocation = withLocation( 156 | PersistentQueryLinkComponent 157 | ); 158 | 159 | export { 160 | LinkWithLocation as Link, 161 | PersistentQueryLinkWithLocation as PersistentQueryLink, 162 | LinkComponent, 163 | PersistentQueryLinkComponent, 164 | mapDispatchToProps 165 | }; 166 | --------------------------------------------------------------------------------