Skip to content

Releases: riccardoperra/statebuilder

statebuilder@0.6.1

20 Oct 16:58
Compare
Choose a tag to compare

Patch Changes

  • 46892dd: add before event to command plugin

statebuilder@0.6.0

08 Nov 21:36
Compare
Choose a tag to compare

Minor Changes

  • 3ce5a15: - States will now get resolved using their Container reactive context instead of the context where they are defined.
    • Errors thrown through the state lifecycle will return a StateBuilderError class.
    • Add the remove method to the Container API to destroy a state
    • Add container hierarchy
    • Export ɵdefineResource andɵWithResourceStorage state resource API

statebuilder@0.5.0

22 Oct 18:11
Compare
Choose a tag to compare

Minor Changes

  • 8d627ba: feat: allow to inject states inside builders

    Since this version, you can inject other states into plugins (.extend).

    const AppState = defineSignal(() => ({}));
    
    const CounterState = defineSignal(() => 1).extend((_, context) => {
      const appState = context.inject(AppState);
    });

statebuilder@0.4.3

07 Oct 12:41
f9343c8
Compare
Choose a tag to compare

Patch Changes

  • 01b51ae: rework on commands devtools
  • ba05d21: improve state commands memory usage

statebuilder@0.4.2

16 Apr 10:46
57e9865
Compare
Choose a tag to compare

What's Changed

  • missing esm exports in statebuilder package

Full Changelog: https://github.com/riccardoperra/statebuilder/compare/statebuilder@0.4.0...statebuilder@0.4.2

statebuilder@0.4.1

16 Apr 10:31
Compare
Choose a tag to compare

What's Changed

  • fix: refactor command listener with @solid-primitives/event-bus by @riccardoperra in #23

Full Changelog: https://github.com/riccardoperra/statebuilder/compare/statebuilder@0.4.0...statebuilder@0.4.1

statebuilder@0.4.0

02 Apr 14:27
f5fb9eb
Compare
Choose a tag to compare

What's new

State plugin hooks - #20

With statebuilder@0.4.0, the core system will now support some initialization hooks under the hood:

  • onInit: it runs when your store state initialises, after all given plugins have been applied.
  • onDestroy: it runs when the reactive owner is disposed.

You can access these hooks while creating a plugin or while defining a store extension through the .extend() method. Hooks are basically registered callbacks in a queue system and they will be applied in order.

const myPlugin = makePlugin((state, context) => {

  context.hooks.onInit(() => console.log('run on state init'));
  context.hooks.onDestroy(() => console.log('run on state destroy'));

}, { name: 'myPlugin' });

createRoot(dispose => {
  const container = Container.create(); 

  const CountState = defineSignal(() => 0)
    .extend(myPlugin);

  const count = container.get(CountState);
  // ✅ onInit hook will run
  container.get(CountState);
 // ❌ onInit hook will not run anymore: state is already initialised

 dispose();
 // ✅ onDestroy hook will run
})

State support for solid-js createResource - #22

This new version add support for creating StateBuilders state definitions using solid-js createResource under the hood. It's now marked as experimental feature.

The state built with this new api will return basically a Resource which uses the mutate function under the hood as store setter. It acts like a wrapper but with the support of StateBuilder plugin extension and hook system.

import { experimental__defineResource } from 'statebuilder';

const TodoAsyncState = experimental__defineResource(
  () => fetch('https://jsonplaceholder.typicode.com/todos/1').then(response => response.json())
).extend(() => {
  // ...
});

const todoState = container.get(TodoAsyncState);
//    ˆ? todoState: Resource<Todo> & { set: Setter<Todo>, refetch(init?: unknown): void }

statebuilder/commands drop support for RxJS - #17

Since this version, the commandplugin will not use anymore RxJS to handle the command event state. Instead, it will use directly the solid-js signal based system.

Since Solid handle signals like RxJS BehaviorSubject, and the previous implementation had an attached Subject under the hood, the code for watching the commands events should change.

Since the watchCommand method will now return an Accessor<Command> instead of a BehaviorSubject, In order to avoid to run the callback before receiving your watched commands, you can mix the createEffect with the on utility.

Before:

interface Commands { 
  add: number; 
}

const CountStore = defineSignal(() => 0)
  .extend(withProxyCommands<Commands>())
  .extend(state => {
    const watch$ = state.watchCommand([state.commands.add]);
    //    ˆ?  watch$: Observable<StateCommand<'add', number>>
    watch$.subscribe((x) => console.log(x))
  })

After:

import {createEffect, on} from 'solid-js'; 

interface Commands { 
  add: number; 
}

const CountStore = defineSignal(() => 0)
  .extend(withProxyCommands<Commands>())
  .extend(state => {
    const watched = state.watchCommand([state.commands.add]);
    //    ˆ?  watched: Accessor<StateCommand<'add', number>>
    
   createEffect(on(watched, command => { 
     console.log(command);
   }))
  })

What's Changed

Full Changelog: https://github.com/riccardoperra/statebuilder/compare/statebuilder@0.3.1...statebuilder@0.4.0

statebuilder@0.3.1

05 Mar 14:24
f4ad02d
Compare
Choose a tag to compare

Patch Changes

  • 16fffae: perf: improve type resolution performance

statebuilder@0.3.0

25 Feb 21:14
3022018
Compare
Choose a tag to compare

Breaking changes

This new version removes withPlugin introduced in 0.2.4. Instead, now plugins will infer automatically the type, and uses a generic signatureby default.

const store = defineSignal(() => 1).extend(
  withProxyCommands<{increment: boolean}>())
);

store.hold(
  store.commands.increment, 
  (command, { set }) => {
  // ✅ Now `set` is Setter<number> instead of (...args: any) => void
  set(v => v + 1);
});

Create plugins with store constraints

In order to create plugins that must follow a specific store signature, you can now use the .typed helper of makePlugin function.

const pluginOnlyForStoreLike = () => makePlugin.typed<Store<{ count: number }>>()(store => {
  // ...
});

// ❌ pluginOnlyForStoreLike cannot be used anymore since store does not follow the { count : number } state signature
const store1 = defineStore(0).extend(pluginOnlyForStoreLike())

What's Changed

  • feat: refactor types for implicit inference by @riccardoperra in #13
  • chore: update versions by @github-actions in #14

Full Changelog: https://github.com/riccardoperra/statebuilder/compare/statebuilder@0.2.4...statebuilder@0.3.0

statebuilder@0.2.4

07 Feb 21:47
6fc3be2
Compare
Choose a tag to compare

What's Changed

Better store typings with store context

This new version introduces withPlugin, a new utility that can be used to be able to type plugins with the current store, instead of the GenericStoreApi alias. This can be useful when some generic plugins uses the get/setter store api and take advanted of its types to create derived properties

import {defineSignal, withPlugin} from 'statebuilder';
import {withProxyCommands} from 'statebuilder/commands';

const store = defineSignal(() => 1).extend(
  withPlugin((ctx) =>
    withProxyCommands.of(ctx).with<{ increment: boolean }>(),
  ),
);

store.hold(
  store.commands.increment, 
  (command, { set }) => {
  // ✅ Now `set` is Setter<number> instead of (...args: any) => void
  set(v => v + 1);
});

Full Changelog: https://github.com/riccardoperra/statebuilder/compare/statebuilder@0.2.3...statebuilder@0.2.4