open-index/open-npm huggingface dataset:
npm package: @seia-soto/checkadb
Description: Half-automated ad-blocking capability end-to-end testing framework.
Author: HoJeong Go
Latest version: 1.1.0

# checkadb

Half-automated ad-blocking capability end-to-end testing framework.
This framework helps ad-blockers to test their functionality with an ease.

See [contributing.md](./contributing.md) for the project development setup.

## Testing

`checkadb` is intended to be self-containable.

### Manual testing

Run web server via `pnpm www` after setting up the development environment.
You can see inline filters to apply and results immeidately.

Accessing `localhost` may disturb matching process of generic cosmetic filters.
For an instance, EasyList ships `@@://localhost:$generichide` by default.
We recommend you to add custom DNS resolver or edit `hosts` file.
You can use any domain without HSTS, for example: `self`.

```
127.0.0.1 self
```

### Programmable

We also providea a programmable way to support your own testing setup.

You can reference `filters` from the main export to acquire filters required
for testing.
Also, the types for easier typing are exported with the name of `Report`.

When accessing the actual values from the page, you can reference: the values
under `globalThis.suite.collection`.
`globalThis.suite.collection.expected` will provide you a number of reports
expected and `globalThis.suite.collection.reports` will provide you an array of
reports.

Typically, you're expected to collect the reports after 2 seconds as the
longest test we're performing takes 1 second after `readystatechange` event.
However, we recommend you to check multiple times rather expecting a constant
load time because it may vary depending on the machine and setup.

```ts
import { filters } from "checkadb";
import type { Report } from "checkadb";
import { createTestingServer } from "checkadb/server";

const server = createTestingServer();

server.listen(PORT, "127.0.0.1", async function () {
  // Install filters
  installFilterToExtension(filters);
  // Access web server
  goToUrl("https://127.0.0.1/");
  // Wait for 2s for assertions to be completed
  await waitFor(2000);
  // Gather test results
  const actuals = await executeInPage(
    `return JSON.stringify(suite.collection.reports)`,
  );
  expect(JSON.parse(actuals)).toBe({
    /* YOUR EXPECTED VALUES HERE */
  } satisfies Report[]);
});
```
npm package: @seiberspace/iterdate
Description: Date iterators.
Author: Arne Seib
Latest version: 1.0.0

# iterdate

Iterators for time ranges to iterate in steps of years, months, days, hours, minutes, or
seconds.

### `years(start, end, step = 1)`

Use to iterate between `start` and `end` in steps of `step` years. `start` and
`end` must be `Date`s. `step` must be >= 1 and defaults to 1.

Iterators are available for `years`, `months`, `days`, `hours`, `minutes`
and `seconds`.

##### Example:

```js
import {
  days,
} from './dist/iterdate.mjs';

const startDate = new Date('2023-06-10T04:01:51.167Z');
const endDate = new Date('2023-06-13T04:01:51.167Z');

for (const value of days(startDate, endDate)) {
  console.log(value.toLocaleString('en-US'));
}

// Output:
// 6/10/2023, 12:00:00 AM
// 6/11/2023, 12:00:00 AM
// 6/12/2023, 12:00:00 AM
```

The returned date is set to the start of the respective interval, meaning for
`days()`, for example, the hour, minute, second, and millisecond are set to 0.

### `makeYmdHmsDate(date)`

