# @checle/zones

> Simplistic, promise-based zones

Latest version **0.7.1** (published 2017-05-25) · MIT license · 0 weekly downloads

## Install

```sh
npm install @checle/zones
pnpm add @checle/zones
yarn add @checle/zones
bun add @checle/zones
```

## Health

**Score 20/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities.

Warnings: low downloads; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.7.1 |
| Published | 2017-05-25 |
| First published | 2017-05-24 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 1 |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Filip Dalüge |
| Maintainers | daluege |

## Links

- npm: https://www.npmjs.com/package/@checle/zones
- Repository: https://github.com/checle/zones
- Issues: https://github.com/checle/zones/issues
- npm.io page: https://npm.io/package/@checle/zones

## Dependencies (1)

- [event-target-shim](https://npm.io/package/event-target-shim.md) ^2.0.0

## Recent versions

- 0.7.1 (latest) — 2017-05-25
- 0.7.0 — 2017-05-25
- 0.6.0 — 2017-05-24

## README

# zones

by Filip Dalüge

[![Build status](https://img.shields.io/travis/checle/zone/master.svg?style=flat-square)](https://travis-ci.org/checle/zone)

For a primer on zones in Dart, take a look at the [Dart article](https://www.dartlang.org/articles/libraries/zones). Find the complete API [here](#api).

## Installation

Install using NPM:

    npm install --save web-zones

Import zones:

```javascript

import * as zones from 'web-zones'

Object.assign(global, zones) // Optionally, shim the host API (overrides setTimeout, Promise etc.)
```

## Usage

Wait for operations spawned by a function
```javascript
await zone.exec(initAppFunction)
```
Listen to state
```javascript
zone.addEventListener('error', listener)
```
Cancel pending operations
```javascript
zone.cancel()
```
Bind function
```javascript
func = zone.bind(func)
```
Number of scheduled tasks
```javascript
zone.tasks.size
```

## Examples

* [Instantiate a zone and listen for events](#instantiate-a-zone-and-listen-for-events)
* [Execute tasks parallely](#execute-tasks-parallely)
* [Asynchronous operations](#asynchronous-operations)
* [Extend zones](#extend-zones)
* [Override enter()](#override-enter)
* [Run untrusted code asynchronously](#run-untrusted-code-asynchronously)

### Instantiate a zone and listen for events

Create a zone object and listen for status events.

```javascript
var zone = new Zone('custom-zone')

zone.addEventListener('finish', () => console.log('Zone has terminated'))
zone.addEventListener('error', error => console.log('Error occurred'))

function application () {
  setTimeout(() => null, 1000)
}

zone.run(application)
```

### Asynchronous operations

Run an application that reads a file making use of asynchronous JS APIs. The result is then awaited, and its content printed.

```javascript
import * as fs from 'fs'

// Application with unknown asynchronous operations
function application() {
  // Waits for a second
  setTimeout(readFile, 1000)

  function readFile () {
    // Read asynchronously
    fs.readFile('data.txt', data => {
      global.fileContent = data
    })
  }
}

try {
  // Call and wait for spawned tasks to terminate
  await global.zone.exec(application)

  console.log('This file content has been read: ' + global.fileContent)
} catch (error) {
  console.log('Either setTimeout or fs.readFile threw an uncatched error')
}
```

### Execute tasks parallely

Run three processes using [`Promise.all`](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) and wait for them to finish. Cancel any other zones if one zone throws an error.

```javascript
try {
  await Promise.all([
    zone.exec(app1),
    zone.exec(app2),
    zone.exec(app3),
  ])

  console.log('All tasks have concluded successfully')
} catch (error) {
  console.log('One zone errored:', error.zone.name)

  // Cancel all remaining zones
  zone.cancel()
}
```

### Extend zones

Add custom properties to `zone` by inheritance.

```javascript
class CustomEnvironment extends Zone {
  constructor () {
    super('custom-environment')

    this.created = Date.now()
  }
}

function routine () {
  if (global.zone instanceof CustomEnvironment) {
    console.log('My environment was created at ' + global.zone.created)
  } else {
    console.log("I think I've been running forever")
  }
}

global.zone.run(routine) // "I think I've been running forever"

new CustomEnvironment().run(routine) // Prints the creation date
```

### Override enter()

You can hook into zone operations overriding `enter()`.

```javascript
let lastDomain

class MozillaZone extends Zone {
  enter (zone) {
    if (zone instanceof MozillaZone) {
      lastDomain = global.domain
      global.domain = 'mozilla.org'
    } else {
      global.domain = lastDomain
    }

    super.enter(zone)
  }
}

global.domain = 'example.com'

new MozillaZone().run(() => console.log(global.domain)) // "mozilla.org"

global.zone.run(() => console.log(global.domain)) // "example.com"
```

### Run untrusted code asynchronously

Run code in a sandbox using NodeJS' [vm module](https://nodejs.org/api/vm.html) and print the result.

```javascript
const vm = require('vm')

// Create sandbox
let sandbox = {
  setTimeout,
  setInterval,
  setImmediate,
  print: console.log
}

let applicationCode = `
  if (typeof console !== 'undefined') {
    console.log("I'm not that secure, it seems.")
  } else {
    print('Oh yes, I am.')
  }
`

try {
  // Use exec with vm to run a program in an isolated environment
  let result = await zone.exec(() => vm.runInNewContext(applicationCode, sandbox))

  console.log('Terminated successfully with result', result)
} catch (error) {
  console.log('An error occurred')
)
```

## API

```typescript
zone: Zone // Get the current zone

interface Task extends Event {
  cancel?: Function
}

interface Zone extends EventTarget, Node {
  onerror?: Function // Set 'error' event handler
  onfinish?: Function // Set 'finish' event handler

  readonly name: any // Optional name, e.g., for debugging
  readonly tasks: Map<any, Task> // Pending tasks
  readonly children: Zone[] // Associated children, modifiable by the DOM
  readonly root: Zone // Root zone - all error events bubble towards this zone

  constructor (nameOrSpec?: any)

  // Add and manage custom tasks
  addTask (task: Task): number
  setTask (id: any, task: Task): this
  getTask (id: any): Task
  hasTask (id: any): boolean
  removeTask (id: any): boolean
  cancelTask (id: any): Promise<void>

  // Run function inside zone
  run (entry: Function, thisArg?: any, ...args: any[]): any
  // Bind function to zone
  bind (fn: Function): Function
  // Cancels all child zones and pending tasks
  cancel (): Promise<void> 
  // Spawns a new child zone, runs `entry` in it and resolves when all new tasks have been worked off
  exec (entry: Function, thisArg?: any, ...args: any[]): Promise<any>

  // Add event listeners
  addEventListener (type: 'finish' | 'error', listener: Function, options: any): void
  // Modify the DOM - affects which children will be cancelled on `cancel()` and where 'error' events will bubble to
  appendChild (node: Zone): this
}

// Zone-enabled standard API
function setTimeout (handler, timeout, ...args)
function setInterval (handler, timeout, ...args)
function clearTimeout (id)
function clearInterval (id)
function Promise (executor)
```

## License

MIT © 2016 Filip Dalüge ([license](./LICENSE))

---
_Source: https://npm.io/package/@checle/zones · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
