open-index/open-npm huggingface dataset:
npm package: @gleissonneves/liz-design-token
Description: Tokens amigáveis para apicações em css ou sass
Author: Gleisson Neves
Latest version: 3.1.1

# Liz Design Token

Token Liz, é uma maneira de escalar o design system de produtos digitais visando a coesão visual


# Como Importar para seu projeto

NPM
```
npm i @gleissonneves/liz-design-token
```

YARN

```
yarn add @gleissonneves/liz-design-token
```

Use no root do app para disponibilizar os token
``
 import '@gleissonneves/liz-design-token'
``


or CDN

```
<!DOCTYPE html>
<html lang="pt-br">
<head>
    ...

    <!-- START LIZ DESIGN TOKEN -->
    
    <link rel="stylesheet" type="text/css" href="https://unpkg.com/@gleissonneves/liz-design-token@2.0.5/dist/index.css">
    
    <!-- END LIZ DESIGN TOKEN -->

    ...
</head>
...
```


# Documento de visão
No link abaixo você encontra o documento de token:

https://www.figma.com/file/cPVx6CuoMyIz2Vwp8RETxe/Liz-Design-Token?node-id=6%3A13&t=SqvGhwafBGXJrevw-1

Parar alterar um token você terar que sobrescrever

Exemplo:
```
Token de origem:
:root {
    --color-brand-primary-100: #FDB9D2;
}


Token de modificado:
:root {
    --color-brand-primary-100: #FF00FF;
}
```
npm package: @glen/jest-raw-loader
Description: Jest transformer mimicking webpack-contrib/raw-loader's functionality
Author: Kepler Sticka-Jones
Latest version: 2.0.0

# jest-raw-loader