In addition to the iterators, `make...` functions are exported that return a date
used by the iterators to generate start and end dates. These set the other values
(e.g. hours, minutes, seconds and milliseconds in case of `makeYmdDate()`) to
0 (or 1 for day of month). See [`date2Array()`](#date2arraydate-precision--7-partial--false).

##### Example:

```js
import {
  makeYmDate,
} from './dist/iterdate.mjs';

// makeYmDate: Keep only year and month. Set everything else to start
// of June 2023.
const d = makeYmDate(new Date('2023-06-10T04:01:51.167Z'));
console.log(d.toLocaleString('en-US'));

// Output:
// 6/1/2023, 12:00:00 AM
```

The following functions are available: `makeYmdHmsDate`, `makeYmdHmDate`,
`makeYmdHDate`, `makeYmdDate`, `makeYmDate`, `makeYDate`.

### `date2Array(date, precision = 7, partial = false)`

Finally, `date2Array(date, precision, partial)` is exported. It's what is behind
everything else, and converts a `Date` into an `Array`. It uses only the first
`precision` values from the date, so for `precision = 3` it uses year, month and
day, while setting hours, minutes, seconds and milliseconds to 0.

Since the day of a month is 1-based, it obviously sets it to 1 instead of 0.

##### Example:

```js
import {
  date2Array,
} from './dist/iterdate.mjs';

const d = new Date('2023-06-10T04:01:51.167Z');
let ar = date2Array(d);
console.log(ar);
// Output (UTC+2):
// [2023, 5, 10, 6, 1, 51, 167]

// When `partial` is true, return only the first `precision` values:
ar = date2Array(d, 3, true);
console.log(ar);
// Output (UTC+2):
// [2023, 5, 10]
```
npm package: @seiberspace/use-mqtt
Description: Reactive mqtt-Client and -Subscriptions using MQTT.js.
Author: Arne Seib
Latest version: 0.2.3

# useMqtt

Reactive mqtt-Client and -Subscriptions using [`MQTT.js`](https://github.com/mqttjs/MQTT.js/).

**Note:** This is currenlty hardly more than a draft, use at your own risc and read the code to figure out what to do how.

## Install

```bash
npm i @seiberspace/use-mqtt

# OR:
yarn add @seiberspace/use-mqtt
```

## Usage

```js
import { useMqtt, useSubscription } from '@seiberspace/use-mqtt';

// One time somewhere in your app:
useMqtt().create('wss://test.mosquitto.org:8081', {
  mapValue: (val) => val.toString(),
});

const { value } = useSubscription(topic, { default: '-' });
```

## Example

```vue
<script>
import {
  defineComponent,
} from 'vue';

import {
  useMqtt,
  useSubscription,
} from '@seiberspace/use-mqtt';

//------------------------------------------------------------------------------
export default defineComponent({
  name: 'MqttValue',

  setup(props) {
    const {
      connected,
      error,
      create,
    } = useMqtt();
    const { value } = useSubscription('testtopic');

    create('wss://test.mosquitto.org:8081', {
      mapValue: (val) => val.toString(),
    });

    return {
      connected,
      value,
      error,
    };
  },
});
</script>

<template>
  <div>
    <div>Connected: {{connected}}</div>
    <div>Value: {{val}}</div>
    <div v-if="!!error">Error: {{error}}</div>
  </div>
</template>
```

Subscriptions are reference counted, `useSubscription()` hooks into the component's
lifecycle. When the last reference is released, the client unsubscribes from
that topic.

You can call `useMqtt()` as often as you like, it will always return the same
instance. You can `open()` and `close()` the connection, and watch `state` for
changes. Additionally there is an `error` which is set to the connection error, if any.

`useMqtt()` offers two convenience-computeds, `connected` and `busy`. `busy` is
set to true while connecting or disconnecting.

`create()` is reentry-save (although ignoring changed parameters), and never fails.
It reports errors via the `error` ref.

If you actually do need multiple MQTT-instances, you can do that: Check `types.ts`,
you will figure it out.

## TODO

A lot: Better typing, tests, full support of `subscribe()`-options and probably much more.
npm package: @seibert/firestore-backup-function
Description: A small helper function to initialize a Firebase Function which creates Firestore backups according to the given schedule
Author: jdepoix@seibert-media.net
Latest version: 1.1.3

# firestore-backup-function

A small helper function to initialize a Firebase Function which creates Firestore backups according to the given schedule

## Setup

To be able to back up data, you'll need to add the `importExportAdmin` role to the service account you are using:

```shell
gcloud projects add-iam-policy-binding <PROJECT_NAME> --member serviceAccount:<SERVICE_ACCOUNT_NAME>@appspot.gserviceaccount.com --role roles/datastore.importExportAdmin
```

If the bucket you want to back up to doesn't exist yet create it (make sure it's in an accessible region):

```shell
gsutil mb -l <REGION> gs://my-backup-bucket
```

## Usage

Simply add this export to your Firebase project's `index.ts/js` to enable Firestore backups for that project:

```typescript
import { createFirestoreBackupFunction } from "@seibert/firestore-backup-function";

// Note that all of these parameters are optional and use a reasonable default
exports.firestoreBackup = createFirestoreBackupFunction({
    // The ID of the Firebase project. (default: process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT)
    projectId: "my-firebase-project",
    // The schedule for your backup. (default: "every day 03:00")
    schedule: "every 24 hours",
    // The URI of the bucket backups are saved to. (default: `gs://${ projectId }-firestore-backup`)
    bucketUri: "gs://my-backup-bucket",
    // How long until your backup function runs into a timeout (max and default: 540 seconds)
    timeoutSeconds: 300,
    // List of regions the cloud function is deployed to (default: ["europe-west1"])
    regions: ["europe-west3"],
});
```

## Restore from backup

To restore from a previously created backup run the following `gcloud` command (using the previously defined bucket URI):

```shell
gcloud firestore import gs://my-backup-bucket/2017-05-25T23:54:39_76544/
```
npm package: @seibert/typed-forge-bridge
Description: A small TypeScript library which introduces end-to-end type-safety into your Atlassian Forge Apps
Author: jdepoix@seibert-media.net
Latest version: 1.0.0

# typed-forge-bridge

A small TypeScript library which introduces end-to-end type-safety into your Atlassian Forge Apps!

## Usage

Centrally define what the API of your FaaS backend is supposed to look like:

```ts
// types.ts
import { ForgeEndpoint } from "@seibert/typed-forge-bridge";

type User = {
  id: string,
  name: string,
  email: string,
};

type GetUserParams = {
  id: string,
};

type CreateUserParams = {
  name: string,
  email: string,
};

export const apiDefinition = {
  getUser: new ForgeEndpoint<GetUserParams, User>(),
  createUser: new ForgeEndpoint<CreateUserParams, void>(),
};
```

We can now use this definition to infer the types of the resolver's handler functions.

```ts
// index.ts
import Resolver from "@forge/resolver";
import { define } from "@seibert/typed-forge-bridge";
import { apiDefinition } from "@shared/types";

const resolver = new Resolver();
// TypeScript ensures that this object implements all the endpoints defined 
// in apiDefinition
define<typeof apiDefinition>(resolver, {
  // TypeScript can infer that payload is of type GetUserParams and this 
  // function is expected to return a User
  getUser: async ({ payload, context }) => {
    // retrieve user ...
    return user;
  },
  // TypeScript can infer that payload is of type CreateUserParams and this 
  // function is expected to return void
  createUser: async ({ payload }) => {
    // create user ...
  }
});
export const handler = resolver.getDefinitions();
```

And on the client-side we can infer a fully typed API client for the FaaS backend.

```tsx
// CreateUserButton.tsx
import { invoke } from "@forge/bridge";
import { buildClient } from "@seibert/typed-forge-bridge";
import { apiDefinition } from "@shared/types";

// this client now has a method for each endpoint defined in apiDefinition
export const bridgeClient = buildClient(apiDefinition, invoke);

function CreateUserButton() {
  return <button
    onClick={ async () => {
      // the method createUser expects CreateUserParams and returns void as 
      // defined in apiDefinition
      await bridgeClient.createUser({ 
        name: "Max Mustermann", 
        email: "max@mustermann.com",
      });
    } }
  >
    create user
  </button>;
}
```
npm package: @seiboston/react-ghe-login
Description: A React Component for GitHub and Github Enterprise Login
Latest version: 1.0.1

# React Github and GHE Login

React component for [GitHub login](https://developer.github.com/v3/oauth/).

Extension of [react-github-login](https://github.com/checkr/react-github-login) with option for host to support Github Enterprise.

## Usage

```js
import React from 'react';
import ReactDOM from 'react-dom';
import GitHubLogin from 'react-github-login';

const onSuccess = response => console.log(response);
const onFailure = response => console.error(response);

ReactDOM.render(
  <GitHubLogin clientId="my-github-client-id"
    onSuccess={onSuccess}
    onFailure={onFailure}
    host="https://my-git-enterprise.com"
  />,
  document.getElementById('example')
);
```

### Props

#### `clientId`

`{string}` _required_

Client ID for GitHub OAuth application.

#### `redirectUri`

`{string}`

Registered redirect URI for GitHub OAuth application.

#### `scope`

`{string}`

Scope for GitHub OAuth application. Defaults to `user:email`.

#### `className`

`{string}`

CSS class for the login button.

#### `buttonText`

`{string}`

Text content for the login button.

#### `onRequest`

`{function}`

Callback for every request.

#### `onSuccess`

`{function}`

Callback for successful login. An object will be passed as an argument to the callback, e.g. `{ "code": "..." }`.

#### `onFailure`

`{function}`

Callback for errors raised during login.

#### `host`

`{string}`

Host for Github login. Defaults to `https://github.com`.
Can be provided to allow login with Github Enterprise.

## Development

```sh
$ npm install
$ npm start
```

Webpack development server starts at [http://localhost:8080](http://localhost:8080), loading [example/index.html](github.com/checkr/react-facebook-login/tree/master/example/index.html).
npm package: @seidhr/react-muna-logo
Description: React icons for Muna
Author: Tarje Sælen Lavik
Latest version: 1.2.0

# react-muna-logo

Shared Seidhr/Muna logo and icon

## Logo

<img width="200" alt="portfolio_view" src="./resources/icons/seidhrLogo.svg">

## Icon

<img width="200" alt="portfolio_view" src="./resources/icons/seidhrIcon.svg">
npm package: @seidhr/sanity-plugin-dashboard-widget-muna-docs
Description: Just links to Muna documentation, for now
Author: Tarje Lavik
Latest version: 3.0.0

# sanity-plugin-dashboard-widget-muna-docs

Just links to Muna documentation, for now.

## Installation

```
npm install @seidhr/sanity-plugin-dashboard-widget-muna-docs
```

Add this code to your `sanity.condig.ts`:

```js
import { munaDocsWidget } from '@seidhr/sanity-plugin-dashboard-widget-muna-docs'

export default defineConfig({
  name: 'default',
  title: 'example-studio',
  //...
  plugins: [
    dashboardTool({
      widgets: [
        munaDocsWidget({ layout: { width: 'small' } }),
      ]
    }),
  ],
  //...
})
```

Example sanity.json:

```json
{
  "plugins": [
    "@sanity/base",
    "@sanity/components",
    "@sanity/default-layout",
    "@sanity/default-login",
    "@sanity/dashboard",
    "@sanity/desk-tool",
    "@seidhr/sanity-plugin-dashboard-widget-muna-docs"
  ],
  "parts": [
    {
      "name": "part:@sanity/base/schema",
      "path": "./schemas/schema"
    },
    {
      "implements": "part:@sanity/dashboard/config",
      "path": "./dashboardConfig.js"
    },
  ]
}
```


## License

MIT © Tarje Lavik. See LICENSE
npm package: @seidhr/sanity-plugin-muna-schemas
Description: Muna or ᛗᚢᚾᚨ means remember in norse. Muna is a schema for the Sanity Studio that enables detailed descriptions of cultural heritage objects and knowledge about their contexts as well as pages about them (or anything else really.)
Author: Tarje Sælen Lavik
Latest version: 1.0.0-alpha.13

# sanity-plugin-muna-schemas

Muna or ᛗᚢᚾᚨ means remember in norse. Muna is a schema for the Sanity Studio that enables detailed descriptions of cultural heritage objects and knowledge about their contexts as well as pages about them (or anything else really.) 

Muna is inspired by CIDOC-CRM and linked.art. The goal is to enable anyone to describe objects without a costly application or infrastructure. Muna tries to combine the expressiveness of CIDOC-CRM and the customizable editor Sanity Studio. Objects can connected to events, actors, reports and loads more.

## Installation

```
sanity install @seidhr/sanity-plugin-muna-schemas

# Install necessary plugins
sanity install @seidhr/sanity-plugin-timespan-input
sanity install @sanity/code-input 
sanity install @sanity/document-internationalization 
sanity install @sanity/language-filter 
sanity install @sanity/hierarchical-document-list
sanity install table 
sanity install iframe-pane 
sanity install documents-pane
yarn add react-icons
```

This schema _depends_ on `config:@sanity/document-internationalization` so it is important to set up this plugin!

```json
{
    "idStructure": "delimiter",
    "referenceBehavior": "strong",
    "base": "en",
    "languages": [
        {
            "id": "en",
            "title": "English",
            "isDefault": true
        },
        {
            "id": "no",
            "title": "Norsk"
        }
    ]
}
```

TODO: More detailed installation instructions for `document-internalization` and `language-filter`.

<!-- ## Configuration

The plugin can be configured through `<your-studio-folder>/config/muna-schemas.json`:

```json
{
  "add-config": "here"
}
``` -->

## License

MIT © Tarje Sælen Lavik
See LICENSE
npm package: @seidhr/sanity-plugin-timespan-input
Description: Make it easier to add timespan information with the help of Extended Date Time Format (EDTF).
Author: Tarje Lavik
Latest version: 4.0.4

# sanity-plugin-timespan-input

> This is a **Sanity Studio v3** plugin.
> For the v2 version, please install the v2.0.2 version.
> `npm install @seidhr/sanity-plugin-timespan-input@v2.0.2`

Make it easier to add timespan information with the help of Extended Date Time Format (EDTF). It will validate the EDTF input and provide a preview of the timespan.

![Screenshot of the plugin](./docs/images/input-preview.png)

## Schema

The plugin stores the edft string and maps to the CIDOC-CRM model for timespan. The stored object will look something like this:

```js
{
  _type: 'Timespan',
  edtf: "2020-01-01/2020-02-01"
  date: "2020-01-01T00:00:00.000Z",
  beginOfTheBegin: "2020-01-01T00:00:00.000Z",
  endOfTheBegin: "2020-01-02T00:00:00.000Z",
  beginOfTheEnd: "2020-02-01T00:00:00.000Z",
  endOfTheEnd: "2020-02-02T00:00:00.000Z",
}
```

Depending on the EDTF string, some of the properties might be `null`. If a precise date is given, the `date` property will be set to that date. If an unprecise date is given, the `beginOfTheBegin` and `endOfTheEnd` properties will be set to the start and end of the range. If an Interval is entered, eg. `2020/` or `2020/3001`, necessary start and end dates will be set.

## Usage

```js
import { timespanInput } from '@seidhr/sanity-plugin-timespan-input'

export default defineConfig({
  name: 'default',
  title: 'example-studio',

  projectId: '...',
  dataset: 'production',

  plugins: [
    timespanInput(),
  ],

  schema: {
    types: [
      ...schemaTypes
    ],
  },
})
```

Use `Timespan` in your schema:

```js
// [...]
{
  fields: [
    // [...]
    defineField({
      name: 'timespan',
      title: 'Timespan',
      type: 'Timespan',
    }),
  ]
}
```


## License

MIT © Tarje Lavik
See LICENSE
npm package: @seidko/koishi-plugin-httpcat
Description: Show cat images for HTTP status codes
Author: 机智的小鱼君
Latest version: 1.0.1

# koishi-plugin-httpcat

[![npm](https://img.shields.io/npm/v/koishi-plugin-httpcat?style=flat-square)](https://www.npmjs.com/package/koishi-plugin-httpcat)

显示 HTTP 状态码对应的猫图。

## 指令：httpcat

- 基本语法：`httpcat <code>`

显示 HTTP 状态码对应的猫图。
npm package: @seidrwork/sdk
Description: Official SDK for the SeidrWork compile API — SeidrScript integration for LLM system prompts
Author: RúnTek Solutions
Latest version: 0.1.0

# @seidrwork/sdk

Official SDK for the [SeidrWork](https://seidrwork.com) compile API. Integrates SeidrScript — compressed, workspace-specific policy encoding — into your LLM system prompts.

## Install

```bash
npm install @seidrwork/sdk
```

## Quick Start

```ts
import { SeidrWork } from "@seidrwork/sdk";

const sw = new SeidrWork("sk_seidr_pro_myworkspace_abc123");

// Compile a single instruction
const result = await sw.compile("reject prompt injection globally");
console.log(result.compiled);
// => "301020" (workspace-specific encoding)

// Compile a block of instructions for a specific agent
const block = await sw.compileBlock(
  ["reject prompt injection", "log all external requests", "allow tool use"],
  "main-agent",
  "allsyn",
);
console.log(block.compiled);
// => "SEID:v1:main-agent:allsyn|301020;210300;102010"

// Inject decoder into a system prompt
const prompt = await sw.injectDecoder("You are a helpful assistant.");
// => "You are a helpful assistant.\n\nSeidrScript v1 — 6-digit policy encoding\n..."
```

## API

### `new SeidrWork(apiKey, options?)`

| Parameter | Type | Description |
|-----------|------|-------------|
| `apiKey` | `string` | Your SeidrWork API key (`sk_seidr_<tier>_<workspace>_<random>`) |
| `options.baseUrl` | `string` | API base URL (default: `https://seidrwork.com`) |

### `compile(text)`

Compile a single English instruction to workspace-specific SeidrScript.

### `compileBlock(instructions, agentId?, platform?)`

Compile multiple instructions. When `agentId` and `platform` are provided, output is prefixed with `SEID:v1:<agentId>:<platform>|`.

### `getDecoder()`

Returns the workspace-specific decoder legend. Include this in your LLM system prompt so it can interpret compiled policies.

### `scan(content)`

Scan content for prompt injection and other threats using the Permatext inoculation engine.

### `checkin(agentId, platform, status?)`

Agent beacon check-in. Returns the latest Permatext rule set for local caching.

### `injectDecoder(systemPrompt)`

Convenience method: fetches the decoder and appends it to the provided system prompt string. Returns the augmented prompt.

## Error Handling

All methods throw `SeidrWorkAPIError` on non-2xx responses:

```ts
import { SeidrWork, SeidrWorkAPIError } from "@seidrwork/sdk";

try {
  await sw.compile("...");
} catch (err) {
  if (err instanceof SeidrWorkAPIError) {
    console.error(err.status); // HTTP status code
    console.error(err.message); // Error message from API
    console.error(err.body); // Full error response body
  }
}
```

## License

MIT
npm package: @seihon/macro
Description: A Babel macro for @seihon/loader
Author: Billy Kwok
Latest version: 0.3.1

# @seihon/macro

[![npm version](https://badgen.net/npm/v/@seihon/macro)](https://www.npmjs.com/package/@seihon/macro)
[![download](https://badgen.net/npm/dm/@seihon/macro)](https://www.npmjs.com/package/@seihon/macro)
[![Babel Macro](https://img.shields.io/badge/babel--macro-%F0%9F%8E%A3-f5da55.svg?style=flat-square)](https://github.com/kentcdodds/babel-plugin-macros)
[![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org)
[![License](https://badgen.net/npm/license/@seihon/macro)](https://github.com/billykwok/seihon/blob/master/LICENSE)
[![CircleCI](https://circleci.com/gh/billykwok/seihon/tree/master.svg?style=svg)](https://circleci.com/gh/billykwok/seihon/tree/master)

> Seihon【製本】(Bookbinding in Japanese) is a JavaScript toolkit that improves your MDX transformation pipeline. It allows you to quickly transform MDX documents into a collection (like turning codices into book).
>
> More importantly, this toolkit is the last piece of the puzzle that enables code-splitted CMS-less MDX-based static site generation.

`@seihon/macro` is a [`babel-macro`](https://github.com/kentcdodds/babel-plugin-macros) that transpiles `collection<Item>('../example.collection.js')` into `require('../example.collection.js')`.

- It allows you to avoid using require directly in your code.

- Additionally, this gives you the ability to type check your Seihon collections.

## Usage

This is an example of using `@seihon/macro` alone. For a complete example of the entire Seihon toolkit, please refer to the main [`README.md`](https://github.com/billykwok/seihon).

```javascript
// src/components/home.jsx
import React from 'react';
import collection from '@seihon/macro';

const posts = collection('../content/posts/seihon.config.js');

export default function Blog() {
  return posts.map(({ postId, minRead }) => (
    <PostPreview postId={postId} minRead={minRead} />
  ));
}
```

## Support

This library has been continuously used in many of my personal projects, and is regarded as production-ready. In the foreseeable future, I will continuously maintain and support this library.

## Issues and Feedback

Please voice your opinion and report bugs in the [issues](https://github.com/billykwok/seihon/issues) sections of this GitHub project.

## Contributing

You are more than welcome to add more functionalities, improve documentation, fix bugs, and anything you think is needed. The build step is pretty self-explanatory. Please refer to [CONTRIBUTING.md](https://github.com/billykwok/seihon/blob/master/CONTRIBUTING.md) for more details.

## License

MIT
npm package: @seihoukei/trigger
Description: Simple global event system
Author: seihoukei
Latest version: 1.0.1

# Trigger

Custom JavaScript event system. There is a svelte-specific version `@seihoukei/trigger-svelte`.

# Usage

You set up handlers for arbitrary triggers and then can trigger them. Both handlers and trigger activations can have any number of arguments. Handler arguments are passed to callback before trigger arguments.

## Set up handlers

Any valid Map key can be a trigger. There are several ways to set up a handler.

There are two types of handlers:

- *Normal* - executes with given arguments and might return a value. Called with `handler(...handlerArguments, ...triggerArguments)`
- *Modifier* - executed with input value in addition to arguments and returns modified value. Called with `handler(input, ...handlerArguments, ...triggerArguments)`

Normal handlers are set up with `Trigger.createHandler(trigger, handler, ...args)` or `Trigger.on(trigger, handler, ...args)`

Modifying handlers are set up with `Trigger.createModifier(trigger, handler, ...args)`

You can cancel either with `.cancel()` method of returned value.

## Triggering events

### Plain execution

Use `Trigger(trigger, ...args)` to execute normal handlers set up for given trigger. This is similar to `array.forEach`

### Polling results

Use `Trigger.poll(trigger, ...args)` to execute normal handlers set up for given trigger and collect execution results. This is similar to `array.map`

### Value modifications

Use `Trigger.modify(input, trigger, ...args)` to execute modifier handlers set up for the trigger in a chain. This is similar to `array.reduce`.

## Miscellaneous

`Trigger.createTrigger()` returns function that executes triggers with itself as a key. `Trigger.createPoll()` and `Trigger.createModification()` create similar functions for polling and modification.

`Trigger.clearTrigger(trigger)` removes all handlers associated with event and removes entry for it from storage.


# Quick example

```js
function counterCallback(handlerArgument, triggerArgument) {
    console.log(`${handlerArgument} + ${triggerArgument} = ${handlerArgument + triggerArgument}`)
    return handlerArgument + triggerArgument
}

// Set up handlers
const handlers = [
    Trigger.on("count", counterCallback, 1),
    Trigger.on("count", counterCallback, 2),
    Trigger.createModifier("boost", x => x + 1).setPriority(1),
    Trigger.createModifier("boost", x => x * 2).setPriority(0),
]

Trigger("count", 3)
//1 + 3 = 4
//2 + 3 = 5

console.log(Trigger.poll("count", 4))
//1 + 4 = 5
//2 + 4 = 6
//[5, 6]

console.log(Trigger.modify(5, "boost"))
//11

// Clean up handlers
handlers.forEach(handler => handler.cancel())

console.log(Trigger.poll("count", 6))
//[]

console.log(Trigger.modify(7, "boost"))
//7
```