open-index/open-npm huggingface dataset:
npm package: @self_id/self-platform-sdk
Description: SELF Platform SDK
Author: vaibhav verma
Latest version: 0.1.3

# SELF Platform SDK

`self` package is useful in developing main functionalities needed to implement flows for secure identity & data sharing. The package is mainly for those who are looking into implementing their custom user flow using SELF echosystem.


# Installation

You can add self package by running following command on root of your nodejs project.

```
npm i @self_id/self-platform-sdk --save
```

# Setup

In order to use this package you will need to register yourself using our onboarding system. You can check more detailed documentation [here](https://gitlab.com/selfid-public/docs/-/blob/main/onboarding.md).


## Backend setup

This package is mainly for backend usage. You will need to setup various environment variables in order to use this package without any issues. For detailed documentation on environment variables setup check [link](https://gitlab.com/selfid-public/docs/-/blob/main/environment.md). You can also visit [link](https://gitlab.com/selfid-public/docs/-/blob/main/self-backend.md) for backend documentations.


## Frontend setup

In order to use `SIGN IN WITH YOUR SELF` button you should check [frontend documentation](https://gitlab.com/selfid-public/docs/-/blob/main/self-frontend.md).


# License

SELF sdk is available under the [MIT](./LICENSE) license.
npm package: @selfage/blocking_loop
Description: Continuously looping in time.
Author: Yuxuan Xie
Latest version: 1.2.0

# @selfage/loop

## Install

`npm install @selfage/loop`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig ](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides a util class to start and stop recurring loops, which only starts scheduling the next loop until the provided async function has finished. It makes sure to handle loops cancellation. Simply cancelling timeout or animation frame doesn't work in this case, because the loop function might be in the middle of execution, waiting for the async function.

## Usage

```TypeScript
import { BlockingLoop } from "@selfage/blocking_loop";

let loop = BlockingLoop.createWithTimeout() // Can be used in either browser or Nodejs environment.
  .setAction(async () => {
    // your async function
  })
  .setInterval(500);
// or BlockingLoop.createWithAinmationFrame()

// The first action will be run after the interval.
loop.start();

// You can wait for the last running loop to be finished, and it won't schedule a new loop.
await loop.stop();
```
npm package: @selfage/closest_locale_finder
Description: Find the closest matching locale.
Author: Yuxuan Xie
Latest version: 1.0.2

# @selfage/closest_locale_finder

## Install

`npm install @selfage/closest_locale_finder`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides helper functions to find the closest locale out of a list of locales you want to support.

Lookup algorithm is based on [lookup-closest-locale](https://github.com/format-message/format-message/blob/v6.2.3/packages/lookup-closest-locale/index.js).

E.g., given a list of supported locales, `['en', 'en-US']`, if you look for `en-GB`, the closest matching locale is `en`.

## Find from a map of localized texts

```TypeScript
type Delimiter = "-" | "_";
function findClosestLocalizedText<T>(targetLocales: Array<string> /* From most preferred to least preferred. */, localizedTexts: Map<string, T>, defaultText: T, delimiter: Delimiter = '-'): T;
```

```TypeScript
import { findClosestLocalizedText } from '@selfage/closest_locale_finder';

let text = findClosestLocalizedText(
  [navigator.language],
  new Map([
    ['en-US', {'welcome': 'Hello'}],
    ['zh-CN', {'welcome': '欢迎'}]
  ]),
  {'welcome': 'Hello'});
console.log(text.welcome);
```

## Find from a set of available locales

```TypeScript
type Delimiter = "-" | "_";
function findClosestLocale(targetLocales: Array<string> /* From most preferred to least preferred. */, availableLocales: Set<string>, defaultLocale: string, delimiter: Delimiter  = '-'): string;
```

```TypeScript
import { findClosestLocale } from '@selfage/closest_locale_finder';

let locale = findClosestLocale(
  [navigator.language],
  new Set(['en-US', 'zh-CN']),
  'en-US');
console.log(locale);
```

## Customize finding

```TypeScript
type Delimiter = "-" | "_";
function forEachLocaleCandidate<T>(targetLocales: Array<string> /* From most preferred to least preferred. */, tryMatch: (localeCandidate: string) => {
    matched: boolean;
    res: T;
}, defaultValue: T, delimiter: Delimiter = '-'): T;
```

`forEachLocaleCandidate` is used internally by both `findClosestLocalizedText` and `findClosestLocale`, which match `localeCandidate` from the map and set respectively.
npm package: @selfage/env_var_getter
Description: Get optional/required variable from process.env.
Author: Yuxuan Xie
Latest version: 1.0.2

# @selfage/env_var_getter

## Install

`npm install @selfage/env_var_getter`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig ](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides a type-safe way to get environment variables from `process.env`. And another important feautre is that you can only get a variable once, to make sure there is no conflicted/duplicated definition of a variable. Therefore, one should get a variable as early as possible and save it in a global variable for future use.
npm package: @selfage/gcs_client
Description: Google Cloud Storage client library.
Author: Yuxuan Xie
Latest version: 1.0.7

# @selfage/gcs_client

## Install

`npm install @selfage/gcs_client`

## Overview

Written in TypeScript and compiled with [@selfage/tsconfig](https://www.npmjs.com/package/@selfage/tsconfig). Provides a client library for a subset APIs of Google Cloud Storage (GCS).

## Features

1. Single chunk upload.
1. Resumable upload, with resumable URL and byteOffset being tracked.

## Test setup

The test is talking to a real GCP project and it's a local unit test.

Prepare for authentication: `gcloud auth application-default login`, or an environment already logged in, such as a Compute Engine.

Make sure the account has suffcient permissions to view/edit/delete objects.

Create a bucket to be used in the test, by setting the environment variable `gcs_bucket=`.
npm package: @selfage/lazy_instance
Description: Lazily constructed instance.
Author: Yuxuan Xie
Latest version: 1.0.1

# @seflage/lazy_instance

## Install

`npm install @selfage/lazy_instance`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides a simply class to only call the provided constructoion function once, when getting the instance.

## Usage

```TypeScript
import { LazyInstance } from '@selfage/lazy_instance';

class Foo {}

let lazyFoo = new LazyInstance(() => new Foo());
let foo = lazyFoo.get(); // Instantiates Foo
let foo2 = lazyFoo.get(); // Returns the same Foo
console.log(foo === foo2);
```
npm package: @selfage/node_service_client
Description: Http client to make remote call to services from Nodejs applications.
Author: Yuxuan Xie
Latest version: 2.2.4

# @selfage/node_service_client

Send HTTP request from Node.js with strongly typed interfaces without touching raw response parsing.

## Why @selfage/node_service_client?
`@selfage/node_service_client` is the Node.js companion to `@selfage/generator_cli`. The generator emits strongly typed TypeScript descriptors for your remote calls, and this package lets you invoke them without touching raw response parsing.

Simply send the generated request factories through `client.send()` and receive typed responses. Avoid hand-written DTOs and unchecked `fetch` calls by relying on descriptors for serialization.

The [`@selfage/generator_cli` README](https://www.npmjs.com/package/@selfage/generator_cli) shows how a single YAML definition yields service descriptors, handler interfaces, and message types. Once you have that output, this package handles everything else.

## How to use it

### 1. Model your API once
Describe your enums, messages, services, and remote calls in YAML and generate the TypeScript descriptors:

```bash
npm install --save-dev @selfage/generator_cli
npx geneage ./definition.yaml
```

The emitted files expose `RemoteCallDescriptor` objects and helper factories (see `test_data/` for examples).

### 2. Install the runtime client

```bash
npm install @selfage/node_service_client
```

### 3. Instantiate a client with session persistence
Provide a `SessionStorage` implementation (use `LocalSessionStorage` for browser `localStorage`, or roll your own):

```ts
import { NodeServiceClient } from "@selfage/node_service_client";
import { LocalSessionStorage } from "@selfage/node_service_client/local_session_storage";

const client = NodeServiceClient.create(
  "https://api.example.com",
);

client.on("httpError", (error) => {
  console.error("Request failed", error.statusCode, error.message);
});
```

### 4. Send strongly typed requests
Use the generated factory functions to keep request and response payloads type-safe end-to-end:

```ts
import { newGetCommentsRequest } from "./generated/get_comments";

const response = await client.send(
  newGetCommentsRequest({ page: 1 }),
  { retries: 3, timeout: 5_000, keepAlive: true },
);

console.log(response.comments); // Typed as string[]
```

Binary bodies and metadata are also covered. For instance, the generated `newUploadFileRequest` combines a `Readable` body with structured metadata, and the client serializes everything according to the descriptor.

## Advanced options
- `retries`, and `timeout` are available per call through `NodeClientOptions` for fine-grained transport tuning.
- Subscribe to the `"error"` event to centralize logging of any failure (HTTP or network).
- Pair with `@selfage/message` helpers for assertions and rich test coverage (see `client_test.ts` for end-to-end scenarios).
npm package: @selfage/puppeteer_test_executor_api
Description: API exposed in browser context when executed by @selfage/puppeteer_test_executor
Author: Yuxuan Xie
Latest version: 5.2.1

# @selfage/puppeteer_test_executor_api

## Install

`npm install @selfage/puppeteer_test_executor_api`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides API definitions for JS files running in browser context, executed by `@selfage/puppeteer_test_executor`, matching version `4.2.x`. See [@selfage/puppeteer_test_executor](https://www.npmjs.com/package/@selfage/puppeteer_test_executor) for full document.
npm package: @selfage/puppeteer_test_runner
Description: Let each test file be executable on its own.
Author: Yuxuan Xie
Latest version: 1.3.0

# @selfage/test_runner

## Install

`npm install @selfage/puppeteer_test_runner`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides a simple test runner that makes each test file itself an exectuable file, executed by `@selfage/puppeteer_test_executor`.

## Test runner for Puppeteer test executor environment

The API to write tests are the same as [@selfage/test_runner](https://github.com/selfage/test_runner/tree/main), except you need to do `import { TEST_RUNNER } from "@selfage/puppeteer_test_runner";`.

```TypeScript
import { TEST_RUNNER } from "@selfage/puppeteer_test_runner";

TEST_RUNNER.run({
  // ...
  // Note this file is run in browser context with an empty HTML page.
  // So you have to make sure that partially created DOM trees are appended to
  // HTML body and also will be cleaned up between test cases.
});
```

In order to run the test file, you need to first bundle the file as the main file, install `@selfage/puppeteer_test_executor`, and then do `$ pexe your_test_file`.
npm package: @selfage/ref
Description: Wrap everything into a pointer/reference.
Author: Yuxuan Xie
Latest version: 1.0.4

# @selfage/ref

## Install

`npm install @selfage/ref`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides a simple wrapper for any values, which can then be passed around by reference. The primary motivation is to pass wrappers to functions as output arguments, just like using C++ output pointer arguments.

## Output argument

See `Ref`'s [definition](https://github.com/selfage/ref/blob/main/ref.ts#L2).

```TypeScript
import { Ref } from '@selfage/ref';

function add(a: number, b: number, res: Ref<number>): void {
  res.val = a + b;
}

let outputArg = new Ref<number>();
add(1, 2, outputArg);
console.log(outputArg.val);
// Prints 3.
```

## Assign output argument while return value

See `assign()`'s [definition](https://github.com/selfage/ref/blob/main/ref.ts#L7).

```TypeScript
import { Ref, assign } from '@selfage/ref';

function add(a: number, b: number, res: Ref<number>): number {
  let value = a + b;
  return assign(res, value);
}

let res = new Ref<number>();
let ret = add(1, 2, res);
// res.val === 3
// ret == 3
```

## Intercept output

Another way to `assign()` is to intercept output while keep returning it.

```TypeScript
import { Ref, assign } from '@selfage/ref';

function add(a: number, b: number): number {
  return a + b;
}

let res1 = new Ref<number>();
let res2 = new Ref<number>();
let res3 = add(assign(res1, add(1,2)), assign(res2, add(3,4)));
// res1.val === 3
// res2.val === 7
// res3 === 10
```

Without `Ref` and `assign()`, the equivalent looks like the following.

```TypeScript
function add(a: number, b: number): number {
  return a + b;
}

let res1 = add(1,2);
let res2 = add(3,4;
let res3 = add(res1, res2);
// res1 === 3
// res2 === 7
// res3 === 10
```

## Return multiple values?

TypeScript/JavaScript can easily return an object as a way to return multiple values. Therefore this package isn't designed for that purpose.
npm package: @selfage/service_descriptor
Description: Descriptor for remote services based on HTTP.
Author: Yuxuan Xie
Latest version: 5.3.2

# @selfage/service_descriptor

## Install

`npm install @selfage/service_descriptor`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides common TypeScript interfaces shared by [@selfage/service_handler](https://github.com/selfage/service_handler) and [@selfage/web_service_client](https://github.com/selfage/web_service_client). Refer to those two packages for usage.
npm package: @selfage/tabs
Description: Common features to navigate between tabs.
Author: Yuxuan Xie
Latest version: 3.0.1

# @selfage/tabs

## Install

`npm install @selfage/tabs`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig ](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides generic helpers to navigator tabs.

## TabSwitcher

Instead of tracking all tabs, it simply hides the tab previously shown and shows a new tab, thus a switcher.

```TypeScript
import { TabsSwitcher } from '@selfage/tabs/switcher';

let tabA: HTMLDivElement;
let tabB: HTMLDIvElement;

let tabsSwitcher = new TabsSwitcher();
tabsSwitcher.show(/* showTab= */ () => {
  tabA.style.display = 'block';
}, /* hideTab= */ () => {
  tabA.style.display = 'none';
});
// Now tabA is shown.
tabsSwitcher.show(/* showTab= */ () => {
  tabB.style.display = 'block';
}, /* hideTab= */ () => {
  tabB.style.display = 'none';
});
// Now tabA is hidden and taB is shown.
```

## TabNavigator

An alternative way to navigator through tabs, requiring a `Tab` enum that contains all possible values. Especailly useful if the same tab needs an update.

```TypeScript
import { TabNavigator } from `@selfage/tabs/navigator`;

enum Tab {
  A = 1,
  B = 2,
  C = 3,
}

function showTab(tab?: Tab) {
  switch (tab) {
    ...
  }
}

function hideTab(tab?: Tab) {
  switch (tab) {
    ...
  }
}

function updateTab(tab?: Tab) {
  switch (tab) {
    ...
  }
}

let navigator = new TabNavigator((tab) => showTab(tab), (tab) => hideTab(tab), (tab) => updateTab(tab));
navigator.goTo(Tab.A);
```
npm package: @selfage/tz_date
Description: Timezone aware date handling.
Author: Yuxuan Xie
Latest version: 1.0.2

# @selfage/tz_date

## Install

`npm install @selfage/tz_date`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig ](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides a class `TzDate` to help move dates wrt to a timezone and format output, currently only supporting negative timezones like `-8`.
npm package: @selfage/web_app_base_dir
Description: Gobal variable declaration of base directory.
Author: Yuxuan Xie
Latest version: 1.0.1

# @selfage/web_app_base_dir

## Install

`npm install @selfage/web_app_base_dir`

## Usage

Please refer to [@selfage/bundler_cli#bundle-web-apps](https://github.com/selfage/bundler_cli#bundle-web-apps) for its usage. It's extracted as a standalone package because there are cases you'd only want to install this package.
npm package: @selfagency/asyncredis
Description: Event-driven async wrapper for ioredis with TypeScript support.
Author: Daniel Sieradski
Latest version: 0.1.2
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# Asyncredis

Event-driven async wrapper for ioredis with TypeScript support. Not a full implementation as of yet.

## Install

```
npm i @selfagency/asyncredis
```

## Usage

```ts
import { Cache } from '@selfagency/asyncredis'

// define cache (ioredis config object)
const cache = new Cache({
  host: 'localhost',
  port: 6379,
  password: 'password',
  db: 0,
})

// define key
const key = 'my:awesome:key'

// define ttl
const ttl = 60 * 60 // 1 hour (default)

// set value
await cache.set(key, { some: 'data' }, ttl)

// get value
const result = await cache.get(key)

// result = { some: 'data' }
```