Skip to content

CatOfJupit3r/lystore

Lystore Logo

Lystore - listeners, which actually listen!


npm package Downloads Semantic Release

Build Status Issues


Lystore is a TypeScript-first library built for creating modular event emitters/listener pattern stores. Lystore provides you with an easy way to create fully type-safe stores with a very versatile API

Usage

There are 2 ways to use Lystore, both provide the same results. If you need a more in-depth explanation, please read the API wiki (although Lystore provides a very in-depth JSDoc documentation) or if you want to see examples, please check out the examples wiki

Same File Stores

Using this approach, you declare your listener store and types for it in the same file. This is the easiest approach ( and one that you could write yourself, but we listen and don't judge).

/user.store.ts
import { type StrictRegistry, StrictStore } from 'lystore';

const ALLOWED_EVENTS = {
    'user:login': 'user:login',
    'user:registration': 'user:registration',
} as const;

type UserEvents = typeof ALLOWED_EVENTS[keyof typeof ALLOWED_EVENTS];

export interface UserRegistry extends StrictRegistry<UserEvents> {
    'user:login': { userId: string, date: Date };
    'user:registration': { username: string, email: string, password: string };
}

const store = new StrictStore<
    UserEvents,
    UserRegistry
>(ALLOWED_EVENTS);

export default store;

Now, you can import this store wherever and your .on() and .notify() will all have provided type-hints with respect to your registry

/some-other-place.ts
import store from './user.store';

store.on('user:login', ({ userId, date }) => {
    console.log(`userId AND date are fully typed!`);
});

store.on('user:logout', (props) => {
    // TS2345: Argument of type 'some-unknown-event' is not assignable to parameter of type keyof UserRegistry
    // StrictStoreKeyCheckFailError: [STRICT STORE] "on" encountered unknown event: user:logout
});

Multi-files of Madness

But let's be honest, we like to separate our types from our store declarations, right? But don't worry, Lystore got you covered!

/user-store/store.ts
import { type StrictRegistry, StrictStore } from 'lystore';

export const ALLOWED_EVENTS = {
    'USER_CREATED': 'USER_CREATED',
    'USER_LOGGED_IN': 'USER_LOGGED_IN',
    'USER_LOGGED_OUT': 'USER_LOGGED_OUT',
} as const;

export type UserEvents = typeof ALLOWED_EVENTS[keyof typeof ALLOWED_EVENTS];

export interface UserRegistry extends StrictRegistry<UserEvents> {}

const store = new StrictStore<UserEvents, UserRegistry>(ALLOWED_EVENTS);

export default store;
/user-store/register.ts
import { StrictRegistry } from 'lystore';
import './store';

declare module './store' {
    export interface UserRegistry extends StrictRegistry<UserEvents> {
        USER_CREATED: {
            userId: string;
            timestamp: number;
        };
        USER_LOGGED_IN: {
            userId: string;
            timestamp: number;
        };
        USER_LOGGED_OUT: {
            userId: string;
            reason: string;
        };
    }
}
/user-store/index.ts
export { default as default, ALLOWED_EVENTS } from './store';
/some-other-place.ts
import userStore, { ALLOWED_EVENTS } from './user-store';

userStore.on(ALLOWED_EVENTS.USER_CREATED, ({ userId, timestamp }) => {
    console.log('Account created:', userId, timestamp);
});

userStore
    .notify(ALLOWED_EVENTS.USER_CREATED, {
        userId: '123',
        timestamp: Date.now(),
    })
    .then(() => console.log('Notification sent!'));
userStore.on('some-unknown-event', () => {
    // TS2345: Argument of type 'some-unknown-event' is not assignable to parameter of type keyof UserRegistry
    // StrictStoreKeyCheckFailError: [STRICT STORE] "on" encountered unknown event: some-unknown-event
});

About

TypeScript-first library for creating type-safe listener stores

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks