Introducing Socket Firewall: Free, Proactive Protection for Your Software Supply Chain.Learn More
Socket
Book a DemoInstallSign in
Socket

@ministerjs/store

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ministerjs/store

Gerenciamento de estado opinado para Vue 3 + Pinia com foco em simplicidade, tipagem forte e reutilização. Fornece factories para **ItemStore** (estado de um único objeto) e **TableStore** (coleções) além de um gerenciador com **cache inteligente** (`useS

latest
npmnpm
Version
2.0.4
Version published
Maintainers
1
Created
Source

@ministerjs/store

Gerenciamento de estado opinado para Vue 3 + Pinia com foco em simplicidade, tipagem forte e reutilização. Fornece factories para ItemStore (estado de um único objeto) e TableStore (coleções) além de um gerenciador com cache inteligente (useStores).

📦 Instalação

npm install @ministerjs/store
# ou
pnpm add @ministerjs/store
# ou
yarn add @ministerjs/store

🚀 Funcionalidades

  • ItemStore: Estado de um item único (perfil, configurações, sessão...)
  • TableStore: Coleções (listas, tabelas, catálogos) com utilidades frequentes
  • Cache inteligente via useStores para evitar recriações
  • Tipagem 100% (inferência de chaves, primary key, partial updates)
  • Pinia under the hood: integra DevTools sem esforço
  • Debug logging opcional (debug: true)
  • APIs mínimas e coesas: apenas o que é realmente usado no dia a dia

📖 Uso Básico

ItemStore – Gerenciando um item único

import { createItemStore } from "@ministerjs/store";

interface UserProfile {
  id: number;
  name: string;
  email: string;
  avatar?: string;
}

// Criando o store
const useUserProfile = createItemStore<UserProfile>({
  displayName: "User Profile",
  initialState: { name: "", email: "" },
  debug: true,
});

// Usando no componente Vue
const { get, set, update, clear } = useUserProfile();

// Estado reativo
const profile = get();
console.log(profile.value.name); // Acesso reativo

// Definindo dados completos
set({ id: 1, name: "João", email: "joao@example.com" });

// Atualizando parcialmente
update({ name: "João Silva" });

// Limpando o estado
clear();

TableStore – Gerenciando coleções

import { createTableStore } from "@ministerjs/store";

interface User {
  id: number;
  name: string;
  email: string;
  active: boolean;
}

// Criando o store
const useUsersStore = createTableStore<User, "id">({
  primaryKey: "id",
  displayName: "Users Store",
  initialState: [],
  debug: true,
});

// Usando no componente Vue
const store = useUsersStore();

// Adicionando itens
store.add({ id: 1, name: "João", email: "joao@example.com", active: true });
store.add({ id: 2, name: "Maria", email: "maria@example.com", active: false });

// Buscando por ID
const user = store.get(1);

// Listando todos (reativo)
const allUsers = store.list();

// Busca por propriedade personalizada
const activeUser = store.getByProperty("email", "joao@example.com");

// Atualizando
store.update(1, { name: "João Silva" });

// Removendo
store.remove(1);

// Substituindo toda a coleção
store.replaceAll([
  { id: 3, name: "Pedro", email: "pedro@example.com", active: true },
]);

// Lista computada com transformação
const activeUsers = store.computedList((users) =>
  users.value.filter((u) => u.active),
);

// Ordenação
const sortedUsers = store.sort((a, b) => a.name.localeCompare(b.name));

🏗️ Gerenciamento Avançado com useStores

O composable useStores centraliza criação e cache de múltiplos stores. Ele exige que você informe as factories padrão (createItemStore, createTableStore) uma única vez.

1. Uso Dinâmico (on-demand)

import {
  useStores,
  createItemStore,
  createTableStore,
} from "@ministerjs/store";

// Passamos `undefined` para o primeiro argumento (não há pré-configuração)
const { generateItem, generateTable, getCacheSize } = useStores(undefined, {
  createItemStore,
  createTableStore,
});

console.log(getCacheSize()); // { items: 0, tables: 0 }

// Cria e cacheia um ItemStore
const userProfile = generateItem<UserProfile>("profile", {
  debug: true,
  initialState: { name: "", email: "" },
});

// Cria e cacheia um TableStore (primaryKey padrão = "id")
const usersTable = generateTable<User>("users", {
  primaryKey: "id", // opcional; se omitido usa 'id'
  debug: true,
});

// Reutiliza do cache
const profileAgain = generateItem("profile"); // Missão cumprida: cache hit

2. Stores Pré-configurados

import {
  useStores,
  createItemStore,
  createTableStore,
} from "@ministerjs/store";

// Definições lazy (cada função só roda uma vez)
const stores = useStores(
  {
    users: () =>
      createTableStore<User>({ primaryKey: "id", displayName: "Users" }),
    profile: () =>
      createItemStore<UserProfile>({ displayName: "Profile", debug: true }),
    settings: () =>
      createItemStore<AppSettings>({
        displayName: "App Settings",
        initialState: { theme: "light", language: "pt-BR" },
      }),
  },
  {
    createItemStore,
    createTableStore,
  },
);

const userStore = stores.get("users"); // primeira chamada instancia
const userStoreAgain = stores.get("users"); // cache hit
console.log(stores.getCacheSize()); // { items: 2, tables: 1 } (exemplo)

3. Integração Rápida em uma App Vue

// main.ts
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";

const app = createApp(App);
app.use(createPinia());
app.mount("#app");

// Em qualquer composable
import {
  useStores,
  createItemStore,
  createTableStore,
} from "@ministerjs/store";
export const stores = useStores(undefined, {
  createItemStore,
  createTableStore,
});

🔧 API Reference

ItemStore Interface

interface ItemStore<T> {
  get(): Ref<Partial<T>>; // Estado reativo
  set(item: Partial<T>): void; // Define dados completos
  update(data: Partial<T>): void; // Atualização parcial
  clear(): void; // Limpa o estado
}

TableStore Interface

interface TableStore<T, PK> {
  add(data: T): void; // Adiciona item
  get(primaryKey: T[PK]): T | undefined; // Busca por ID
  list(): T[]; // Lista todos os itens
  computedList<R>(callback: (items: Ref<T[]>) => R): Ref<R>; // Lista computada
  getByProperty<K>(key: K, value: T[K]): T | undefined; // Busca por propriedade
  update(primaryKey: T[PK], data: Partial<T>): void; // Atualiza item
  remove(primaryKey: T[PK]): boolean; // Remove item
  replaceAll(data: T[]): void; // Substitui todos
  sort(callback: (a: T, b: T) => number): T[]; // Ordena itens
}

Opções de Configuração

interface CreateItemStoreOptions<T> {
  displayName?: string; // Nome para DevTools
  initialState?: T; // Estado inicial
  debug?: boolean; // Logs de debug
}

interface CreateTableStoreOptions<T, PK> {
  primaryKey?: PK; // Chave primária (default: 'id')
  displayName?: string; // Nome para DevTools
  initialState?: T[]; // Estado inicial
  debug?: boolean; // Logs de debug
}

### useStores

```typescript
// Sem stores pré-configurados
useStores(undefined, {
  createItemStore,
  createTableStore,
});

// Com stores pré-configurados
useStores({
  users: () => createTableStore<User>({ primaryKey: 'id' }),
  profile: () => createItemStore<UserProfile>({}),
}, {
  createItemStore,
  createTableStore,
});

Métodos retornados:

generateItem(key, options?) // Cria ou retorna ItemStore cacheado
generateTable(key, options?) // Cria ou retorna TableStore cacheado
get(key) // Quando configurado com objeto de setups
getCacheSize() // { items, tables }

## 🏆 Boas Práticas

### 1. Organização de Stores

```typescript
// stores/user.ts
export const useUserProfile = createItemStore<UserProfile>({
  displayName: "User Profile",
});

export const useUsers = createTableStore<User, "id">({
  primaryKey: "id",
  displayName: "Users",
});

// stores/index.ts
export const stores = useStores({
  userProfile: () => useUserProfile(),
  users: () => useUsers(),
});

2. Composables Especializados

// composables/useAuth.ts
export const useAuth = () => {
  const profile = stores.get("userProfile");

  const login = async (credentials: LoginData) => {
    const user = await authService.login(credentials);
    profile.set(user);
  };

  const logout = () => {
    profile.clear();
  };

  return { login, logout, profile: profile.get() };
};

3. Integração com APIs

// composables/useUsersApi.ts
export const useUsersApi = () => {
  const store = stores.get("users");

  const fetchUsers = async () => {
    const users = await api.get<User[]>("/users");
    store.replaceAll(users);
  };

  const createUser = async (userData: Omit<User, "id">) => {
    const user = await api.post<User>("/users", userData);
    store.add(user);
    return user;
  };

  return { fetchUsers, createUser, store };
};

🔗 Dependências & Peer Deps

Certifique-se de ter instalado (peer dependencies):

pnpm add vue pinia

Versões sugeridas:

  • Vue >= 3.5
  • Pinia >= 2.0
  • TypeScript >= 5

O pacote não inicializa o Pinia automaticamente; você ainda precisa chamar app.use(createPinia()) em sua aplicação.

🧪 Testes

Dentro do monorepo:

pnpm test --filter @ministerjs/store

⚠️ Notas & Gotchas

  • primaryKey em createTableStore é opcional (default "id").
  • generateItem e generateTable não recebem a factory como argumento (a factory é injetada uma vez em useStores).
  • computedList recebe um callback que recebe um Ref<T[]> e retorna um valor derivado reativo.
  • Evite mutar diretamente objetos retornados por get() / itens da lista fora de ações controladas se quiser padronizar logs.
  • O cache vive no escopo onde useStores foi chamado; para um cache global, exporte a instância.

📄 Licença

UNLICENSED – Uso interno do MinisterJS Framework.

🤝 Contribuindo

Este pacote faz parte do monorepo MinisterJS. Para contribuir:

  • Clone o repositório principal
  • Instale as dependências: pnpm install
  • Execute os testes: pnpm test
  • Faça suas alterações no pacote packages/store/
  • Execute o build: pnpm build

Para mais informações, consulte o README principal do MinisterJS.

FAQs

Package last updated on 03 Sep 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts