@ngstato/core 0.2.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 +163 -63
- package/dist/index.d.mts +251 -4
- package/dist/index.d.ts +251 -4
- package/dist/index.js +1316 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1293 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -3
package/dist/index.d.ts
CHANGED
|
@@ -44,7 +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
|
|
47
|
+
declare function createStore<S extends object>(config: S & StatoStoreConfig<S>, __internal?: {
|
|
48
|
+
skipInit?: boolean;
|
|
49
|
+
}): any;
|
|
50
|
+
type OnEvent = {
|
|
51
|
+
name: string;
|
|
52
|
+
args: unknown[];
|
|
53
|
+
status: 'success' | 'error';
|
|
54
|
+
duration: number;
|
|
55
|
+
error?: Error;
|
|
56
|
+
};
|
|
57
|
+
declare function on<S extends object>(sourceAction: Function | Function[], handler: (store: S, event: OnEvent) => void | Promise<void>): () => void;
|
|
48
58
|
|
|
49
59
|
interface RequestOptions {
|
|
50
60
|
params?: Record<string, string | number | boolean>;
|
|
@@ -106,6 +116,149 @@ declare function fromStream<S, T>(setupFn: (state: S) => StatoObservable<T>, upd
|
|
|
106
116
|
|
|
107
117
|
declare function optimistic<S, A extends unknown[]>(immediate: (state: S, ...args: A) => void, confirm: (state: S, ...args: A) => Promise<void>): (state: S, ...args: A) => Promise<void>;
|
|
108
118
|
|
|
119
|
+
declare function exclusive<S, A extends unknown[]>(fn: (state: S, ...args: A) => Promise<void>): (state: S, ...args: A) => Promise<void>;
|
|
120
|
+
|
|
121
|
+
declare function queued<S, A extends unknown[]>(fn: (state: S, ...args: A) => Promise<void>): (state: S, ...args: A) => Promise<void>;
|
|
122
|
+
|
|
123
|
+
type Comparator<T> = (prev: T, next: T) => boolean;
|
|
124
|
+
declare function distinctUntilChanged<S, A extends unknown[], K>(fn: (state: S, ...args: A) => void | Promise<void>, keySelector: (...args: A) => K, comparator?: Comparator<K>): (state: S, ...args: A) => Promise<void>;
|
|
125
|
+
|
|
126
|
+
type TaskContext$1 = {
|
|
127
|
+
signal: AbortSignal;
|
|
128
|
+
};
|
|
129
|
+
type Task$1<T> = (ctx: TaskContext$1) => Promise<T> | T;
|
|
130
|
+
type ForkJoinOptions = {
|
|
131
|
+
signal?: AbortSignal;
|
|
132
|
+
};
|
|
133
|
+
declare function forkJoin<T extends Record<string, Task$1<any>>>(tasks: T, options?: ForkJoinOptions): Promise<{
|
|
134
|
+
[K in keyof T]: Awaited<ReturnType<T[K]>>;
|
|
135
|
+
}>;
|
|
136
|
+
|
|
137
|
+
type TaskContext = {
|
|
138
|
+
signal: AbortSignal;
|
|
139
|
+
};
|
|
140
|
+
type Task<T> = (ctx: TaskContext) => Promise<T> | T;
|
|
141
|
+
type RaceOptions = {
|
|
142
|
+
signal?: AbortSignal;
|
|
143
|
+
};
|
|
144
|
+
declare function race<T>(tasks: Array<Task<T>>, options?: RaceOptions): Promise<T>;
|
|
145
|
+
|
|
146
|
+
type DepFn<S, T> = (state: S) => T;
|
|
147
|
+
declare function combineLatest<S>(): <T extends unknown[]>(...deps: { [K in keyof T]: DepFn<S, T[K]>; }) => (state: S) => T;
|
|
148
|
+
|
|
149
|
+
declare function combineLatestStream<T extends unknown[]>(...sources: {
|
|
150
|
+
[K in keyof T]: StatoObservable<T[K]>;
|
|
151
|
+
}): StatoObservable<T>;
|
|
152
|
+
|
|
153
|
+
type EntityId = string | number;
|
|
154
|
+
interface EntityState<T> {
|
|
155
|
+
ids: EntityId[];
|
|
156
|
+
entities: Record<string, T>;
|
|
157
|
+
}
|
|
158
|
+
type Update<T> = {
|
|
159
|
+
id: EntityId;
|
|
160
|
+
changes: Partial<T>;
|
|
161
|
+
};
|
|
162
|
+
type SelectId<T> = (entity: T) => EntityId;
|
|
163
|
+
interface EntityAdapterOptions<T> {
|
|
164
|
+
selectId?: SelectId<T>;
|
|
165
|
+
sortComparer?: (a: T, b: T) => number;
|
|
166
|
+
}
|
|
167
|
+
declare function createEntityAdapter<T extends Record<string, any>>(options?: EntityAdapterOptions<T>): {
|
|
168
|
+
selectId: SelectId<T>;
|
|
169
|
+
sortComparer: ((a: T, b: T) => number) | undefined;
|
|
170
|
+
getInitialState: <E extends object = {}>(extra?: E) => EntityState<T> & E;
|
|
171
|
+
addOne: (entity: T, state: EntityState<T>) => void;
|
|
172
|
+
addMany: (entities: T[], state: EntityState<T>) => void;
|
|
173
|
+
setAll: (entities: T[], state: EntityState<T>) => void;
|
|
174
|
+
upsertOne: (entity: T, state: EntityState<T>) => void;
|
|
175
|
+
upsertMany: (entities: T[], state: EntityState<T>) => void;
|
|
176
|
+
updateOne: (update: Update<T>, state: EntityState<T>) => void;
|
|
177
|
+
removeOne: (id: EntityId, state: EntityState<T>) => void;
|
|
178
|
+
removeMany: (ids: EntityId[], state: EntityState<T>) => void;
|
|
179
|
+
removeAll: (state: EntityState<T>) => void;
|
|
180
|
+
getSelectors: <S = EntityState<T>>(selectState?: (state: S) => EntityState<T>) => {
|
|
181
|
+
selectIds: (state: S | EntityState<T>) => EntityId[];
|
|
182
|
+
selectEntities: (state: S | EntityState<T>) => Record<string, T>;
|
|
183
|
+
selectAll: (state: S | EntityState<T>) => T[];
|
|
184
|
+
selectTotal: (state: S | EntityState<T>) => number;
|
|
185
|
+
selectById: (state: S | EntityState<T>, id: EntityId) => T;
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
type EntityAdapter<T> = {
|
|
190
|
+
getInitialState: <E extends object = {}>(extra?: E) => EntityState<T> & E;
|
|
191
|
+
addOne: (entity: T, state: EntityState<T>) => void;
|
|
192
|
+
addMany: (entities: T[], state: EntityState<T>) => void;
|
|
193
|
+
setAll: (entities: T[], state: EntityState<T>) => void;
|
|
194
|
+
upsertOne: (entity: T, state: EntityState<T>) => void;
|
|
195
|
+
upsertMany: (entities: T[], state: EntityState<T>) => void;
|
|
196
|
+
updateOne: (update: Update<T>, state: EntityState<T>) => void;
|
|
197
|
+
removeOne: (id: EntityId, state: EntityState<T>) => void;
|
|
198
|
+
removeMany: (ids: EntityId[], state: EntityState<T>) => void;
|
|
199
|
+
removeAll: (state: EntityState<T>) => void;
|
|
200
|
+
getSelectors: <S = EntityState<T>>(selectState?: (state: S) => EntityState<T>) => {
|
|
201
|
+
selectIds: (state: S | EntityState<T>) => EntityId[];
|
|
202
|
+
selectEntities: (state: S | EntityState<T>) => Record<string, T>;
|
|
203
|
+
selectAll: (state: S | EntityState<T>) => T[];
|
|
204
|
+
selectTotal: (state: S | EntityState<T>) => number;
|
|
205
|
+
selectById: (state: S | EntityState<T>, id: EntityId) => T | undefined;
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
type WithEntitiesSelectorsNames = Partial<{
|
|
209
|
+
ids: string;
|
|
210
|
+
entities: string;
|
|
211
|
+
all: string;
|
|
212
|
+
total: string;
|
|
213
|
+
byId: string;
|
|
214
|
+
}>;
|
|
215
|
+
type WithEntitiesActionsNames = Partial<{
|
|
216
|
+
addOne: string;
|
|
217
|
+
addMany: string;
|
|
218
|
+
setAll: string;
|
|
219
|
+
upsertOne: string;
|
|
220
|
+
upsertMany: string;
|
|
221
|
+
updateOne: string;
|
|
222
|
+
removeOne: string;
|
|
223
|
+
removeMany: string;
|
|
224
|
+
removeAll: string;
|
|
225
|
+
}>;
|
|
226
|
+
type WithEntitiesOptions<T> = {
|
|
227
|
+
key: string;
|
|
228
|
+
adapter: EntityAdapter<T>;
|
|
229
|
+
initial?: T[];
|
|
230
|
+
selectors?: WithEntitiesSelectorsNames;
|
|
231
|
+
actions?: WithEntitiesActionsNames;
|
|
232
|
+
};
|
|
233
|
+
declare function withEntities<S extends object, T>(config: S & StatoStoreConfig<S>, options: WithEntitiesOptions<T>): S & StatoStoreConfig<S>;
|
|
234
|
+
|
|
235
|
+
type MaybeObservable<T> = StatoObservable<T> | Promise<T> | T;
|
|
236
|
+
type StreamOperator<I, O> = (source: StatoObservable<I>) => StatoObservable<O>;
|
|
237
|
+
declare function pipeStream<T>(source: StatoObservable<T>): StatoObservable<T>;
|
|
238
|
+
declare function pipeStream<T, A>(source: StatoObservable<T>, op1: StreamOperator<T, A>): StatoObservable<A>;
|
|
239
|
+
declare function pipeStream<T, A, B>(source: StatoObservable<T>, op1: StreamOperator<T, A>, op2: StreamOperator<A, B>): StatoObservable<B>;
|
|
240
|
+
declare function pipeStream<T, A, B, C>(source: StatoObservable<T>, op1: StreamOperator<T, A>, op2: StreamOperator<A, B>, op3: StreamOperator<B, C>): StatoObservable<C>;
|
|
241
|
+
declare function mapStream<I, O>(mapFn: (value: I) => O): StreamOperator<I, O>;
|
|
242
|
+
declare function filterStream<T>(predicate: (value: T) => boolean): StreamOperator<T, T>;
|
|
243
|
+
type Mapper<I, O> = (value: I, ctx: {
|
|
244
|
+
signal: AbortSignal;
|
|
245
|
+
}) => MaybeObservable<O>;
|
|
246
|
+
declare function switchMapStream<I, O>(mapper: Mapper<I, O>): StreamOperator<I, O>;
|
|
247
|
+
declare function concatMapStream<I, O>(mapper: Mapper<I, O>): StreamOperator<I, O>;
|
|
248
|
+
declare function exhaustMapStream<I, O>(mapper: Mapper<I, O>): StreamOperator<I, O>;
|
|
249
|
+
declare function mergeMapStream<I, O>(mapper: Mapper<I, O>, options?: {
|
|
250
|
+
concurrency?: number;
|
|
251
|
+
}): StreamOperator<I, O>;
|
|
252
|
+
declare function distinctUntilChangedStream<T, K = T>(keySelector?: (value: T) => K, comparator?: (prev: K, next: K) => boolean): StreamOperator<T, T>;
|
|
253
|
+
declare function debounceStream<T>(ms: number): StreamOperator<T, T>;
|
|
254
|
+
declare function throttleStream<T>(ms: number): StreamOperator<T, T>;
|
|
255
|
+
declare function catchErrorStream<T>(handler: (error: unknown) => MaybeObservable<T>): StreamOperator<T, T>;
|
|
256
|
+
declare function retryStream<T>(options?: {
|
|
257
|
+
attempts?: number;
|
|
258
|
+
delay?: number;
|
|
259
|
+
backoff?: 'fixed' | 'exponential';
|
|
260
|
+
}): StreamOperator<T, T>;
|
|
261
|
+
|
|
109
262
|
interface PersistStorage {
|
|
110
263
|
getItem(key: string): string | null;
|
|
111
264
|
setItem(key: string, value: string): void;
|
|
@@ -121,21 +274,103 @@ interface PersistOptions<S extends object> {
|
|
|
121
274
|
}
|
|
122
275
|
declare function withPersist<S extends object>(config: S & StatoStoreConfig<S>, options: PersistOptions<StateSlice<S>>): S & StatoStoreConfig<S>;
|
|
123
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
|
+
|
|
124
350
|
interface ActionLog {
|
|
125
351
|
id: number;
|
|
126
352
|
name: string;
|
|
353
|
+
storeName: string;
|
|
127
354
|
args: unknown[];
|
|
128
355
|
duration: number;
|
|
129
356
|
status: 'success' | 'error';
|
|
130
357
|
error?: string;
|
|
131
|
-
prevState: unknown
|
|
132
|
-
nextState: unknown
|
|
358
|
+
prevState: Record<string, unknown>;
|
|
359
|
+
nextState: Record<string, unknown>;
|
|
133
360
|
at: string;
|
|
134
361
|
}
|
|
135
362
|
interface DevToolsState {
|
|
136
363
|
logs: ActionLog[];
|
|
137
364
|
isOpen: boolean;
|
|
138
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[];
|
|
139
374
|
}
|
|
140
375
|
interface DevToolsInstance {
|
|
141
376
|
state: DevToolsState;
|
|
@@ -145,9 +380,21 @@ interface DevToolsInstance {
|
|
|
145
380
|
close: () => void;
|
|
146
381
|
toggle: () => void;
|
|
147
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
|
+
}>;
|
|
148
395
|
}
|
|
149
396
|
declare function createDevTools(maxLogs?: number): DevToolsInstance;
|
|
150
397
|
declare const devTools: DevToolsInstance;
|
|
151
398
|
declare function connectDevTools(store: any, storeName: string): void;
|
|
152
399
|
|
|
153
|
-
export { type ActionLog, type DevToolsInstance, type DevToolsState, type EffectDepsFn, type EffectEntry, type EffectRunner, type PersistOptions, type PersistStorage, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, abortable, configureHttp, connectDevTools, createDevTools, createHttp, createStore, debounced, devTools, fromStream, http, optimistic, retryable, throttled, 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 };
|