CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pinia

Intuitive, type safe and flexible Store for Vue

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

store-definition.mddocs/

Store Definition

Functions for defining stores with both composition API (setup function) and options API syntax, providing flexible patterns for different development preferences.

Capabilities

Define Store with Options API

Creates a store definition using the options API syntax with explicit state, getters, and actions properties.

/**
 * Creates a store definition using options API syntax
 * @param id - Unique identifier for the store
 * @param options - Store configuration with state, getters, and actions
 * @returns Store definition function that creates store instances
 */
function defineStore<
  Id extends string,
  S extends StateTree = {},
  G extends _GettersTree<S> = {},
  A = {}
>(
  id: Id,
  options: Omit<DefineStoreOptions<Id, S, G, A>, 'id'>
): StoreDefinition<Id, S, G, A>;

interface DefineStoreOptions<Id extends string, S extends StateTree, G extends _GettersTree<S>, A> {
  /** Unique store identifier */
  id: Id;
  /** Function that returns the initial state */
  state?: () => S;
  /** Object containing getter functions */
  getters?: G & _GettersTree<S>;
  /** Object containing action methods */
  actions?: A & _ActionsTree;
  /** Hydration function for SSR */
  hydrate?(storeState: UnwrapRef<S>, initialState: UnwrapRef<S>): void;
}

Usage Examples:

import { defineStore } from "pinia";

// Basic options store
const useCounterStore = defineStore("counter", {
  state: () => ({
    count: 0,
    name: "Counter",
  }),
  getters: {
    doubleCount: (state) => state.count * 2,
    displayName: (state) => `${state.name}: ${state.count}`,
  },
  actions: {
    increment() {
      this.count++;
    },
    setName(newName: string) {
      this.name = newName;
    },
    async fetchInitialData() {
      const response = await fetch("/api/counter");
      const data = await response.json();
      this.count = data.count;
    },
  },
});

// Store with complex state and getters
const useUserStore = defineStore("user", {
  state: () => ({
    users: [] as User[],
    currentUserId: null as string | null,
    loading: false,
  }),
  getters: {
    currentUser: (state) => 
      state.users.find(user => user.id === state.currentUserId),
    activeUsers: (state) => 
      state.users.filter(user => user.active),
    getUserById: (state) => {
      return (userId: string) => state.users.find(user => user.id === userId);
    },
  },
  actions: {
    async loadUsers() {
      this.loading = true;
      try {
        const users = await fetchUsers();
        this.users = users;
      } finally {
        this.loading = false;
      }
    },
    setCurrentUser(userId: string) {
      this.currentUserId = userId;
    },
  },
});

Define Store with Setup Function

Creates a store definition using the composition API syntax with a setup function that returns the store's reactive state, computed properties, and methods.

/**
 * Creates a store definition using composition API setup function
 * @param id - Unique identifier for the store
 * @param storeSetup - Setup function that defines the store logic
 * @param options - Additional options for the setup store
 * @returns Store definition function that creates store instances
 */
function defineStore<Id extends string, SS>(
  id: Id,
  storeSetup: () => SS,
  options?: DefineSetupStoreOptions<
    Id,
    _ExtractStateFromSetupStore<SS>,
    _ExtractGettersFromSetupStore<SS>,
    _ExtractActionsFromSetupStore<SS>
  >
): StoreDefinition<
  Id,
  _ExtractStateFromSetupStore<SS>,
  _ExtractGettersFromSetupStore<SS>,
  _ExtractActionsFromSetupStore<SS>
>;

interface DefineSetupStoreOptions<Id extends string, S extends StateTree, G, A> {
  /** Hydration function for SSR */
  hydrate?(storeState: UnwrapRef<S>, initialState: UnwrapRef<S>): void;
  /** Actions that should be serialized for devtools */
  actions?: Record<string, any>;
}

Usage Examples:

import { defineStore } from "pinia";
import { ref, computed } from "vue";

