@ngstato/core 0.3.0 → 0.4.0

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
@@ -1,101 +1,163 @@
1
- # @ngstato/core
2
-
3
- State management framework-agnostic — Signals-first, sans RxJS obligatoire.
4
-
5
- ## Installation
6
- ```bash
7
- npm install @ngstato/core
8
- ```
9
-
10
- ## Usage
11
- ```ts
12
- import { createStore, http } from '@ngstato/core'
13
-
14
- const store = createStore({
15
- users: [] as User[],
16
- isLoading: false,
17
-
18
- actions: {
19
- async loadUsers(state) {
20
- state.isLoading = true
21
- state.users = await http.get('/users')
22
- state.isLoading = false
23
- }
24
- },
25
-
26
- selectors: {
27
- total: (state) => state.users.length
28
- },
29
-
30
- effects: [
31
- [
32
- (state) => state.users.length,
33
- (count) => console.log('Total users:', count)
34
- ]
35
- ]
36
- })
37
-
38
- await store.loadUsers()
39
- console.log(store.users) // User[]
40
- console.log(store.total) // number (selector memoïzé)
41
- ```
42
-
43
- ## Réactions inter-stores (`on`)
44
-
45
- Écouter la fin d’exécution d’une action précise (success **ou** error) et réagir ailleurs (toast, analytics, déclencher une autre action, etc.).
46
-
47
- ```ts
48
- import { createStore, on } from '@ngstato/core'
49
-
50
- const userStore = createStore({
51
- users: [] as { id: string; name: string }[],
52
- actions: {
53
- async loadUsers(state) {
54
- state.users = await fetch('/api/users').then(r => r.json())
55
- }
56
- }
57
- })
58
-
59
- const unsubscribe = on(userStore.loadUsers, (_store, event) => {
60
- if (event?.status === 'success') {
61
- console.log(`[users] loaded in ${event.duration}ms`)
62
- } else {
63
- console.error('[users] load failed:', event?.error)
64
- }
65
- })
66
-
67
- // Plus tard…
68
- unsubscribe()
69
- ```
70
-
71
- ## Helpers
72
-
73
- | Helper | Description |
74
- |--------|-------------|
75
- | `abortable()` | Annule la requête précédente si l'action est rappelée |
76
- | `debounced()` | Debounce sans RxJS |
77
- | `throttled()` | Throttle sans RxJS |
78
- | `exclusive()` | Ignore les nouveaux appels pendant qu'une exécution est en cours |
79
- | `retryable()` | Retry avec backoff fixe ou exponentiel |
80
- | `queued()` | Met en file et exécute les appels dans l'ordre d'arrivée |
81
- | `distinctUntilChanged()` | Ignore les appels si l’entrée ne change pas |
82
- | `forkJoin()` | Lance des tâches en parallèle, attend tout |
83
- | `race()` | Retourne la première tâche terminée |
84
- | `createEntityAdapter()` | Collections normalisées (ids/entities) + CRUD/selectors |
85
- | `withEntities()` | Injecte une slice entities + actions/selectors générés |
86
- | `combineLatest()` | Compose plusieurs deps pour `effects` |
87
- | `combineLatestStream()` | Combine plusieurs flux externes (compatible RxJS) |
88
- | `pipeStream()` + operators | Composable streams (`map`, `filter`, `distinctUntilChanged`, `debounce`, `throttle`, `switchMap`, `concatMap`, `exhaustMap`, `mergeMap`, `catchError`, `retry`) |
89
- | `fromStream()` | Realtime — WebSocket, Firebase, Supabase |
90
- | `optimistic()` | Optimistic update + rollback automatique |
91
- | `withPersist()` | Persistance localStorage/sessionStorage + migration |
92
-
93
- ## Nouvautés v0.2
94
-
95
- - `selectors` memoïzés (recalcul seulement quand les dépendances changent)
96
- - `effects` réactifs explicites avec cleanup automatique
97
- - `withPersist()` pour hydrater/persister le state
98
-
99
- ## Documentation
100
-
101
- Voir [github.com/becher/ngstato](https://github.com/becher/ngstato)
1
+ <div align="center">
2
+
3
+ # @ngstato/core
4
+
5
+ ### Tired of 14 lines of RxJS for a simple API call?
6
+
7
+ **Write `async/await`. Get the same result. Ship ~3 KB instead of ~50 KB.**
8
+
9
+ [![npm](https://img.shields.io/badge/npm-v0.3.0-blue)](https://www.npmjs.com/package/@ngstato/core)
10
+ [![gzip](https://img.shields.io/badge/gzip-~3KB-brightgreen)](#)
11
+ [![tests](https://img.shields.io/badge/tests-136%2B-green)](#)
12
+ [![license](https://img.shields.io/badge/license-MIT-lightgrey)](#)
13
+
14
+ [Documentation](https://becher.github.io/ngStato/) · [API Reference](https://becher.github.io/ngStato/api/core) · [Helpers](https://becher.github.io/ngStato/api/helpers)
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## Before / After
21
+
22
+ **NgRx** rxMethod + pipe + tap + switchMap + from + tapResponse + patchState:
23
+
24
+ ```ts
25
+ load: rxMethod<void>(pipe(
26
+ tap(() => patchState(store, { loading: true })),
27
+ switchMap(() => from(service.getAll()).pipe(
28
+ tapResponse({
29
+ next: (users) => patchState(store, { users, loading: false }),
30
+ error: (e) => patchState(store, { error: e.message })
31
+ })
32
+ ))
33
+ ))
34
+ ```
35
+
36
+ **ngStato** — async/await:
37
+
38
+ ```ts
39
+ async load(state) {
40
+ state.loading = true
41
+ state.users = await http.get('/users')
42
+ state.loading = false
43
+ }
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Install
49
+
50
+ ```bash
51
+ npm install @ngstato/core
52
+ ```
53
+
54
+ ## 30-second example
55
+
56
+ ```ts
57
+ import { createStore } from '@ngstato/core'
58
+
59
+ const store = createStore({
60
+ count: 0,
61
+
62
+ selectors: { doubled: (s) => s.count * 2 },
63
+
64
+ actions: {
65
+ inc(state) { state.count++ },
66
+ add(state, n: number) { state.count += n },
67
+ async load(state) { state.count = await fetchCount() }
68
+ }
69
+ })
70
+
71
+ await store.inc()
72
+ store.count // 1
73
+ store.doubled // 2 (memoized)
74
+ ```
75
+
76
+ ## Real-world store
77
+
78
+ ```ts
79
+ import { createStore, http, retryable, optimistic } from '@ngstato/core'
80
+
81
+ const store = createStore({
82
+ users: [] as User[],
83
+ loading: false,
84
+ error: null as string | null,
85
+
86
+ selectors: {
87
+ total: (s) => s.users.length,
88
+ admins: (s) => s.users.filter(u => u.role === 'admin')
89
+ },
90
+
91
+ actions: {
92
+ loadUsers: retryable(async (state) => {
93
+ state.loading = true
94
+ state.users = await http.get('/users')
95
+ state.loading = false
96
+ }, { attempts: 3, backoff: 'exponential' }),
97
+
98
+ deleteUser: optimistic(
99
+ (state, id: string) => { state.users = state.users.filter(u => u.id !== id) },
100
+ async (_, id) => { await http.delete(`/users/${id}`) }
101
+ )
102
+ },
103
+
104
+ hooks: {
105
+ onInit: (store) => store.loadUsers(),
106
+ onError: (err, name) => console.error(`[${name}]`, err.message)
107
+ }
108
+ })
109
+ ```
110
+
111
+ ## Concurrency — without RxJS
112
+
113
+ ```ts
114
+ import { exclusive, abortable, queued, retryable, optimistic } from '@ngstato/core'
115
+
116
+ actions: {
117
+ submit: exclusive(async (s) => { ... }), // → exhaustMap
118
+ search: abortable(async (s, q, { signal }) => { }), // → switchMap
119
+ send: queued(async (s, msg) => { ... }), // → concatMap
120
+ load: retryable(async (s) => { ... }, opts), // → retryWhen
121
+ delete: optimistic(apply, confirm), // → manual in NgRx
122
+ }
123
+ ```
124
+
125
+ Plus `debounced` · `throttled` · `distinctUntilChanged` · `forkJoin` · `race` · `combineLatest` · `fromStream` · `pipeStream` + 12 stream operators · `createEntityAdapter` · `withEntities` · `withPersist` · `mergeFeatures` · `on()` → [Full API →](https://becher.github.io/ngStato/api/helpers)
126
+
127
+ ## Inter-store reactions
128
+
129
+ ```ts
130
+ import { on } from '@ngstato/core'
131
+
132
+ on([userStore.create, userStore.delete], (_, event) => {
133
+ console.log(`${event.name} ${event.status} in ${event.duration}ms`)
134
+ })
135
+ ```
136
+
137
+ ## Feature composition
138
+
139
+ ```ts
140
+ const store = createStore({
141
+ items: [] as Item[],
142
+ ...mergeFeatures(withLoading(), withPagination()),
143
+ actions: { async load(state) { ... } }
144
+ })
145
+ // store.loading, store.page, store.hasError — all available
146
+ ```
147
+
148
+ ## The numbers
149
+
150
+ | | NgRx v21 | ngStato |
151
+ |:--|:--|:--|
152
+ | Bundle | ~50 KB | **~3 KB** |
153
+ | CRUD store | ~90 lines | **~45 lines** |
154
+ | Concepts for async | 9 | **1** |
155
+ | RxJS required | Yes | **No** |
156
+
157
+ ## 📖 Documentation
158
+
159
+ **[becher.github.io/ngStato](https://becher.github.io/ngStato/)** — [Quick start](https://becher.github.io/ngStato/guide/start-in-5-min) · [Core concepts](https://becher.github.io/ngStato/guide/core-concepts) · [API](https://becher.github.io/ngStato/api/core) · [Helpers](https://becher.github.io/ngStato/api/helpers) · [NgRx migration](https://becher.github.io/ngStato/migration/ngrx-to-ngstato)
160
+
161
+ ## License
162
+
163
+ MIT
package/dist/index.d.mts CHANGED
@@ -44,14 +44,17 @@ declare class StatoHttpError extends Error {
44
44
  constructor(status: number, body: string);
45
45
  }
46
46
 
47
- declare function createStore<S extends object>(config: S & StatoStoreConfig<S>): any;
48
- declare function on<S extends object>(sourceAction: Function, handler: (store: S, event?: {
47
+ declare function createStore<S extends object>(config: S & StatoStoreConfig<S>, __internal?: {
48
+ skipInit?: boolean;
49
+ }): any;
50
+ type OnEvent = {
49
51
  name: string;
50
52
  args: unknown[];
51
53
  status: 'success' | 'error';
52
54
  duration: number;
53
55
  error?: Error;
54
- }) => void | Promise<void>): () => void;
56
+ };
57
+ declare function on<S extends object>(sourceAction: Function | Function[], handler: (store: S, event: OnEvent) => void | Promise<void>): () => void;
55
58
 
56
59
  interface RequestOptions {
57
60
  params?: Record<string, string | number | boolean>;
@@ -271,21 +274,103 @@ interface PersistOptions<S extends object> {
271
274
  }
272
275
  declare function withPersist<S extends object>(config: S & StatoStoreConfig<S>, options: PersistOptions<StateSlice<S>>): S & StatoStoreConfig<S>;
273
276
 
277
+ interface FeatureConfig {
278
+ state?: Record<string, unknown>;
279
+ actions?: Record<string, Function>;
280
+ computed?: Record<string, Function>;
281
+ selectors?: Record<string, Function>;
282
+ effects?: EffectEntry<any>[];
283
+ hooks?: Partial<StatoHooks<any>>;
284
+ }
285
+ type MergedFeature = {
286
+ actions?: Record<string, Function>;
287
+ computed?: Record<string, Function>;
288
+ selectors?: Record<string, Function>;
289
+ effects?: EffectEntry<any>[];
290
+ hooks?: Partial<StatoHooks<any>>;
291
+ [key: string]: unknown;
292
+ };
293
+ declare function mergeFeatures(...features: FeatureConfig[]): MergedFeature;
294
+
295
+ /**
296
+ * withProps() — Attach external properties to a store config.
297
+ *
298
+ * Properties are accessible on the store instance but NOT part of the state.
299
+ * Use this to expose injected services on the store object.
300
+ *
301
+ * @example
302
+ * ```ts
303
+ * // Pattern 1: Expose services on the store
304
+ * export const UsersStore = StatoStore(() => {
305
+ * const api = inject(ApiService)
306
+ * const notifier = inject(NotificationService)
307
+ *
308
+ * const store = createStore({
309
+ * users: [] as User[],
310
+ * loading: false,
311
+ *
312
+ * actions: {
313
+ * async loadUsers(state) {
314
+ * state.loading = true
315
+ * state.users = await api.getUsers() // closure over injected service
316
+ * state.loading = false
317
+ * },
318
+ *
319
+ * async deleteUser(state, id: string) {
320
+ * await api.deleteUser(id)
321
+ * state.users = state.users.filter(u => u.id !== id)
322
+ * notifier.success('User deleted')
323
+ * }
324
+ * }
325
+ * })
326
+ *
327
+ * // Attach props to the store — accessible but not in state
328
+ * return withProps(store, { api, notifier })
329
+ * })
330
+ *
331
+ * // In a component:
332
+ * store = injectStore(UsersStore)
333
+ * store.users() // Signal<User[]>
334
+ * store.loadUsers() // action
335
+ * store.api // ApiService — read-only, not in state
336
+ * ```
337
+ *
338
+ * @example
339
+ * ```ts
340
+ * // Pattern 2: Configuration props
341
+ * return withProps(store, {
342
+ * storeName: 'Users',
343
+ * version: '1.0.0',
344
+ * config: { pageSize: 20, cacheTTL: 60_000 }
345
+ * })
346
+ * ```
347
+ */
348
+ declare function withProps<S extends object, P extends Record<string, unknown>>(store: S, props: P): S & Readonly<P>;
349
+
274
350
  interface ActionLog {
275
351
  id: number;
276
352
  name: string;
353
+ storeName: string;
277
354
  args: unknown[];
278
355
  duration: number;
279
356
  status: 'success' | 'error';
280
357
  error?: string;
281
- prevState: unknown;
282
- nextState: unknown;
358
+ prevState: Record<string, unknown>;
359
+ nextState: Record<string, unknown>;
283
360
  at: string;
284
361
  }
285
362
  interface DevToolsState {
286
363
  logs: ActionLog[];
287
364
  isOpen: boolean;
288
365
  maxLogs: number;
366
+ activeLogId: number | null;
367
+ isTimeTraveling: boolean;
368
+ }
369
+ interface DevToolsSnapshot {
370
+ version: number;
371
+ timestamp: string;
372
+ stores: Record<string, unknown>;
373
+ logs: ActionLog[];
289
374
  }
290
375
  interface DevToolsInstance {
291
376
  state: DevToolsState;
@@ -295,9 +380,21 @@ interface DevToolsInstance {
295
380
  close: () => void;
296
381
  toggle: () => void;
297
382
  subscribe: (cb: (state: DevToolsState) => void) => () => void;
383
+ travelTo: (logId: number) => void;
384
+ undo: () => void;
385
+ redo: () => void;
386
+ resume: () => void;
387
+ replay: (logId: number) => void;
388
+ exportSnapshot: () => DevToolsSnapshot;
389
+ importSnapshot: (snapshot: DevToolsSnapshot) => void;
390
+ registerStore: (name: string, publicStore: any, internalStore: any) => void;
391
+ getStoreRegistry: () => Map<string, {
392
+ store: any;
393
+ internalStore: any;
394
+ }>;
298
395
  }
299
396
  declare function createDevTools(maxLogs?: number): DevToolsInstance;
300
397
  declare const devTools: DevToolsInstance;
301
398
  declare function connectDevTools(store: any, storeName: string): void;
302
399
 
303
- export { type ActionLog, type DevToolsInstance, type DevToolsState, type EffectDepsFn, type EffectEntry, type EffectRunner, type EntityAdapterOptions, type EntityId, type EntityState, type PersistOptions, type PersistStorage, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, type Update, type WithEntitiesOptions, abortable, catchErrorStream, combineLatest, combineLatestStream, concatMapStream, configureHttp, connectDevTools, createDevTools, createEntityAdapter, createHttp, createStore, debounceStream, debounced, devTools, distinctUntilChanged, distinctUntilChangedStream, exclusive, exhaustMapStream, filterStream, forkJoin, fromStream, http, mapStream, mergeMapStream, on, optimistic, pipeStream, queued, race, retryStream, retryable, switchMapStream, throttleStream, throttled, withEntities, withPersist };
400
+ export { type ActionLog, type DevToolsInstance, type DevToolsSnapshot, type DevToolsState, type EffectDepsFn, type EffectEntry, type EffectRunner, type EntityAdapterOptions, type EntityId, type EntityState, type FeatureConfig, type MergedFeature, type OnEvent, type PersistOptions, type PersistStorage, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, type Update, type WithEntitiesOptions, abortable, catchErrorStream, combineLatest, combineLatestStream, concatMapStream, configureHttp, connectDevTools, createDevTools, createEntityAdapter, createHttp, createStore, debounceStream, debounced, devTools, distinctUntilChanged, distinctUntilChangedStream, exclusive, exhaustMapStream, filterStream, forkJoin, fromStream, http, mapStream, mergeFeatures, mergeMapStream, on, optimistic, pipeStream, queued, race, retryStream, retryable, switchMapStream, throttleStream, throttled, withEntities, withPersist, withProps };
package/dist/index.d.ts CHANGED
@@ -44,14 +44,17 @@ declare class StatoHttpError extends Error {
44
44
  constructor(status: number, body: string);
45
45
  }
46
46
 
47
- declare function createStore<S extends object>(config: S & StatoStoreConfig<S>): any;
48
- declare function on<S extends object>(sourceAction: Function, handler: (store: S, event?: {
47
+ declare function createStore<S extends object>(config: S & StatoStoreConfig<S>, __internal?: {
48
+ skipInit?: boolean;
49
+ }): any;
50
+ type OnEvent = {
49
51
  name: string;
50
52
  args: unknown[];
51
53
  status: 'success' | 'error';
52
54
  duration: number;
53
55
  error?: Error;
54
- }) => void | Promise<void>): () => void;
56
+ };
57
+ declare function on<S extends object>(sourceAction: Function | Function[], handler: (store: S, event: OnEvent) => void | Promise<void>): () => void;
55
58
 
56
59
  interface RequestOptions {
57
60
  params?: Record<string, string | number | boolean>;
@@ -271,21 +274,103 @@ interface PersistOptions<S extends object> {
271
274
  }
272
275
  declare function withPersist<S extends object>(config: S & StatoStoreConfig<S>, options: PersistOptions<StateSlice<S>>): S & StatoStoreConfig<S>;
273
276
 
277
+ interface FeatureConfig {
278
+ state?: Record<string, unknown>;
279
+ actions?: Record<string, Function>;
280
+ computed?: Record<string, Function>;
281
+ selectors?: Record<string, Function>;
282
+ effects?: EffectEntry<any>[];
283
+ hooks?: Partial<StatoHooks<any>>;
284
+ }
285
+ type MergedFeature = {
286
+ actions?: Record<string, Function>;
287
+ computed?: Record<string, Function>;
288
+ selectors?: Record<string, Function>;
289
+ effects?: EffectEntry<any>[];
290
+ hooks?: Partial<StatoHooks<any>>;
291
+ [key: string]: unknown;
292
+ };
293
+ declare function mergeFeatures(...features: FeatureConfig[]): MergedFeature;
294
+
295
+ /**
296
+ * withProps() — Attach external properties to a store config.
297
+ *
298
+ * Properties are accessible on the store instance but NOT part of the state.
299
+ * Use this to expose injected services on the store object.
300
+ *
301
+ * @example
302
+ * ```ts
303
+ * // Pattern 1: Expose services on the store
304
+ * export const UsersStore = StatoStore(() => {
305
+ * const api = inject(ApiService)
306
+ * const notifier = inject(NotificationService)
307
+ *
308
+ * const store = createStore({
309
+ * users: [] as User[],
310
+ * loading: false,
311
+ *
312
+ * actions: {
313
+ * async loadUsers(state) {
314
+ * state.loading = true
315
+ * state.users = await api.getUsers() // closure over injected service
316
+ * state.loading = false
317
+ * },
318
+ *
319
+ * async deleteUser(state, id: string) {
320
+ * await api.deleteUser(id)
321
+ * state.users = state.users.filter(u => u.id !== id)
322
+ * notifier.success('User deleted')
323
+ * }
324
+ * }
325
+ * })
326
+ *
327
+ * // Attach props to the store — accessible but not in state
328
+ * return withProps(store, { api, notifier })
329
+ * })
330
+ *
331
+ * // In a component:
332
+ * store = injectStore(UsersStore)
333
+ * store.users() // Signal<User[]>
334
+ * store.loadUsers() // action
335
+ * store.api // ApiService — read-only, not in state
336
+ * ```
337
+ *
338
+ * @example
339
+ * ```ts
340
+ * // Pattern 2: Configuration props
341
+ * return withProps(store, {
342
+ * storeName: 'Users',
343
+ * version: '1.0.0',
344
+ * config: { pageSize: 20, cacheTTL: 60_000 }
345
+ * })
346
+ * ```
347
+ */
348
+ declare function withProps<S extends object, P extends Record<string, unknown>>(store: S, props: P): S & Readonly<P>;
349
+
274
350
  interface ActionLog {
275
351
  id: number;
276
352
  name: string;
353
+ storeName: string;
277
354
  args: unknown[];
278
355
  duration: number;
279
356
  status: 'success' | 'error';
280
357
  error?: string;
281
- prevState: unknown;
282
- nextState: unknown;
358
+ prevState: Record<string, unknown>;
359
+ nextState: Record<string, unknown>;
283
360
  at: string;
284
361
  }
285
362
  interface DevToolsState {
286
363
  logs: ActionLog[];
287
364
  isOpen: boolean;
288
365
  maxLogs: number;
366
+ activeLogId: number | null;
367
+ isTimeTraveling: boolean;
368
+ }
369
+ interface DevToolsSnapshot {
370
+ version: number;
371
+ timestamp: string;
372
+ stores: Record<string, unknown>;
373
+ logs: ActionLog[];
289
374
  }
290
375
  interface DevToolsInstance {
291
376
  state: DevToolsState;
@@ -295,9 +380,21 @@ interface DevToolsInstance {
295
380
  close: () => void;
296
381
  toggle: () => void;
297
382
  subscribe: (cb: (state: DevToolsState) => void) => () => void;
383
+ travelTo: (logId: number) => void;
384
+ undo: () => void;
385
+ redo: () => void;
386
+ resume: () => void;
387
+ replay: (logId: number) => void;
388
+ exportSnapshot: () => DevToolsSnapshot;
389
+ importSnapshot: (snapshot: DevToolsSnapshot) => void;
390
+ registerStore: (name: string, publicStore: any, internalStore: any) => void;
391
+ getStoreRegistry: () => Map<string, {
392
+ store: any;
393
+ internalStore: any;
394
+ }>;
298
395
  }
299
396
  declare function createDevTools(maxLogs?: number): DevToolsInstance;
300
397
  declare const devTools: DevToolsInstance;
301
398
  declare function connectDevTools(store: any, storeName: string): void;
302
399
 
303
- export { type ActionLog, type DevToolsInstance, type DevToolsState, type EffectDepsFn, type EffectEntry, type EffectRunner, type EntityAdapterOptions, type EntityId, type EntityState, type PersistOptions, type PersistStorage, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, type Update, type WithEntitiesOptions, abortable, catchErrorStream, combineLatest, combineLatestStream, concatMapStream, configureHttp, connectDevTools, createDevTools, createEntityAdapter, createHttp, createStore, debounceStream, debounced, devTools, distinctUntilChanged, distinctUntilChangedStream, exclusive, exhaustMapStream, filterStream, forkJoin, fromStream, http, mapStream, mergeMapStream, on, optimistic, pipeStream, queued, race, retryStream, retryable, switchMapStream, throttleStream, throttled, withEntities, withPersist };
400
+ export { type ActionLog, type DevToolsInstance, type DevToolsSnapshot, type DevToolsState, type EffectDepsFn, type EffectEntry, type EffectRunner, type EntityAdapterOptions, type EntityId, type EntityState, type FeatureConfig, type MergedFeature, type OnEvent, type PersistOptions, type PersistStorage, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, type Update, type WithEntitiesOptions, abortable, catchErrorStream, combineLatest, combineLatestStream, concatMapStream, configureHttp, connectDevTools, createDevTools, createEntityAdapter, createHttp, createStore, debounceStream, debounced, devTools, distinctUntilChanged, distinctUntilChangedStream, exclusive, exhaustMapStream, filterStream, forkJoin, fromStream, http, mapStream, mergeFeatures, mergeMapStream, on, optimistic, pipeStream, queued, race, retryStream, retryable, switchMapStream, throttleStream, throttled, withEntities, withPersist, withProps };