open-index/open-npm huggingface dataset:
npm package: @hazae41/future
Description: Just like a Promise but you can manually resolve or reject it
Author: hazae41
Latest version: 2.0.1

<div align="center">
<img src="https://user-images.githubusercontent.com/4405263/222497326-825b2ebb-910b-41ca-8759-785c4876faf0.png" />
</div>

Just like a Promise but you can manually resolve or reject it

```bash
npm i @hazae41/future
```

[**Node Package 📦**](https://www.npmjs.com/package/@hazae41/future)

## Features

### Current features
- 100% TypeScript and ESM
- No external dependencies
- Unit-tested

## Usage

```typescript
import { Future } from "@hazae41/future"

const future = new Future<void>()

const t1 = setTimeout(() => future.resolve(), 1000)
const t2 = setTimeout(() => future.reject(), 2000)

try {
  await future.promise
} finally {
  clearTimeout(t1)
  clearTimeout(t2)
}
```
npm package: @hazae41/gardien
Description: Type-safe runtime schema validation and parsing
Author: hazae41
Latest version: 0.4.3

# Gardien

Type-safe runtime schema validation and parsing

```bash
npm i @hazae41/gardien
```

[**Node Package 📦**](https://www.npmjs.com/package/@hazae41/gardien)

## Features

### Current features
- 100% TypeScript and ESM
- No external dependencies
- Rust-like patterns
- Fully type-safe
- Unit-tested
- Zod-like syntax

## Usage

### Parsing a number

We can parse something as a number and then validate it

```typescript
import { Guard, z } from "@hazae41/gardien"

const value = Guard.asOrThrow(z.numberable().nonNegative(), "0x123")
```

This is like

```typescript
const value = Number("0x123")

if (value < 0)
  throw new Error()

return value
```

### Validating a string with an error message

```typescript
import { Guard, z } from "@hazae41/gardien"

Guard.asOrThrow(z.string().minmax(6, 24, "Password must be between 6 and 24 characters"), password)
```

This is like

```typescript
if (typeof password !== "string")
  throw new Error()
if (password.length < 6)
  throw new Error("Password must be between 6 and 24 characters")
if (password.length > 24)
  throw new Error("Password must be between 6 and 24 characters")
```

### Validating a complex record

We can define complex guards that include other guards

```typescript
import { Guard, z } from "@hazae41/gardien"

const RpcRequestGuard = z.record({
  jsonrpc: z.strong("2.0"),
  id: z.union([z.strong(null), z.number(), z.string()]),
  method: z.string(),
  params: z.optional(z.unknown())
} as const)

function onMessage(message: string) {
  const request = Guard.asOrThrow(RpcRequestGuard, JSON.parse(message) as unknown)

  if (request.method === "example")
    return void example(request)
  
  throw new Error("Unknown method")
}
```

### Validating a complex generic record

We can define high-order guards that dynamically include other guards

```typescript
import { Guard, z } from "@hazae41/gardien"

const RpcRequestGuard = <M extends Guard<string, string>, P extends Guard>(method: M, params: P) => z.record({
  jsonrpc: z.strong("2.0"),
  id: z.union([z.strong(null), z.number(), z.string()]),
  method: method,
  params: params
} as const)

const ExampleParamsGuard = z.record({
  example: z.string()
} as const)

const request = Guard.asOrThrow(RpcRequestGuard(z.strong("example"), ExampleParamsGuard), JSON.parse(message) as unknown)
```

### Validating with your own logic

```typescript
class IPv4Guard {

  static asOrThrow(value: string): string {
    if (!/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(value))
      throw new Error()
    return value
  }

}

Guard.asOrThrow(z.string().pipe(IPv4Guard, "This is not an IPv4 address"), input)
```

### Parsing with your own logic

```typescript
class ZeroHexlifyGuard {

  static asOrThrow(value: any): `0x${string}` {
    return `0x${BigInt(value).toString(16)}`
  }

}

const hex = Guard.asOrThrow(ZeroHexlifyGuard, "12345")
```
npm package: @hazae41/glacier
Description: Yet another React data (re)fetching library
Author: hazae41
Latest version: 2.2.6

<div align="center">
<img src="https://user-images.githubusercontent.com/4405263/269623949-10c3fb8c-c492-4284-b39a-e51132fb27c4.png" />
</div>

```bash
npm i @hazae41/glacier
```

[**Node Package 📦**](https://www.npmjs.com/package/@hazae41/glacier) • [**Read the docs 📚**](https://github.com/hazae41/glacier/blob/master/docs) • [**Next.js Example 🪣**](https://codesandbox.io/p/github/hazae41/glacier-example-next) • [**Expo Example 🪣**](https://snack.expo.dev/@git/github.com/hazae41/xswr-example-expo) • [**Comparison with other libs 🌐**](https://github.com/hazae41/glacier/blob/master/docs/comparison.md)

## Philosophy 🧠

Glacier uses two new approaches compared to other data fetching libraries like swr or react-query:
1) Encapsulating key+fetcher+params in a single abstraction called schema.
2) Composing features with very simple hooks instead of having bloated configuration and unexpected behaviors.

```tsx
function useAutoFetchMixture(query: Query) {
  useFetch(query) // Fetch on mount and url change
  useVisible(query) // Fetch when the page is focused
  useOnline(query) // Fetch when the browser is online
}

function useHelloWithAutoFetch() {
  const query = useQuery(createHelloQuery, [])
  useAutoFetchMixture(query)
  return query
}

function MyApp() {
  const { data, error } = useHelloWithAutoFetch()

  if (error != null)
    return <MyError error={error} />
  if (data == null)
    return <MyLoading />
  return <MyPage data={data} />
}
```

## Features 🔥

- 100% TypeScript and ESM
- No external dependency
- Composition-based hooks
- Rust-like patterns
- Transport agnostic (REST, GraphQL, WebSocket)
- Storage agnostic (IndexedDB, localStorage)
- Works in a Service Worker or in a serverless function
- Per-query, encrypted, garbage-collected, persistent storage
- Store normalization and indexes
- Concurrent and multi-step optimistic states
- Request deduplication, cooldown, timeout, cancellation, expiration, and retrying
- Automatic refetching based on various signals
- Page-based and cursor-based pagination
- SSR & ISR support
- React Suspense support
- React Native support
npm package: @hazae41/hex
Description: Hexadecimal string types
Author: hazae41
Latest version: 1.0.3

# Hex

Hexadecimal string types

```bash
npm i @hazae41/hex
```

[**Node Package 📦**](https://www.npmjs.com/package/@hazae41/hex)

## Features

### Current features
- 100% TypeScript and ESM
- No external dependencies

## Usage

```tsx
function recover(signature: ZeroHexString<32>) {
  // just use signature like a normal string
}

const raw = prompt("Enter your signature as zero-hex")
const hex = ZeroHexString.String.Length.fromOrThrow(raw, 32)

recover(hex)
```
npm package: @hazae41/hexane
Description: Hexadecimal string types
Author: hazae41
Latest version: 1.0.11

# Hex

Hexadecimal string types

```bash
npm i @hazae41/hexane
```

[**Node Package 📦**](https://www.npmjs.com/package/@hazae41/hexane)

## Features

### Current features
- 100% TypeScript and ESM
- No external dependencies

## Usage

```tsx
function recover(signature: ZeroHexString<32>) {
  // just use signature like a normal string
}

const raw = prompt("Enter your signature as zero-hex")
const hex = ZeroHexString.String.Length.asOrThrow(raw, 32)

recover(hex)
```
npm package: @hazae41/immutable
Description: Create immutable webapps
Author: hazae41
Latest version: 2.1.3

# The Immutable Toolbox

Create immutable webapps that are secure and resilient

```bash
npm install @hazae41/immutable
```

[**📦 NPM**](https://www.npmjs.com/package/@hazae41/immutable)

## Philosophy

The philosophy is to build webapps that are as immutable as native apps but benefit from the wide distribution of the web. Such webapps are built with strong client-side and offline capabilities. Once downloaded they should be immutably cached and only be updated when the user requests it or has opted-in automatic updates.

### Why?

Security and resilience. An immutable webapp is not prone to server-side attacks (e.g. DNS attack, BGP attack, TLS attack). An immutable webapp is always available to its users even if the server is compromised or censored. An immutable webapp can be distributed by other means than a centralized server (e.g. IPFS).

### How?

New and smart engineering techniques. The extensive use of service-workers and new web APIs allow you to build such webapps. By using `Cache-Control`, `Fetch API` and `Crypto API` to distribute and cache webapps immutably. This toolbox improves and merges already existing tools such as `Workbox` to fit exactly our needs.

## Technology

The most important thing about The Immutable Toolbox is that service-workers are immutably cached.

This is done by using `Cache-Control` headers and `{ updateViaCache: "all" }` options.

The service-worker is cached for one year, so it won't be auto-updated before one year has passed.

In order to update it before one year, we need to `register()` a new service-worker at a different URL.

The webapp runtime fetches `service_worker.js` and check its integrity hash in order to detect updates.

If an update is detected, it can `register()` the new `service_worker.js?version=<version>` file.

Thus the developer or user is in control of when to update the webapp (e.g. a yes/no/always button).

-

The other great thing is that all other files are also immutably cached by the service-worker.

This is done just like `workbox` but with even more checks as the hashes are also verified.

All files are hashed and verified using native SHA-256 which is both strong and fast.

This makes your webapp immutable, as long as the service worker is not updated.

-

It is compatible with [HTTPSec](https://github.com/hazae41/httpsec), which means the HTML page can have its integrity enforced.

Unfortunately, HTTPSec can't enforce the service worker, but it can enforce pages, and pages can enforce in-page scripts and assets.

So you shouldn't use the service worker for anything important except caching your webapp or doing normal service worker stuff.

-

The webapp is only compromisable when you first download it, when you manually update it, or when it's auto-updated after one year.

## Examples

Here is a list of immutable webapps

- [Starter](https://github.com/hazae41/starter)
- [Brume Website](https://github.com/brumeproject/www)
npm package: @hazae41/jsonrpc
Description: Rust-like JSON-RPC for TypeScript
Author: hazae41
Latest version: 1.1.11

# JSON-RPC

Rust-like JSON-RPC for TypeScript

```bash
npm install @hazae41/jsonrpc
```

```bash
deno install jsr:@hazae41/jsonrpc
```

[**📦 NPM**](https://www.npmjs.com/package/@hazae41/jsonrpc) • [**📦 JSR**](https://jsr.io/@hazae41/jsonrpc)

## Features

### Current features
- 100% TypeScript and ESM
- No external dependencies
- Rust-like patterns
- Uses `@hazae41/result`
- [Specification](https://www.jsonrpc.org/specification) compliant

## Usage

### Request using fetch

```tsx
import { RpcCounter, RpcResponse } from "@hazae41/jsonrpc"

/**
 * Assign an incremental id to a request
 */
const counter = new RpcCounter()
const request = counter.prepare({ method: "hello_world", params: ["hello"] })

/**
 * JSON-stringify and send the request using your preferred transport
 */
const body = JSON.stringify(request)
const headers = { "Content-Type": "application/json" }
const res = await fetch("https://example.com", { method: "POST", body, headers })

/**
 * JSON-parse the response and unwrap it
 */
const response = RpcResponse.from<string>(await res.json()) // RpcOk<string> | RpcErr
const data = response.unwrap() // string
console.log(data) // "world"
```

### Handle requests

```tsx
import { RpcRequestInit, RpcRequestPreinit, RpcResponse, RpcMethodNotFoundError, RpcInvalidParamsError } from "@hazae41/jsonrpc"

/**
 * Handle JSON requests and return a JSON response
 */
function onMessage(message: string): string {
  const request = JSON.parse(message) as RpcRequestInit<unknown>
  const response = RpcResponse.rewrap(request.id, onRequest(request))
  return JSON.stringify(response)
}

/**
 * Route requests and return a result
 */
function onRequest(request: RpcRequestPreinit<unknown>): Result<unknown, Error> {
  if (request.method === "hello_world")
    return onHelloWorld(request)
  return new Err(new RpcMethodNotFoundError())
}

/**
 * Handle "hello_world" requests
 */
function onHelloWorld(request: RpcRequestPreinit<unknown>): Result<string, RpcInvalidParamsError> {
  const [hello] = (request as RpcRequestPreinit<[string]>).params

  if (hello === "hello")
    return new Ok("world")
  return new Err(new RpcInvalidParamsError())
}
```
npm package: @hazae41/kcp
Description: Zero-copy KCP protocol for the web
Author: hazae41
Latest version: 1.1.6

# KCP

Zero-copy KCP protocol for the web

```bash
npm i @hazae41/kcp
```

[**Node Package 📦**](https://www.npmjs.com/package/@hazae41/kcp)

## Features

### Current features
- 100% TypeScript and ESM
- Zero-copy reading and writing
- Works in the browser

## Usage

```typescript
import { KcpDuplex } from "@hazae41/kcp"
import { Opaque, Writable } from "@hazae41/binary"
import { SuperTransformStream } from "@hazae41/cascade"
import { None } from "@hazae41/kcp"

const conversation = 12345

function pipeToKcp(raw: { outer: ReadableWritablePair<Opaque, Writable> }): { outer: ReadableWritablePair<Opaque, Writable> } {
  const kcp = new KcpDuplex({ conversation })

  raw.outer.readable
    .pipeTo(kcp.inner.writable)
    .catch(() => { })

  kcp.inner.readable
    .pipeTo(raw.outer.writable)
    .catch(() => { })

  return kcp
}

function pipeToDummy(kcp: { outer: ReadableWritablePair<Opaque, Writable> }) {
  const dummy = new Dummy()

  kcp.outer.readable
    .pipeTo(dummy.inner.writable)
    .catch(() => { })

  dummy.inner.readable
    .pipeTo(kcp.outer.writable)
    .catch(() => { })

  return dummy
}

class Dummy extends HalfDuplex<Opaque, Writable> {

  constructor() {
    super()
  }

  send(data: Writable) {
    this.output.enqueue(data)
  }

}

const forward = new TransformStream<Writable, Opaque>({ transform: (chunk, controller) => controller.enqueue(Opaque.writeFromOrThrow(chunk)) })
const backward = new TransformStream<Writable, Opaque>({ transform: (chunk, controller) => controller.enqueue(Opaque.writeFromOrThrow(chunk)) })

const rawA = { outer: { readable: forward.readable, writable: backward.writable } }
const rawB = { outer: { readable: backward.readable, writable: forward.writable } }

const kcpA = pipeToKcp(rawA)
const kcpB = pipeToKcp(rawB)

const dummyA = pipeToDummy(kcpA)
const dummyB = pipeToDummy(kcpB)

dummyB.input.events.on("message", (data) => {
  console.log("b", data.bytes)
  return new None()
})

dummyA.input.events.on("message", (data) => {
  console.log("a", data.bytes)
  return new None()
})

dummyA.send(new Opaque(new Uint8Array([1, 2, 3])))
dummyB.send(new Opaque(new Uint8Array([4, 5, 6])))

```