[Jest](https://facebook.github.io/jest/) transformer mimicking [webpack-contrib/raw-loader](https://github.com/webpack-contrib/raw-loader)'s functionality

## Install

```
$ npm install --save-dev @glen/jest-raw-loader
```

## Usage

Use [jest's `transform` configuration options](https://facebook.github.io/jest/docs/en/configuration.html#transform-object-string-string) to use this package in your unit tests.

For example use the following to raw load `.md` and `.graphql` files:

```json
"jest": {
  "transform": {
    "\\.graphql$": "@glen/jest-raw-loader",
    "\\.md$": "@glen/jest-raw-loader"
  }
}
```

This is for jest >= 28, if you are using older version use `jest-raw-loader` package:

- https://github.com/keplersj/jest-raw-loader

## License

Copyright 2017-2020 [Kepler Sticka-Jones](https://keplersj.com/). Licensed MIT.
npm package: @glen/wiki-rpc-client
Description: TypeScript client for [Wiki RPC Interface 2.0][1] ([web.archive.org][2]).
Author: Elan Ruusamäe
Latest version: 0.4.0

# Client for Wiki RPC Interface 2.0

TypeScript client for [Wiki RPC Interface 2.0][1] ([web.archive.org][2]).

This is the [Remote API interface][3] that [Dokuwiki][4] implements.

[1]: http://www.jspwiki.org/wiki/WikiRPCInterface2
[2]: https://web.archive.org/web/20130526043929/http://www.jspwiki.org/wiki/WikiRPCInterface2
[3]: https://www.dokuwiki.org/xmlrpc
[4]: https://www.dokuwiki.org

## Usage

```ts
import { WikiRpcClient } from "@glen/wiki-rpc-client";

const main = async () => {
  const url = "http://localhost/lib/exe/xmlrpc.php";
  const client = new WikiRpcClient(url);
  const data = await client.call("wiki.getPage", ["start"]);
  console.log(data);
};

main().catch((e: Error) => console.error(e));
```

Additionally, you can create client proxy and specify function signatures

```ts
import { WikiRpcClient, WikiService, DokuwikiService, DokuwikiPluginStructService } from "@glen/wiki-rpc-client";

// create client proxy with DokuwikiService service definitions
const client = WikiRpcClient.create<DokuwikiService>(url);

// the services can be combined as well:
const client = WikiRpcClient.create<WikiService & DokuwikiService>(url);

// combine with "struct" plugin methods:
const client = WikiRpcClient.create<WikiService & DokuwikiService & DokuwikiPluginStructService>(url);

const dwVersion = await client["dokuwiki.getVersion"]();
console.log(dwVersion);

const data = await client["wiki.getPage"]("start");
console.log(data);
```
npm package: @glenjamin/webpack-hot-client-overlay
Description:  An overlay for webpack-hot-client
Author: Glen Mailer
Latest version: 1.0.0

# webpack-hot-client-overlay

This is an early prototype.

## Installation

Install package
```
npm install --save-dev @glenjamin/webpack-hot-client-overlay
```

Add to `webpack.config.js`'s `entry` array.

```
entry: [
  "./client",
  mode === "development" && "@glenjamin/webpack-hot-client-overlay"
].filter(Boolean),
```
npm package: @glenngijsberts/customstorage
Description: Easy to use wrapper for [localStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) 🧠.
Author: Glenn Gijsberts
Latest version: 2.0.0

# CustomStorage

Easy to use wrapper for [localStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) 🧠.

## Install

```shell
# Install
npm install @glenngijsberts/customstorage --save
```

```javascript
import CustomStorage from '@glenngijsberts/customstorage'
```

## Usage

```javascript
/*
    get item
*/
const token = CustomStorage.get('token')

/*
    set: token, value, cachetime
*/
const token = 'AABB12'
CustomStorage.set('token', token, 60)

/*
    remove item
*/
CustomStorage.remove('token')

/*
    clear storage (all items)
*/
CustomStorage.clear()
```

## Clone

```shell
# clone the repo
git clone https://github.com/glenngijsberts/CustomStorage.git

# install dependencies / or npm install
yarn

# tests / or npm run test
yarn test

# build / or npm run prepare
yarn prepare
```

## Contribution

Feel free to contribute to this package. If you have any questions you can reach out to me on [twitter](https://twitter.com/glenngijsberts) 😄 This package is inspired by this [vue tabs package](https://github.com/spatie/vue-tabs-component) from the guys at [spatie](https://github.com/spatie).

## License

MIT
npm package: @glennjones/nunjucks-tools
Description: A set of simple tools build to help convert other templates types into nunjucks
Author: Glenn Jones
Latest version: 0.0.2

# Nunjucks Tools

A set of simple tools build to help convert other templates types into nunjucks

## Installation

```
npm i nunjucks-tools
```

## Usage

```js
const Nunjucks = require('nunjucks');
const NunjucksTools = require('nunjucks-tools');
const env = new Nunjucks.Environment();

env.addExtension('with', new NunjucksTools.with(env));
env.addExtension('withInclude', new NunjucksTools.withInclude(env));

````

### with
```
{% with obj.size, as='image' %}
   with: {{ image.width }}
{% endwith %}
```

### includeWith
```
{% includeWith "template.njk", with={
    x: 5,
    y: 4
} %}
```


## Issues
If you find any issue please file here on github and I will try and fix them.
npm package: @glennjones/prompt
Description: At the moment this code is more of a sketched idea than a library, but it is usable if you are interested in tring it out. It may be well your time worth looking at the [Langchain JS](https://github.com/hwchase17/langchainjs) which is the most heavily use
Latest version: 1.0.4

# Prompt

At the moment this code is more of a sketched idea than a library, but it is usable if you are interested in tring it out. It may be well your time worth looking at the [Langchain JS](https://github.com/hwchase17/langchainjs) which is the most heavily used tool of this type at the moment (Apr 2023). It is more advanced and has a lot of additional/useful features this tool does not have.

### What is prompt

Its a light warpper around LLM inetrfaces such as OpenAI's ChatGPT. It provides:

- Prompt templating
- Simple interface prompt building in JavaScript
- Switching between model providers - OpenAI built-in, expanable to others
- Fine-tuned model selection for OpenAI
- Structured output for coding aginst
- Safe conversion output text to JSON
- Automatic API retries if service is busy
- Caching archecture

I have been using it to benchmark NER and Classification tasks with OpenAI prompts against other approcahes.  


### Install library

```
npm i @glennjones/prompt
```

### Setup the objects

```
const Prompt = require('prompt');
const {Prompter, OpenAI} = Prompt;
```

### Example of Image result for Named entity recognition (NER)

```
import {OpenAI, Prompter} from prompt

let model = new OpenAI(apiKey);
let prompt = new Prompter(model);

let result = await prompt.fit('ner', {
    domain: 'ux design',
    textInput: 'Senior UX Researcher, part-time 6 month contract, Edinburgh - Hybrid',
  });
console.log(result);

### Output

{
  promptTokens: 152,
  completionTokens: 99,
  totalTokens: 251,
  data: [
    { label: 'Position', text: 'Senior UX Researcher' },
    { label: 'Contract Type', text: 'part-time' },
    { label: 'Contract Duration', text: '6 month' },
    { label: 'Location', text: 'Edinburgh' },
    { label: 'Work Type', text: 'Hybrid' },
    { branch: 'UX Design', group: 'Research' }
  ]
}
```






### TODO

- ~~Get list of models from rest API~~
- ~~Selection of fine tuned models works~~
- ~~Request retry after fixed period~~
- ~~Add Prompt hash~~
- ~~Add Cache interface~~
- ~~Add simple json file cache~~
- Add examples for all templates
- Add JSDocs to support typescript
- Add memory cache
- Parse templates to give user list all variables
- Check chat gtp 3.5 works
  - Check user context is working
  - Check prompt-chains are working
  - Consider extending template structure to have prompt-chains
- Look at allowing the upload and storage of templates

Based on the ideas/code of Promptify - https://github.com/promptslab/promptify
npm package: @glennjong/pixel-window
Description: 像素風格的 React 視窗元件庫，支援可自訂邊框、顏色與拖曳、縮放。
Latest version: 0.1.7

# @glennjong/pixel-window

像素風格的 React 視窗元件庫，支援可自訂邊框、顏色與拖曳、縮放。

## 安裝

```bash
yarn add @glennjong/pixel-window
# 或
npm install @glennjong/pixel-window
```

## 使用方式

```tsx
import { PixelWindow, FreePixelWindow } from '@glennjong/pixel-window';

function App() {
  return (
    <>
      <PixelWindow pixel={24} stroke="#000" frame="#F0F0F0" background="#F0F0F0">
        <div>內容</div>
      </PixelWindow>
      <FreePixelWindow name="demo" pixel={24} stroke="#000" frame="#F0F0F0" background="#F0F0F0">
        <div>可拖曳視窗</div>
      </FreePixelWindow>
    </>
  );
}
```

## API

### `<PixelWindow />`
| Prop         | Type     | Default   | 說明         |
|--------------|----------|-----------|--------------|
| pixel        | number   | 160       | 邊框像素大小 |
| stroke       | string   | #000      | 邊框顏色     |
| frame        | string   | #333      | 框色         |
| background   | string   | #DDD      | 背景色       |
| style        | object   |           | 內容區樣式   |
| children     | ReactNode|           | 內容         |

### `<FreePixelWindow />`
| Prop         | Type     | Default   | 說明             |
|--------------|----------|-----------|------------------|
| name         | string   |           | 唯一名稱(儲存位置/大小) |
| pixel        | number   | 16        | 邊框像素大小     |
| stroke       | string   | #000      | 邊框顏色         |
| frame        | string   | #333      | 框色             |
| background   | string   | #DDD      | 背景色           |
| position     | object   | {x:100,y:100}| 初始位置      |
| minWidth     | number   | 120       | 最小寬度         |
| minHeight    | number   | 100       | 最小高度         |
| style        | object   |           | 內容區樣式       |
| children     | ReactNode|           | 內容             |

## 授權

MIT License
npm package: @glennlee/query-format
Description: format query
Author: glennlee
Latest version: 0.0.9

### How to use

```js
import QueryFormat from '@glennlee/query-format'

const format = new QueryFormat(true) // if true will use base64 format the query's value
const query = {
  a: undefined,
  b: null,
  c: 1,
  d: 'd',
  e: [1, 2, '3', { a: 'a' }],
  f: { a: 'a', b: 1, c: [1, 2, '3'] },
  g: 1.1111112223123
}
const res1 = format.encodeQuery(query)
console.log('TCL: res1', res1)
const res2 = format.decodeQuery(res1)
console.log('TCL: res2', res2) // res2.result 是解析结果， res2.flag 表示解析是否正常(true代表正常),res.failedItems代表解析失败项
```
npm package: @glennreyes/eslint-config
Description: Opinionated ESLint config with TypeScript, React, and Next.js support
Author: Glenn Reyes
Latest version: 1.1.0

# @glennreyes/eslint-config

Opinionated ESLint config with TypeScript, React, and Next.js support.

## Features

- 🎯 TypeScript support with type-checking
- ⚛️ React & React Hooks support
- ⚡ Next.js optimized configuration
- 🎨 Stylistic rules for consistent code formatting
- 📦 Import sorting and organization
- 🧹 Automatic unused imports removal
- ♿ Accessibility checks (jsx-a11y)

> Requires Node.js 18+ and ESLint 9 or newer.

## Installation

```bash
pnpm add -D @glennreyes/eslint-config eslint typescript
# or
npm install --save-dev @glennreyes/eslint-config eslint typescript
# or
yarn add -D @glennreyes/eslint-config eslint typescript
```

## Usage

### Next.js (default)

```ts
// eslint.config.ts
export { default } from '@glennreyes/eslint-config';
```

### React

```ts
// eslint.config.ts
export { default } from '@glennreyes/eslint-config/react';
```

### Node.js

```ts
// eslint.config.ts
export { default } from '@glennreyes/eslint-config/node';
```

### Base (TypeScript/JavaScript)

```ts
// eslint.config.ts
export { default } from '@glennreyes/eslint-config/base';
```

### Extending the config

```ts
// eslint.config.ts
import baseConfig from '@glennreyes/eslint-config';
import { defineConfig } from 'eslint/config';

export default defineConfig([
  ...baseConfig,
  {
    // Your custom rules
    rules: {
      'no-console': 'off',
    },
  },
]);
```

## What's included

### Plugins

- `@eslint/js` - ESLint recommended rules
- `@stylistic/eslint-plugin` - Stylistic rules for code formatting
- `@typescript-eslint/parser` - TypeScript parser
- `eslint-plugin-import` - Import/export syntax support
- `eslint-plugin-jsx-a11y` - Accessibility rules for JSX
- `eslint-plugin-perfectionist` - Sorting and organization
- `eslint-plugin-prefer-arrow-functions` - Prefer arrow functions
- `eslint-plugin-react` - React specific rules
- `eslint-plugin-react-hooks` - React Hooks rules
- `eslint-plugin-unicorn` - Various awesome ESLint rules
- `eslint-plugin-unused-imports` - Auto-remove unused imports
- `typescript-eslint` - TypeScript ESLint rules

## License

MIT © [Glenn Reyes](https://glennreyes.com)
npm package: @glennreyes/is-webpack
Description: Simple check if code is running through webpack
Author: Glenn Reyes
Latest version: 1.0.0

# @glennreyes/is-webpack

Simple check if code is running through webpack

## Installation & Usage

```sh
npm install @glennreyes/is-webpack
```

```js
const isWebpack = require('@glennreyes/webpack')

if (isWebpack) {
  // ...
}
```
npm package: @glennreyes/react-click-outside
Description: 🐭 Handles clicks outside of a component
Author: Glenn Reyes
Latest version: 0.1.0-alpha.0

# React ClickOutside

🐭 Handles clicks outside of a component.

## Installation

```
yarn add @glennreyes/react-click-outside
```

## Usage

### Simple example

```js
<ClickOutside onClickOutside={() => closeMenu()}>
  <Menu />
</ClickOutside>
```

This will wrap the children with a `div` container.

### Custom container

To use a custom container, you can use the component with a render prop:

```js
<ClickOutside onClickOutside={() => closeMenu()}>
  {({ containerRef }) => <Menu innerRef={containerRef} />}
</ClickOutside>
```

To just discard the `div` container, you can do following:

```js
<ClickOutside onClickOutside={() => closeMenu()}>
  {() => <Menu />}
</ClickOutside>
```

## Inspired by

-  [tj/react-click-outside](https://github.com/tj/react-click-outside)

## License

MIT
npm package: @glennreyes/secretsanta
Description: 🎅 Draw secret santa
Author: Glenn Reyes
Latest version: 1.0.0-alpha.1

# Secret Santa

🎅 Simple secret santa draw

## Installation

```sh
yarn add @glennreyes/secretsanta
```

## Usage

```js
const drawSecretSanta = require('@glennreyes/secretsanta');

drawSecretSanta(['Glenn', 'Charmaine', 'Nolan']);
// Returns random selections, eg:
// [
//   { giver: 'Nolan', recipient: 'Charmaine' },
//   { giver: 'Charmaine', recipient: 'Glenn' },
//   { giver: 'Glenn', recipient: 'Nolan' },
// ]
```

## License

MIT
npm package: @glennsl/bs-revamp
Description: A safe and functional API for JavaScript regexes
Author: glennsl
Latest version: 0.2.0

# bs-re:vamp

An experimental safe and functional API for JavaScript regexes

[![npm](https://img.shields.io/npm/v/@glennsl/bs-revamp.svg)](https://npmjs.org/@glennsl/bs-revamp)
[![Travis](https://img.shields.io/travis/glennsl/bs-revamp/master.svg)](https://travis-ci.org/glennsl/bs-revamp)
[![Coveralls](https://img.shields.io/coveralls/glennsl/bs-revamp/master.svg)](https://coveralls.io/github/glennsl/bs-revamp?branch=master)
[![Dependencies](https://img.shields.io/david/glennsl/bs-revamp.svg)](https://github.com/glennsl/bs-revamp/network/dependencies)
[![Issues](https://img.shields.io/github/issues/glennsl/bs-revamp.svg)](https://github.com/glennsl/bs-revamp/issues)
[![Last Commit](https://img.shields.io/github/last-commit/glennsl/bs-revamp.svg)](https://github.com/glennsl/bs-revamp/commits/master)
[![Size](https://img.shields.io/github/size/glennsl/bs-revamp/lib/js/src/Revamp.js.svg)](https://github.com/glennsl/bs-revamp/blob/master/lib/js/src/Revamp.js)

## Example

```reason
/*
 * Dasherize camelCased identifiers inside string literals
 */

let code = {|
  let borderLeftColor = "borderLeftColor";
  let borderRightColor = "borderRightColor";
|};

code |> Revamp.replace({|"([^"]+)"|},                /* Matches the content of string literals */
          Revamp.replace("[A-Z]", letter =>          /* Matches uppercase letters */
            "-" ++ letter |> Js.String.toLowerCase)) /* Convert to lower case and prefix with a dash */
     |> Js.log;

/* Outputs:

  let borderLeftColor = "border-left-color";
  let borderRightColor = "border-right-color";
*/
```

## Installation

```sh
npm install --save @glennsl/bs-revamp
```

Then add `@glennsl/bs-revamp` to `bs-dependencies` in your `bsconfig.json`:

```js
{
  ...
  "bs-dependencies": ["@glennsl/bs-revamp"]
}
```

## Goals

- A sane, safe API
- Low performance overhead (secondary)

## Non-goals

- Full feature parity

## Documentation

For the moment, please see the interface file, [Revamp.rei](https://github.com/glennsl/bs-revamp/blob/master/src/Revamp.rei).

## Changes

### 0.2.0

- [BREAKING] Removed `Match.matches`, deprecated in 0.1.0, due to being unsound

### 0.1.0

- Changed type of `captures` from `Sequence.t(array(string))` to `Sequence.t(list(option(string)))` because the former was unsound.
- Added `Match.match` and `Match.captures`
- Deprecated `Match.matches` due to being unsound
npm package: @glennsl/rebase
Description: A minimal base library for Reason
Author: glennsl
Latest version: 0.2.2

# re:base
A minimal base library intended for the BuckleScript/Reason ecosystem. Uses Reasonable conventions and is easily consumed via npm.

[![npm](https://img.shields.io/npm/v/@glennsl/rebase.svg)](https://npmjs.org/@glennsl/rebase)
[![Travis](https://img.shields.io/travis/glennsl/rebase/master.svg)](https://travis-ci.org/glennsl/rebase)
[![Coveralls](https://img.shields.io/coveralls/glennsl/rebase/master.svg)](https://coveralls.io/github/glennsl/rebase?branch=master)
[![Issues](https://img.shields.io/github/issues/glennsl/rebase.svg)]()
[![Last Commit](https://img.shields.io/github/last-commit/glennsl/rebase.svg)]()

## Status
Mostly undocumented and untested. Prone to change without warning. Use at your own risk.

## Project Goals
* Cross-platform
* Compile to efficient JavaScript code
* Compile to readable JavaScript code

## Design Principles
* JS first
* No platform-specific APIs exposed
* Prefer piped form, e.g. `"a" |> String.concat("b") == "ab"`
* The subject of functions in type-wrapping modules should always be `t`
* Enforce common patterns using module signatures

## Installation

```sh
npm install --save @glennsl/rebase
```

Then add `@glennsl/rebase` to `bs-dependencies` in your `bsconfig.json`:
```js
{
  ...
  "bs-dependencies": ["@glennsl/rebase"]
}
```

## Documentation

For the moment, please see [Rebase.rei](https://github.com/glennsl/rebase/blob/master/src/Rebase.rei). There's not many
doc comments yet, but most functions should be pretty self-explanatory.
npm package: @glennsl/rebug
Description: Reason/BuckleScript port of debug, with some extras
Author: glennsl
Latest version: 0.2.2


# rebug

Originally a port of [debug](https://github.com/visionmedia/debug) to BuckleScript, but has since expanded a bit.

[![npm](https://img.shields.io/npm/v/@glennsl/rebug.svg)](https://npmjs.org/@glennsl/rebug)
[![Issues](https://img.shields.io/github/issues/glennsl/rebug.svg)](https://github.com/glennsl/rebug/issues)
[![Last Commit](https://img.shields.io/github/last-commit/glennsl/rebug.svg)](https://github.com/glennsl/rebug/commits/master)
[![Size](https://img.shields.io/github/size/glennsl/rebug/lib/js/src/Debug.js.svg)]()

_**NOTE:** NPM package has moved to `@glennsl/rebug`. Remember to update both `package.json` AND `bsconfig.json`._

## Status

* Browser back-end has been implemented, Node.js back-end has not
* Formatting isn't properly supported yet
* Colors are always on
* Isn't quite as customizable (yet)

## Example

```reason
/* Reason */

/* creates a logger with the given namespace */
let debug = Debug.make("my:namespace");

/* debug.log* logs the message only if the namespace of the logger is enabled */
debug.log1("The red cow jumps over the lazy giraffe");

/* debug.error* will log the message regardless of whether the namespace is
   enabled, format it as an error and include a stack trace */
try (...) {
| error => a.error2("Error occurred while doing stuff: ", error)
};

/* debug.fn* groups any log output during its execution, and logs the arguments
   passed to and the value returned from the function */
let loggedParse = debug.fn1("JSON.parse", Js.Json.parseExn);
```

See [examples](https://github.com/glennsl/rebug/blob/master/examples/) for more.

## Installation

```sh
npm install --save @glennsl/rebug
```

Then add `@glennsl/rebug` to `bs-dependencies` in your `bsconfig.json`:
```js
{
  ...
  "bs-dependencies": ["@glennsl/rebug"]
}
```
npm package: @glennsl/rescript-fetch
Description: Zero-cost rescript bindings to the WHATWG Fetch API
Author: Glenn Slotte
Latest version: 0.2.3

# rescript-fetch
Zero-cost rescript bindings to the WHATWG Fetch API

[![npm](https://img.shields.io/npm/v/@glennsl/rescript-fetch.svg)](https://npmjs.org/@glennsl/rescript-fetch)
[![Issues](https://img.shields.io/github/issues/glennsl/rescript-fetch.svg)](https://github.com/glennsl/rescript-fetch/issues)
[![Last Commit](https://img.shields.io/github/last-commit/glennsl/rescript-fetch.svg)](https://github.com/glennsl/rescript-fetch/commits/master)


## Example

```rescript
let postBanana = async data => {
  open Fetch

  let response = await fetch(
    "/api/bananas",
    {
      method: #POST,
      body: data->Js.Json.stringifyAny->Belt.Option.getExn->Body.string,
      headers: Headers.fromObject({
        "Content-type": "application/json",
      }),
    },
  )

  await response->Response.json
}
```

See [examples](https://github.com/glennsl/rescript-fetch/blob/master/examples/) for more.


## Installation

```sh
npm install --save @glennsl/rescript-fetch
```

Then add `@glennsl/rescript-fetch` to `bs-dependencies` in your `bsconfig.json`:

```diff
 {
   "bs-dependencies": [
+    "@glennsl/rescript-fetch"
   ]
 }
```

## Documentation

### API

For the moment, please see the interface file:

* [Fetch](https://github.com/glennsl/rescript-fetch/blob/master/src/Fetch.res)


## Changes

### 0.2.3

* Added `Headers.getSetCookie`

### 0.2.2

* Fixed typo in `Request.credentials` binding.

### 0.2.1

* Fleshed out `AbortSignal` bindings.

### 0.2.0

* [BREAKING] Updated required minimum version of rescript to 10.1.2 in order to use the new promise type alias and async/await.
* Removed `@ryyppy/rescript-promise` dependency.

### 0.1.0
Initial release
npm package: @glennsl/timber
Description: Opinionated logging framework based on @dbuenzli/logs
Latest version: 1.2.0

# timber
Opinionated logging framework based on [@dbuenzli/logs](https://github.com/dbuenzli/logs)

![Screenshot](https://github.com/glennsl/timber/blob/master/assets/screenshot.png)

### Features
- Colorized output (except on Windows, because Windows)
- Namespaces, filterable and colorized by hash
- Delta timestamp showing time since previous message
- Console and file reporter out-of-the-box
- TRACE level
- Very simple API

### Example

```reason
Timber.App.enable();
Timber.App.setLevel(Timber.Level.debug);
Timber.App.setLogFile("test.log");

module Log = (val Timber.Log.withNamespace("Timber"));

Log.trace("This won't be logged");

Log.infof(m => m("Formatting and lazy evaluation %i", Random.int(100)));

Log.error("Something went horribly wrong!");
```
npm package: @glenstack/cf-workers-access
Description: Authenticate with Cloudflare Access from within a Cloudflare Worker
Author: Greg Brimble
Latest version: 1.0.8

# Cloudflare Workers Access

Authenticate with [Cloudflare Access](https://teams.cloudflare.com/access/) from within a [Cloudflare Worker](https://workers.cloudflare.com/).

## Installation

```sh
npm install --save @glenstack/cf-workers-access
```

## Usage

```typescript
import { createAuthenticator } from "@glenstack/cf-workers-access";

const AUTHENTICATION_DOMAIN = "glenstack.cloudflareaccess.com";
const POLICY_AUD =
  "f8612530c08484786e83e00ff7b549bc3763747beae55ec909cc28a6a56b81d1";

const handleRequest = async (request: Request) => {
  const authenticator = await createAuthenticator(AUTHENTICATION_DOMAIN, {
    aud: POLICY_AUD,
  });

  const jwt = await authenticator(request);

  if (jwt) {
    return new Response(`Hello, ${jwt.email}!`);
  }

  return new Response("Unauthorized", { status: 401 });
};

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});
```

`createAuthenticator` takes two parameters:

1. The "Login Page Domain" of your Cloudflare Access account e.g. `glenstack.cloudflareaccess.com`.
1. Optionally, an object with the optional parameters:

   - `aud`: The "Audience Tag" of your Access Policy.
   - `iss`: Automatically set to the "Login Page Domain", but optionally overridable.
   - `tolerance`: Number of seconds of leeway for validating `exp` and `nbf` claims. Defaults to `0`.

It returns a Promise of a function which, in turn, takes a Request and returns a Promise of either:

- `false` if the Request failed authentication, or
- [the JWT payload](https://developers.cloudflare.com/access/setting-up-access/json-web-token/#payload).
npm package: @glenstack/cf-workers-algolia-search
Description: An Algolia search client for Cloudflare Workers
Author: Greg Brimble
Latest version: 1.0.2

# Cloudflare Workers Algolia Search

An [Algolia](https://www.algolia.com/) search client for [Cloudflare Workers](https://workers.cloudflare.com/).

## Installation

```sh
npm install --save @glenstack/cf-workers-algolia-search
```

## Usage

```typescript
import algoliasearch from "@glenstack/cf-workers-algolia-search";

const client = algoliasearch("ApplicationID", "APIKey");
const index = client.initIndex("IndexName");

const handleRequest = async (request) => {
  const term = request.searchParams.get("term");
  const { hits } = await index.search(term);

  return new Response(JSON.stringify(hits), {
    headers: { "Content-Type": "application/json" },
  });
};

addEventListener("fetch", (event) => {
  const { request } = event;
  event.respondWith(handleRequest(request));
});
```

`algoliasearch` is an implementation of the official Algolia search client, so reference [its documentation](https://www.algolia.com/doc/api-client/methods/search/). **Note however, that [timeouts](https://www.algolia.com/doc/api-reference/api-methods/configuring-timeouts/) are not respected.**
npm package: @glenstack/cf-workers-customevent
Description: A polyfill CustomEvent implementation for Cloudflare Workers
Author: Greg Brimble
Latest version: 1.0.2

# Cloudflare Workers CustomEvent

A polyfill [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) implementation for [Cloudflare Workers](https://workers.cloudflare.com/).

## Installation

```sh
npm install --save @glenstack/cf-workers-customevent
```

## Usage

```typescript
import { CustomEvent } from "@glenstack/cf-workers-customevent";

addEventListener("myCustomEvent", (event) => {
  // Note: the `event` argument is the MyCustomEvent instance, rather than the FetchEvent.
  console.log("Hello from a myCustomEvent instance!");
});

addEventListener("fetch", (event) => {
  const url = new URL(event.request.url);
  if (url.pathname === "/fireCustomEvent") {
    const e = new CustomEvent("myCustomEvent");
    dispatchEvent(e);
  }

  event.respondWith(new Response("Hello, world!"));
});

// GET-ing `/fireCustomEvent` will log "Hello from a myCustomEvent instance!" and respond with "Hello, world!"
// GET-ing `/` will just respond with "Hello, world!"
```

Optionally, you can also pass through extra information with the CustomEvent using the `detail` property:

```typescript
import { CustomEvent } from "@glenstack/cf-workers-customevent";

addEventListener("myCustomEvent", (event: any) => {
  const name = event.detail.searchParams.get("name");
  console.log(`Hello ${name}, from a myCustomEvent instance!`);
});

addEventListener("fetch", (event) => {
  const url = new URL(event.request.url);
  if (url.pathname === "/fireCustomEvent") {
    const e = new CustomEvent("myCustomEvent", {
      detail: { searchParams: url.searchParams },
    });
    dispatchEvent(e);
  }

  event.respondWith(new Response("Hello, world!"));
});

// GET-ing `/fireCustomEvent?name=Greg` will log "Hello Greg, from a myCustomEvent instance!" and respond with "Hello, world!"
// GET-ing `/` will just respond with "Hello, world!"
```

And finally, you can also pass through the original FetchEvent, in order to respond from within the custom event listener:

```typescript
import { CustomEvent } from "@glenstack/cf-workers-customevent";

addEventListener("myCustomEvent", (event: any) => {
  const name = event.detail.searchParams.get("name");
  event.detail.fetchEvent.respondWith(new Response(`Hello, ${name}!`));
});

addEventListener("fetch", (event) => {
  const url = new URL(event.request.url);
  if (url.pathname === "/fireCustomEvent") {
    const e = new CustomEvent("myCustomEvent", {
      detail: { searchParams: url.searchParams, fetchEvent: event },
    });
    dispatchEvent(e);
  } else {
    event.respondWith(new Response("Hello, world!"));
  }
});

// GET-ing `/fireCustomEvent?name=Greg` will respond with "Hello, Greg!"
// GET-ing `/` will just respond with "Hello, world!"
```
npm package: @glenstack/cf-workers-function-memoizer
Description: A wrapper which utilizes Cloudflare Workers KV to memoize a function
Author: Greg Brimble
Latest version: 1.0.1

# Cloudflare Workers Function Memoizer

A wrapper which utilizes [Cloudflare Workers KV](https://developers.cloudflare.com/workers/learning/how-kv-works) to memoize a function.

## Installation

```sh
npm install --save @glenstack/cf-workers-function-memoizer
```

## Usage

```typescript
import { makeMemoizer } from "@glenstack/cf-workers-function-memoizer";

const memoize = makeMemoizer(CACHE_KV_NAMESPACE);

let anExpensiveFunction = async (anArgument: string) => {
  // ...
  return someResult;
};

anExpensiveFunction = memoize(
  anExpensiveFunction,
  {
    keyGenerator: (anArgument) => `anExpensiveFunction:${anArgument}`,
    resultTransformer: JSON.stringify,
    type: "json",
  },
  {
    expirationTtl: 60 * 60,
  }
);

// anExpensiveFunction is then ready to call with argument e.g. "hello"

(async () => {
  // First time, it'll execute and then cache the `JSON.stringify`-d result with `anExpensiveFunction:hello`. The cached value is set to expire in 60 minutes.
  let result = await anExpensiveFunction("hello");

  // Subsequent calls will first look up the CACHE_KV_NAMESPACE and return the result if it is found, parsing as "json".
  result = await anExpensiveFunction("hello");

  // One hour later...
  // Once the cached result is evicted, anExpensiveFunction will be re-run, and the result re-cached.
  result = await anExpensiveFunction("hello");
})();
```

`makeMemoizer` takes one parameter:

1. The KV Namespace to be used as the cache.

It returns a function which, in turn, takes a three parameters:

1. The expensive async function to be memoized

1. Optionally, an object with the optional parameters:

   - `keyGenerator`: A function which takes the same arguments as the memoized function, and returns a string to be used as the key in the cache KV namespace. By default, it creates a string formatted like:

     `functionName:arg0,arg1,arg2...`

     Where `functionName` is the name of the memoized function and the `argX`'s are the arguments passed to it. **Note: Function names often get minified by bundlers such as webpack, so you should strongly consider defining your own `keyGenerator` function.**


    - `resultTransformer`: A function which converts the memoized function's return value to a storable value in the KV namespace. Defaults to `JSON.stringify`.

    - `type`: [One of the supported types to parse KV values](https://developers.cloudflare.com/workers/runtime-apis/kv#types) (the inverse of `resultTransformer`). Defaults to 'json'.

1. Optionally, an object of options to pass to KV when setting the value e.g. [expiration times](https://developers.cloudflare.com/workers/runtime-apis/kv#creating-expiring-keys) or [metadata](https://developers.cloudflare.com/workers/runtime-apis/kv#metadata-1).

Finally, this can then be called in the same manner as the memoized function.
npm package: @glenstack/cf-workers-graphql
Description: A lightweight GraphQL Server for Cloudflare Workers
Author: Greg Brimble
Latest version: 1.0.4

# Cloudflare Workers GraphQL

A lightweight [GraphQL](https://graphql.org/) Server for [Cloudflare Workers](https://workers.cloudflare.com/).

## Installation

```sh
npm install --save @glenstack/cf-workers-graphql
```

## Usage

```typescript
import { makeGraphQLHandler } from "@glenstack/cf-workers-graphql";
import { makeExecutableSchema } from "@graphql-tools/schema";
import gql from "graphql-tag";

const typeDefs = gql`
  type Query {
    hello: String
  }
`;

const resolvers = {
  Query: {
    hello: (obj, args, context) =>
      context?.name ? `Hello, ${context?.name}!` : "Hello, world!",
  },
};

const schema = makeExecutableSchema({ typeDefs, resolvers });
const handler = makeGraphQLHandler(schema, {
  makeContextValue: (request) =>
    Promise.resolve({ name: request.headers.get("X-Name") }),
});

const handleRequest = async (request) => {
  return await handler(request);
};

addEventListener("fetch", (event) => {
  const { request } = event;
  event.respondWith(handleRequest(request));
});
```

`makeGraphQLHandler` takes a two parameters:

1. A [GraphQLSchema](https://graphql.org/graphql-js/type/#graphqlschema).
1. Optionally, an object with the optional parameters:

   - `makeContextValue`: A function which takes a Request and returns a Promise of a context value which is given to the schema resolvers.
   - `makeErrorResponse`: A function which takes two parameters (the Request and an Error) which returns a Promise of either void or a custom Response. If you wish to log errors, do so from within this function.

It returns a Promise of a function which, in turn, takes [a GraphQL specification compliant GET or POST Request](https://graphql.org/learn/serving-over-http/#http-methods-headers-and-body) and returns a Promise of [a GraphQL specification compliant Response](https://graphql.org/learn/serving-over-http/#response).
npm package: @glenstack/cf-workers-hcaptcha
Description: Verify a hCaptcha token from within a Cloudflare Worker
Author: Greg Brimble
Latest version: 1.0.0

# Cloudflare Workers hCaptcha

Verify a [hCaptcha](https://www.hcaptcha.com/) token from within a [Cloudflare Worker](https://workers.cloudflare.com/).

## Installation

```sh
npm install --save @glenstack/cf-workers-hcaptcha
```

## Usage

```typescript
import { createVerifier } from "@glenstack/cf-workers-hcaptcha";

const verify = createVerifier("0x0000000000000000000000000000000000000000");

const handleRequest = async (request) => {
  try {
    const payload = await verify(request);
    return new Response("Verified!");
  } catch (e) {
    return new Response(`Could not verify hCaptcha token: ${e.message}`, {
      status: 401,
    });
  }
};

addEventListener("fetch", (event) => {
  const { request } = event;
  event.respondWith(handleRequest(request));
});
```

`createVerifier` takes a single parameter, the secret key used to verify tokens.

It returns a function which, in turn, takes two parameters:

1. The Request.
1. Optionally, an object with the optional parameters:

   - `tokenExtractor`: An asynchronous function which, when given a Request, returns the token to verify. This defaults to extracting `h-captcha-response` from the `formData` body.

It returns a Promise of the [the hCaptcha payload](https://docs.hcaptcha.com/#server) if the verification was successful, else throws an error with [a human-readable error message](https://docs.hcaptcha.com/#server).
npm package: @glenstack/cf-workers-router
Description: A router for Cloudflare Workers
Author: Greg Brimble
Latest version: 1.0.1

# Cloudflare Workers Router

A router for Cloudflare Workers.

Adapted from the official [`worker-template-router`](https://github.com/cloudflare/worker-template-router), but written in TypeScript, and [available for installation from npm](#installation).

## Installation

```sh
npm install --save @glenstack/cf-workers-router
```

## Usage

```typescript
import { Router, Method, Header, Path } from "@glenstack/cf-workers-router";

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

const router = new Router();
router.handle(
  [
    Method("CustomHTTPVerb"),
    Header("Authorization", "aPassword"),
    Path("/secrets"),
  ],
  (request) => new Response("Secrets unlocked!")
);
router.get("/index.html", () => new Response("<html></html>"));
router.post(/\/api\/.*/, (request) => fetch(request));

const handleRequest = (request: Request) => {
  const response = await router.route(request);
  return response;
};
```

`Router` is initialized with no parameters. It returns an instance of the Router class, which has the following methods:

- `handle` which takes two parameters:

  1. A single, or a list of, function(s) which take a request and return a boolean (true if the request should be handled by this handler, false if not).

     The following helper functions are also available to aid the construction of these condition functions. Each return a function which can be used for this parameter.

     - `Method` takes a single parameter, a string for the method name.
     - `Header` takes two parameters, the header name (a string), and the header value (a string).
     - `Path` takes a single parameter, a string or RegExp which is used to match against the pathname of the request.

  1. A function which takes a Request and returns a Response or a Promise of a Response.

- `route` which takes a single parameter, a Request to route. It returns a Response or a Promise of a Response. Requests are delegated to routes in the order the routes were registered (i.e. the first registered handler has priority). By default, if no handlers match a Request, a 404 Response is returned.

- A `Router` instance also has the following helper methods to match on a HTTP verb and URL pathname, which take two parameters (a string or RegExp which the Request's pathname is tested against, and, like `handle`, a function which takes a Request and returns a Response or a Promise of a Response):

  - `connect`
  - `delete`
  - `get`
  - `head`
  - `options`
  - `patch`
  - `post`
  - `put`
  - `trace`

- Finally, `all` takes only one parameter, a function which takes a Request and returns a Response or a Promise of a Response. All requests will be handled by this function. This can be useful to change the default 404 behaviour.