npm package: @qix-js/core
Description: ## Cool Features
Latest version: 0.0.10

# Qix-js: A Lightweight Atomic-CQRS based State Management Library

## Cool Features

- Atomic state management coupled with CQRS principles.
- Minimal syntax, too short!
- Framework Agnostic.
- Automatic naming of commands/queries using ASTs.
- SSR-friendly listening with minimal renders.
- Synchronous state!
- Different types of queries to suit your needs.
- Command limiting & easy feature flagging.
- Super TypeScript friendly API!

## Why Qix-js?

I got hooked on Canaan's scalability but wanted something simpler and faster to use. So, I created Qix-js - a compact version with shorter syntax and better TypeScript support.

## Core Concepts

Qix-js is inspired by:

- Atomic state management (like Jotai)
- CQRS (Command Query Responsibility Segregation)
- PubSub (Publishers & Subscribers)
- Abstract Syntax Trees (ASTs)

## A glimpse of the power of Qix-js

### Queries

A query is a read-only state.

```ts
import { q } from "qix-js";

const count = q(0);
count.get(); // 0
```

### Commands

When a query is passed to a command, it will be its setter! Typescript support? YES!!

```ts
import { q, c } from "qix-js";

const count = q(0);
const setCount = c(count);

setCount(1);
count.get(); // 1
```

### Listening to Changes

With maximum render efficiency!

```ts
count.listen(value => {
  console.log(value); // Only called when set
});
```

### Map Queries

More memory efficient, more render efficient!

```ts
const state = q.map({ count: 0 });
const setState = c(state);

setState("count", 1); // Less overhead, more efficient!

setState({ count: 2 }); // You can still replace full object if needed.
```

### Derived Queries

Like a second version of a query, inherits all features!

```ts
const doubled = q.derived(count, value => value * 2);
```

### Commands as Actions

This unlocks missing powers in many state libraries, while imporving code distribution.

```ts
const command = c();

command.on(() => {
  // Action logic here
});

command();
```

Payload is also supported!

```ts
const greet = c<string>();

greet.on(payload => {
  // Action logic here, payload is string!
});

greet("Hello World!");
```

### Limiting Commands

Great for limiting users access to freemium features :)

```ts
const maxUses = 3;

command.enabled(
  ({ execs }) => execs <= maxUses,
  () => showUpgradeDialog()
);
```

### Feature Flagging

Great for limiting user access, whether for premium apps or AB tests :)

```ts
command.enabled(
  () => isFeatureEnabled(command.id),
  () => showUpgradeDialog()
);
```

### Automatic Naming

Thanks to ASTs, you don't need to manually name your commands. That will be automatically assigned based on your variable name.

```ts
const upgradeMembership = c();

upgradeMembership.id; // "upgradeMembership"
```

### Groups

Groups allow you to group commands and queries under one scope, they will also automatically prefix the name of your commands/queries with the group name,

```ts
const uikit = group();

const theme = uikit.q("light");
const setTheme = uikit.c(theme);

const fontSize = uikit.q(14);
const setFontSize = uikit.c(fontSize);

theme.id; // uikit-theme
fontSize.id; // uikit-fontSize
setTheme.id; // uikit-setTheme
setFontSize.id; // uikit-setFontSize
```

This is super helpful for tracking and leaves your commands self-documented with zero extra effort!

## Watching Commands and Groups

You can watch commands to trigger a callback of your choice.

```ts
const upgrade = c();

watch(upgrade, ({ id }, payload) => {
  console.log(`'${id}' called!`); // 'upgrade' called!
});
```

You can do the same with groups and it will automatically watch all of the group commands for you!

```ts
const uikit = group();
const setTheme = uikit.c<"light" | "dark">();
const setFontSize = uikit.c<number>();

watch(uikit, ({ id }, payload) => {
  console.log(`'${id}' called!`); // 'uikit-setTheme' called!
  // 'uikit-setFontSize' called!
});

setTheme("light");
setFontSize(14);
```

That's it! Qix-js gives you powerful state management without any sign of complexity!