npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-composable-store

v0.1.3

Published

Vue composable store

Downloads

4

Readme

npm downloads Conventional Commitscoverage Coverage badge

Vue composable store

The original idea was spoilered in a video about Vuex 5 draft by the maker (Kia King Ishii). I never liked the current syntax, but this new API made me to want to use it ASAP. So I started to implement it, for fun and for internal use in some hobby project.

It's not supposed to be a replacement of Vuex. It's just a fun project for me.

Currently its pretty lightweight: 1.26 KB minified (625 byte Gzipped) - with stripped asserts

It's supports plugins, app-scoped stores and TypeScript.

Do NOT use it in production environment. It's under continuous refactor, and as soon as Vuex 5 released it's will be useless anyway.

Peer dependencies

  • Vue 3.0 or higher

Installation

npm i vue-composable-store

NOTE: There is a "hidden" production build in the dist folder which is ~30% smaller due to stripped asserts.

import { createVueStore } from 'vue-composable-store/dist/index-prod-es.js';

Usage

The Options API not supported!

defineStore() - the way you define your store

import { readonly, reactive, ref, computed } from 'vue';
import { defineStore } from 'vue-store';

export default defineStore('shop', () => {
    // state
    const list = reactive([]);
    const page = ref(1);
    const limit = ref(20);
    
    // actions
    const hasNext = computed(() => {
        return list.length === limit;
    });  
    
    async function load(page) {
        // ...fetch data into `list`...
        page.value = page;
    }
    
    // final store object
    return {
        hasNext,
        list: readonly(list), // <---- in case you do not want it to be modifiable from outside
        page, 
        load
    };
});

use() - the way you compose stores (replacement for store modules)

import { readonly, reactive, ref, computed } from 'vue';
import { defineStore } from 'vue-store';

// imported just in the component which using the store,
// so it's can be properly code-splitted/tree-shaken, etc
import cartStore from './stores/cart';

export default defineStore('shop', ({ use }) => {
    // state
    const products = reactive([]);
    
    async function load(page) {
        // ...fetch data into `list`...
        page.value = page;
    }
    
    // final store object
    return {
        cart: use(cartStore), // <--- store composition instead of store modules
        products,
        load
    };
});

useStore() - the way you access your store in components

import { defineComponent } from 'vue';
import { useStore } from 'vue-composable-store';
import productsStore from './stores/products';

export default defineComponent({
    name: 'ProductList',
    setup() {
        // the store lazy initialized on the first use
        const { load, list, hasNext } = useStore(productsStore); 
        
        load(1);
        
        return {
            list, 
            hexNext
        };
    }
});

createStore() - how you connect it to your app

import { createApp } from 'vue';
import { createVueStore } from 'vue-composable-store';
import App from './App.vue';

const store = createVueStore();

const app = createApp(App);
app.use(store);
app.mount('#el');

Plugins

Plugins was not really explained in the video (outside of the provide function) so the hooks bellow are my own implementation and will be different in Vuex 5

Providing your plugin

Plugins can provide utility function or data object to be exposed in the storeContext.

// api-plugin.js
export default (provide) => {
    provide('api', (uri) => fetch(`https://localhost:5000/${uri}`));
}


// app.js
import { createApp } from 'vue';
import { createVueStore } from 'vue-composable-store';
import apiPlugin from './api-plugin.js';
import App from './App.vue';

const options = { plugins: [ apiPlugin ] };
const vueStore = createVueStore(options);
const app = createApp(App);
app.use(vueStore); 
// optionally you can pass the `options` at the app.use() too
// in this case the plugin list will be overridden
// app.use(vueStore, options)


// my-store.js
export default defineStore(('my-store', ({ api }) => { // <-- `api` in the context
    // you can use your api() plugin here... 
    return {};
}));

Hooks

The usable hooks are passed in the second argument of the plugin.

// my-plugin.js
export default function myPlugin(provide, hooks) => { /* plugin code */};

The first two arguments passed to the callback functions are always:

  • The name of the store which triggered the callback
  • The storeInstance contains the exact object which is returned from the initializer function passed to defineStore().

onUse(callback: (storeName, storeInstance, context) => void)

Called every time a store is being accessed by the useStore() or composed via use().

The context is the same as in the defineStore , you can use it to access or detect other plugins

Example:

// my-store-logger.js
export default function logger(provide, { onUse }) {
    onUse((name, instance, context) => {
        console.log(`Used: "${name}"`);
    });
}

onInitialized(callback: (storeName, storeInstance, context) => void)

Called once per store per app after the first time usage of useStore() or composed via use()

// my-store-logger.js
export default function logger(provide, { onInitialized }) {
    onInitialized((name, instance, context) => {
        console.log(`[Initialized] Store name: "${name}"`);
    });
}

onAction(callback: (storeName, storeInstance, actionName, actionArgs, actionResult, context) => void)

Called after a store function invoked.

// my-store-logger.js
export default function logger(provide, { onAction }) {
    onAction((name, instance, action, actionArgs, actionResult, context) => {
        console.log(`[Action invoked] Store action: "${name}.${action}"`);
        console.log(`  args: ${actionArgs.map(JSON.stringify).join(', ')}`)
        console.log(`  return value: ${JSON.stingify(actionResult)}`);
    });
}

onMutated(callback: (storeName, storeInstance, stateKey, value, oldValue, context) => void)

Called when any watchable store property mutated (the value changed).

// my-store-logger.js
export default function logger(provide, { onMutated }) {
    onMutated((name, instance, key, newValue, oldValue, context) => {
        const oldJSON = JSON.encode(oldValue);
        const newJSON = JSON.encode(newValue);
        console.log(`[State mutated] "${name}.${key}" is being mutated from ${oldJSON} to ${newJSON}`);
    });
}

Changelog

See the CHANGELOG.md

License

Copyright © 2020 Kövesdi György

Licensed under the MIT License.