// Basic setup store
const useCounterStore = defineStore("counter", () => {
  // State (equivalent to state in options API)
  const count = ref(0);
  const name = ref("Counter");

  // Getters (equivalent to getters in options API)
  const doubleCount = computed(() => count.value * 2);
  const displayName = computed(() => `${name.value}: ${count.value}`);

  // Actions (equivalent to actions in options API)
  function increment() {
    count.value++;
  }

  function setName(newName: string) {
    name.value = newName;
  }

  async function fetchInitialData() {
    const response = await fetch("/api/counter");
    const data = await response.json();
    count.value = data.count;
  }

  // Return all state, getters, and actions
  return {
    count,
    name, 
    doubleCount,
    displayName,
    increment,
    setName,
    fetchInitialData,
  };
});

// Advanced setup store with complex logic
const useTaskStore = defineStore("tasks", () => {
  const tasks = ref<Task[]>([]);
  const filter = ref<"all" | "active" | "completed">("all");
  const loading = ref(false);

  // Computed properties
  const filteredTasks = computed(() => {
    switch (filter.value) {
      case "active":
        return tasks.value.filter(task => !task.completed);
      case "completed":
        return tasks.value.filter(task => task.completed);
      default:
        return tasks.value;
    }
  });

  const taskStats = computed(() => ({
    total: tasks.value.length,
    active: tasks.value.filter(t => !t.completed).length,
    completed: tasks.value.filter(t => t.completed).length,
  }));

  // Actions
  async function loadTasks() {
    loading.value = true;
    try {
      const response = await fetch("/api/tasks");
      tasks.value = await response.json();
    } finally {
      loading.value = false;
    }
  }

  function addTask(title: string) {
    tasks.value.push({
      id: Date.now().toString(),
      title,
      completed: false,
      createdAt: new Date(),
    });
  }

  function toggleTask(id: string) {
    const task = tasks.value.find(t => t.id === id);
    if (task) {
      task.completed = !task.completed;
    }
  }

  function setFilter(newFilter: typeof filter.value) {
    filter.value = newFilter;
  }

  return {
    // State
    tasks: readonly(tasks),
    filter,
    loading,
    // Getters
    filteredTasks,
    taskStats,
    // Actions
    loadTasks,
    addTask,
    toggleTask,
    setFilter,
  };
});

Setup Store with Options

Setup stores can include additional options for hydration and action configuration.

const useAdvancedStore = defineStore("advanced", () => {
  const data = ref<any>(null);
  
  function updateData(newData: any) {
    data.value = newData;
  }

  return { data, updateData };
}, {
  // Custom hydration logic for SSR
  hydrate(storeState, initialState) {
    storeState.data = initialState.data;
  },
});

Store Definition Types

type StoreDefinition<Id extends string = string, S extends StateTree = {}, G = {}, A = {}> = 
  () => Store<Id, S, G, A>;

type _GettersTree<S extends StateTree> = Record<
  string,
  ((state: UnwrapRef<S> & UnwrapRef<PiniaCustomStateProperties>) => any) | (() => any)
>;

type _ActionsTree = Record<string, _Method>;

type _Method = (...args: any[]) => any;

// Extraction types for setup stores
type _ExtractStateFromSetupStore<SS> = SS extends undefined | void
  ? {}
  : _ExtractStateFromSetupStore_Keys<SS> extends keyof SS
  ? Pick<SS, _ExtractStateFromSetupStore_Keys<SS>>
  : never;

type _ExtractGettersFromSetupStore<SS> = SS extends undefined | void
  ? {}
  : _ExtractGettersFromSetupStore_Keys<SS> extends keyof SS
  ? Pick<SS, _ExtractGettersFromSetupStore_Keys<SS>>
  : never;

type _ExtractActionsFromSetupStore<SS> = SS extends undefined | void
  ? {}
  : _ExtractActionsFromSetupStore_Keys<SS> extends keyof SS
  ? Pick<SS, _ExtractActionsFromSetupStore_Keys<SS>>
  : never;

Install with Tessl CLI

npx tessl i tessl/npm-pinia

docs

index.md

options-api.md

pinia-instance.md

store-definition.md

store-usage.md

tile.json