open-index/open-npm huggingface dataset:
npm package: @spine/bootstrap
Description: A bootstrap standard for your project
Author: Ezequiel S. Pereira
Latest version: 0.2.3

# Spine Bootstrap

This module will make sure your entire project
is pluggable.

> This is an additional dependency for [Spine Hook](https://gitlab.com/ezsper.com/spine/hook)

## Usage

### Create your hook

```
# myPlugin.ts
import {
  bootstrapHook,
  initHook,
  deathHook,
} from '@spine/bootstrap';

bootstrapHook.addAction('your-plugin', () => {
  /* This is an opportunite to bind or unbind any plugin */
  console.log('bootstrap');
});

initHook.addAction('your-plugin', async () => {
  /* Initialize something  */
  console.log('executed after bootstrap hook');
});

deathHook.addAction('your-plugin', async () => {
  /* It will execute when window unloads or process is killed */
  console.log('destroy');
});
```

### Bootstrap your project
```
# index.ts
import { bootstrap } from '@spine/bootstrap/server';

// load your plugins
import './myPlugin';

bootstrap()
  .catch(error => console.log(error.stack || error.message));
```
npm package: @spine/config
Description: A configuration utility valid for both client and server
Author: Ezequiel S. Pereira
Latest version: 0.0.40

# Spine Config Utility

A configuration utility valid for both client and server

## Key aspects

* Exports config safely on browser
* Typed config structure
* Namespaces

## How to use it

1. Create a `config` directory in your project's root path

2. Create `config/clientConfigFilter.ts` and define which config should be safely exported to client

  ```
  import { ConfigSource } from '.';
  
  export const clientConfigFilter: ConfigSource['clientConfigFilter'] = {
    htmlPage: {
      welcomeMessage: true,
    },
  }
  ```

3. Create your `config/index.ts` to be imported in both client and server

  ```
  import {
    createConfig,
    ClientConfigFilter,
  } from '@spine/config';

  export interface MyProjectConfigSource {
    clientConfigFilter: ClientConfigFilter<this>;
    port: number;
    host: string;
    htmlPage: {
      welcomeMessage: string;
    };
  }

  export interface ConfigSource extends MyProjectConfigSource {}
  export const config = createConfig<ConfigSource>('MyProject', '__CONFIG__');
  export default config;

  const isBrowser = typeof window !== 'undefined';

  if (isBrowser) {
    config.hydrate();
  } else {
    require('./load');
  }
  ```

4. Create `config/load.ts` and load your config

  ```
  import * as envVars from '@spine/config/envVars';
  import { config } from '.';
  import { clientConfigFilter } from './clientConfigFilter';

  config.load({
    clientConfigFilter,
    port: envVars.number('PORT', 1337),
    host: envVars.number('HOST', '0.0.0.0'),
    htmlPage: {
      welcomeMessage: 'Welcome',
    },
  });
  ```

5. Start using your config inside your project

  ```
  import config from '../config';
  console.log(config.htmlPage.welcomeMessage);
  console.log(config('htmlPage.welcomeMessage'));
  ```

### Export config from your server to your client

  ```
  import { renderClientConfig } from '@spine/config/server';
  import { config } from './config';
  console.log(renderClientConfig(config, config.clientConfigFilter, 'your nonce here'));
  ```
  outputs

  ```
  <script nonce="your nonce here">
  window.__CONFIG__={
      htmlPage: {
        welcomeMessage: "Hello World"
      },
  }
  </script>
  ```
npm package: @spine/env-vars
Description: Utility to load and handle environment variables.
Author: Ezequiel S. Pereira
Latest version: 0.0.2

# Spine Env Vars Utility

An utility to find and cast environment to Javascript types

### How to use
```
import { EnvVars } from '@spine/env-vars';

const envVars = new EnvVars();

export default {
   listenPort: envVars.int('LISTEN_PORT', 3000),
   listenAddress: envVars.string('LISTEN_ADDRESS', 'localhost'),
   secure: {
     enabled: envVars.bool('SECURE_ENABLED', false),
     certKey: envVars.value('SECURE_CERT_KEY'),
     privateKey: envVars.value('SECURE_PRIVATE_KEY'),
   },
   someJSONConfig: envVars.json('MY_CONFIG', {}),
};
```

### Casting processes

##### `envVars.value`

Returns the original string value

##### `envVars.string`

Perform a trim and remove initial and final double quotes, if it's empty
returns default value

##### `envVars.number`

Execute `envVars.string()` and after cast with `Number()` if strict, if not strict it uses `parseFloat`, and if it is `NaN` returns default value

##### `envVars.int`

Execute `envVars.number()` and after truncates to integer (if not strict)

##### `envVars.bool`

Execute `envVars.string()` and after matches for a boolean value, the following is accepted...

|   |   |
|---|---|
| `true` | `false`  |
|  `1` | `0`  | 
|  `t` | `f`  | 
|  `on` | `off`  | 
|  `enable` | `disable`  | 
|  `enabled` | `disabled`  | 

Otherwise returns default value

##### `envVars.json`

Parses environment as JSON, and in case of an error returns default value

#### Throw or Log Cast Error

Cast errors are silent by default, in case of a cast error it just returns the default value.

You can change this behavior by specifying the `throwOrLogCastError` property.

```
envVars.throwOrLogCastError = error => throw error;
```

or simply log it, without breaking name matches or preventing default from returning.

```
envVars.throwOrLogCastError = (error, name, type, value) => {
  console.log(`Env "${name}" does not represent a valid ${type}.`);
};
```

#### Strict Cast Numbers

If set to false it will use `parseInt()` and `parseFloat()` instead of `Number()` to cast numbers.

```
process.env.LISTEN_PORT = '80whatever';
envVars.int('LISTEN_PORT', 3000);
// Returns 3000
envVars.strictCastNumber = false;
envVars.int('LISTEN_PORT', 3000);
// Returns 80
```

#### Cast Error Break Matches

If set to false and cast errors are not being thrown it will try to cast
the next environment name.

```
envVars.castErrorBreakMatches = false;
process.env.LISTEN_PORT = 'invalid number';
process.env.HTTP_LISTEN_PORT = '80';
envVars.int(['LISTEN_PORT', 'HTTP_LISTEN_PORT'], 3000);
// Returns 80
```
npm package: @spine/filter-object
Description: An utility to filter object by nested rules with extracted types
Author: Ezequiel S. Pereira
Latest version: 0.0.1

# Spine Filter Object

An utility to filter object by nested rules with extracted types.

## Key aspects

* Smart typings, it filters in typing level (no `any`)
* Readable filter statements

### Rule

```
type FilterObjectRule = true | false | { [key: string]: Rule }
```


## Usage

```
const obj = {
  foo: 'bar',
  htmlPage: {
    title: 'Hello World',
    metas: [
      { name: 'description', content: 'My Hello World Page' },
    ],
  },
  environment: {
    NODE_ENV: 'production',
    FOO: 'bar',
  }
};

console.log(JSON.stringify(filterObject(obj, { foo: true, htmlPage: { title: true } })));
// {"foo":"bar","htmlPage":{"title":"Hello World"}}

console.log(JSON.stringify(filterObject(obj, { htmlPage: { metas: { name: true } } })));
// {"htmlPage":{"metas":[{"name":"description"}]}}

console.log(JSON.stringify(filterObject(obj, { environemnt: { NODE_ENV: true } })));
// {"environment":{"NODE_ENV":"production"}}

console.log(JSON.stringify(filterObject(obj, { environemnt: true })));
// {"environment":{"NODE_ENV":"production","FOO":"bar"}}

console.log(JSON.stringify(filterObject(obj, { environemnt: { '*': true } })));
// {"environment":{"NODE_ENV":"production","FOO":"bar"}}

console.log(JSON.stringify(filterObject(obj, true)));
// {"foo":"bar","htmlPage":{"title":"Hello World","metas":[{"name":"description","content":"My Hello World Page"}]}}

console.log(JSON.stringify(filterObject(obj, {})));
// {}
```
npm package: @spine/logger
Description: A hookable logger API for your project that can work in both client and server
Author: Ezequiel S. Pereira
Latest version: 0.1.2

# Spine Logger Utility

Spine Logger logs your project and let users format their logs the way they want.

## Usage

#### Environment keys

##### `MAX_LOG_LEVEL`

Define the maximum log to display, default is `3`.

##### `DEBUG` | `VERBOSE` | `LOG_${LABEL}`

Defines specific log namespaces to display overwriting maximum log level

#### Basic

```
import { logger } from '@spine/logger';

export const log = logger('my-project');

log.debug('My debug message');
```

#### Custom levels

```
// LOG_FOOBAR=my-project
import { logger } from '@spine/logger';

export const log = logger('my-project', {
  levels: {
    foobar: 1,
  },
});

log.foobar('My foobar message');
// my-project[foobar]: My foobar message
```

#### Hooks

```
import { loggerHook, displayNameHook } from '@spine/logger';

displayNameHook.addFilter('your-plugin', (displayName, parents, path) => {
  return path.join('/');
});

loggerHook.addAction('your-plugin', (label, message, params, enabled, logger) => {
  if (enabled) {
    console.log(`${logger.getDisplayName()}: ${message}`, ...params);
  }
});
```
npm package: @spine/pluggable
Description: A pluggable module for spine
Author: Ezequiel S. Pereira
Latest version: 0.0.8

# Spine Pluggable Utility

A pluggable utility valid for both client and server

## How to use it

Make sure to import `@spine/pluggable` before bootstraping.

```
# index.ts
import config from './config';
import { bootstrap } from '@spine/bootstrap';

bootstrap()
  .catch(error => console.error(error.stack));
```

```
# config/index.ts
import {
  PluggableConfig,
} from '@spine/pluggable';
import {
  ConfigSource as BaseConfigSource,
  extendConfig,
} from '@spine/config';

export interface ConfigSource extends extends BaseConfigSource, PluggableConfig {}

export const {
  config,
  loadConfig,
} = extendConfig<ConfigSource>('MyConfig');

loadConfig({
  plugins: {
    'my-plugin-module': {
      enabled: true,
    },  
  },
});

export default config;
```
npm package: @spine/project-path
Description: An utility to get and set project root path
Author: Ezequiel S. Pereira
Latest version: 0.0.4

# Spine Project Path Utility

It's an utility module to determines project root path

### How to use it

```
import { getProjectPath } from '@spine/project-path';
import { exec } from 'child_process';

exec('npm install', {
  stdio: 'inherit',
  cwd: getProjectPath(),
});
```

### Matching order

To determine project path it follows these strict cases in order...

##### First case scenario

If `process.cwd()` contains a `/node_modules/` return the path before it;

##### Second case scenario

If a `package.json` is present in `process.cwd()` path, than returns the same path;

##### Third case scenario

If `@spine/project-path` installation path contains `/node_modules/` return the path before it;

> If `@spine/project-path` is a submodule of another installed dependency, it will return the parent
of all, which means the parent directory of the first encounter of `/node_modules/`.

##### Default scenario

Otherwise throws an error.

If you don't want any possibility for an error you can use

```
setProjectDefaultPath(() => {
  return '-- Your default project root path fallback --';
});
```
npm package: @spines/sdk
Description: Official TypeScript SDK for the SPINES API
Latest version: 1.0.0

# SPINES SDK

Official TypeScript SDK for the [SPINES API](https://getspines.com/developers) — identify books from bookshelf photos and build structured, explorable collections.

## Installation

```bash
npm install @spines/sdk
```

## Quick Start

```typescript
import { SpinesClient } from '@spines/sdk';

const spines = new SpinesClient({ apiKey: 'gtspn_live_...' });

// Search for books
const results = await spines.books.search({ query: 'Sapiens' });
console.log(results.data);

// List public collections
const collections = await spines.collections.list({ sort: 'popular', limit: 10 });

// Start a bookshelf recognition job
const job = await spines.recognition.start({
  image_url: 'https://example.com/shelf.jpg',
  title: 'My Bookshelf',
});
console.log(job.job_id); // poll with spines.recognition.status(job.job_id)
```

## Available Resources

| Resource | Methods |
|----------|---------|
| `spines.books` | `search`, `get`, `pairings`, `collections` |
| `spines.collections` | `list`, `get`, `create`, `update`, `delete`, `books`, `addBook`, `removeBook` |
| `spines.personas` | `list`, `get` |
| `spines.categories` | `list` |
| `spines.readingLists` | `list`, `add`, `update`, `remove` |
| `spines.recognition` | `start`, `status` |
| `spines.profile` | `get`, `update`, `credits` |

## Error Handling

All API errors throw a `SpinesError` with structured details:

```typescript
import { SpinesClient, SpinesError } from '@spines/sdk';

const spines = new SpinesClient({ apiKey: 'gtspn_live_...' });

try {
  await spines.books.get('non-existent-id');
} catch (err) {
  if (err instanceof SpinesError) {
    console.error(err.status);    // 404
    console.error(err.code);      // "NOT_FOUND"
    console.error(err.message);   // "Book not found"
    console.error(err.requestId); // "req_abc123"
  }
}
```

## Configuration

```typescript
const spines = new SpinesClient({
  apiKey: 'gtspn_live_...',           // Required — your API key
  baseUrl: 'https://getspines.com/api/v1', // Optional — defaults to production
});
```

## Pagination

List endpoints return cursor-based paginated responses:

```typescript
let cursor: string | undefined;

do {
  const page = await spines.collections.list({ limit: 20, cursor });
  for (const collection of page.data) {
    console.log(collection.title);
  }
  cursor = page.meta.has_more ? (page.meta.next_cursor ?? undefined) : undefined;
} while (cursor);
```

## Requirements

- Node.js 18+ (uses native `fetch`)
- TypeScript 5.3+ recommended

## Documentation

Full API reference and guides: [getspines.com/developers](https://getspines.com/developers)

## License

MIT
npm package: @spinfi/core
Description: - [**Contract api**](https://docs.api.spin.fi/#introduction)
Latest version: 2.2.1

# Links

- [**Contract api**](https://docs.api.spin.fi/#introduction)

- [**JS api**](https://spin-fi.github.io/near-dex-core-js/)

- [**@spinfi/core**](https://github.com/spin-fi/near-dex-core-js)

- [**@spinfi/node**](https://github.com/spin-fi/near-dex-node-js)

# @spinfi/node

Spin node create spin api for node

### How to install

```bash
yarn add @spinfi/node
```

### How to init

```js
const {spin} = await createApi({
  accountId: 'some account id value',
  privateKey: 'some private key value',
});
```

# @spinfi/core

Spin core create spin api instace that work exactly in browser and node.js

```js
const response = await spin.depositFt(request);
```

## Websocket

Websocket property provide functions to call `spin` off-chain methods by websocket

Websocket method divided in two types:

- method (similar to async call with callback)
- subscription

### 1. Method

Method require some parameters in `json rpc` format and return some data with `onOk` callback.
If websocket return not expected data format - api will ignore it. If websocket return correct
message without connection/js error, but with error field - data handled by `onError` callback

### How to use

```js
const unsubscribe = spin.ping({
  onOk: (data) => console.log(data),
  onError: (error) => console.error(error),
});
```

### 2. Subscription

Subscription its like method but more complex. It work like that:

- subscription send method `sub` and create `channel` to server
- if `sub` ok (channel created) then api create listners for websocket
- if new websocket message its for `channel` then api call corresponding subscription callbacks

```js
const unsubscribe = spin.listenOrders(request, {
  onSubOk: (data) => console.log(data),
  onSubError: (error) => console.error(error),
});
```

Channel - its stream of websocket message that have same `subscription id` and have some format.
Messages in channel maybe different. Some channel have first uniq message and some not.
First uniq message in channel its `state` and other messages its `notification`

Websoket message match with channel by `json rpc` id created when subscription called and `subscription id`
created by server

```js
const unsubscribe = spin.listenOrders(request, {
  onNotifyOk: (data) => console.log(data),
  onNotifyError: (error) => console.error(error),
  onStateOk: (data) => console.log(data),
  onStateError: (error) => console.error(error),
});
```

Some times its needed unsubscribe from subscription. It work like that:

- subscription send method `unsub` and get response
- if response is `true` then `channel` is closed
- internal `rxjs` subscriptions its also unsubscribed
- if response is `false` then `channel` not closed
- `onUnsubError` handle `false` branch

```js
const unsubscribe = spin.listenOrders(request, {
  onSubError: (error) => console.error(error),
  onUnsubError: (error) => console.error(error),
});
```
npm package: @spinfi/node
Description: ## Links
Latest version: 2.2.1

# @spinfi/node

## Links

- [**Contract api**](https://docs.api.spin.fi/#introduction)

- [**JS api**](https://spin-fi.github.io/near-dex-core-js/)

- [**@spinfi/core**](https://github.com/spin-fi/near-dex-core-js)

- [**@spinfi/node**](https://github.com/spin-fi/near-dex-node-js)

## How to install

```bash
yarn add @spinfi/node
```