open-index/open-npm huggingface dataset:
npm package: @pedrofurtado/cocoon-vanilla-js
Description: A vanilla JS replacement for (Rails) Cocoon's jQuery script
Author: Odd Camp
Latest version: 1.1.2-patched

# cocoon-vanilla-js

A vanilla JS replacement for (Rails) [Cocoon](https://github.com/nathanvda/cocoon)'s jQuery script

## Usage

Run:

```
yarn add @oddcamp/cocoon-vanilla-js
```

Import as ES6 module:

```js
import "@oddcamp/cocoon-vanilla-js";
```

## Notes

To broaden browser support, include the following polyfills in your project:

- [Element.closest](https://www.npmjs.com/package/element-closest)
- [Element.classList](https://www.npmjs.com/package/classlist-polyfill)
- [Array.from](https://www.npmjs.com/package/array-from-polyfill)
- [CustomEvent](https://www.npmjs.com/package/custom-event-polyfill)
npm package: @pedrofurtado/redux
Description: My own Redux. Just for fun.
Author: Pedro Furtado
Latest version: 1.0.1

# Redux

My own Redux. Just for fun.

## Usage

```javascript
import { createStore } from '@pedrofurtado/redux'

const reducer1 = (state = [], action) => {
  switch(action.type) {
    case 'SOME_ACTION':
      return [...state, action.payload]
    case 'ANOTHER_ACTION':
      return [...state, action.another_payload]
    case 'LAST_ACTION':
      return []
    default:
      return state
  }
}

const reducer2 = (state = 5, action) => {
  switch(action.type) {
    case 'UNIQUE_ACTION':
      return 9
    default:
      return state
  }
}

const middleware1 = (state, action) => {
  console.log('Middleware 1 executing!')
  console.log('State at this moment', state)
  console.log('Action at this moment', action)
  console.log('Middleware 1 executed!')
}

const middleware2 = (state, action) => {
  console.log('Middleware 2 executing!')
  console.log('State at this moment', state)
  console.log('Action at this moment', action)
  console.log('Middleware 2 executed!')
}

const store = createStore(
  {
    key1: reducer1,
    key2: reducer2
  },
  [
    middleware1,
    middleware2
  ]
)

store.subscribe(() => {
  console.log('Changes detected in state!')
});

store.dispatch({ type: 'SOME_ACTION', payload: 'SOMETHING' })
store.dispatch({ type: 'ANOTHER_ACTION', another_payload: 'ANOTHER_THING' })
store.dispatch({ type: 'ACTION_THAT_NOT_EXISTS' })
store.dispatch({ type: 'UNIQUE_ACTION' })
```

## Build

To build the `dist/` folder, execute the following command:

```bash
$ docker-compose up --build -d
```

or

```bash
$ docker container run --rm -it -v $(pwd):/srv -w /srv node:10 /bin/bash
$ npm install
$ npm run build
```

Enjoy!
npm package: @pedrogbraz/commit-cli
Description: A CLI for creating conventional commits with automatic git push
Author: Pedro Gontijo Braz pedrobrazdevs@gmail.com
Latest version: 1.0.1

# Commit CLI

   A CLI for creating conventional commits with automatic git push.

   ## Installation

   ```bash
   npm install -g @pedrogbraz/commit-cli
   ```

   ## Usage

   1. Navigate to a Git repository.
   2. Run:
      ```bash
      commit-cli
      ```
   3. Follow the prompts to:
      - Select files to commit.
      - Choose a commit type (feat, fix, docs, etc.).
      - Enter a scope (optional) and description.
      - Decide whether to push to the remote repository.

   ## Prerequisites

   - Node.js (v14 or higher)
   - Git

   ## License

   MIT
npm package: @pedroguia/react-draft-wysiwyg
Description: A wysiwyg on top of DraftJS.
Author: Jyoti Puri
Latest version: 1.18.1

# React Draft Wysiwyg

A Wysiwyg editor built using ReactJS and DraftJS libraries.
[Demo Page](https://jpuri.github.io/react-draft-wysiwyg).

[![Build Status](https://travis-ci.org/jpuri/react-draft-wysiwyg.svg?branch=master)](https://travis-ci.org/jpuri/react-draft-wysiwyg)

![](http://i.imgur.com/tU7kJ6i.gif)

## Features
- Configurable toolbar with option to add/remove controls.
- Option to change the order of the controls in the toolbar.
- Option to add custom controls to the toolbar.
- Option to change styles and icons in the toolbar.
- Option to show toolbar only when editor is focused.
- Support for inline styles: Bold, Italic, Underline, StrikeThrough, Code, Subscript, Superscript.
- Support for block types: Paragraph, H1 - H6, Blockquote, Code.
- Support for setting font-size and font-family.
- Support for ordered / unordered lists and indenting.
- Support for text-alignment.
- Support for coloring text or background.
- Support for adding / editing links
- Choice of more than 150 emojis.
- Support for mentions.
- Support for hashtags.
- Support for adding / uploading images.
- Support for aligning images, setting height, width.
- Support for Embedded links, flexibility to set height and width.
- Option provided to remove added styling.
- Option of undo and redo.
- Configurable behavior for RTL and Spellcheck.
- Support for placeholder.
- Support for WAI-ARIA Support attributes
- Using editor as controlled or un-controlled React component.
- Support to convert Editor Content to HTML, JSON, Markdown.
- Support to convert the HTML generated by the editor back to editor content.
- Support for internationalization.

## Installing
The package can be installed from npm `react-draft-wysiwyg`

```
$ npm install --save react-draft-wysiwyg draft-js
```

## Getting started
Editor can be used as simple React Component:
```js
import { Editor } from 'react-draft-wysiwyg';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
<Editor
  editorState={editorState}
  toolbarClassName="toolbarClassName"
  wrapperClassName="wrapperClassName"
  editorClassName="editorClassName"
  onEditorStateChange={this.onEditorStateChange}
/>
```

## Docs
For more documentation check [here](https://jpuri.github.io/react-draft-wysiwyg/#/docs?_k=jjqinp).

## Questions Discussions
For discussions join public channel #rd_wysiwyg in [DraftJS Slack Organization](https://draftjs.herokuapp.com/).

## Thanks
Original motivation and sponsorship for this work came from [iPaoo](http://www.ipaoo.com/). I am thankful to them for allowing the Editor to be open-sourced.

## License
MIT.
npm package: @pedrohccs/gestao-empresarial
Description: Módulo de Gestão Empresarial do Sistema de Licitações
Author: Lugar de Tech
Latest version: 1.0.2

# @licita/gestao-empresarial

Módulo de Gestão Empresarial do Sistema de Licitações.

## Funcionalidades

- ✅ CRUD completo de empresas
- ✅ Validação de CNPJ
- ✅ Hooks React para gerenciamento de estado
- ✅ Integração com Supabase
- ✅ Tipos TypeScript completos

## Instalação

```bash
npm install @licita/gestao-empresarial @licita/shared-libs
```

## Uso

### Services

```typescript
import { EmpresaService } from '@licita/gestao-empresarial'

// Listar empresas
const empresas = await EmpresaService.listar()

// Criar empresa
const novaEmpresa = await EmpresaService.criar({
  cnpj: '12345678000190',
  razao_social: 'Empresa Exemplo LTDA',
  tipo_empresa: 'LTDA'
})

// Validar CNPJ
const isValid = EmpresaService.validarCnpj('12345678000190')

// Formatar CNPJ
const formatted = EmpresaService.formatarCnpj('12345678000190')
```

### Hooks React

```typescript
import { useEmpresas, useEmpresa } from '@licita/gestao-empresarial'

function EmpresasPage() {
  const { empresas, loading, error, criar, atualizar, desativar } = useEmpresas()

  const handleCreate = async (data) => {
    try {
      await criar(data)
      // Empresa criada com sucesso
    } catch (error) {
      // Tratar erro
    }
  }

  if (loading) return <div>Carregando...</div>
  if (error) return <div>Erro: {error}</div>

  return (
    <div>
      {empresas.map(empresa => (
        <div key={empresa.id}>{empresa.razao_social}</div>
      ))}
    </div>
  )
}

function EmpresaDetails({ id }: { id: string }) {
  const { empresa, loading, error } = useEmpresa(id)

  if (loading) return <div>Carregando...</div>
  if (error) return <div>Erro: {error}</div>
  if (!empresa) return <div>Empresa não encontrada</div>

  return <div>{empresa.razao_social}</div>
}
```

### Tipos

```typescript
import { EmpresaFormData, TIPOS_EMPRESA } from '@licita/gestao-empresarial'

const formData: EmpresaFormData = {
  cnpj: '12345678000190',
  razao_social: 'Empresa Exemplo',
  tipo_empresa: 'LTDA'
}

// Lista de tipos de empresa
TIPOS_EMPRESA.forEach(tipo => {
  console.log(tipo.value, tipo.label)
})
```

## Dependências

- `@licita/shared-libs`: Bibliotecas compartilhadas
- `@supabase/supabase-js`: Cliente Supabase
- `react`: React (peer dependency)
- `react-hook-form`: Formulários (peer dependency)
- `zod`: Validação (peer dependency)

## Desenvolvimento

```bash
# Instalar dependências
npm install

# Build
npm run build

# Watch mode
npm run dev

# Testes
npm test

# Lint
npm run lint
```

## Estrutura

```
src/
├── services/           # Lógica de negócios
│   └── EmpresaService.ts
├── hooks/              # React hooks
│   └── useEmpresas.ts
├── types/              # Tipos TypeScript
│   └── empresa.ts
└── index.ts           # Exports públicos
```
npm package: @pedrohccs/shared-libs
Description: Bibliotecas compartilhadas do Sistema de Licitações
Author: Lugar de Tech
Latest version: 1.1.3

# @licita/shared-libs

Bibliotecas compartilhadas do Sistema de Gestão de Licitações.

## Instalação

```bash
npm install @licita/shared-libs
```

## Uso

### Supabase

```typescript
import { createBrowserSupabaseClient, createServerSupabaseClient } from '@licita/shared-libs'

// Cliente browser
const supabase = createBrowserSupabaseClient()

// Cliente servidor (Next.js)
const supabase = await createServerSupabaseClient()
```

### UI Components

```typescript
import { Layout, PageHeader } from '@licita/shared-libs'

function MyPage() {
  return (
    <Layout title="Minha Página">
      <PageHeader 
        title="Dashboard" 
        subtitle="Visão geral do sistema"
        actions={<button>Nova Ação</button>}
      />
      {/* conteúdo */}
    </Layout>
  )
}
```

### Utilitários

```typescript
import { validateCnpj, formatCnpj, formatCurrency } from '@licita/shared-libs'

const isValid = validateCnpj('12345678000190')
const formatted = formatCnpj('12345678000190') // 12.345.678/0001-90
const price = formatCurrency(1234.56) // R$ 1.234,56
```

### Tipos

```typescript
import { ApiResponse, User, LoadingState } from '@licita/shared-libs'

const response: ApiResponse<User> = {
  data: { id: '1', email: 'user@example.com', ... },
  success: true
}
```

## Desenvolvimento

```bash
# Instalar dependências
npm install

# Build
npm run build

# Watch mode
npm run dev

# Testes
npm test

# Lint
npm run lint
```

## Publicação

Este pacote é publicado automaticamente no npm quando uma tag é criada no repositório.

```bash
npm version patch|minor|major
git push origin main --tags
```
npm package: @pedrohenry-santos/eslint-config
Description: ESLint configuration used by Pedro.
Author: pedrohenry-santos
Latest version: 1.5.7

# Pedro ESLint config

## Whats included?

- Standard config base;
- React plugin;
- React Hooks plugin;
- JSX a11y plugin;
- Prettier;

## Setup

### React (with Next.js)

Install dependencies:

```
npm i -D eslint @pedrohenry-santos/eslint-config
```

Inside `.eslintrc.json`

```
{
  "extends": [
    "@pedrohenry-santos/eslint-config/next", 
    "next/core-web-vitals"
  ]
}
```

### React (without Next.js)

Install dependencies:

```
npm i -D eslint @pedrohenry-santos/eslint-config
```

Inside `.eslintrc.json`

```
{
  "extends": "@pedrohenry-santos/eslint-config/react"
}
```

### Node.js

Install dependencies:

```
npm i -D eslint @pedrohenry-santos/eslint-config
```

Inside `.eslintrc.json`

```
{
  "extends": "@pedrohenry-santos/eslint-config/node"
}
```
npm package: @pedrohnas/livchat-mcp
Description: MCP Server para controle do LivChat - Gerenciamento de buffer de mensagens
Author: Pedro
Latest version: 0.1.3

# LivChat MCP Server

Servidor MCP (Model Context Protocol) para controle do sistema LivChat. Permite que agentes AI ajustem configurações do buffer de mensagens do WhatsApp.

## Instalação

```bash
npm install -g @pedrohnas/livchat-mcp
```

Ou use diretamente com `npx`:

```bash
npx @pedrohnas/livchat-mcp
```

## Configuração

### Adicionar ao seu agente MCP

Em seu arquivo de configuração MCP (ex: `config/mcp_servers.json`):

```json
{
  "mcpServers": {
    "livchat": {
      "command": "npx",
      "args": ["-y", "@pedrohnas/livchat-mcp"],
      "env": {
        "LIVCHAT_CORE_URL": "http://livchat-core:8082"
      },
      "transport": "stdio"
    }
  }
}
```

### Variáveis de Ambiente

- `LIVCHAT_CORE_URL`: URL do LivChat Core (padrão: `http://localhost:8082`)

## Ferramentas Disponíveis

### `obter-timeouts-buffer`
Obtém a configuração atual dos timeouts do buffer de mensagens.

### `configurar-timeouts-buffer`
Define os tempos mínimo e máximo de espera para agrupar mensagens.

**Parâmetros:**
- `minimo_segundos`: 1-60 segundos
- `maximo_segundos`: 2-300 segundos (deve ser maior que o mínimo)

### `verificar-status-sistema`
Verifica se o sistema está online e mostra a configuração atual.

### `aplicar-preset-buffer`
Aplica configurações predefinidas:
- `instantaneo`: 1-2s (respostas imediatas)
- `rapido`: 2-5s (conversas dinâmicas)
- `balanceado`: 4-17s (configuração padrão)
- `paciente`: 10-30s (aguarda múltiplas mensagens)

## Exemplos de Uso com Agentes AI

```
"Configure o buffer para respostas rápidas"
"Defina o tempo de espera entre 10 e 20 segundos"
"Aplique o modo paciente no buffer"
"Qual a configuração atual do sistema?"
```

## Desenvolvimento

```bash
# Instalar dependências
npm install

# Compilar TypeScript
npm run build

# Executar localmente
npm start
```

## Licença

MIT
npm package: @pedrohvfernandes/eslint-config
Description: ESLint configuration used by pedrohvfernandes.
Latest version: 0.1.5

# ESLint config  <img src="https://img.shields.io/badge/eslint-3A33D1?style=for-the-badge&logo=eslint&logoColor=white">

## Whats included?

- Standard config base;
- React plugin;
- React Hooks plugin;
- No Only Tests plugin;
- Import Helpers Order Imports;
- JSX a11y plugin;
- Prettier;
  - Does not have commas at the end;
-  *In this case, it is not necessary to create the .prettier file in the project root, as the eslintrc configured in this package already contains the exact settings for prettier.*
-  *Note: Remove the prettier extension and install the eslint extension*
- TypeScript;
## VSCode Configuration for Auto Formatting on Save

In some cases, it's necessary to enable the **Format on Save** option in your VSCode.

To do this:

1. Click on the **gear icon (⚙️)** in the bottom-left corner of VSCode.
2. Select **Settings**.
3. In the search bar, type: `Format on Save`.
4. Enable the **Format on Save** checkbox.

---

## Project Configuration

In the root directory of your project, create a folder named `.vscode`, and inside it, create a file named `settings.json` with the following configuration:

```json
{
  "editor.tabSize": 2,
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll": "always",
    "source.fixAll.eslint": "always"
  },
  "eslint.format.enable": true
}
```

## Commands suggestions(script in package.json)

```json
{
  "scripts": {
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "lint:mysrc": "eslint ./src --max-warnings 0",
    "lint:fix": "eslint . --fix",
    "lint:fixmysrc": "eslint src/**/*.{ts,tsx} --fix",
  }
}
```

## Setup

### React (with Next.js)

Install dependencies:
```
npm i -D eslint @pedrohvfernandes/eslint-config
```
Inside `.eslintrc.json`
```
{
  "extends": [
    "@pedrohvfernandes/eslint-config/next", 
    "next/core-web-vitals"
  ]
}
```

### React (Vite or CRA)

Install dependencies: 
```
npm i -D eslint @pedrohvfernandes/eslint-config
```
Inside `.eslintrc.json`
```
{
  "extends": "@pedrohvfernandes/eslint-config/react"
}
```

### Node.js

Install dependencies:
```
npm i -D eslint @pedrohvfernandes/eslint-config
```
Inside `.eslintrc.json`
```
{
  "extends": "@pedrohvfernandes/eslint-config/node"
}
```
### My config: Dev Junior + Rocketseat + Igor React (Vite or CRA)

Install dependencies:
```
npm i -D eslint @pedrohvfernandes/eslint-config
```
Inside `.eslintrc.json`
```
{
  "extends": "@pedrohvfernandes/eslint-config/myconfigreact"
}
```
### My config: Node.js

Install dependencies:
```
npm i -D eslint @pedrohvfernandes/eslint-config
```
Inside `.eslintrc.json`
```
{
  "extends": "@pedrohvfernandes/eslint-config/myconfignode"
}
```
npm package: @pedrohvfernandes/eslint-config-nestjs
Description: ESLint configuration used by pedrohvfernandes.
Latest version: 0.0.3

# ESLint config  <img src="https://img.shields.io/badge/eslint-3A33D1?style=for-the-badge&logo=eslint&logoColor=white">

## Whats included?

- Eslint;
- Prettier;
  - Does not have commas at the end;
-  *In this case, it is not necessary to create the .prettier file in the project root, as the eslintrc configured in this package already contains the exact settings for prettier.*
-  *Note: Remove the prettier extension and install the eslint extension*
- Typescript;

## Commands suggestions(script in package.json)

```json
{
  "scripts": {
    "lint": "eslint . --ext ts --report-unused-disable-directives --max-warnings 0",
    "lint:mysrc": "eslint ./src --max-warnings 0",
    "lint:fix": "eslint . --fix",
    "lint:fixmysrc": "eslint src/**/*.{ts} --fix",
    "lint:general": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
  }
}
```

## Setup

### NestJs Node

Install dependencies: 
```
npm i -D eslint @pedrohvfernandes/eslint-config-nestjs
```
Inside `.eslintrc.json`
```
{
  "extends": "@pedrohvfernandes/eslint-config-nestjs/nestjs"
}
```

### Uninstall

```
npm uninstall eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier eslint-plugin-prettier prettier
```
npm package: @pedrohvfernandes/eslint-config-vue
Description: ESLint configuration used by pedrohvfernandes.
Latest version: 0.0.5

# ESLint config  <img src="https://img.shields.io/badge/eslint-3A33D1?style=for-the-badge&logo=eslint&logoColor=white">

## Whats included?

- Eslint;
- eslint-plugin-vuejs-a11y;
- Prettier;
  - Does not have commas at the end;
-  *In this case, it is not necessary to create the .prettier file in the project root, as the eslintrc configured in this package already contains the exact settings for prettier.*
-  *Note: Remove the prettier extension and install the eslint extension*
- vue/vue3-strongly-recommended;
- Vue plugin;
- Typescript;

## Commands suggestions(script in package.json)

```json
{
  "scripts": {
    "lint": "eslint . --ext ts,vue --report-unused-disable-directives --max-warnings 0",
    "lint:mysrc": "eslint ./src --max-warnings 0",
    "lint:fix": "eslint . --fix",
    "lint:fixmysrc": "eslint src/**/*.{ts,vue} --fix"
  }
}
```

## Setup

### Vue (Vite or CRA)

Install dependencies: 
```
npm i -D eslint @pedrohvfernandes/eslint-config-vue
```
Inside `.eslintrc.json`
```
{
  "extends": "@pedrohvfernandes/eslint-config-vue/vue"
}
```
npm package: @pedroladeira/jsb
Description: cli Code generator
Author: Pedro Ladeira
Latest version: 0.0.3

# Javascript Builder

Generate your code components trough a simple command line

```
Usage: react-generate [options]

  Options:

    -h, --help                output usage information
    -V, --version             output the version number
```

## Install

```
npm i -g @pedroladeira/jsb
```

## Just type the command

```
jsb
```
npm package: @pedroladeira/reactbuilder
Description: Generate react components
Author: Pedro Ladeira
Latest version: 1.0.4

# React Builder

Generate your code components trough a simple command line

```
Usage: react-generate [options] <name>

  Options:

    -h, --help                output usage information
    -V, --version             output the version number
    -s, --styles [extension]  styles extension [default: css]
    -t, --typescript          use typescript style [default: false]
```

## Install

```
npm i -g @pedroladeira/reactbuilder
```

## Create a React Typescript file Component

```
reactbuilder button -f tsx
```

## Create a Javascript File

```
reactbuilder button -f tsx
```

## Create a file inside a path

```
reactbuilder example.button -f tsx
reactbuilder components.example.button -f tsx
```

will create

```
button
├── index.tsx
├── Button.tsx
└── Button.scss
```
npm package: @pedrolamas/plugin-vue2
Description: > [!CAUTION] > Vue 2 has reached EOL, and this project is no longer actively maintained.
Author: Pedro Lamas
Latest version: 2.4.0

# @pedrolamas/plugin-vue2 [![npm](https://img.shields.io/npm/v/@pedrolamas/plugin-vue2.svg)](https://npmjs.com/package/@pedrolamas/plugin-vue2)

> [!CAUTION]
> Vue 2 has reached EOL, and this project is no longer actively maintained.

---

> Note: this plugin requires Vite 8 (`vite >= 8.0.0`) and only works with Vue@^2.7.0.

```js
// vite.config.js
import vue from '@pedrolamas/plugin-vue2'

export default {
  plugins: [vue()]
}
```

## Options

```ts
export interface Options {
  include?: string | RegExp | (string | RegExp)[]
  exclude?: string | RegExp | (string | RegExp)[]

  isProduction?: boolean

  // options to pass on to vue/compiler-sfc
  script?: Partial<Pick<SFCScriptCompileOptions, 'babelParserPlugins'>>
  template?: Partial<
    Pick<
      SFCTemplateCompileOptions,
      | 'compiler'
      | 'compilerOptions'
      | 'preprocessOptions'
      | 'transpileOptions'
      | 'transformAssetUrls'
      | 'transformAssetUrlsOptions'
    >
  >
  style?: Partial<Pick<SFCStyleCompileOptions, 'trim'>>
}
```

## Asset URL handling

When `@pedrolamas/plugin-vue2` compiles the `<template>` blocks in SFCs, it also converts any encountered asset URLs into ESM imports.

For example, the following template snippet:

```vue
<img src="../image.png" />
```

Is the same as:

```vue
<script setup>
import _imports_0 from '../image.png'
</script>
```

```vue
<img :src="_imports_0" />
```

By default the following tag/attribute combinations are transformed, and can be configured using the `template.transformAssetUrls` option.

```js
{
  video: ['src', 'poster'],
  source: ['src'],
  img: ['src'],
  image: ['xlink:href', 'href'],
  use: ['xlink:href', 'href']
}
```

Note that only attribute values that are static strings are transformed. Otherwise, you'd need to import the asset manually, e.g. `import imgUrl from '../image.png'`.

## Example for passing options to `vue/compiler-sfc`:

```ts
import vue from '@pedrolamas/plugin-vue2'

export default {
  plugins: [
    vue({
      template: {
        compilerOptions: {
          // ...
        },
        transformAssetUrls: {
          // ...
        }
      }
    })
  ]
}
```

## Example for transforming custom blocks

```ts
import vue from '@pedrolamas/plugin-vue2'

const vueI18nPlugin = {
  name: 'vue-i18n',
  transform(code, id) {
    if (!/vue&type=i18n/.test(id)) {
      return
    }
    if (/\.ya?ml$/.test(id)) {
      code = JSON.stringify(require('js-yaml').load(code.trim()))
    }
    return `export default Comp => {
      Comp.i18n = ${code}
    }`
  }
}

export default {
  plugins: [vue(), vueI18nPlugin]
}
```

## License

MIT
npm package: @pedrolcn/time-safe
Description: Type-safe time classes
Author: Pedro Nascimento
Latest version: 0.2.6

# Time-safe

Have you ever mistakenly passed an interval in miliseconds to a function which expected seconds?  
We all have, and then your cache entry which you intended to only last for 1 minute now lasts for 16 hours.

time-safe strives to turn such runtime bugs into compile-time errors by providing a strongly-typed interval API.

## Usage

install via your package manager of choice:
```shell
$ yarn add @pedrolcn/time-safe
$ npm i @pedrolcn/time-safe
```

time-safe\`s API is exposed via the TimeSafe object exported from the lib\`s index and contains factory methods for all supported interval types:

```typescript
import { TimeSafe, Second } from '@pedrolcn/time-safe';

async function setRedisEntry(key: string, value: any, ttl: Second) {
  const redisClient = ... //acquire redis client somehow
  await redisClient.set(key, value, `EX`, ttl.asSeconds());
}

setRedisEntry('foo', 'bar', TimeSafe.seconds(60))
```

This way the function signature is very explicit about what type of interval it expects (seconds) and if you try and pass is anything other than a duration in seconds it emmits a type-error.

```typescript
//Argument of type 'number' is not assignable to parameter of type 'Second'.
setRedisEntry('foo', 'bar', 60)

//Argument of type 'Milisecond' is not assignable to parameter of type 'Second'.
//  Types of property 'variant' are incompatible.
//    Type 'Variant.MILISECOND' is not assignable to type 'Variant.SECOND'
setRedisEntry('foo', 'bar', TimeSafe.miliseconds(60))
```

## Supported intervals

time-safe supports the following interval types, exporting interfaces representing these types and providing factory functions for them on the time-safe object as well as `as<INTERVAL>()` methods on the instances of the Interval classes to convert between the interval objets and the underlying number of a given unit of time contained in it.
 - Milisecond
 - Second
 - Minute
 - Hour
 - Day
 - Week

It does not support months or years because they do not represent a fixed amount of time and thus are beyond the scope of this project.