
Security News
PodRocket Podcast: Inside the Recent npm Supply Chain Attacks
Socket CEO Feross Aboukhadijeh discusses the recent npm supply chain attacks on PodRocket, covering novel attack vectors and how developers can protect themselves.
@ministerjs/store
Advanced tools
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
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
).
npm install @ministerjs/store
# ou
pnpm add @ministerjs/store
# ou
yarn add @ministerjs/store
useStores
para evitar recriaçõesdebug: true
)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();
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));
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.
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
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)
// 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,
});
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
}
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
}
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(),
});
// 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() };
};
// 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 };
};
Certifique-se de ter instalado (peer dependencies):
pnpm add vue pinia
Versões sugeridas:
O pacote não inicializa o Pinia automaticamente; você ainda precisa chamar app.use(createPinia())
em sua aplicação.
Dentro do monorepo:
pnpm test --filter @ministerjs/store
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.get()
/ itens da lista fora de ações controladas se quiser padronizar logs.useStores
foi chamado; para um cache global, exporte a instância.UNLICENSED – Uso interno do MinisterJS Framework.
Este pacote faz parte do monorepo MinisterJS. Para contribuir:
pnpm install
pnpm test
packages/store/
pnpm build
Para mais informações, consulte o README principal do MinisterJS.
FAQs
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
We found that @ministerjs/store demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
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.
Security News
Socket CEO Feross Aboukhadijeh discusses the recent npm supply chain attacks on PodRocket, covering novel attack vectors and how developers can protect themselves.
Security News
Maintainers back GitHub’s npm security overhaul but raise concerns about CI/CD workflows, enterprise support, and token management.
Product
Socket Firewall is a free tool that blocks malicious packages at install time, giving developers proactive protection against rising supply chain attacks.