orchestore 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,9 +25,9 @@ Stay tuned for updates.
25
25
 
26
26
  ## About
27
27
 
28
- > 🧩 A function-oriented state orchestration architecture built on top of Redux Toolkit.
28
+ > 🧩 A function-oriented state orchestration architecture built on top of Redux Toolkit, inspired by Vuex.
29
29
 
30
- OrcheStore simplifies and automates common state management patterns in React, Redux Toolkit, and TypeScript applications by unifying state and behavior into directly callable runtime modules.
30
+ OrcheStore brings a Vuex-inspired developer experience to React and Redux Toolkit applications by unifying state and behavior into directly callable runtime modules.
31
31
 
32
32
  Instead of distributing logic across reducers, actions, thunks, selectors, hooks, middleware, and utility files, OrcheStore organizes related functionality into cohesive slice modules.
33
33
 
@@ -35,133 +35,124 @@ The goal is simple:
35
35
 
36
36
  > ⚡ Spend less time wiring state management infrastructure and more time building application features.
37
37
 
38
- ## Table of Contents
38
+ ## Installation
39
39
 
40
- - [Introduction](#orchestore)
41
- - [Core Principles](#core-principles)
42
- - [Why OrcheStore?](#why-orchestore)
43
- - [Redux Toolkit Comparison](#redux-toolkit-comparison)
44
- - [Architecture Overview](#architecture-overview)
45
-
46
- - [Quick Example](#quick-example)
47
-
48
- - [Slice Layers](#slice-layers)
49
- - [name](#name)
50
- - [state](#state)
51
- - [Mutations](#mutations)
52
- - [Methods](#methods)
53
- - [Computed State (Planned)](#computed-state-planned)
54
- - [Nested Slices](#nested-slices)
55
- - [Reusing Slices](#reusing-slices)
56
- - [Runtime Paths](#runtime-paths)
57
-
58
- - [State Access & Subscriptions](#state-access--subscriptions)
59
- - [State Snapshots](#state-snapshots)
60
- - [State Subscriptions](#state-subscriptions)
61
- - [Draft State](#draft-state)
62
-
63
- - [Store Integration](#store-integration)
64
- - [Creating the Store](#creating-the-store)
65
- - [Store Provider](#store-provider)
66
- - [Accessing Slices through Store](#accessing-slices-through-store)
67
- - [Accessing Store from Slices](#accessing-store-from-slices)
68
- - [Root Store Type Extension (Planned)](#root-store-type-extension-planned)
69
-
70
- - [Lineage & Clones](#lineage--clones)
71
- - [Automatic Cloning](#automatic-cloning)
72
- - [Manual Cloning](#manual-cloning)
73
- - [Inspecting a Lineage](#inspecting-a-lineage)
74
- - [Definition Type Checking](#definition-type-checking)
75
-
76
- - [Global Utilities](#global-utilities)
77
- - [Accessing Global Utilities](#accessing-global-utilities)
78
- - [Utilities Type Extension](#utilities-type-extension)
79
- - [Providing Runtime Utilities](#providing-runtime-utilities)
80
- - [Using Global Utilities in Slices](#using-global-utilities-in-slices)
81
-
82
- - [TypeScript Inference](#typescript-inference)
83
-
84
- - [Status](#status)
40
+ With npm:
85
41
 
86
- ---
42
+ ```bash
43
+ npm install orchestore
44
+ ```
87
45
 
88
- ## Core Principles
46
+ Or with Yarn:
89
47
 
90
- - Simplify state management architecture
91
- - Automate repetitive Redux patterns
92
- - Reduce infrastructure code
93
- - Centralize state and application logic
94
- - Provide direct and intuitive APIs
95
- - Preserve predictable state transitions
96
- - Maintain strong TypeScript inference
97
- - Scale naturally through composition
48
+ ```bash
49
+ yarn add orchestore
50
+ ```
98
51
 
99
- ## Why OrcheStore?
52
+ Or with pnpm:
100
53
 
101
- Redux Toolkit significantly improves the Redux developer experience, but many applications still require developers to coordinate logic across multiple concepts:
54
+ ```bash
55
+ pnpm add orchestore
56
+ ```
57
+
58
+ **Peer Dependencies**
102
59
 
103
- - reducers
104
- - action creators
105
- - thunks
106
- - selectors
107
- - middleware
108
- - hooks
109
- - utility functions
60
+ OrcheStore requires:
110
61
 
111
- As applications grow, state management often becomes less about solving business problems and more about connecting infrastructure.
62
+ * React 16.9+
63
+ * React DOM 16.9+
112
64
 
113
- OrcheStore reduces that coordination overhead by exposing state management through unified slice modules.
65
+ **Included Dependencies**
114
66
 
115
- A slice is more than a state container. It is a runtime module that can encapsulate:
67
+ `@reduxjs/toolkit` and `react-redux` are installed automatically with OrcheStore.
116
68
 
117
- - state
118
- - computed state
119
- - mutations
120
- - methods
121
- - selectors
122
- - child slices
123
- - shared utilities
69
+ ## Table of Contents
124
70
 
125
- This allows state and application logic to evolve together within the same domain boundary.
71
+ * [Introduction](#orchestore)
72
+ * [Installation](#installation)
73
+ * [Core Principles](#core-principles)
74
+ * [Why OrcheStore?](#why-orchestore)
75
+ * [Architecture Overview](#architecture-overview)
76
+
77
+ * [Quick Example](#quick-example)
78
+
79
+ * [Slice Layers](#slice-layers)
80
+ * [name](#name)
81
+ * [state](#state)
82
+ * [Mutations](#mutations)
83
+ * [Methods](#methods)
84
+ * [Computed State (Planned)](#computed-state-planned)
85
+ * [Nested Slices](#nested-slices)
86
+ * [Accessing Children through Parent Slice](#accessing-children-through-parent-slice)
87
+ * [Accessing Parent Slice from Children](#accessing-parent-slice-from-children)
88
+ * [Reusing Slices](#reusing-slices)
89
+ * [Runtime Paths](#runtime-paths)
90
+
91
+ * [State Access & Subscriptions](#state-access--subscriptions)
92
+ * [State Snapshots](#state-snapshots)
93
+ * [State Subscriptions](#state-subscriptions)
94
+ * [Draft State](#draft-state)
95
+
96
+ * [Store Integration](#store-integration)
97
+ * [Creating the Store](#creating-the-store)
98
+ * [Store Provider](#store-provider)
99
+ * [Accessing Slices through Store](#accessing-slices-through-store)
100
+ * [Accessing Store from Slices](#accessing-store-from-slices)
101
+
102
+ * [Lineage & Clones](#lineage--clones)
103
+ * [Manual Cloning](#manual-cloning)
104
+ * [Automatic Cloning](#automatic-cloning)
105
+ * [Inspecting a Lineage](#inspecting-a-lineage)
106
+ * [Definition Type Checking](#definition-type-checking)
107
+
108
+ * [Utilities](#utilities)
109
+ * [Accessing Utilities](#accessing-utilities)
110
+ * [Utilities Type Extension](#utilities-type-extension)
111
+ * [Providing Runtime Utilities](#providing-runtime-utilities)
112
+ * [Using Utilities in Slices](#using-utilities-in-slices)
113
+
114
+ * [TypeScript Inference](#typescript-inference)
115
+
116
+ * [Status](#status)
117
+
118
+ ---
126
119
 
127
- Many common Redux patterns are automated by default:
120
+ ## Core Principles
128
121
 
129
- | Traditional Redux Pattern | OrcheStore |
130
- | ----------------------------- | ----------------------------------------------- |
131
- | Action creators | Direct callable mutations |
132
- | Thunks | Built-in methods |
133
- | Dispatch calls | Direct function calls |
134
- | `PayloadAction` wrappers | Native function arguments |
135
- | Cross-slice imports | Root store access |
136
- | Shared service wiring | Global utilities |
137
- | Manual state tree composition | Nested slices with automatic cloning & isolation |
138
- | Complex type declarations | Automatic inference |
139
- | Instance identity management | Lineage-based slice model (shared definition, isolated mounts) |
122
+ * Simplify state management architecture
123
+ * Automate repetitive Redux patterns
124
+ * Reduce infrastructure code
125
+ * Centralize state and application logic
126
+ * Provide direct and intuitive APIs
127
+ * Preserve predictable state transitions
128
+ * Maintain strong TypeScript inference
129
+ * Scale naturally through composition
140
130
 
141
- The result is a simpler architecture with fewer moving parts, less boilerplate, and a more direct development experience.
131
+ ## Why OrcheStore?
142
132
 
143
- Developers can focus on application behavior rather than framework plumbing.
133
+ Redux Toolkit greatly improves the Redux experience, but applications still often require developers to coordinate reducers, actions, selectors, thunks, hooks, utilities, and state composition.
144
134
 
145
- ## Redux Toolkit Comparison
135
+ OrcheStore builds on top of Redux Toolkit and combines these patterns into a unified slice model. A slice can encapsulate state, mutations, methods, computed values, child slices, and shared application utilities within a single module.
146
136
 
147
- OrcheStore builds on top of Redux Toolkit while providing a higher-level API for organizing state and behavior.
137
+ The goal is to reduce framework plumbing and allow application behavior to remain close to the state it operates on.
148
138
 
149
- | Feature | OrcheStore | Redux Toolkit |
150
- | ------------------------------ | ---------- | ------------- |
151
- | Multiple mutation arguments | | |
152
- | Direct callable mutations | | |
153
- | `PayloadAction` wrappers | | |
154
- | Dispatch required | | |
155
- | Built-in orchestration methods | | |
156
- | Nested slice composition | (isolated context) | ⚠️ Manual (shared state) |
157
- | Automatic path generation | | ⚠️ Manual |
158
- | Global utilities | | |
159
- | Unified slice API | ✅ | |
160
- | Per-slice React hooks | | ❌ |
161
- | Deep TypeScript inference | | ⚠️ Partial |
162
- | Lineage & cloning model | | |
139
+ | Concern | Redux Toolkit | OrcheStore |
140
+ | ------------------ | ---------------------------------------- | ----------------------------------------------- |
141
+ | State updates | Actions + dispatch | Direct callable mutations |
142
+ | Mutation arguments | `PayloadAction` wrappers | Native function arguments |
143
+ | Async logic | Separate thunks | Built-in methods |
144
+ | State selection | Global store selector hooks | Global + slice-scoped selection hooks |
145
+ | Cross-slice access | Imports & wiring | Runtime tree access (Root / Parent / Children) |
146
+ | Shared services | Manual integration | Application-wide utilities |
147
+ | State composition | Manual reducer composition | Nested slices |
148
+ | Identity model | Singleton-like slice definition | Lineage-based identity system |
149
+ | Instance reuse | Function-level reuse of slice reducers | Reused slices create isolated runtime instances |
150
+ | Cloning model | Factory pattern required for re-creation | Built-in cloning with lineage tracking |
151
+ | Exposed API | Reducers, actions and some helpers | Direct usable slice APIs |
152
+ | Type inference | Strong | Deep end-to-end inference |
153
+ | Developer focus | Connect infrastructure | Implement behavior |
163
154
 
164
- OrcheStore does not replace Redux Toolkit. Instead, it builds on top of it by automating common patterns and providing a more cohesive developer experience.
155
+ OrcheStore does not replace Redux Toolkit. It builds on top of it, providing a higher-level API for organizing state and application behavior with stronger automation of Redux patterns and reduced coordination overhead for developers.
165
156
 
166
157
  ## Architecture Overview
167
158
 
@@ -230,6 +221,15 @@ export const counter = createSlice({
230
221
  ```tsx
231
222
  import { createSlice, createAsyncThunk, type PayloadAction } from "@reduxjs/toolkit";
232
223
 
224
+ // Separate APIs for async workflows
225
+ export const incrementAfter = createAsyncThunk(
226
+ "counter/incrementAfter",
227
+ async ({ amount, delay }: { amount: number; delay: number }) => {
228
+ await new Promise((resolve) => setTimeout(resolve, delay));
229
+ return amount;
230
+ }
231
+ );
232
+
233
233
  export const counter = createSlice({
234
234
  name: "counter",
235
235
 
@@ -251,20 +251,14 @@ export const counter = createSlice({
251
251
  );
252
252
  },
253
253
  },
254
- });
255
-
256
- // Separate APIs for async workflows
257
- export const incrementAfter = createAsyncThunk(
258
- "counter/incrementAfter",
259
- async (
260
- { amount, delay }: { amount: number; delay: number },
261
- { dispatch }
262
- ) => {
263
- await new Promise((resolve) => setTimeout(resolve, delay));
264
254
 
265
- dispatch(counter.actions.increment(amount));
266
- }
267
- );
255
+ extraReducers: (builder) => {
256
+ // Handles fulfilled async thunk result
257
+ builder.addCase(incrementAfter.fulfilled, (state, action) => {
258
+ state.value += action.payload;
259
+ });
260
+ },
261
+ });
268
262
  ```
269
263
 
270
264
  ## Slice Usage
@@ -434,9 +428,8 @@ methods: {
434
428
 
435
429
  **Rules:**
436
430
 
437
- - Slice names should not contain `"."` or `"/"`, because dots are reserved for nested slice paths
431
+ - Names should not contain `"."` or `"/"`, because they are reserved for nested slice paths
438
432
  - Two slices cannot share the same name
439
- - Registering the same slice instance multiple times with the same name is not allowed
440
433
 
441
434
  ---
442
435
 
@@ -527,8 +520,10 @@ Methods are the orchestration layer of a slice.
527
520
  - receive any number of arguments
528
521
  - can return synchronous values or Promises
529
522
  - can access:
530
- - state, mutations, slibling methods, nested slices (through `this`)
531
- - Application-wide utilities (`this.global`)
523
+ - state, mutations, slibling methods, nested slices (through `this`)
524
+ - Root store (`this.root`)
525
+ - Parent slice (`this.parent`)
526
+ - Application-wide utilities (`this.utils`)
532
527
 
533
528
  Methods are not serialized, replayable, or represented in Redux DevTools action history.
534
529
 
@@ -548,20 +543,9 @@ Methods are designed for centralizing any slice-related logic:
548
543
  Methods should NOT:
549
544
 
550
545
  - include slice-unrelated logic.
546
+ - include UI layer logic.
551
547
  - mutate state directly. use mutations instead.
552
548
 
553
- Prefer:
554
-
555
- ```ts
556
- this.increment(1);
557
- ```
558
-
559
- Instead of:
560
-
561
- ```ts
562
- this.getState().value++;
563
- ```
564
-
565
549
  **Example:**
566
550
 
567
551
  ```ts
@@ -582,7 +566,7 @@ const counter = createSlice({
582
566
  async incrementAfter(amount: number, delay = 1000) {
583
567
  await new Promise((resolve) => setTimeout(resolve, delay));
584
568
  this.increment(amount);
585
- this.global.logger.info("Counter incremented");
569
+ this.utils.logger.info("Counter incremented");
586
570
  },
587
571
  },
588
572
  });
@@ -622,27 +606,27 @@ This currently not supported
622
606
 
623
607
  Slices can be composed by registering other slice instances through the `children` property.
624
608
 
625
- This allows related state and behavior to be organized into a hierarchical structure while preserving full type inference and ownership isolation.
609
+ This allows related state and behavior to be structured into a hierarchical ownership tree, while preserving full type inference, runtime path resolution, and instance isolation.
626
610
 
627
611
  ```ts
628
612
  import { products } from "./productsSlice";
629
613
  import { categories } from "./categoriesSlice";
630
614
 
631
615
  export const shop = createSlice({
632
- name: "shop",
616
+ name: "shop",
633
617
 
634
- state: {},
618
+ state: {},
635
619
 
636
- children: {
637
- products,
638
- categories,
639
- },
620
+ children: {
621
+ products,
622
+ categories,
623
+ },
640
624
  });
641
625
  ```
642
626
 
643
- **Accessing Child Slices:**
627
+ ### Accessing Children through Parent Slice
644
628
 
645
- Child slices are exposed directly on their parent slice.
629
+ Child slices are exposed directly on their parent slice instance.
646
630
 
647
631
  ```ts
648
632
  shop.products.add(...)
@@ -651,7 +635,7 @@ shop.categories.create(...)
651
635
  console.log(shop.products.getState());
652
636
  ```
653
637
 
654
- Deeply nested slice hierarchies are fully supported.
638
+ Deeply nested slice trees are fully supported, including recursive composition.
655
639
 
656
640
  ```ts
657
641
  admin.users.permissions.grant(...);
@@ -659,6 +643,16 @@ admin.users.permissions.grant(...);
659
643
  console.log(admin.users.permissions.getState());
660
644
  ```
661
645
 
646
+ ### Accessing Parent Slice from Children
647
+
648
+ Every slice instance has a runtime reference to its parent via `slice.parent`.
649
+
650
+ This allows also child slices to interact with sibling slices through the parent ownership scope.
651
+
652
+ ```ts
653
+ this.parent.categories.getState().list;
654
+ ```
655
+
662
656
  ### Reusing Slices
663
657
 
664
658
  A slice can be mounted multiple times within the same tree.
@@ -916,7 +910,7 @@ console.log(store.counter.getState());
916
910
 
917
911
  ## Accessing Store from Slices
918
912
 
919
- Every slice has access to the root store instance through `this.root`.
913
+ Every slice has access to the root store instance via `slice.root`.
920
914
 
921
915
  ```ts
922
916
  this.root.auth.getState().isAuthenticated;
@@ -928,68 +922,103 @@ this.root.auth.getState().isAuthenticated;
928
922
  - avoiding circular imports
929
923
  - application-wide orchestration
930
924
 
931
- ## Root Store Type Extension (Planned)
925
+ ---
932
926
 
933
- Overriding `OrcheStore.Slots.root` provides full root store typing throughout the application.
927
+ # Lineage & Clones
934
928
 
935
- > 🐞 Under active development: this currently causes a circular type inference limitation.
929
+ OrcheStore uses a lineage-based model for slice identity.
936
930
 
937
- ```ts
938
- import { createStore } from "orchestore";
931
+ **Why?**
939
932
 
940
- export const store = createStore({
941
- slices: {
942
- counter,
943
- },
944
- });
933
+ Slices can be used in multiple places in the store tree.
945
934
 
946
- declare module "orchestore" {
947
- namespace OrcheStore {
948
- interface Slots {
949
- root: typeof store; // Bugfix: Causes a circular type inference
950
- }
951
- }
952
- }
953
- ```
935
+ When this happens, OrcheStore creates a separate runtime instance for each usage. These instances are called **clones**.
936
+
937
+ A clone is an independent instance of a slice at runtime. It has its own state and runs separately from other clones, while still remaining part of a shared lineage.
938
+
939
+ A lineage (or family) is the set of all runtime instances that originate from the same slice definition.
940
+
941
+ **This means:**
942
+
943
+ - slices are not singletons
944
+ - a slice can appear multiple times in a tree
945
+ - each clone is fully isolated
946
+ - all instances created from the same definition are linked through lineage
947
+
948
+ ## Manual Cloning
949
+
950
+ A new detached clone can be created manually from any slice instance.
951
+
952
+ ### 1. Clone without state transformation
954
953
 
955
954
  ```ts
956
- this.root; // Before: any
957
- this.root; // After: fully typed store
955
+ const clone = slice.prototype.clone();
958
956
  ```
959
957
 
960
- **Rules:**
958
+ The new instance:
961
959
 
962
- - `root` must be a store instance created using `createStore`
963
- - `null` and `undefined` are excluded automatically
964
- - `typeof store | null | undefined` is equivalent to `typeof store`
965
- - Invalid types fall back to `any`
960
+ - belongs to the same lineage
961
+ - starts detached from the tree
962
+ - has no mounted path initially
963
+ - has its own ownership context
964
+ - uses the exact initial state of the source slice
966
965
 
967
- ---
966
+ ### 2. Clone with state transformation
968
967
 
969
- # Lineage & Clones
968
+ ```ts
969
+ const clone = slice.prototype.clone((state) => newState);
970
+ ```
970
971
 
971
- OrcheStore uses a lineage-based model for slice identity.
972
+ The provided function receives the fully resolved initial state (including nested slices) and returns the modified state for the new instance.
972
973
 
973
- **Why?**
974
+ The state transformer:
974
975
 
975
- Slices can be used in multiple places in the store tree.
976
+ - does not affect other lineage members
977
+ - supports nested slice state updates
978
+ - supports immutable updates (returning a new state object)
979
+ - supports mutable updates (Immer-style — no return required)
976
980
 
977
- When this happens, OrcheStore creates a separate runtime instance for each usage. These instances are called **clones**.
981
+ **Example:**
978
982
 
979
- A clone is an independent instance copy of a slice at runtime. It has its own state and runs separately from other clones, while still remaining part of a shared lineage.
983
+ ```ts
984
+ const crudSlice = createSlice({
985
+ name: "CRUD-Slice",
980
986
 
981
- A lineage (or family) is the set of all instances that come from the same slice definition.
987
+ state: {
988
+ endpoint: "",
989
+ },
982
990
 
983
- **This means:**
991
+ children: {
992
+ pagination: paginationSlice,
993
+ dropdown: searchDropdownSlice,
994
+ },
995
+ });
984
996
 
985
- - slices are not singletons
986
- - a slice can appear multiple times in a tree
987
- - each clone is fully isolated
988
- - all instances cloned from the same slice are linked through lineage
997
+ // Immutable style (returns new state object)
998
+ const productsSlice = crudSlice.prototype.clone((state) => ({
999
+ ...state,
1000
+ endpoint: "api/v1/products",
1001
+
1002
+ dropdown: {
1003
+ ...state.dropdown,
1004
+ supported: false,
1005
+ },
1006
+ }));
1007
+
1008
+ // Immer-style mutation (no return needed)
1009
+ const categoriesSlice = crudSlice.prototype.clone((state) => {
1010
+ state.endpoint = "api/v1/categories";
1011
+ state.pagination.supported = false;
1012
+ });
1013
+ ```
989
1014
 
990
1015
  ## Automatic Cloning
991
1016
 
992
- When a slice is reused through `children` or `slices`, OrcheStore automatically creates a new mounted instance for each usage.
1017
+ OrcheStore creates slice instances automatically in two cases:
1018
+
1019
+ ### 1. Reuse through `children` / `slices`
1020
+
1021
+ When a slice is reused through `children` (or `slices`), OrcheStore creates a new mounted instance for each usage.
993
1022
 
994
1023
  ```ts
995
1024
  const paginationSlice = createSlice({ ... });
@@ -1024,36 +1053,49 @@ shopSlice.a !== adminSlice.a;
1024
1053
  shopSlice.b !== adminSlice.a;
1025
1054
  ```
1026
1055
 
1027
- Each instance also receives its own path and its own ownership context:
1056
+ Each instance has its own ownership context:
1028
1057
 
1029
1058
  ```ts
1030
- shopSlice.a.path; // "shop.a"
1031
- shopSlice.b.path; // "shop.b"
1032
- adminSlice.a.path; // "admin.a"
1059
+ shopSlice.a.path; // "shop.a"
1060
+ shopSlice.b.path; // "shop.b"
1061
+ adminSlice.a.path; // "admin.a"
1033
1062
  ```
1034
1063
 
1035
- Although these instances are independent at runtime, they still belong to the same lineage.
1036
-
1037
- ## Manual Cloning
1064
+ ### 2. Cloning a parent slice (cascade cloning)
1038
1065
 
1039
- A new detached clone can be created manually from any slice instance:
1066
+ When a parent slice is cloned or reused, all its nested children are automatically cloned as well.
1040
1067
 
1041
1068
  ```ts
1042
- const clone = slice.prototype.clone();
1069
+ const crudSlice = createSlice({
1070
+ name: "CRUD-Slice",
1071
+
1072
+ state: {
1073
+ endpoint: "",
1074
+ },
1075
+
1076
+ children: {
1077
+ pagination: paginationSlice,
1078
+ dropdown: searchDropdownSlice,
1079
+ },
1080
+ });
1081
+
1082
+ const productsSlice = crudSlice.prototype.clone();
1083
+ const categoriesSlice = crudSlice.prototype.clone();
1043
1084
  ```
1044
1085
 
1045
- The new instance:
1086
+ Each clone receives its own independent subtree:
1046
1087
 
1047
- - belongs to the same lineage
1048
- - starts detached from the tree
1049
- - has no mounted path initially
1050
- - has its own ownership context
1088
+ ```ts
1089
+ productsSlice.pagination !== categoriesSlice.pagination;
1090
+ ```
1091
+
1092
+ This ensures that both parent and child slices remain fully isolated across all clone instances.
1051
1093
 
1052
1094
  ## Inspecting a Lineage
1053
1095
 
1054
1096
  **Get All Related Instances:**
1055
1097
 
1056
- Returns every instance in the lineage, **including** the current one.
1098
+ Returns every instance in the lineage, **including** the current instance.
1057
1099
 
1058
1100
  ```ts
1059
1101
  const lineage = slice.prototype.getLineage();
@@ -1065,9 +1107,9 @@ Useful for:
1065
1107
  - inspecting mounted instances
1066
1108
  - understanding tree distribution
1067
1109
 
1068
- **Get Clones:**
1110
+ **Get Sibling Clones:**
1069
1111
 
1070
- Returns all lineage members **except** the current instance.
1112
+ Returns every sibling in the lineage, **except** the current instance.
1071
1113
 
1072
1114
  ```ts
1073
1115
  const siblings = slice.prototype.getClones();
@@ -1081,8 +1123,6 @@ Useful for:
1081
1123
 
1082
1124
  ## Definition Type Checking
1083
1125
 
1084
- You can determine whether two slices belong to the same lineage:
1085
-
1086
1126
  You can check whether two slices belong to the same lineage:
1087
1127
 
1088
1128
  ```ts
@@ -1108,19 +1148,20 @@ slice2.prototype.isTypeOf(clone1); // false
1108
1148
 
1109
1149
  ## Summary
1110
1150
 
1111
- - Reusing a slice automatically creates mounted clones.
1112
1151
  - `clone()` creates a new detached lineage member.
1152
+ - `clone(stateTransformer)` allows per-instance state customization at creation time.
1153
+ - Reusing a slice automatically creates mounted clones.
1113
1154
  - Every clone is isolated at runtime.
1114
1155
  - All clones from the same definition belong to a shared lineage.
1115
1156
  - `getLineage()` returns all instances in a lineage.
1116
- - `getClones()` returns all related instances except the current one.
1157
+ - `getClones()` returns all related instances except the current instance.
1117
1158
  - `isTypeOf()` checks whether two instances belong to the same lineage.
1118
1159
 
1119
1160
  ---
1120
1161
 
1121
- # Global Utilities
1162
+ # Utilities
1122
1163
 
1123
- Global utilities allow slices and the root store to access shared runtime services through `global`.
1164
+ Application-wide utilities allow slices and stores to access shared runtime services through `utils`.
1124
1165
 
1125
1166
  Common use cases include:
1126
1167
 
@@ -1131,28 +1172,33 @@ Common use cases include:
1131
1172
  - runtime values that are difficult to access directly from slices
1132
1173
  - integrations with React hooks and third-party libraries
1133
1174
 
1134
- Utilities are registered using `provideGlobalUtils` and are accessible from any slice or the root store.
1175
+ Utilities are registered using `setUtils` and are accessible from any slice or the root store.
1135
1176
 
1136
- ## Accessing Global Utilities
1177
+ ## Accessing Utilities
1137
1178
 
1138
1179
  **Available:**
1139
1180
 
1140
- - Through the exposed store or slice instances
1181
+ - Through exposed store and slice instances
1141
1182
 
1142
1183
  ```ts
1143
- store.global;
1144
- slice.global;
1184
+ store.utils;
1185
+ slice.utils;
1186
+ this.utils; // Inside slice methods and mutations
1145
1187
  ```
1146
1188
 
1147
- - Inside slice methods
1189
+ - Through `getUtils`
1148
1190
 
1149
1191
  ```ts
1150
- this.global.notify("success", "Saved!");
1192
+ import { getUtils } from "orchestore";
1193
+
1194
+ const utils = getUtils();
1151
1195
  ```
1152
1196
 
1153
1197
  ## Utilities Type Extension
1154
1198
 
1155
- Overriding `OrcheStore.Slots.global` provides full typing everywhere.
1199
+ OrcheStore exposes user-definable type slots through `OrcheStore.Slots`.
1200
+
1201
+ By overriding `OrcheStore.Slots.utils`, application-specific utilities become available throughout the framework with full type safety.
1156
1202
 
1157
1203
  ```ts
1158
1204
  import type { NavigateFunction } from "react-router";
@@ -1160,7 +1206,7 @@ import type { NavigateFunction } from "react-router";
1160
1206
  declare module "orchestore" {
1161
1207
  namespace OrcheStore {
1162
1208
  interface Slots {
1163
- global: {
1209
+ utils: {
1164
1210
  navigate: NavigateFunction;
1165
1211
 
1166
1212
  notify(type: "info" | "error" | "success", message: string): void;
@@ -1170,30 +1216,43 @@ declare module "orchestore" {
1170
1216
  }
1171
1217
  ```
1172
1218
 
1173
- ```ts
1174
- this.global; // Before: any
1175
- this.global; // After: fully typed
1176
- ```
1219
+ **Notes:**
1177
1220
 
1178
- **Rules:**
1221
+ * `OrcheStore.Slots` can be extended using either `declare module "orchestore"` or `declare global`, depending on your project's type organization preferences.
1222
+ * If your project uses JavaScript without TypeScript, you can still extend these types by creating a separate declaration file (for example, `orchestore.d.ts`). This allows editors and tooling to provide type checking and IntelliSense while keeping your application code in JavaScript.
1223
+
1224
+ **Rules**
1225
+
1226
+ * `utils` must resolve to an object type; otherwise, it falls back to `any`.
1227
+ * `null` and `undefined` are automatically excluded. For example, `object | null | undefined` resolves to `object`.
1228
+
1229
+ **Type Safety**
1230
+
1231
+ Before extending `OrcheStore.Slots.utils`, all utility-related APIs are typed as `any`.
1232
+
1233
+ After extending `OrcheStore.Slots.utils`, the inferred type is automatically applied throughout the framework, including:
1234
+
1235
+ * `store.utils`
1236
+ * `slice.utils`
1237
+ * `this.utils` inside mutations and methods
1238
+ * `getUtils()`
1239
+ * `setUtils()`
1240
+ * `type Utils`
1179
1241
 
1180
- - `global` must be an object
1181
- - `null` and `undefined` are excluded automatically
1182
- - `object | null | undefined` is equivalent to `object`
1183
- - Invalid types fall back to `any`
1242
+ This provides consistent type safety and IntelliSense across all utility access points without requiring additional type declarations.
1184
1243
 
1185
1244
  ## Providing Runtime Utilities
1186
1245
 
1187
- Global utility values can be registered or updated at runtime.
1246
+ Application-wide utility values can be registered or updated at runtime.
1188
1247
 
1189
1248
  ```ts
1190
1249
  import { useEffect } from "react";
1191
1250
  import { useNavigate } from "react-router";
1192
- import { provideGlobalUtils } from "orchestore";
1251
+ import { setUtils } from "orchestore";
1193
1252
  import { feedbacks } from "./ui-feedbacks";
1194
1253
  import { store } from "./store";
1195
1254
 
1196
- provideGlobalUtils({
1255
+ setUtils({
1197
1256
  notify(type, message) {
1198
1257
  feedbacks.notify(type, message);
1199
1258
  },
@@ -1203,7 +1262,7 @@ export default function App() {
1203
1262
  const navigate = useNavigate();
1204
1263
 
1205
1264
  useEffect(() => {
1206
- provideGlobalUtils({ navigate });
1265
+ setUtils({ navigate });
1207
1266
  }, [navigate]);
1208
1267
 
1209
1268
  return (
@@ -1214,9 +1273,9 @@ export default function App() {
1214
1273
  }
1215
1274
  ```
1216
1275
 
1217
- ## Using Global Utilities in Slices
1276
+ ## Using Utilities in Slices
1218
1277
 
1219
- Global utilities can be used anywhere a slice instance is available.
1278
+ Application-wide utilities can be used anywhere a slice instance is available.
1220
1279
 
1221
1280
  ```ts
1222
1281
  methods: {
@@ -1226,13 +1285,13 @@ methods: {
1226
1285
 
1227
1286
  const response = await api.users.add(data);
1228
1287
 
1229
- this.global.notify("success", "User added successfully!");
1288
+ this.utils.notify("success", "User added successfully!");
1230
1289
 
1231
1290
  this.setLoading(false);
1232
1291
 
1233
- this.global.navigate("/users/" + response.id);
1292
+ this.utils.navigate("/users/" + response.id);
1234
1293
  } catch (error) {
1235
- this.global.notify("error", "Failed to add user");
1294
+ this.utils.notify("error", "Failed to add user");
1236
1295
 
1237
1296
  console.error(error);
1238
1297
  }
@@ -1268,13 +1327,13 @@ const counter = createSlice({
1268
1327
  },
1269
1328
 
1270
1329
  children: {
1271
- subCounter: createSlice({
1272
- name: "subCounter",
1330
+ subCounter: createSlice({
1331
+ name: "subCounter",
1273
1332
 
1274
- state: {
1275
- value: 0,
1276
- },
1277
- }),
1333
+ state: {
1334
+ value: 0,
1335
+ },
1336
+ }),
1278
1337
  },
1279
1338
  });
1280
1339
  ```
@@ -1295,42 +1354,6 @@ counter.incrementAfter(amount: number, delay?: number): Promise<number>;
1295
1354
 
1296
1355
  No manual type declarations required.
1297
1356
 
1298
- ## Framework Type Extensions
1299
-
1300
- OrcheStore also exposes user-definable type slots through `OrcheStore.Slots`.
1301
-
1302
- These slots allow application-specific types to be injected into the framework and become available everywhere with full type safety.
1303
-
1304
- | Slot | Purpose |
1305
- | -------------------------- | ----------------------- |
1306
- | `OrcheStore.Slots.root` | Root store typing |
1307
- | `OrcheStore.Slots.global` | Global utilities typing |
1308
-
1309
- ```ts
1310
- declare module "orhestore" {
1311
- namespace OrcheStore {
1312
- interface Slots {
1313
- root: typeof store; // Bugfix: Causes a circular type inference
1314
-
1315
- global: {
1316
- navigate: NavigateFunction;
1317
- notify(type: "info" | "error" | "success", message: string): void;
1318
- };
1319
- }
1320
- }
1321
- }
1322
- ```
1323
-
1324
- This provides full typing for APIs such as:
1325
-
1326
- ```ts
1327
- this.root;
1328
- this.global;
1329
-
1330
- store.global;
1331
- counter.global;
1332
- ```
1333
-
1334
1357
  ---
1335
1358
 
1336
1359
  # Status