open-index/open-npm huggingface dataset:
npm package: @suchipi/prettier-impact-js
Description: Prettier is an opinionated code formatter
Author: James Long
Latest version: 1.18.2

# @suchipi/prettier-impact-js

This is a fork of prettier that formats the ![Impact](https://impactjs.com/) module wrapper like so:

<!-- prettier-ignore -->
```js
ig.module(
  "game.entities.player"
)
.requires(
  "impact.entity",
  "impact.animation"
)
.defines(() => {

PlayerEntity = /* ... */;

});
```
npm package: @suchipi/pretty-print-ast
Description: Formats ASTs as nice readable strings, with colors
Author: Lily Scott
Latest version: 1.0.1

# pretty-print-ast

> Formats ASTs as nice readable strings, with colors

## Usage Example

<!-- prettier-ignore -->
```ts
import { formatAst } from "pretty-print-ast";

const ast = /* get an AST from whatever */

console.log(formatAst(ast));
```

Outputs something like:

![picture of script output](https://user-images.githubusercontent.com/1341513/155487536-8eab1863-e182-45d6-aae3-2e6e0e2d292a.png)

## API Documentation

Please see [api/index.d.ts](https://github.com/suchipi/pretty-print-ast/blob/main/api/index.d.ts) for API documentation.

## License

MIT
npm package: @suchipi/resizable-buffer
Description: "Resize" an ArrayBuffer (via slice or new+copy)
Author: Lily Skye
Latest version: 1.0.0

# `@suchipi/resizable-buffer`

Helper class for "resizing" an ArrayBuffer.

- When reducing the size, ArrayBuffer.slice is used (cheap).
- When increasing the size, a new ArrayBuffer is created and the contents are copied over (expensive).

```ts
export declare class ResizableBuffer {
  constructor(byteLength: number);
  buffer: ArrayBuffer;
  resizeTo(byteLength: number): void;
  resizeBy(bytes: number): void;
}
```
npm package: @suchipi/run-main
Description: CLI app entrypoint function runner
Author: Lily Skye
Latest version: 1.0.0

# `@suchipi/run-main`

A helper function suitable for use in command-line applications. Runs the user-provided "main" function (which can be sync or async), and if it errors, formats the error message, prints it to stderr, and calls `process.exit(1)`.

```ts
export function runMain(
  /**
   * The function to run. If it's async, it'll be `await`ed.
   */
  mainFunction: () => any,
  runOptions?: {
    /**
     * The function used to exit when an error occurs. If called, it will
     * receive the value `1`.
     *
     * Defaults to `process.exit`.
     */
    exit?: (code: number) => void;
    /**
     * The function used to print the formatted error text.
     *
     * Defaults to `console.error`, which writes to stderr.
     */
    printError?: (formattedError: string) => void;
    /**
     * The function used to convert an unknown value to a string when a
     * non-error value is thrown.
     *
     * Defaults to `require("util").inspect`.
     */
    inspect?: (value: any) => string;
  },
): Promise<void>;
```
npm package: @suchipi/shinobi
Description: Generate ninja build files from js scripts
Author: Lily Skye
Latest version: 1.4.3

# @suchipi/shinobi

generate ninja build files from js scripts

## Usage

- Install nodejs
- Install shinobi:

```
npm install -D @suchipi/shinobi
```

- Write scripts using the global functions documented in [`node_modules/@suchipi/shinobi/globals.d.ts`](https://github.com/suchipi/shinobi/blob/main/globals.d.ts), for example:

```js
// variables to be used in rules
declare("compiler", "gcc");
declareOrAppend("cflags", "-Wall");
declareOrAppend("cflags", "-g");

// rules for building things
rule("cc", {
  command: "$compiler $cflags $in -o $out", // $in and $out are builtin variables
  description: "CC $out",
});

// things to build
build({
  output: builddir("something.o"), // builddir defaults to `build/` but can be overridden
  inputs: [rel("something.c")], // rel resolves paths relative to the current file
  rule: "cc", // name of rule as defined above
});
```

- Pass those scripts to the shinobi CLI (maybe using a glob). It will output the contents of a ninja file

```bash
shopt -s globstar

npx shinobi ./**/*.ninja.js > build.ninja
```

For instance, the example script from above outputs something like this:

```ninja
# variable 'builddir' from builtin (override with env var BUILDDIR)
builddir = ./build
# variable 'compiler' from myscript.js
compiler = gcc
# variable 'cflags' from myscript.js
cflags = -Wall -g

# rule 'cc' from myscript.js
rule cc
  command = $compiler $cflags $in -o $out
  description = CC $out

# build for '$builddir/something.o' from myscript.js
build $builddir/something.o: cc /tmp/mycode/something.c
```

## License

MIT
npm package: @suchipi/sponge-case
Description: Transform into a string with random capitalization applied
Author: Nate Rabins
Latest version: 2.0.3

# Sponge Case

> Transform into a string with random capitalization applied.

## Installation

```
npm install sponge-case --save
```

## Usage

```js
import { spongeCase } from "sponge-case";

spongeCase("string"); //=> "sTrinG"
spongeCase("dot.case"); //=> "dOt.caSE"
spongeCase("PascalCase"); //=> "pASCaLCasE"
spongeCase("version 1.2.10"); //=> "VErSIoN 1.2.10"
```

## TypeScript and ESM

This package is a [pure ESM package](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and ships with TypeScript definitions. It cannot be `require`'d or used with CommonJS module resolution in TypeScript.

## License

MIT
npm package: @suchipi/spotify-player
Description: This is a JavaScript API that drives Spotify in a Chrome window.
Latest version: 1.0.4

# spotify-player

This is a JavaScript API that drives Spotify in a Chrome window.

You need to have Chrome installed. And it can't run headless, so on Linux, you need an x window server. You can use xvfb if you don't have a graphics card or are in a container.

## Usage

You need the following environment variable(s) set:

```sh
CHROME_PATH="path to your chrome executable"
```

Then:

```js
const spotify = require("@suchipi/spotify-player");

// You have to login first
spotify.login(username, password);

// Then you can search for something and play the first result
spotify.searchAndPlay("c418");

// Or, you can play an album or playlist URL directly
spotify.playURL("https://open.spotify.com/playlist/1L3GAiiBL5sBNbDEAMGMEA");

// These functions click the corresponding buttons at the bottom of the screen:
spotify.play();
spotify.pause();
spotify.previous();
spotify.next();

// To start radio for the currently-playing song:
spotify.startRadio();

// To get info about the currently-playing song:
const infoString = await spotify.nowPlayingInfo();
```

## Example REPL

Given a `.env` file in the current working directory with the following environment variables defined:

```
SPOTIFY_USERNAME="your spotify username or email"
SPOTIFY_PASSWORD="your spotify password"
CHROME_PATH="path to your chrome executable"
```

You can run `node -r @suchipi/spotify-player/repl -e ''` to load a sample song and open a repl where you can test other commands.

## License

MIT
npm package: @suchipi/string-utils
Description: A collection of several functions which wrap or transform strings
Author: Lily Skye
Latest version: 1.0.1

# `@suchipi/string-utils`

This package is a collection of several functions which wrap or transform strings.

It exports:

- The `dedent` function and template tag function from [string-dedent](https://npm.im/string-dedent),
- a `stripAnsi` function which removes ANSI control characters from a string, from [strip-ansi](https://npm.im/strip-ansi),
- a `quote` function which wraps a string in double quotes and escapes any double quotes within it,
- and all the styling functions from [kleur](https://npm.im/kleur).
npm package: @suchipi/swap-case
Description: Transform a string by swapping every character from upper to lower case, or lower to upper case
Author: Blake Embrey
Latest version: 3.0.3

# Swap Case

> Transform a string by swapping every character from upper to lower case, or lower to upper case.

## Installation

```
npm install swap-case --save
```

## Usage

```js
import { swapCase } from "swap-case";

swapCase("string"); //=> "STRING"
swapCase("dot.case"); //=> "DOT.CASE"
swapCase("PascalCase"); //=> "pASCALcASE"
```

## TypeScript and ESM

This package is a [pure ESM package](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and ships with TypeScript definitions. It cannot be `require`'d or used with CommonJS module resolution in TypeScript.

## License

MIT
npm package: @suchipi/title-case
Description: Transform a string into title case following English rules
Author: Blake Embrey
Latest version: 4.3.1

# Title Case

> Transform a string into [title case](https://en.wikipedia.org/wiki/Letter_case#Title_case) following English rules.

## Installation

```
npm install title-case --save
```

## Usage

```js
import { titleCase } from "title-case";

titleCase("string"); //=> "String"
titleCase("follow step-by-step instructions"); //=> "Follow Step-by-Step Instructions"
```

### Options

- `locale?: string | string[]` Locale used for `toLocaleUpperCase` during case transformation (default: `undefined`)
- `sentenceCase?: boolean` Only capitalize the first word of each sentence (default: `false`)
- `sentenceTerminators?: Set<string>` Set of characters to consider a new sentence under sentence case behavior (e.g. `.`, default: `SENTENCE_TERMINATORS`)
- `smallWords?: Set<string>` Set of words to keep lower-case when `sentenceCase === false` (default: `SMALL_WORDS`)
- `titleTerminators?: Set<string>` Set of characters to consider a new sentence under title case behavior (e.g. `:`, default: `TITLE_TERMINATORS`)
- `wordSeparators?: Set<string>` Set of characters to consider a new word for capitalization, such as hyphenation (default: `WORD_SEPARATORS`)

## TypeScript and ESM

This package is a [pure ESM package](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and ships with TypeScript definitions. It cannot be `require`'d or used with CommonJS module resolution in TypeScript.

## License

MIT
npm package: @suchipi/tracker
Description: Reactive tracker; forked from Meteor's `Tracker` api.
Author: Lily Scott
Latest version: 0.1.2

# `@suchipi/tracker`

Standalone Reactive tracker, like [Meteor's `Tracker`](https://docs.meteor.com/api/tracker.html).

Less than 1KiB gzipped.

## Installation

```sh
npm install --save @suchipi/tracker
```

## Sample usage

```ts
import { autorun, ReactiveVar } from "@suchipi/tracker";

const points = new ReactiveVar(0);

autorun(() => {
  // Because this function calls `points.get`, it will automatically be
  // re-run whenever `points.set` is called.
  console.log(`Score: ${points.get()}`);
});

points.set(1); // Logs "Score: 1"
points.set(45); // Logs "Score: 45"
points.set(0); // Logs "Score: 0"
```

## API

### `autorun`

Runs its received function now, and also registers it to be re-run in the future if any `Dependency` objects accessed during the function run get changed.

```ts
import { autorun } from "@suchipi/tracker";

Tracker.autorun(() => {
  // your code that uses Dependency objects goes here
});
```

### `Dependency`

Used to represent a value or resource that can be changed. When it changes, any functions that accessed it during a `Tracker.autorun` call will be automatically re-run.

```ts
import { Dependency } from "@suchipi/tracker";

const dep = new Dependency();

// When something is reading from the value/resource, call:
dep.depend();

// When something has updated the value/resource, call:
dep.changed();
```

### `ReactiveVar`

An object that holds a current value and creates a `Dependency` to track it. When the value is changed, the `Dependency`'s `changed` method is called.

```ts
import { ReactiveVar } from "@suchipi/tracker";

const myVar = new ReactiveVar<number>(42);

myVar.get(); // 42
myVar.set(45);
myVar.get(); // 45
```
npm package: @suchipi/ts-json-utils
Description: Utility types/functions to be used when working with JSON in TypeScript
Author: Lily Skye
Latest version: 1.0.0

# `@suchipi/ts-json-utils`

Utility types for describing JSON values in TypeScript

## Exports

### Types

- `JSONValue` (type for any value which is valid in JSON)
- `JSONObject` (type for object with string/number keys and `JSONValue` values)
- `JSONArray` (type for array of `JSONValue`)
- `JSONPrimitive` (type for all non-composite values which are valid in JSON)

### Functions

- `parse` (re-export of `JSON.parse`, but typed as returning `JSONValue` instead of `any`)
- `stringify` (re-export of `JSON.stringify`, but typed as accepting `JSONValue` instead of `any`)

## Installation

```sh
npm install --save-dev @suchipi/ts-json-utils
```

## License

MIT
npm package: @suchipi/webview
Description: This package wraps https://github.com/suchipi/webview so it can be distributed on npm and run from node.
Latest version: 0.2.1

# `@suchipi/webview`

This package wraps https://github.com/suchipi/webview so it can be distributed on npm and run from node.

## Installation

As a global CLI application:

```
npm i -g @suchipi/webview
```

As a node module:

```
npm i --save @suchipi/webview
```

## Usage (CLI)

```
webview
webview -d ./public --title "My Site"
webview --url http://google.com --width 1024 --height 768
webview --help
```

## Usage (Node)

```js
var webview = require("@suchipi/webview");

// webview is an object with this shape:
// {
//   binaryPath: string, // The absolute path to the binary for your platform
//   optionsToArgv: Function, // Convert an options object to the appropriate argv to pass to the binary
//   spawn: Function, // use child_process.spawn to run the binary
//   spawnSync: Function, // use child_process.spawnSync to run the binary
//   exec: Function, // use child_process.execFile to run the binary
//   execSync: Function, // use child_process.execFileSync to run the binary
// }

// You can either use webview.binaryPath and webview.optionsToArgv to spawn it yourself:
var child = require("child_process").spawn(
  webview.binaryPath,
  optionsToArgv({
    title: "My App",
    width: 1024,
    height: 768,
    dir: "./public",
  }),
  {
    cwd: process.cwd(),
  }
);

// or you can use the provided helper functions to spawn it using child_process.
// Note that the helper function accepts webview options and spawn options in the same object.
var child = webview.spawn({
  // options for webview
  title: "My App",
  width: 1024,
  height: 768,
  dir: "./public",

  // options for child_process.spawn
  cwd: process.cwd(),
});
```
npm package: @suchitadoshi1987/ember-language-server
Description: A language server implementation for Ember.js projects.
Latest version: 1.3.0

# Ember Language Server

[![Greenkeeper badge](https://badges.greenkeeper.io/suchitadoshi1987/ember-language-server.svg)](https://greenkeeper.io/)

The Ember Language Server (ELS) implements the [Language Server Protocol](https://github.com/Microsoft/language-server-protocol) for Ember.js projects. ELS enables editors to provide features like auto complete, goto definition and diagnostics. To get these features, you have to install the plugin for your editor.

## Features

All features currently only work in Ember CLI application that use the default classic structure, and are a rough first draft with a lot of room for improvements. Pods and addons are not supported yet.

- Autocompletion
  - `*.{js/ts}`: services, models, routes, transforms
  - `*.hbs`: components, route names, helpers, modifiers, local paths
  - GlimmerNative components autocompletion support
  - Namespaces support (batman syntax)

- Definition providers for (enable features like "Go To Definition" or "Peek Definition"):
  - Components (in Templates)
  - Helpers (in Templates)
  - Modifiers (in Templates)
  - Models
  - Transforms
  - Component imports (from addons)
  - Namespace components (batman syntax)

- Route autocompletion in `link-to` and `<LinkTo>` components.
- Diagnostics for `ember-template-lint` (if it is included in a project)
- `ember-template-lint` template fixes support (if exists).
- Workspaces support
- Supports Ignoring of LS initialization on unneeded projects by using `ignoredProjects` config option

## Editor Plugins

* VSCode: [Experimental Ember Language Server](https://github.com/suchitadoshi1987/vscode-ember)
npm package: @sucho/react-native-typewriter
Description: React Native text component with animated typewriter effect
Author: Suchandrim Sarkar
Latest version: 1.0.0

# React Native Typewriter

React Native text component with animated typewriter effect.

<p align="center"><img src="https://github.com/suchoX/react-native-typewriter/blob/main/assets/demo.gif"></p>

# Installation

```bash
yarn add react-native-type-writer
```

OR

```bash
npm install --save react-native-type-writer
```

# Usage

Add the `Typewriter` component to your app

```javascript
import React from 'react'
import { StyleSheet, View } from 'react-native'
import TypeWriter from 'react-native-type-writer'

const BACKGROUND = '#263238'
const WHITE = '#ffffff'
const PINK = '#c2185b'

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: BACKGROUND,
    justifyContent: 'center',
  },
  typeWriterText: {
    color: WHITE,
    fontSize: 24,
  },
  typeWriterCursorText: {
    color: PINK,
    fontSize: 24,
  },
})

const App = () => {
  return (
    <View style={styles.container}>
      <TypeWriter
        textArray={['Hello', 'How', 'Are', 'You', 'Doing?']}
        loop
        speed={200}
        delay={500}
        textStyle={styles.typeWriterText}
        cursorStyle={styles.typeWriterCursorText}
      />
    </View>
  )
}
```

# Documentation

The Typewriter has the following props

## text (Mandatory)

type: `Array of Strings`

The Typerwriter component will animate each string one by one. If there's only one string, just pass a single string as a single item of the array

## loop

type: `boolean` default: `false`

After all the strings have been types out, the Text will start looping from the beginning if loop=true. Else, the string will be left visible

## speed

type: `number` default: `300`

The speed of the typing animation. Lower value is higher speed

## delay

type: `number` default: `40`

Delay between two strings in the text array

## textStyle

type: `TextStyle`

Style of the Text being typed

## cursorStyle

type: `TextStyle`

Style of the blinking cursor

## License

Released under the MIT license. See [LICENSE](https://github.com/suchoX/react-native-type-writer/blob/main/LICENSE) for details
npm package: @suchsoftware/practical-microservices-video-publishing-component
Description: Component that owns publishing videos
Author: Ethan Garofolo
Latest version: 1.0.0

# video-publishing-component

The Video Publishing component from the book [Practical Microservices: Build Event-Driven Architectures with Event Sourcing and CQRS](https://pragprog.com/book/egmicro/practical-microservices).

Check out the book!
npm package: @suckless/duration
Description: Parse and format duration strings
Author: brielov
Latest version: 0.6.0

# @suckless/duration

Parse and format duration strings. ~60 lines, zero dependencies, runtime-agnostic.

## Install

```sh
npm install @suckless/duration
```

## Usage

```ts
import { parse, format } from "@suckless/duration"

parse("2h30m") // 9000000
parse("500ms") // 500
parse("1.5h") // 5400000

format(90000) // "1m30s"
format(86400000) // "1d"
format(0) // "0ms"
```

## API

### `parse(input: string): number`

Parses a duration string into milliseconds.

- Accepts compound strings: `"2h30m"`, `"1d12h"`, `"500ms"`, `"90s"`
- Accepts single units: `"5m"`, `"100ms"`
- Supports decimals: `"1.5h"` → 5400000
- Whitespace between segments is allowed: `"2h 30m"`
- Throws `SyntaxError` on invalid input (empty string, unknown units, bare numbers, negative values)
- Returns integer milliseconds (rounds result)

### `format(ms: number): string`

Formats milliseconds into a human-readable duration string.

- Returns the most compact representation using largest units first
- `format(90000)` → `"1m30s"`, `format(86400000)` → `"1d"`
- `format(0)` → `"0ms"`
- Sub-millisecond remainders are dropped
- Throws `RangeError` on negative, NaN, or Infinity input

### `Unit`

```ts
type Unit = "ms" | "s" | "m" | "h" | "d"
```

### Unit table

| Unit | Multiplier |
| ---- | ---------- |
| ms   | 1          |
| s    | 1000       |
| m    | 60000      |
| h    | 3600000    |
| d    | 86400000   |

## License

MIT
npm package: @suckless/emitter
Description: Type-safe event emitter
Author: brielov
Latest version: 0.6.0

# @suckless/emitter

Type-safe event emitter. Zero dependencies, runtime-agnostic.

## Install

```sh
npm install @suckless/emitter
```

## Usage

```ts
import { createEmitter } from "@suckless/emitter"

type Events = {
	message: [string]
	error: [Error]
	connect: []
}

const emitter = createEmitter<Events>()

// Subscribe — returns an unsubscribe function
const off = emitter.on("message", (msg) => console.log(msg))

// Emit
emitter.emit("message", "hello")

// Unsubscribe
off()

// Fire once
emitter.once("connect", () => console.log("connected"))
```

## How it works

Event names and argument types are enforced at compile time through a generic event map. Each event maps to a tuple of arguments, giving you full autocomplete and type checking on both `emit` and listener parameters.

Listeners are stored in insertion-order Sets. Emit iterates a snapshot, so adding or removing listeners during emission is safe.

## API

### `createEmitter<E>(): Emitter<E>`

Creates a new emitter. `E` is a record mapping event names to argument tuples.

### `emitter.on(event, listener): () => void`

Subscribes to an event. Returns an unsubscribe function.

### `emitter.once(event, listener): () => void`

Like `on`, but the listener fires at most once. Returns an unsubscribe function that can cancel before firing.

### `emitter.emit(event, ...args): void`

Fires all listeners for the event with the given arguments.

### Cleanup

The emitter implements `Disposable` for cleanup:

```ts
using emitter = createEmitter<Events>()
```

## License

MIT
npm package: @suckless/jsx
Description: JSX-to-string runtime for server-side HTML rendering with XSS escaping and strict per-element types
Author: brielov
Latest version: 0.6.0

# @suckless/jsx

JSX-to-string runtime for server-side HTML rendering. No virtual DOM, no framework, no hydration — JSX expressions evaluate directly to strings with automatic XSS escaping.

## Install

```sh
bun add @suckless/jsx
```

## Setup

Add the JSX pragma to files that use JSX:

```tsx
/** @jsxImportSource @suckless/jsx */
```

Or configure it globally in `tsconfig.json`:

```json
{
	"compilerOptions": {
		"jsx": "react-jsx",
		"jsxImportSource": "@suckless/jsx"
	}
}
```

## Usage

```tsx
/** @jsxImportSource @suckless/jsx */

const page = (
	<html>
		<head>
			<title>Hello</title>
		</head>
		<body>
			<h1>Hello, world!</h1>
		</body>
	</html>
)
// page is a plain string: "<html><head><title>Hello</title></head>..."
```

### Components

Function components receive props and return strings:

```tsx
/** @jsxImportSource @suckless/jsx */
import type { Component } from "@suckless/jsx"

const Card: Component<{ title: string }> = (props) => (
	<div class="card">
		<h2>{props.title}</h2>
		{props.children}
	</div>
)

const html = (
	<Card title="Welcome">
		<p>Content here</p>
	</Card>
)
```

### Escaping

All string children and attribute values are escaped by default:

```tsx
/** @jsxImportSource @suckless/jsx */
import { raw } from "@suckless/jsx"

// Escaped (safe)
const safe = <div>{"<script>alert('xss')</script>"}</div>
// → <div>&lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;</div>

// Unescaped (trusted content only)
const trusted = <div>{raw("<b>bold</b>")}</div>
// → <div><b>bold</b></div>
```

### Fragments

```tsx
/** @jsxImportSource @suckless/jsx */

const items = (
	<>
		<li>One</li>
		<li>Two</li>
	</>
)
// → "<li>One</li><li>Two</li>"
```

## API

### `escape(value: string): string`

Escapes `&`, `<`, `>`, `"`, and `'` to their HTML entity equivalents.

### `raw(value: string): RawHtml`

Wraps a string to bypass automatic escaping. Use only with trusted content.

### `Fragment(props: { children?: Children }): string`

Renders children without a wrapper element. Used automatically by `<>...</>` syntax.

## Type Safety

Every HTML and SVG element has strict per-element attribute types:

- Void elements (`<br>`, `<img>`, `<input>`, etc.) reject children at the type level
- Element-specific attributes are enforced (`href` on `<a>`, not on `<div>`)
- Standard HTML attributes (`class`, `for`) — not React conventions
- No event handler types — this is a server-side renderer
- `data-*` and `aria-*` attributes are supported on all elements

## License

MIT
npm package: @suckless/key
Description: Deterministic serialization of complex values into stable string keys
Author: brielov
Latest version: 0.6.0

# @suckless/key

Deterministic serialization of complex values into stable string keys. Produces compact, unambiguous strings suitable for cache keys, deduplication, and memoization.

## Install

```sh
npm install @suckless/key
```

## Usage

```typescript
import { stableKey } from "@suckless/key"

stableKey("hello") // 's"hello"'
stableKey(42) // "n42"
stableKey(true) // "T"
stableKey(null) // "N"
stableKey(undefined) // "U"
stableKey(42n) // "b42"
stableKey([1, "a"]) // '[n1,s"a"]'
stableKey({ b: 2, a: 1 }) // '{"a":n1,"b":n2}' (sorted keys)
```

## Determinism

Object keys are sorted, so property insertion order does not affect output:

```typescript
stableKey({ a: 1, b: 2 }) === stableKey({ b: 2, a: 1 }) // true
```

## Edge cases

Special numeric values each produce a distinct key:

```typescript
stableKey(NaN) // "Z"
stableKey(Infinity) // "I"
stableKey(-Infinity) // "J"
stableKey(-0) // "K"
```

## Error handling

Circular references and non-serializable types throw `TypeError`:

```typescript
const obj = {}
obj.self = obj
stableKey(obj) // TypeError: Circular reference detected

stableKey(new Date()) // TypeError: Non-serializable type: Date
stableKey(() => {}) // TypeError: Non-serializable type: function
stableKey(Symbol("x")) // TypeError: Non-serializable type: symbol
```

## License

MIT
npm package: @suckless/limiter
Description: Token bucket rate limiter
Author: brielov
Latest version: 0.6.0

# @suckless/limiter

Token bucket rate limiter. Zero dependencies, runtime-agnostic, pluggable storage.

## Install

```sh
npm install @suckless/limiter
```

## Usage

```ts
import { createLimiter, memoryAdapter } from "@suckless/limiter"

const limiter = createLimiter(100, 60_000, memoryAdapter()) // 100 requests per minute

const { ok, remaining, retryAfter } = await limiter.check("user:123")
if (!ok) {
	// retry after `retryAfter` ms
}
```

## With middleware

```ts
import { createLimiter, memoryAdapter } from "@suckless/limiter"
import { parse } from "@suckless/duration"
import type { Middleware } from "@suckless/middleware"

const limiter = createLimiter(100, parse("1m"), memoryAdapter())

const rateLimit: Middleware<Request, Response> = async (req, next) => {
	const ip = req.headers.get("x-forwarded-for") ?? "unknown"
	const { ok, retryAfter } = await limiter.check(ip)
	if (!ok) {
		return new Response("Too Many Requests", {
			status: 429,
			headers: { "Retry-After": String(Math.ceil(retryAfter / 1000)) },
		})
	}
	return next(req)
}
```

## Custom adapter

By default, state is stored in memory with automatic stale-bucket sweeping. Pass a custom `LimiterAdapter` for external storage (Redis, database, etc.):

```ts
import {
	createLimiter,
	type LimiterAdapter,
	type Bucket,
} from "@suckless/limiter"

const redisAdapter: LimiterAdapter = {
	async get(key) {
		const data = await redis.get(`limiter:${key}`)
		return data ? JSON.parse(data) : undefined
	},
	async set(key, bucket) {
		await redis.set(`limiter:${key}`, JSON.stringify(bucket))
	},
	async delete(key) {
		await redis.del(`limiter:${key}`)
	},
	async [Symbol.asyncDispose]() {
		await redis.quit()
	},
}

const limiter = createLimiter(100, 60_000, redisAdapter)
```

## How it works

Uses a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) algorithm. Each key gets a bucket with `max` tokens. Tokens refill at a constant rate of `max / window` per millisecond. Each `check` consumes one token.

This allows short bursts up to `max` while enforcing the average rate over the window.

## API

### `createLimiter(max, window, adapter): Limiter`

- `max` — maximum tokens (requests) per window
- `window` — time window in milliseconds
- `adapter` — a `LimiterAdapter` storage backend

### `limiter.check(key): Promise<CheckResult>`

Consumes a token and returns:

- `ok` — whether the request is allowed
- `remaining` — tokens left after this check
- `retryAfter` — milliseconds until a token is available (0 if ok)

### `limiter.reset(key): Promise<void>`

Clears the bucket for a key, restoring it to full capacity.

### `memoryAdapter(sweepIntervalMs?): LimiterAdapter`

In-memory adapter with automatic stale-bucket sweeping.

### Cleanup

Stale buckets are swept automatically. The limiter implements `AsyncDisposable` for cleanup:

```ts
await using limiter = createLimiter(100, 60_000, memoryAdapter())
```

## License

MIT
npm package: @suckless/memo
Description: Memoization with explicit key functions and optional LRU eviction
Author: brielov
Latest version: 0.6.0

# @suckless/memo

Memoization with explicit key functions and optional LRU eviction.

## Install

```sh
npm install @suckless/memo
```

## Usage

```typescript
import { memo } from "@suckless/memo"

const expensive = memo(
	(a: number, b: number) => a + b,
	(a, b) => `${a},${b}`,
)

expensive(1, 2) // computes
expensive(1, 2) // cached
```

### With LRU eviction

```typescript
const memoized = memo(fn, key, { max: 100 })
```

When the cache reaches `max` entries, the least recently used entry is evicted. Cache hits update recency.

### With @suckless/key

```typescript
import { memo } from "@suckless/memo"
import { stableKey } from "@suckless/key"

const memoized = memo(fn, (...args) => stableKey(args))
```

## API

### `memo(fn, key, options?)`

- **fn** — the function to memoize
- **key** — maps arguments to a cache key string
- **options.max** — optional; caps cache size with LRU eviction (must be a positive integer)

Returns a function with the same signature as `fn`.

## License

MIT
npm package: @suckless/middleware
Description: Generic composable middleware
Author: brielov
Latest version: 0.6.0

# @suckless/middleware

Generic composable middleware. ~20 lines, zero dependencies, runtime-agnostic.

## Install

```sh
npm install @suckless/middleware
```

## Usage

```ts
import { compose } from "@suckless/middleware"

const enhance = compose<Request, Response>(cors(), logger())

Bun.serve({ fetch: enhance(app) })
```

## Writing middleware

A middleware receives the input and a `next` function. Call `next` to continue the chain, or return early to short-circuit:

```ts
import type { Middleware } from "@suckless/middleware"

const logger: Middleware<Request, Response> = async (req, next) => {
	const start = performance.now()
	const res = await next(req)
	console.log(`${req.method} ${req.url} ${performance.now() - start}ms`)
	return res
}

const cors: Middleware<Request, Response> = async (req, next) => {
	if (req.method === "OPTIONS") {
		return new Response(null, {
			headers: { "Access-Control-Allow-Origin": "*" },
		})
	}
	const res = await next(req)
	res.headers.set("Access-Control-Allow-Origin", "*")
	return res
}
```

## API

### `compose<In, Out>(...middlewares): (handler) => handler`

Composes middleware into a handler wrapper. Middleware executes left to right — the first middleware in the list runs first.

```ts
const enhance = compose(a, b, c)
// Execution order: a → b → c → handler
```

### `Handler<In, Out>`

```ts
type Handler<In, Out> = (input: In) => Out | Promise<Out>
```

### `Middleware<In, Out>`

```ts
type Middleware<In, Out> = (
	input: In,
	next: Handler<In, Out>,
) => Out | Promise<Out>
```

## License

MIT
npm package: @suckless/queue
Description: Producer/consumer queue with pluggable storage
Author: brielov
Latest version: 0.6.0

# @suckless/queue

Producer/consumer queue with pluggable storage. Zero dependencies, runtime-agnostic.

## Install

```sh
npm install @suckless/queue
```

## Usage

```ts
import { createQueue, memoryAdapter } from "@suckless/queue"

const queue = createQueue<string>(
	async (url) => {
		const res = await fetch(url)
		await saveToDb(res)
	},
	memoryAdapter(),
	{ concurrency: 4 },
)

// Push items — fire-and-forget
await queue.push("https://example.com/1")
await queue.push("https://example.com/2")

// Wait for all in-flight work to finish
await queue.drain()
```

## How it works

The queue separates producers (who push items) from consumers (worker loops that process them). On creation, `concurrency` worker loops start pulling items from the adapter and passing them to the handler. This design enables pluggable backends — swap the in-memory adapter for Redis, PostgreSQL, or any message broker.

Handler errors are caught to prevent worker death. The handler is responsible for its own error handling (retry, dead-letter, logging).

## API

### `createQueue<T>(handler, adapter, options?): Queue<T>`

Creates a new queue. Workers start pulling immediately.

- `handler` — called for each item. May be sync or async.
- `adapter` — a `QueueAdapter<T>` storage backend.
- `options.concurrency` — max concurrent handlers. Must be a positive finite integer. Defaults to `1`.
- `options.onError` — called when the handler throws. Receives the error and the item.

### `queue.push(item): Promise<void>`

Enqueues an item. Rejects with `Error` if the queue is closed.

### `queue.drain(): Promise<void>`

Resolves when all pushed items have been processed. Resolves immediately if nothing is pending.

### `queue.running`

Number of handlers currently executing.

### Cleanup

The queue implements `AsyncDisposable`. Disposing marks the queue as closed, stops workers from pulling new items, waits for in-flight handlers, then disposes the adapter:

```ts
await using queue = createQueue<Job>(processJob, memoryAdapter(), {
	concurrency: 4,
})
```

## Adapters

### `memoryAdapter<T>(): QueueAdapter<T>`

In-memory FIFO adapter. Array-backed with a waiter queue for efficient blocking pull. Items are handed directly to waiting consumers when possible (zero-copy).

### Custom adapters

Implement `QueueAdapter<T>` to plug in any backend:

```ts
import { RedisClient } from "bun"
import type { QueueAdapter } from "@suckless/queue"

function redisAdapter<T>(key: string, url?: string): QueueAdapter<T> {
	const redis = new RedisClient(url)
	return {
		async push(item) {
			await redis.send("LPUSH", [key, JSON.stringify(item)])
		},
		async pull(signal) {
			// Poll with a short timeout so the signal can be checked
			while (!signal.aborted) {
				const result = await redis.send("BRPOP", [key, "1"])
				if (result) {
					return JSON.parse(result[1]) as T
				}
			}
			return undefined
		},
		[Symbol.asyncDispose]() {
			redis.close()
			return Promise.resolve()
		},
	}
}
```

## License

MIT
npm package: @suckless/retry
Description: Retry with exponential backoff and jitter
Author: brielov
Latest version: 0.6.0

# @suckless/retry

Retry with exponential backoff and jitter. ~80 lines, zero dependencies, runtime-agnostic.

## Install

```sh
npm install @suckless/retry
```

## Usage

```ts
import { retry } from "@suckless/retry"

const data = await retry(async (attempt, signal) => {
	const res = await fetch("https://api.example.com/data", { signal })
	if (!res.ok) throw new Error(`HTTP ${res.status}`)
	return res.json()
})
```

By default, `retry` makes up to 3 attempts with exponential backoff and full jitter.

## Options

```ts
await retry(fn, {
	maxAttempts: 5, // default: 3
	baseDelay: 500, // default: 1000 (ms)
	maxDelay: 10_000, // default: 30000 (ms)
	signal: controller.signal,
	shouldRetry: (error) => error instanceof TransientError,
})
```

### `maxAttempts`

Total number of attempts including the first. Setting this to `1` disables retrying.

### `baseDelay` / `maxDelay`

Controls the backoff timing. The delay before attempt `n` is:

```
random() * min(maxDelay, baseDelay * 2^n)
```

This is full jitter over exponential backoff — the canonical strategy for preventing thundering herd. For a constant delay, set `baseDelay` and `maxDelay` to the same value.

### `signal`

Standard `AbortSignal` for cancellation. Works with `AbortController` and `AbortSignal.timeout()`:

```ts
// Cancel after 10 seconds total
await retry(fn, { signal: AbortSignal.timeout(10_000) })

// Manual cancellation
const controller = new AbortController()
retry(fn, { signal: controller.signal })
controller.abort()
```

The signal is forwarded to `fn` so you can pass it to `fetch` or any other API that accepts it.

### `shouldRetry`

A predicate that receives the thrown error. Return `false` to stop retrying immediately. Useful for non-retryable errors like 4xx HTTP responses or validation failures:

```ts
await retry(
	async () => {
		const res = await fetch("https://api.example.com/data")
		if (!res.ok) throw new HttpError(res.status)
		return res.json()
	},
	{
		shouldRetry: (error) => error instanceof HttpError && error.status >= 500,
	},
)
```

## Error handling

On exhaustion, `retry` throws the error from the last failed attempt. If the original throw value is not an `Error`, it is wrapped via `new Error(String(value), { cause: value })`, preserving the original value as `cause`.

## API

### `retry<T>(fn, options?): Promise<T>`

- `fn(attempt, signal)` — the async function to retry. `attempt` is zero-indexed.
- Returns the result of the first successful call to `fn`.
- Throws the last error if all attempts fail, `shouldRetry` returns false, or the signal is aborted.

## License

MIT
npm package: @suckless/router
Description: Fast URL pattern router
Author: brielov
Latest version: 0.6.0

# @suckless/router

Fast URL pattern router. ~100 lines, zero dependencies, runtime-agnostic.

## Install

```sh
npm install @suckless/router
```

## Usage

```ts
import { createRouter } from "@suckless/router"

const router = createRouter<string>()
	.add("/health", "health")
	.add("/users/:id", "getUser")
	.add("/users/:id/posts/:postId", "getPost")
	.add("/files/*path", "getFile")

router.find("/users/42")
// { value: "getUser", params: { id: "42" } }

router.find("/users/42/posts/7")
// { value: "getPost", params: { id: "42", postId: "7" } }

router.find("/files/a/b/c")
// { value: "getFile", params: { path: "a/b/c" } }

router.find("/missing")
// undefined
```

## With Bun

```ts
import { createRouter } from "@suckless/router"

type Handler = (req: Request, params: Record<string, string>) => Response

const router = createRouter<Handler>()
	.add("/users/:id", (req, params) => {
		return new Response(`User ${params.id}`)
	})
	.add("/health", () => new Response("ok"))

Bun.serve({
	fetch(req) {
		const url = new URL(req.url)
		const match = router.find(url.pathname)
		if (match) return match.value(req, match.params)
		return new Response("Not Found", { status: 404 })
	},
})
```

## Patterns

- **Static**: `/health`, `/api/users` — exact match
- **Params**: `/users/:id` — captures a single path segment
- **Wildcard**: `/files/*path` — captures the rest of the path

Priority: static > param > wildcard. If a param branch fails to match deeper segments, the router backtracks to try wildcard.

## Performance

- **Static routes** are stored in a flat `Map` — O(1) lookup
- **Dynamic routes** use a segment trie with `Map` children — O(depth) with O(1) per level
- Path scanning uses `indexOf` instead of `split` — zero array allocation on the hot path
- Backtracking only occurs when param and wildcard compete at the same level

## API

### `createRouter<T>(): Router<T>`

Creates a new router that maps patterns to values of type `T`.

### `router.add(pattern, value): Router<T>`

Registers a route. Returns the router for chaining.

### `router.find(path): Match<T> | undefined`

Matches a path against registered routes. Returns `{ value, params }` or `undefined`.

## License

MIT
npm package: @suckless/sse
Description: Server-Sent Events channel for Web API servers
Author: brielov
Latest version: 0.6.0

# @suckless/sse

Server-Sent Events channel for Web API servers. Zero dependencies, runtime-agnostic.

## Install

```sh
npm install @suckless/sse
```

## Usage

```ts
import { createSSEChannel } from "@suckless/sse"

const channel = createSSEChannel({ heartbeat: 15_000, replay: 50 })

// In your request handler
function handler(req: Request): Response {
	return channel.connect(req)
}

// Broadcast from anywhere
channel.send("message", { text: "hello" })
channel.send("update", { count: 42 })

// Cleanup
channel.close()
```

## How it works

Each call to `connect()` creates a `ReadableStream` wired to the client via the standard `Response` constructor. Events are broadcast to all connected clients as SSE-formatted text chunks. Clients that disconnect (via `AbortSignal` or stream cancellation) are cleaned up automatically.

Optional keepalive comments (`: keepalive`) prevent proxies and load balancers from closing idle connections. An optional replay buffer stores recent events so reconnecting clients can catch up via the `Last-Event-ID` header.

To avoid unbounded memory growth, clients that stop draining their stream are disconnected once their pending buffer exceeds the internal safety limit.

## API

### `createSSEChannel(options?): SSEChannel`

Creates a new SSE channel.

| Option      | Type     | Default | Description                                               |
| ----------- | -------- | ------- | --------------------------------------------------------- |
| `heartbeat` | `number` | `15000` | Keepalive interval in ms. Set to `0` to disable.          |
| `replay`    | `number` | `0`     | Number of recent events to buffer. Set to `0` to disable. |

### `channel.connect(req): Response`

Accepts a `Request` and returns an SSE `Response`. Honors `Last-Event-ID` for replay. Returns a `503` if the channel is closed.

### `channel.send(event, data): void`

Broadcasts an event to all connected clients. `event` must not contain CR/LF characters, and `data` must serialize with `JSON.stringify()`. Throws if validation fails or the channel is closed.

### `channel.close(): void`

Closes the channel, disconnects all clients, and clears the replay buffer. Idempotent.

### `channel.clients: number`

Number of currently connected clients.

### Cleanup

The channel implements the standard disposal protocol:

```ts
using channel = createSSEChannel()
```

`using` requires toolchain support for Explicit Resource Management (TypeScript 5.2+).

You can also call `channel[Symbol.dispose]()` directly.

## License

MIT
npm package: @sucodev/rn-mma-core
Description: This repository is part of "[Building a scalable APP with multi-module architecture](https://github.com/G33N/rn-mma-app)"
Author: Hai Quy
Latest version: 0.21.0

# rn-mma-core

This repository is part of "[Building a scalable APP with multi-module architecture](https://github.com/G33N/rn-mma-app)"

## What we place in this repo?

* Provide an infraestructure to modules
* Native dependencies
* Binaries to Android and iOS
* Load and run modules by a config file
* Push notifications, Error Handling, Network...

## Tree

```
├── ios                                 iOS Native Code
├── android                             Android Native Code
├── app_builds                          iOS and Android output builds
└── src
     └── package.json                   Native dependencies
```
npm package: @sucrase/gulp-plugin
Description: Gulp plugin for Sucrase
Author: Alan Pierce
Latest version: 2.0.0

# Sucrase Gulp plugin

[![npm version](https://badge.fury.io/js/@sucrase%2Fgulp-plugin.svg)](https://www.npmjs.com/package/@sucrase/gulp-plugin)
[![MIT License](https://img.shields.io/npm/l/express.svg?maxAge=2592000)](LICENSE)

This is a simple Gulp plugin that makes it easy to tie
[Sucrase](https://github.com/alangpierce/sucrase) into your build.

## Usage

Sucrase is a peer dependency, so you'll need to install it as well: 
```
yarn add --dev @sucrase/gulp-plugin sucrase
```

In your gulpfile, you can add it like this:

```
const sucrase = require('@sucrase/gulp-plugin');

...
  .pipe(sucrase({transforms: ['imports', 'jsx']}))
...
```
npm package: @sucrase/jest-plugin
Description: Jest plugin for Sucrase
Author: Alan Pierce
Latest version: 3.0.0

# Sucrase Jest plugin

[![npm version](https://badge.fury.io/js/@sucrase%2Fjest-plugin.svg)](https://www.npmjs.com/package/@sucrase/jest-plugin)
[![MIT License](https://img.shields.io/npm/l/express.svg?maxAge=2592000)](LICENSE)

This is a simple Jest plugin that makes it easy to use
[Sucrase](https://github.com/alangpierce/sucrase) when running Jest tests.

## Usage

First install the package and `sucrase` as a dev dependency:
```
yarn add --dev @sucrase/jest-plugin sucrase
```

Then change the default transform in jest.config.js file:
```ts
  ...
  transform: { "\\.(js|jsx|ts|tsx)$": "@sucrase/jest-plugin" },
  ...
```

You can specify additional transformation options to Sucrase by passing an object. For example, to enable automatic react transforms:

```ts
  ...
  transform: { "\\.(js|jsx|ts|tsx)$": ["@sucrase/jest-plugin", { jsxRuntime: 'automatic' }] },
  ...
```

By default, the `transforms` option is automatically detected based on file type and Jest mode.
If you pass a `transforms` array in the options, it will apply to all files, regardless of extension.
npm package: @sucrase/webpack-loader
Description: Webpack loader for Sucrase
Author: Alan Pierce
Latest version: 2.0.0

# Sucrase Webpack loader

[![npm version](https://badge.fury.io/js/@sucrase%2Fwebpack-loader.svg)](https://www.npmjs.com/package/@sucrase/webpack-loader)
[![MIT License](https://img.shields.io/npm/l/express.svg?maxAge=2592000)](LICENSE)

This is a simple Webpack loader that makes it easy to use
[Sucrase](https://github.com/alangpierce/sucrase) in your build.

**Note: Object rest/spread syntax (e.g. `{...a, b: c}`) requires Webpack 4. For
earlier Webpack versions, you can use
[webpack-object-rest-spread-plugin](https://github.com/alangpierce/sucrase/tree/master/integrations/webpack-object-rest-spread-plugin)
alongside this loader.**

## Usage

First install the package and Sucrase as a dev dependency:
```
yarn add --dev @sucrase/webpack-loader sucrase
```

Then add it as a loader to your webpack config:
```
module: {
  rules: [
    {
      test: /\.js$/,
      use: {
        loader: '@sucrase/webpack-loader',
        options: {
          transforms: ['jsx']
        }
      }
    }
  ]
}
```
npm package: @sucrase/webpack-object-rest-spread-plugin
Description: Webpack plugin to enable object rest/spread syntax
Author: Alan Pierce
Latest version: 1.0.1

# Webpack object rest/spread plugin

[![npm version](https://badge.fury.io/js/@sucrase%2Fwebpack-object-rest-spread-plugin.svg)](https://www.npmjs.com/package/@sucrase/webpack-object-rest-spread-plugin)
[![MIT License](https://img.shields.io/npm/l/express.svg?maxAge=2592000)](LICENSE)

This is a Webpack plugin that hacks the Webpack parser to allow object
rest/spread syntax (e.g. `{...a, b: c}`) in Webpack 3 and earlier.

**Note: This plugin is only necessary when using Webpack 3 or earlier. Webpack 4
natively supports object rest/spread. See https://github.com/webpack/webpack/issues/5548
for troubleshooting tips.**

## Usage

First install the package as a dev dependency:
```
yarn add --dev @sucrase/webpack-object-rest-spread-plugin
```

Then add it as a plugin to your webpack config:
```
const ObjectRestSpreadPlugin = require('@sucrase/webpack-object-rest-spread-plugin');

...

  plugins: [
    new ObjectRestSpreadPlugin(),
  ],
}
```