{"_id":"@elegantthemes/cerebral-router","_rev":"2-30c581cd41aae3dc53dc2a82a839a44a","name":"@elegantthemes/cerebral-router","dist-tags":{"latest":"3.2.4"},"versions":{"3.2.4":{"name":"@elegantthemes/cerebral-router","version":"3.2.4","description":"An opinionated URL change handler for Cerebral","main":"lib/index.js","author":{"name":"Dustin Falgout","email":"dustin@elegantthemes.com"},"contributors":[{"name":"Christian Alfoni","email":"christianalfoni@gmail.com"},{"name":"Aleksey Guryanov","email":"gurianov@gmail.com"}],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/elegantthemes/cerebral-router.git"},"bugs":{"url":"https://github.com/elegantthemes/cerebral-router/issues"},"homepage":"https://github.com/elegantthemes/cerebral-router","dependencies":{"addressbar":"1.0.3","cerebral":"4.2.2","url-mapper":"2.0.0"},"scripts":{"test":"mocha -r test/setup  --require babel-register \"src/**/*.test.js\" \"test/**/*.test.js\"","build":"cross-env BABEL_ENV=production babel src/ --out-dir=lib/ -s","coverage":"nyc --reporter=lcov --reporter=json yarn run test","prepublish":"yarn build"},"nyc":{"exclude":["node_modules","lib","tests","**/*.test.js","**/testHelper.js"]},"devDependencies":{"cross-env":"5.2.0","babel-cli":"6.24.1","babel-core":"6.24.1","babel-jest":"22.0.6","babel-plugin-transform-builtin-extend":"1.1.2","babel-plugin-transform-decorators-legacy":"1.3.4","babel-plugin-version-transform":"1.0.0","babel-preset-es2015":"6.24.1","babel-preset-typescript":"7.0.0-alpha.19","babel-register":"6.23.0","babel-watch":"2.0.5"},"_id":"@elegantthemes/cerebral-router@3.2.4","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-6T8e7b3d6HPnmHzK1uxudNwbWFYWiCSab7v17uOcu/0SAkFB0EiCPccjelGd6+lviC7GSvVlNC/+zI2dhv38kg==","shasum":"040f0a85ba8180aecd64c030dbfc1e279928155d","tarball":"https://registry.npmjs.org/@elegantthemes/cerebral-router/-/cerebral-router-3.2.4.tgz","fileCount":24,"unpackedSize":62488,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+FeNCRA9TVsSAnZWagAAuHQQAJrqnM2s2SPfRr/6Ah9n\ngQhtLENKnBbc/PcgFBpTqxUp3C1Sd/x4+J7usYw2T/PKkaj+aswXCr0j+1ON\nM+EMVX7Y12pAPVFqHOTy9aabx3nHJ3dwE3fx/KDHTL47EoWnsO8mgejZDJXR\nWo1oTYrBBHhK2DdVdOrG5EOqq1e4NIl86XM/VikgbGZzOyWZ4ki+9n0ziITd\nAtDK/PcSjyXE2oP7D68M1725MFPnGlGrTGpjBiqUfTHe7q7CcqvQg9Ho57go\nG0MpK5cx0qgmEzlkptQs7V/mBJNvdaQtIsHt0E8Y9Jhv8Yw1rxhOPKH7n8ge\n0A0Y8DNGCI3LVI/X5ef5RrbJbMsEkeYqohs9YvAFrKrbV0RVCDXTki7qTlvU\n7VIMCMI6li7k/wMdabnbhuLVsAlNz/bUOGEYSoaGEjN/rs2Y+c/Liigb+u0n\ncwckw4PhzNqJ8jsNUXqPUOE73ax+dWIC3+x1JoD4N6JG35GoGsyLdOMT5bOp\nMU7o64xftzoIofFJ5JM6pjQMp8vcM+C/DUv3pvEBaCeUVLbkJtocpuivDNvU\n0haJ+tcuAFhP179DFb80h5QdRZiLNjZH73wuqDzeG3rnaLcJo8+ZsoNv1IHs\ncJMj5Epw737Nv6HqJUdIdgaZ3IpKFRxcO2mTnrpGu99obuiJ3veEw9W5nPUW\nC6X2\r\n=6Hf+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCD65F/N+RwmGCE2VIJ9azvLa4ndzE6TfDrMT5aClaHWQIhAObBu5to3XRiR3F0z+ZHhYcDCdnyz0ZXSHOKkQSVF0af"}]},"maintainers":[{"name":"etdevs","email":"dustin@elegantthemes.com"},{"name":"lots0logs","email":"dustin@falgout.us"}],"_npmUser":{"name":"lots0logs","email":"dustin@falgout.us"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/cerebral-router_3.2.4_1559779212198_0.11618322557364635"},"_hasShrinkwrap":false}},"time":{"created":"2019-06-06T00:00:12.133Z","3.2.4":"2019-06-06T00:00:12.332Z","modified":"2023-04-06T20:13:17.435Z"},"maintainers":[{"email":"tahery.michael@gmail.com","name":"7ahery"},{"email":"dustin@elegantthemes.com","name":"etdevs"},{"email":"dustin@falgout.us","name":"lots0logs"}],"description":"An opinionated URL change handler for Cerebral","homepage":"https://github.com/elegantthemes/cerebral-router","repository":{"type":"git","url":"git+https://github.com/elegantthemes/cerebral-router.git"},"contributors":[{"name":"Christian Alfoni","email":"christianalfoni@gmail.com"},{"name":"Aleksey Guryanov","email":"gurianov@gmail.com"}],"author":{"name":"Dustin Falgout","email":"dustin@elegantthemes.com"},"bugs":{"url":"https://github.com/elegantthemes/cerebral-router/issues"},"license":"MIT","readme":"# cerebral-router\nThis is a fork of `@cerebral/router` created to use the latest version of `url-mapper`.\n\nFor more info, see cerebral/cerebral#1259.\n\n## Install\n\n`yarn add elegantthemes/cerebral-router`\n\n## Description\n\nThe router of Cerebral does not affect your view layer. A url change triggers a signal that puts your application in the correct state. Your view just reacts to this state, like any other state change.\n\nRead more about the router in the [Cerebral in depth - Routing](https://www.jsblog.io/articles/christianalfoni/cerebral_in_depth_routing) article.\n\n## Instantiate\n\n```js\nimport { Controller, Module } from 'cerebral'\nimport Router from '@cerebral/router'\n\nconst router = Router({\n  // Define routes and point to signals\n  routes: [\n    {\n      path: '/',\n      signal: 'app.homeRouted'\n    }\n  ],\n\n  // Only react to hash urls\n  onlyHash: false,\n\n  // Set a base url, if your app lives on a subpath\n  baseUrl: null,\n\n  // Will allow none matching routes on same origin to run as normal\n  allowEscape: false,\n\n  // Will make the router not run the initial route\n  preventAutostart: false\n})\nconst app = Module({\n  modules: { router }\n})\n\nconst controller = Controller(app)\n```\n\n## getOrigin\n\n```js\nfunction myAction({ router }) {\n  // If url is \"http://localhost:3000/items?foo=bar\", returns \"http://localhost:3000\"\n  router.getOrigin()\n}\n```\n\n## getPath\n\n```js\nfunction myAction({ router }) {\n  // If url is \"http://localhost:3000/items?foo=bar\", returns \"/items\"\n  router.getPath()\n}\n```\n\n## getSignalUrl\n\nAllows you to convert a signal to its corresponding url. This is useful when you actually want to produce the url for a hyperlink etc. To do this you need to create the router in its own file:\n\n_router.js_\n\n```js\nimport Router from '@cerebral/router'\n\nexport default Router({\n  routes: [\n    {\n      path: '/items/:itemKey',\n      signal: 'items.itemRouted'\n    }\n  ]\n})\n```\n\nAnd attaching it to the controller:\n\n_controller.js_\n\n```js\nimport { Controller } from 'cerebral'\nimport router from './modules/router'\nimport items from './modules/items'\n\nexport default Controller({\n  modules: { items, router }\n})\n```\n\nYou will be able to use the same router instance to produce url based on registered signals:\n\n```js\nimport router from './router'\n\nexport default connect(\n  {\n    item: state`items.list.${props`itemKey`}`\n  },\n  function ListItem({ itemKey, item, itemRouted }) {\n    return (\n      <li key={itemKey}>\n        <a href={router.getSignalUrl('items.itemRouted', { itemKey })}>\n          {item.name}\n        </a>\n      </li>\n    )\n  }\n)\n```\n\n## getUrl\n\n```js\nfunction myAction({ router }) {\n  // If url is \"http://localhost:3000/items?foo=bar\", returns \"/items?foo=bar\"\n  router.getUrl()\n}\n```\n\n## getValues\n\n```js\nfunction myAction({ router }) {\n  // If url is \"http://localhost:3000/items/123?foo=bar\", returns \"{itemId: '123', foo: 'bar'}\"\n  router.getValues()\n}\n```\n\n## goTo\n\n_action_\n\n```js\nfunction myAction({ router }) {\n  // Go to a new url\n  router.goTo('/items')\n}\n```\n\n_operator_\n\n```js\nimport { goTo } from '@cerebral/router/operators'\n\nexport default [goTo('/items')]\n```\n\n_operator with dynamic URL_\n\n```js\nimport { state, string } from 'cerebral/tags'\nimport { goTo } from '@cerebral/router/operators'\n\nexport default [goTo(string`/${state`app.currentView`}`)]\n```\n\n## redirect\n\n_action_\n\n```js\nfunction myAction({ router }) {\n  // Go to a new url, replacing current url\n  router.redirect('/items')\n}\n```\n\n_operator_\n\n```js\nimport { redirect } from '@cerebral/router/operators'\n\nexport default [redirect('/items')]\n```\n\n_operator with dynamic URL_\n\n```js\nimport { state, string } from 'cerebral/tags'\nimport { redirect } from '@cerebral/router/operators'\n\nexport default [redirect(string`/${state`app.currentView`}`)]\n```\n\n## redirectToSignal\n\n_action_\n\n```js\nfunction myAction({ router }) {\n  // Trigger a signal bound to router\n  router.redirectToSignal('app.itemsRouted', { foo: 'bar' })\n}\n```\n\n_operator_\n\n```js\nimport { redirectToSignal } from '@cerebral/router/operators'\n\nexport default [redirectToSignal('app.itemsRouted', props`payload`)]\n```\n\n## reload\n\n_action_\n\n```js\nfunction myAction({ router }) {\n  // reload the current route\n  router.reload()\n}\n```\n\n_operator_\n\n```js\nimport { reload } from '@cerebral/router/operators'\n\nexport default [reload]\n```\n\n## routes\n\n```js\nimport { Controller } from 'cerebral'\nimport Router from '@cerebral/router'\n\nconst controller = Controller({\n  modules: {\n    router: Router({\n      routes: [\n        {\n          path: '/',\n          signal: 'app.homeRouted'\n        },\n        {\n          // Params are passed as props to the signal.\n          // Query parameters are also passed as props\n          path: '/projects/:projectId',\n          signal: 'app.projectRouted'\n        }\n      ]\n    })\n  }\n})\n```\n\nWhen a mapped signal triggers it will trigger with a payload if either **params** are defined on the route or the url has a **query**. For example _/projects/123?showUser=true_ will produce the following payload to the signal, available on the **props** :\n\n```js\n{\n  projectId: '123',\n  showUser: true\n}\n```\n\n## setUrl\n\n```js\nfunction myAction({ router }) {\n  // If url is \"http://localhost:3000\", changes to \"http://localhost:3000/foo\"\n  router.setUrl('/foo')\n}\n```\n\n### EXPERIMENTAL\n\nWe are currently working on functionality that allows you to bind urls to your state, also allowing you to create more complex relationships between your application state and the url. This API is very likely to change, but please feel free to try it out and give us feedback.\n\n#### mapping\n\nThe `map` property let's you create a mapping between state and\nurl parameters. This works both ways: when you change the state,\nit sets the url from state and when the url changes, it triggers\nthe state changes.\n\nThis automatic mapping is only active if the current url\nis active. Note also that when you use state mapping, the 'signal'\nis optional.\n\n```js\nimport { Controller } from 'cerebral'\nimport Router from '@cerebral/router'\n\nconst controller = Controller({\n  modules: {\n    router: Router({\n      routes: [\n        {\n          path: '/projects/:projectId',\n          map: { projectId: state`app.currentProjectId` },\n          signal: 'app.projectRouted'\n        },\n        {\n          path: '/settings/:tab',\n          // whitelist 'focus' query parameter\n          // and 'tab' url parameter\n          map: { tab: props`tab`, focus: props`focus` },\n          signal: 'app.settingsRouted'\n        }\n      ]\n    })\n  }\n})\n```\n\n#### computed mapping\n\nYou can use a `Compute` value here to run a computed in order to prepare\nthe value passed to build the url.\n\n```js\nmap: {\n  urlKey: Compute(/* ... */)\n}\n```\n\nIf you use a `Compute` the router cannot map back from the url key to the\nstate and you need to define a reverse map with `rmap`:\n\n```js\nrmap: {\n  'some.state': Compute(props`urlKey`, (urlKey) => /* ... */),\n  'other.state': Compute(props`urlKey`, (urlKey) => /* ... */)\n}\n```\n\n```js\nimport { Controller } from 'cerebral'\nimport Router from '@cerebral/router'\nimport { props, state } from 'cerebral/tags'\n\nconst controller = Controller({\n  modules: {\n    router: Router({\n      routes: [\n        {\n          path: '/settings/:tab',\n          // This maps a complex app state to the `opts` param in\n          // url query.\n          map: {\n            opts: Compute(\n              state`projectId`,\n              state`user.lang`,\n              (projectId, lang) => ({ projectId, lang })\n            )\n          },\n          // This parses the url query `opts` into two state values.\n          // It does a 'reverse map' hence the 'rmap' name.\n          rmap: {\n            projectId: Compute(\n              state`projectId`,\n              props`opts`,\n              (projectId, opts) => opts.projectId || projectId\n            ),\n            'user.lang': Compute(\n              state`validLangs`,\n              props`opts`,\n              (validLangs, opts) => (validLangs[opts.lang] ? opts.lang : 'en')\n            )\n          }\n        }\n      ],\n      query: true\n    })\n  }\n})\n```\n\n#### Dynamically add routes\n\nApps that use code splitting for security reasons may not want to define all routes until after the user has been verified.\n\nThe `addRoutes()` method allows routes to be added after the app has been initialized.\n\nDefine your initial set of routes as normal:\n\n```js\nimport Router from '@cerebral/router'\n\nexport default Router({\n  routes: [\n    { path: '/', signal: 'homeRouted' },\n    { path: '/login', signal: 'loginRouted' }\n  ]\n})\n```\n\nThen later you can call `addRoutes`:\n\n```js\nimport router from './router'\n\nrouter.addRoutes([\n  { path: '/now-you-see-me', signal: 'hiddenModule.hiddenRouted' }\n])\n```\n\nWhen used together with code splitting and `controller.addModule()` you can dynamically add functionality to a running cerebral application.\n\nThe only gotcha is that you might need to refresh the current route when reloading the app. Due to the order of events, the router may fire before the routes have loaded.\n\n```js\n// app init signal\nimport { reload } from '@cerebral/router/operators'\nimport checkAuthToken from '../actions/checkAuthToken'\nimport addExtraRoutes from '../actions/addExtraRoutes'\n\nexport default [\n  checkAuthToken,\n  {\n    valid: [\n      addExtraRoutes,\n      reload // ensure that the route which was added after app was loaded is called\n    ],\n    invalid: []\n  }\n]\n```\n","readmeFilename":"README.md"}