open-index/open-npm huggingface dataset:
npm package: @profiscience/knockout-contrib-observable-fn-subscribe-once
Description: KnockoutJS Observable.fn.subscribeOnce()
Author: Casey Webb
Latest version: 1.0.0-alpha.8

# @profiscience/knockout-contrib-observable-fn-subscribe-once

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.subscribeOnce
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/observable.fn.subscribeOnce

[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.subscribeOnce&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/observable.fn.subscribeOnce

[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.subscribeOnce&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/observable.fn.subscribeOnce

[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-observable-fn-subscribe-once
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-observable-fn-subscribe-once.svg

[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-observable-fn-subscribe-once&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-observable-fn-subscribe-once.svg?maxAge=2592000

**NOTE:** It is recommended to use the [@profiscience/knockout-contrib-observable-fn metapackage](../observable.fn)

Creates a subscription that is called once and then disposed.

## Usage
> observable<T>.fn.subscribeOnce(fn: (newValue: T) => void)

```javascript
import '@profiscience/knockout-contrib-observable-fn/subscribeOnce'

const foo = ko.observable(0)

foo.subscribeOnce(() => console.log('hit!'))

foo(1)
// hit!

foo(2)
// nothing...
```
npm package: @profiscience/knockout-contrib-observable-fn-to-string
Description: KnockoutJS Observable.fn.toString()
Author: Casey Webb
Latest version: 1.0.0-alpha.8

# @profiscience/knockout-contrib-observable-fn-to-string

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.toString
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/observable.fn.toString

[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.toString&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/observable.fn.toString

[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.toString&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/observable.fn.toString

[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-observable-fn-to-string
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-observable-fn-to-string.svg

[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-observable-fn-to-string&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-observable-fn-to-string.svg?maxAge=2592000

**NOTE:** It is recommended to use the [@profiscience/knockout-contrib-observable-fn metapackage](../observable.fn)

Make debugging nicer; you won't ever need to actually call this.

## Usage

```javascript
import '@profiscience/knockout-contrib-observable-fn/toString'
```
npm package: @profiscience/knockout-contrib-observable-fn-toggle
Description: KnockoutJS Observable.fn.toggle()
Author: Casey Webb
Latest version: 0.0.3

# @profiscience/knockout-contrib-observable-fn-toggle

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.toggle
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/observable.fn.toggle

[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.toggle&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/observable.fn.toggle

[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/observable.fn.toggle&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/observable.fn.toggle

[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-observable-fn-toggle
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-observable-fn-toggle.svg

[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-observable-fn-toggle&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-observable-fn-toggle.svg?maxAge=2592000

**NOTE:** It is recommended to use the [@profiscience/knockout-contrib-observable-fn metapackage](../observable.fn)

toggles/decrements numeric observables

## Usage

```javascript
import '@profiscience/knockout-contrib-observable-fn/toggle'

const foo = ko.observable(true)

foo.toggle()  // false
foo.toggle()  // true
```
npm package: @profiscience/knockout-contrib-router-middleware
Description: @profiscience/knockout-contrib-router middleware
Author: Casey Webb
Latest version: 1.0.0-alpha.11

# @profiscience/knockout-contrib-router-middleware

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

> This is a metapackage including all `@profiscience/knockout-contrib-router-middleware-*` packages

[Router Middleware](../router/docs/middleware) for [@profiscience-knockout-contrib-router](../router)

<!-- TOC -->
### Contents
- [flashMessage](../router.middleware.flashMessage)
- [progressBar](../router.middleware.progressBar)
- [scrollPosition](../router.middleware.scrollPosition)
<!-- /TOC -->

### Usage

All named exports from each child package (see the table of contents above) are available to import.

If using a bundler that supports tree-shaking, this will safely minify.

```javascript
import { flashMessageMiddleware } from '@profiscience/knockout-contrib-router-middleware'
```

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.middleware

[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.middleware

[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.middleware

[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-middleware
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-middleware.svg

[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-middleware&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-middleware.svg?maxAge=2592000
npm package: @profiscience/knockout-contrib-router-middleware-loading
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 1.0.18

# router.middleware.loading

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.loading
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.middleware.loading
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.loading&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.middleware.loading
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.loading&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.middleware.loading
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-middleware-loading
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-middleware-loading.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-middleware-loading&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-middleware-loading.svg?maxAge=2592000

> **NOTE:** This package is intended for consumption via the [@profiscience/knockout-contrib metapackage](../_)

Eases creation of loading middlware

## Usage

```typescript
import { Router, createLoadingMiddleware } from '@profiscience/knockout-contrib'

Router.use(
  createLoadingMiddleware({
    start() {
      showLoader()
    },
    end() {
      hideLoader()
    },

    /* OPTIONAL */
    minDuration: 0, // prevent flickering on fast navigation (show loader for at least <n> ms)
  })
)
```
npm package: @profiscience/knockout-contrib-router-middleware-progress-bar
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.17

# router.middleware.progressBar

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.progressBar
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.middleware.progressBar
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.progressBar&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.middleware.progressBar
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.progressBar&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.middleware.progressBar
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-middleware-progress-bar
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-middleware-progress-bar.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-middleware-progress-bar&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-middleware-progress-bar.svg?maxAge=2592000

> **NOTE:** This package is intended for consumption via the [@profiscience/knockout-contrib metapackage](../_)

Displays a progress bar using [toprogress2][] during navigation. Accepts all toprogress2 options.

## Usage

```typescript
import {
  Router,
  createProgressBarMiddleware,
} from '@profiscience/knockout-contrib'

Router.use(
  createProgressBarMiddleware({
    color: '#fff',
    height: '5px',
    // ... any toprogress2 option
  })
)
```
npm package: @profiscience/knockout-contrib-router-middleware-scroll-position
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.17

# router.middleware.scrollPosition

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.scrollPosition
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.middleware.scrollPosition
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.scrollPosition&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.middleware.scrollPosition
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.middleware.scrollPosition&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.middleware.scrollPosition
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-middleware-scroll-position
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-middleware-scroll-position.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-middleware-scroll-position&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-middleware-scroll-position.svg?maxAge=2592000

Add support for:

- restoring scroll position on back-button navigation
- scrolling to anchors (#hash), or the top on forward navigation

## Usage

```typescript
import {
  Router,
  createScrollPositionMiddleware
} from '@profiscience/knockout-contrib'

Router.use(
  createScrollPositionMiddleware({
    // optionally supply a custom scroll function (add smooth scrolling, use Velocity, etc.)
    scrollTo(x, y) { ... }
  })
)
```
npm package: @profiscience/knockout-contrib-router-plugins
Description: @profiscience/knockout-contrib-router plugins
Author: Casey Webb
Latest version: 1.0.0-alpha.14

# @profiscience/knockout-contrib-router-plugins

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

> This is a metapackage including all `@profiscience/knockout-contrib-router-plugins-*` packages

[Route Plugins](../router/docs/plugins) for [@profiscience-knockout-contrib-router](../router)

<!-- TOC -->
### Contents
- [authorization](../router.plugins.authorization)
- [children](../router.plugins.children)
- [component](../router.plugins.component)
- [components](../router.plugins.components)
- [init](../router.plugins.init)
- [redirect](../router.plugins.redirect)
- [title](../router.plugins.title)
- [with](../router.plugins.with)
<!-- /TOC -->

### Usage

All named exports from each child package (see the table of contents above) are available to import.

If using a bundler that supports tree-shaking, this will safely minify.

```javascript
// import all
import * as routerPlugins from '@profiscience/knockout-contrib-router-plugins'

// import single
import { childrenPlugin } from '@profiscience/knockout-contrib-router-plugins'
```

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.plugins

[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.plugins

[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.plugins

[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-plugins
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-plugins.svg

[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-plugins&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-plugins.svg?maxAge=2592000
npm package: @profiscience/knockout-contrib-router-plugins-children
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.17

# router.plugins.children

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.children
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.plugins.children
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.children&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.plugins.children
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.children&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.plugins.children
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-plugins-children
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-plugins-children.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-plugins-children&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-plugins-children.svg?maxAge=2592000

Idiomatically set child/nested routes

## Usage

```typescript
import {
  Route,
  childrenRoutePlugin
} from '@profiscience/knockout-contrib'

Route.usePlugin(childrenRoutePlugin)

new Route('/users', {
  children: [
    new Route('/', ...),
    new Route('/:id', ...),
    new Route('/:id/edit', ...)
  ]
})
```

Object-shorthand _is_ supported, but it should only be used to migrate legacy routes as it requires casting as any (with TypeScript).
This is due to the fact that in order to support object shorthand (which uses keys as the route names, meaning they are dynamic), and
index signature must be added, and in doing so the strictness of the typechecking (and thus the usefulness) is greatly diminished when
using the (preferred) route constructor syntax. But alas... here it is.

```typescript
new Route('/users', {
  children: {
    '/': ...,
    '/:id': ...,
    '/:id/edit': ...
  } as any // <----- If you're using TS, you HAVE to do this, or it will not compile
})
```
npm package: @profiscience/knockout-contrib-router-plugins-components
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 1.0.17

# router.plugins.components

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.components
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.plugins.components
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.components&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.plugins.components
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.components&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.plugins.components
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-plugins-components
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-plugins-components.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-plugins-components&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-plugins-components.svg?maxAge=2592000

Register components only for the life of the page (unregister before dispose).

Allows breaking views into multiple components while helping to avoid naming conflicts.

## Usage

```typescript
import { Route, componentsRoutePlugin } from '@profiscience/knockout-contrib'

Route.usePlugin(componentsRoutePlugin)

new Route('/', {
  components: () => ({
    // will register the <toolbar></toolbar> component for use in this view and its children
    toolbar: import('./toolbar'),
  }),
})
```

**toolbar.ts**

```typescript
export const template = 'Hello, World!'
export class viewModel {}
```
npm package: @profiscience/knockout-contrib-router-plugins-redirect
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.17

# router.plugins.redirect

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.redirect
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.plugins.redirect
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.redirect&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.plugins.redirect
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.redirect&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.plugins.redirect
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-plugins-redirect
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-plugins-redirect.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-plugins-redirect&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-plugins-redirect.svg?maxAge=2592000

Support `redirect` option in route configurations.

## Usage

Redirects to the returned path, if any. Supports async via promise.

```typescript
import { Route, redirectRoutePlugin } from '@profiscience/knockout-contrib'

Route.usePlugin(redirectRoutePlugin)

function shouldRedirect(ctx) {
  // ...do something...
}

// Sync
new Route('/', {
  redirect: (ctx) => {
    if (shouldRedirect(ctx)) return '//redirect/to/this/route'
  },
})

// Async
new Route('/', {
  redirect: async (ctx) => {
    if (await shouldRedirect(ctx)) return '//redirect/to/this/route'
  },
})
```
npm package: @profiscience/knockout-contrib-router-plugins-title
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.18

# router.plugins.title

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.title
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.plugins.title
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.title&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.plugins.title
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.title&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.plugins.title
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-plugins-title
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-plugins-title.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-plugins-title&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-plugins-title.svg?maxAge=2592000

Set `document.title` for a route. Supports nesting/composition.

## Usage

```typescript
import { Route, createTitleRoutePlugin } from '@profiscience/knockout-contrib'

Route.usePlugin(createTitleRoutePlugin())

// Basic
new Route('/', {
  title: 'Home',
})

// Sync Accessor Function
new Route('/profile', [loadUser], {
  title: (ctx) => `Profile | ${ctx.user.name}`,
})

// Async Accessor Function
new Route('/profile', {
  title: async (ctx) => `Profile | ${await getUserName()}`,
})
```

### Nested Routing

If you have nested routes that both supply a title, by default they will be joined with "|"...

```typescript
new Route('/', {
  title: 'My Awesome App',
  children: [
    new Route('/', {
      title: 'Home',
    }),
    new Route('/profile', {
      title: 'Profile',
    }),
  ],
})
```

If you land on `/` the title will be set to "My Awesome App | Home"; likewise navigating to `/profile` will update the title to "My Awesome App | Profile".

### Using a Custom Formatter

If you'd like to using something other than "|" to join your routes, you may pass a custom formatter function to `createTitleRoutePlugin`.

```typescript
Route.usePlugin(
  createTitleRoutePlugin((ts: string[]) => `My Awesome App | ${ts.join(' > ')}`)
)
```
npm package: @profiscience/knockout-contrib-router-plugins-with
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.17

# router.plugins.with

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.with
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/router.plugins.with
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.with&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/router.plugins.with
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/router.plugins.with&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/router.plugins.with
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-router-plugins-with
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-router-plugins-with.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-router-plugins-with&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-router-plugins-with.svg?maxAge=2592000

Allows extending the context for a route with arbitrary data

## Usage

```typescript
import { Route, withRoutePlugin } from '@profiscience/knockout-contrib'

Route.usePlugin(withRoutePlugin)

// Sync
new Route('/', {
  with: {
    myAdditionalProp: true,
  },
})

// Accessor
new Route('/', {
  with: (ctx) => {
    // synchronous
    return {
      myAdditionalProp: true,
    }

    // async via promises
    return Promise.resolve({
      myAdditionalProp: true,
    })
  },
})
```

Now, in the viewModel (as well as any subsequent middleware), `ctx.myAdditionalProp` will be `true`.

**NOTE:** If you're using TypeScript, it's worth noting that the return type _is strongly typed_. The properties it adds _must_
be defined on the IContext interface, _or_ cast as `any`.

e.g.

```typescript
declare module '@profiscience/knockout-contrib-router' {
  interface IContext {
    myAdditionalProp?: boolean
  }
}

// ...or...

new Route('/', {
  with: {
    myAdditionalProp: true,
  } as any,
})
```
npm package: @profiscience/knockout-contrib-utils
Description: Handy Utilities for Knockout JS
Author: Casey Webb
Latest version: 1.0.0-alpha.16

# @profiscience/knockout-contrib-utils

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

> This is a metapackage including all `@profiscience/knockout-contrib-utils-*` packages

<!-- TOC -->
### Contents
- [defaults](../utils.defaults)
- [fromJS](../utils.fromJS)
- [merge](../utils.merge)
<!-- /TOC -->

### Usage

Each child package (see the table of contents above) is available as a named export.

If using a bundler that supports tree-shaking, this will safely minify.

```javascript
// import all
import * as utils from '@profiscience/knockout-contrib-utils'

// import single
import { defaults } from '@profiscience/knockout-contrib-utils'
```

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/utils

[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/utils

[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/utils

[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-utils
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-utils.svg

[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-utils&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-utils.svg?maxAge=2592000
npm package: @profiscience/knockout-contrib-utils-defaults
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.1.4

# utils.defaults

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.defaults
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/utils.defaults
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.defaults&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/utils.defaults
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.defaults&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/utils.defaults
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-utils-defaults
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-utils-defaults.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-utils-defaults&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-utils-defaults.svg?maxAge=2592000

> This package is intended for consumption via the [@profiscience/knockout-contrib] metapackage

## Usage

> defaults(dest, defaultValues[, mapArrays = false])

Creates observables for enumerable properties of `defaultValues` where undefined in the destination object.

If `mapArrayElements` is true, array elements will be created using [utils.fromJS](../utils.fromJS).

```javascript
import { defaults } from '@profiscience/knockout-contrib'

const foos = { foo: 'foo' }
defaults(foos, { foo: 'bar', bar: 'bar' })

foos()
// { foo: 'foo', bar: 'bar' }
```
npm package: @profiscience/knockout-contrib-utils-from-js
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.4

# utils.fromJS

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.fromJS
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/utils.fromJS
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.fromJS&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/utils.fromJS
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.fromJS&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/utils.fromJS
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-utils-from-js
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-utils-from-js.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-utils-from-js&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-utils-from-js.svg?maxAge=2592000

> This package is intended for consumption via the [@profiscience/knockout-contrib] metapackage

## Usage

> fromJS(src[, mapArrayElements = false])

Creates a tree of observables from `src`.

If `mapArrayElements` is true, array elements will be passed to `fromJS` as well, else bare objects/primitives.

The much needed inverse to the undocumented `ko.toJS` function; a dumb version of [ko.mapping.fromJS](http://knockoutjs.com/documentation/plugins-mapping.html) that is [_a lot faster_](#benchmark).

```javascript
import { fromJS } from '@profiscience/knockout-contrib'

const foos = {
  foo: 'foo',
  bar: {
    baz: 'baz',
    qux: ['qux'],
  },
}

fromJS(foos)
// {
//   foo: ko.observable('foo'),
//   bar: {
//     baz: ko.observable('baz'),
//     qux: ko.observableArray([
//       'qux'
//     ])
//   }
// }

fromJS(foos, true)
// {
//   foo: ko.observable('foo'),
//   bar: {
//     baz: ko.observable('baz'),
//     qux: ko.observableArray([
//       ko.observable('qux') <--------- Array contents mapped when second argument is true
//     ])
//   }
// }
```

## Benchmark

```shell
$ ./benchmark.ts
utils.fromJS                    x 316,313 ops/sec ±3.37% (79 runs sampled)
utils.fromJS (mapArrayElements) x 151,401 ops/sec ±3.24% (81 runs sampled)
mapping.fromJS                  x 11,995 ops/sec ±3.82% (81 runs sampled)
```
npm package: @profiscience/knockout-contrib-utils-increment
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.1

# utils.increment / utils.decrement

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.increment
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/utils.increment
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.increment&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/utils.increment
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.increment&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/utils.increment
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-utils-increment
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-utils-increment.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-utils-increment&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-utils-increment.svg?maxAge=2592000

> This package is intended for consumption via the [@profiscience/knockout-contrib] metapackage.

Increments/decrements a numeric observable. Returns the new value.

## Usage

```javascript
import { increment, decrement } from '@profiscience/knockout-contrib'

const foo = ko.observable(0)

increment(foo) // 1
increment(foo, 3) // 4
decrement(foo) // 3
decrement(foo, 2) // 1
```
npm package: @profiscience/knockout-contrib-utils-merge
Description: Handy Utilities for Knockout JS
Author: Casey Webb
Latest version: 1.0.0-alpha.14

# @profiscience/knockout-contrib-utils-merge

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.merge
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/utils.merge

[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.merge&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/utils.merge

[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.merge&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/utils.merge

[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-utils-merge
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-utils-merge.svg

[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-utils-merge&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-utils-merge.svg?maxAge=2592000

**NOTE:** It is recommended to use the [@profiscience/knockout-contrib-utils metapackage](../utils)

## Usage
> merge(dest, src[, mapArrays = false])

For each enumerable property of src,
  a) creates an observable when undefined on dest
  b) updates when existing observable on dest
  c) sets when existing non-observable on dest.

If `mapArrays` is true, array elements will be created as mapped observables, else bare objects/primitives.
__NOTE__: Merging new arrays onto existing ones that have been mapped deep will create new observable elements,
__not__ update the existing ones. No attempts are made to key elements, nor will they. If you need more, you
probably want [ko.mapping](http://knockoutjs.com/documentation/plugins-mapping.html) which is much more powerful,
but far slower.

```javascript
import { merge } from '@profiscience/knockout-contrib-utils'

const foos = {
  foo: ko.observable('foo'),
  bar: 'bar'
}

merge(foos, {
  foo: 'new foo',
  bar: 'new bar',
  baz: 'baz'
})

foos()
// {
//   foo: ko.observable('new foo'),
//   bar: 'new bar',
//   baz: ko.observable('baz')
// }
```
npm package: @profiscience/knockout-contrib-utils-modify
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.1

# utils.modify

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.modify
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/utils.modify
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.modify&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/utils.modify
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.modify&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/utils.modify
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-utils-modify
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-utils-modify.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-utils-modify&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-utils-modify.svg?maxAge=2592000

> This package is intended for consumption via the [@profiscience/knockout-contrib] metapackage

Modifies an observable using a transform function. Returns the new value.

Useful for wrapping general purpose utilities functions for Knockout observables.

## Usage

```javascript
import { modify } from '@profiscience/knockout-contrib'

const foobar = ko.observable('foobar')

function reverseString(str) {
  return str
    .split('')
    .reverse()
    .join('')
}

const ret = modify(foobar, reverseString)
;(foobar() === ret) === 'raboof'
```
npm package: @profiscience/knockout-contrib-utils-once
Description: [![Version][npm-version-shield]][npm] [![Dependency Status][david-dm-shield]][david-dm] [![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer] [![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev] [![Downloads][npm-stats-shield]][npm-sta
Author: Casey Webb
Latest version: 2.0.1

# utils.once

[![Version][npm-version-shield]][npm]
[![Dependency Status][david-dm-shield]][david-dm]
[![Peer Dependency Status][david-dm-peer-shield]][david-dm-peer]
[![Dev Dependency Status][david-dm-dev-shield]][david-dm-dev]
[![Downloads][npm-stats-shield]][npm-stats]

[david-dm]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.once
[david-dm-shield]: https://david-dm.org/Profiscience/knockout-contrib/status.svg?path=packages/utils.once
[david-dm-peer]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.once&type=peer
[david-dm-peer-shield]: https://david-dm.org/Profiscience/knockout-contrib/peer-status.svg?path=packages/utils.once
[david-dm-dev]: https://david-dm.org/Profiscience/knockout-contrib?path=packages/utils.once&type=dev
[david-dm-dev-shield]: https://david-dm.org/Profiscience/knockout-contrib/dev-status.svg?path=packages/utils.once
[npm]: https://www.npmjs.com/package/@profiscience/knockout-contrib-utils-once
[npm-version-shield]: https://img.shields.io/npm/v/@profiscience/knockout-contrib-utils-once.svg
[npm-stats]: http://npm-stat.com/charts.html?package=@profiscience/knockout-contrib-utils-once&author=&from=&to=
[npm-stats-shield]: https://img.shields.io/npm/dt/@profiscience/knockout-contrib-utils-once.svg?maxAge=2592000

> This package is intended for consumption via the [@profiscience/knockout-contrib] metapackage

Creates a subscription that is called once and then disposed. Returns subscription for early disposal if necessary.

## Usage

```javascript
import { once } from '@profiscience/knockout-contrib'

const foo = ko.observable(0)

const sub = once(foo, () => console.log('hit!'))

foo(1)
// hit!

foo(2)
// nothing...
```