unwrapped 0.1.5 → 0.1.7

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.
@@ -1,6 +1,7 @@
1
+ import * as unwrapped_core from 'unwrapped/core';
2
+ import { ErrorBase, AsyncResult, Result, FlatChainStep, Action, AsyncResultGenerator, AsyncResultList } from 'unwrapped/core';
1
3
  import * as vue from 'vue';
2
- import { Ref, WatchSource, VNode } from 'vue';
3
- import { ErrorBase, AsyncResult, Result, FlatChainStep, Action, AsyncResultGenerator } from 'unwrapped/core';
4
+ import { Ref, WatchSource, VNode, SlotsType } from 'vue';
4
5
 
5
6
  interface ReactiveProcessOptions {
6
7
  immediate: boolean;
@@ -12,7 +13,7 @@ interface ReactiveProcessOptions {
12
13
  * @param asyncResult the result to make reactive
13
14
  * @returns the ref to the result
14
15
  */
15
- declare function useAsyncResultRef<T, E extends ErrorBase = ErrorBase>(asyncResult: AsyncResult<T, E>): Ref<AsyncResult<T, E>, AsyncResult<T, E>>;
16
+ declare function useAsyncResultRef<T, E extends ErrorBase = ErrorBase>(asyncResult?: AsyncResult<T, E>): Ref<AsyncResult<T, E>, AsyncResult<T, E>>;
16
17
  /**
17
18
  * Creates an AsyncResult ref from a promise returning a Result.
18
19
  * @param promise the promise returning a Result
@@ -78,68 +79,280 @@ declare function useLazyGenerator<T>(generatorFunc: () => AsyncResultGenerator<T
78
79
  * @returns ref to the result
79
80
  */
80
81
  declare function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs) => AsyncResultGenerator<T>, options?: ReactiveProcessOptions): Ref<AsyncResult<T, E>>;
81
-
82
82
  /**
83
- * A Vue component that displays different content based on the state of an AsyncResult.
84
- * It supports slots for 'loading', 'error', 'success' (default), and 'idle' states.
83
+ * Creates a reactive AsyncResultList wrapped in a Vue ref.
84
+ * The AsyncResultList notifies Vue's reactivity system whenever its state changes.
85
85
  *
86
- * @example
87
- * <AsyncResultLoader :result="myAsyncResult">
88
- * <template #loading>
89
- * <div>Loading data...</div>
90
- * </template>
91
- * <template #error="{ error }">
92
- * <div>Error occurred: {{ error.message }}</div>
93
- * </template>
94
- * <template #default="{ value }">
95
- * <div>Data loaded: {{ value }}</div>
96
- * </template>
97
- * <template #idle>
98
- * <div>Waiting to start...</div>
99
- * </template>
100
- * </AsyncResultLoader>
86
+ * @template T - The type of the values in the AsyncResultList.
87
+ * @template E - The type of the error, extending ErrorBase (default is ErrorBase).
88
+ * @returns a ref to the AsyncResultList
101
89
  */
102
- declare const AsyncResultLoader: vue.DefineComponent<vue.ExtractPropTypes<{
103
- result: {
104
- type: () => AsyncResult<unknown>;
105
- required: true;
106
- };
107
- }>, () => VNode<vue.RendererNode, vue.RendererElement, {
108
- [key: string]: any;
109
- }> | VNode<vue.RendererNode, vue.RendererElement, {
110
- [key: string]: any;
111
- }>[] | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
112
- result: {
113
- type: () => AsyncResult<unknown>;
114
- required: true;
115
- };
116
- }>> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
90
+ declare function useAsyncResultList<T = any, E extends ErrorBase = ErrorBase>(): Ref<{
91
+ readonly tasks: Map<string, {
92
+ key: string;
93
+ result: {
94
+ state: {
95
+ status: "idle";
96
+ } | {
97
+ status: "loading";
98
+ promise: {
99
+ then: <TResult1 = Result<T, E>, TResult2 = never>(onfulfilled?: ((value: Result<T, E>) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>;
100
+ catch: <TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined) => Promise<Result<T, E> | TResult>;
101
+ finally: (onfinally?: (() => void) | null | undefined) => Promise<Result<T, E>>;
102
+ readonly [Symbol.toStringTag]: string;
103
+ };
104
+ } | {
105
+ status: "success";
106
+ value: vue.UnwrapRef<T>;
107
+ } | {
108
+ status: "error";
109
+ error: vue.UnwrapRef<E>;
110
+ };
111
+ isSuccess: () => boolean;
112
+ isError: () => boolean;
113
+ isIdle: () => boolean;
114
+ isLoading: () => boolean;
115
+ unwrapOrNull: () => T | null;
116
+ unwrapOrThrow: () => T;
117
+ unwrapErrorOrNull: () => E | null;
118
+ updateFromValue: (value: T) => AsyncResult<T, E>;
119
+ updateFromError: (error: E) => AsyncResult<T, E>;
120
+ updateFromValuePromise: (promise: Promise<T>) => AsyncResult<T, E>;
121
+ waitForSettled: () => Promise<AsyncResult<T, E>>;
122
+ toResultPromise: () => Promise<Result<T, E>>;
123
+ toValueOrThrowPromise: () => Promise<T>;
124
+ toValueOrNullPromise: () => Promise<T | null>;
125
+ updateFromResultPromise: (promise: Promise<Result<T, E>>) => AsyncResult<T, E>;
126
+ listen: (listener: unwrapped_core.AsyncResultListener<T, E>, immediate?: boolean) => () => void;
127
+ listenUntilSettled: (listener: unwrapped_core.AsyncResultListener<T, E>, immediate?: boolean) => () => void;
128
+ mirror: (other: AsyncResult<T, E>) => () => void;
129
+ mirrorUntilSettled: (other: AsyncResult<T, E>) => () => void;
130
+ chain: <O, E2 extends ErrorBase = ErrorBase>(fn: unwrapped_core.ChainStep<T, O, E | E2>) => AsyncResult<O, E | E2>;
131
+ flatChain: <O, E2 extends ErrorBase = ErrorBase>(fn: FlatChainStep<T, O, E | E2>) => AsyncResult<O, E | E2>;
132
+ runInPlace: (generatorFunc: () => AsyncResultGenerator<T>) => AsyncResult<T, E>;
133
+ log: (name?: string) => void;
134
+ debug: (name?: string) => () => void;
135
+ [Symbol.iterator]: () => Generator<AsyncResult<T, E>, T, any>;
136
+ };
137
+ unsub: () => void;
138
+ }> & Omit<Map<string, unwrapped_core.AsyncResultListItem<T, E>>, keyof Map<any, any>>;
139
+ readonly length: number;
140
+ readonly items: {
141
+ state: {
142
+ status: "idle";
143
+ } | {
144
+ status: "loading";
145
+ promise: {
146
+ then: <TResult1 = Result<T, E>, TResult2 = never>(onfulfilled?: ((value: Result<T, E>) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>;
147
+ catch: <TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined) => Promise<Result<T, E> | TResult>;
148
+ finally: (onfinally?: (() => void) | null | undefined) => Promise<Result<T, E>>;
149
+ readonly [Symbol.toStringTag]: string;
150
+ };
151
+ } | {
152
+ status: "success";
153
+ value: vue.UnwrapRef<T>;
154
+ } | {
155
+ status: "error";
156
+ error: vue.UnwrapRef<E>;
157
+ };
158
+ isSuccess: () => boolean;
159
+ isError: () => boolean;
160
+ isIdle: () => boolean;
161
+ isLoading: () => boolean;
162
+ unwrapOrNull: () => T | null;
163
+ unwrapOrThrow: () => T;
164
+ unwrapErrorOrNull: () => E | null;
165
+ updateFromValue: (value: T) => AsyncResult<T, E>;
166
+ updateFromError: (error: E) => AsyncResult<T, E>;
167
+ updateFromValuePromise: (promise: Promise<T>) => AsyncResult<T, E>;
168
+ waitForSettled: () => Promise<AsyncResult<T, E>>;
169
+ toResultPromise: () => Promise<Result<T, E>>;
170
+ toValueOrThrowPromise: () => Promise<T>;
171
+ toValueOrNullPromise: () => Promise<T | null>;
172
+ updateFromResultPromise: (promise: Promise<Result<T, E>>) => AsyncResult<T, E>;
173
+ listen: (listener: unwrapped_core.AsyncResultListener<T, E>, immediate?: boolean) => () => void;
174
+ listenUntilSettled: (listener: unwrapped_core.AsyncResultListener<T, E>, immediate?: boolean) => () => void;
175
+ mirror: (other: AsyncResult<T, E>) => () => void;
176
+ mirrorUntilSettled: (other: AsyncResult<T, E>) => () => void;
177
+ chain: <O, E2 extends ErrorBase = ErrorBase>(fn: unwrapped_core.ChainStep<T, O, E | E2>) => AsyncResult<O, E | E2>;
178
+ flatChain: <O, E2 extends ErrorBase = ErrorBase>(fn: FlatChainStep<T, O, E | E2>) => AsyncResult<O, E | E2>;
179
+ runInPlace: (generatorFunc: () => AsyncResultGenerator<T>) => AsyncResult<T, E>;
180
+ log: (name?: string) => void;
181
+ debug: (name?: string) => () => void;
182
+ [Symbol.iterator]: () => Generator<AsyncResult<T, E>, T, any>;
183
+ }[];
184
+ state: unwrapped_core.AsyncResultListState;
185
+ listen: (listener: (taskQueue: AsyncResultList<T, E>) => void) => () => void;
186
+ add: (key: string, task: AsyncResult<T, E>, removeOnSettle?: boolean) => AsyncResult<T, E>;
187
+ clear: () => void;
188
+ anyLoading: () => boolean;
189
+ getAllFiltered: (predicate: (task: AsyncResult<T, E>) => boolean) => AsyncResult<T, E>[];
190
+ getAllFilteredAndMap: <U>(filterPredicate: (task: AsyncResult<T, E>) => boolean, mapFunc: (task: AsyncResult<T, E>) => U) => U[];
191
+ getAllSuccess: () => AsyncResult<T, E>[];
192
+ getAllSuccessValues: () => T[];
193
+ getAllErrors: () => AsyncResult<T, E>[];
194
+ getAllErrorValues: () => E[];
195
+ getAllLoading: () => AsyncResult<T, E>[];
196
+ getAllLoadingPromises: () => Promise<Result<T, E>>[];
197
+ log: (name?: string) => void;
198
+ debug: (name?: string) => () => void;
199
+ }, AsyncResultList<T, E> | {
200
+ readonly tasks: Map<string, {
201
+ key: string;
202
+ result: {
203
+ state: {
204
+ status: "idle";
205
+ } | {
206
+ status: "loading";
207
+ promise: {
208
+ then: <TResult1 = Result<T, E>, TResult2 = never>(onfulfilled?: ((value: Result<T, E>) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>;
209
+ catch: <TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined) => Promise<Result<T, E> | TResult>;
210
+ finally: (onfinally?: (() => void) | null | undefined) => Promise<Result<T, E>>;
211
+ readonly [Symbol.toStringTag]: string;
212
+ };
213
+ } | {
214
+ status: "success";
215
+ value: vue.UnwrapRef<T>;
216
+ } | {
217
+ status: "error";
218
+ error: vue.UnwrapRef<E>;
219
+ };
220
+ isSuccess: () => boolean;
221
+ isError: () => boolean;
222
+ isIdle: () => boolean;
223
+ isLoading: () => boolean;
224
+ unwrapOrNull: () => T | null;
225
+ unwrapOrThrow: () => T;
226
+ unwrapErrorOrNull: () => E | null;
227
+ updateFromValue: (value: T) => AsyncResult<T, E>;
228
+ updateFromError: (error: E) => AsyncResult<T, E>;
229
+ updateFromValuePromise: (promise: Promise<T>) => AsyncResult<T, E>;
230
+ waitForSettled: () => Promise<AsyncResult<T, E>>;
231
+ toResultPromise: () => Promise<Result<T, E>>;
232
+ toValueOrThrowPromise: () => Promise<T>;
233
+ toValueOrNullPromise: () => Promise<T | null>;
234
+ updateFromResultPromise: (promise: Promise<Result<T, E>>) => AsyncResult<T, E>;
235
+ listen: (listener: unwrapped_core.AsyncResultListener<T, E>, immediate?: boolean) => () => void;
236
+ listenUntilSettled: (listener: unwrapped_core.AsyncResultListener<T, E>, immediate?: boolean) => () => void;
237
+ mirror: (other: AsyncResult<T, E>) => () => void;
238
+ mirrorUntilSettled: (other: AsyncResult<T, E>) => () => void;
239
+ chain: <O, E2 extends ErrorBase = ErrorBase>(fn: unwrapped_core.ChainStep<T, O, E | E2>) => AsyncResult<O, E | E2>;
240
+ flatChain: <O, E2 extends ErrorBase = ErrorBase>(fn: FlatChainStep<T, O, E | E2>) => AsyncResult<O, E | E2>;
241
+ runInPlace: (generatorFunc: () => AsyncResultGenerator<T>) => AsyncResult<T, E>;
242
+ log: (name?: string) => void;
243
+ debug: (name?: string) => () => void;
244
+ [Symbol.iterator]: () => Generator<AsyncResult<T, E>, T, any>;
245
+ };
246
+ unsub: () => void;
247
+ }> & Omit<Map<string, unwrapped_core.AsyncResultListItem<T, E>>, keyof Map<any, any>>;
248
+ readonly length: number;
249
+ readonly items: {
250
+ state: {
251
+ status: "idle";
252
+ } | {
253
+ status: "loading";
254
+ promise: {
255
+ then: <TResult1 = Result<T, E>, TResult2 = never>(onfulfilled?: ((value: Result<T, E>) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>;
256
+ catch: <TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined) => Promise<Result<T, E> | TResult>;
257
+ finally: (onfinally?: (() => void) | null | undefined) => Promise<Result<T, E>>;
258
+ readonly [Symbol.toStringTag]: string;
259
+ };
260
+ } | {
261
+ status: "success";
262
+ value: vue.UnwrapRef<T>;
263
+ } | {
264
+ status: "error";
265
+ error: vue.UnwrapRef<E>;
266
+ };
267
+ isSuccess: () => boolean;
268
+ isError: () => boolean;
269
+ isIdle: () => boolean;
270
+ isLoading: () => boolean;
271
+ unwrapOrNull: () => T | null;
272
+ unwrapOrThrow: () => T;
273
+ unwrapErrorOrNull: () => E | null;
274
+ updateFromValue: (value: T) => AsyncResult<T, E>;
275
+ updateFromError: (error: E) => AsyncResult<T, E>;
276
+ updateFromValuePromise: (promise: Promise<T>) => AsyncResult<T, E>;
277
+ waitForSettled: () => Promise<AsyncResult<T, E>>;
278
+ toResultPromise: () => Promise<Result<T, E>>;
279
+ toValueOrThrowPromise: () => Promise<T>;
280
+ toValueOrNullPromise: () => Promise<T | null>;
281
+ updateFromResultPromise: (promise: Promise<Result<T, E>>) => AsyncResult<T, E>;
282
+ listen: (listener: unwrapped_core.AsyncResultListener<T, E>, immediate?: boolean) => () => void;
283
+ listenUntilSettled: (listener: unwrapped_core.AsyncResultListener<T, E>, immediate?: boolean) => () => void;
284
+ mirror: (other: AsyncResult<T, E>) => () => void;
285
+ mirrorUntilSettled: (other: AsyncResult<T, E>) => () => void;
286
+ chain: <O, E2 extends ErrorBase = ErrorBase>(fn: unwrapped_core.ChainStep<T, O, E | E2>) => AsyncResult<O, E | E2>;
287
+ flatChain: <O, E2 extends ErrorBase = ErrorBase>(fn: FlatChainStep<T, O, E | E2>) => AsyncResult<O, E | E2>;
288
+ runInPlace: (generatorFunc: () => AsyncResultGenerator<T>) => AsyncResult<T, E>;
289
+ log: (name?: string) => void;
290
+ debug: (name?: string) => () => void;
291
+ [Symbol.iterator]: () => Generator<AsyncResult<T, E>, T, any>;
292
+ }[];
293
+ state: unwrapped_core.AsyncResultListState;
294
+ listen: (listener: (taskQueue: AsyncResultList<T, E>) => void) => () => void;
295
+ add: (key: string, task: AsyncResult<T, E>, removeOnSettle?: boolean) => AsyncResult<T, E>;
296
+ clear: () => void;
297
+ anyLoading: () => boolean;
298
+ getAllFiltered: (predicate: (task: AsyncResult<T, E>) => boolean) => AsyncResult<T, E>[];
299
+ getAllFilteredAndMap: <U>(filterPredicate: (task: AsyncResult<T, E>) => boolean, mapFunc: (task: AsyncResult<T, E>) => U) => U[];
300
+ getAllSuccess: () => AsyncResult<T, E>[];
301
+ getAllSuccessValues: () => T[];
302
+ getAllErrors: () => AsyncResult<T, E>[];
303
+ getAllErrorValues: () => E[];
304
+ getAllLoading: () => AsyncResult<T, E>[];
305
+ getAllLoadingPromises: () => Promise<Result<T, E>>[];
306
+ log: (name?: string) => void;
307
+ debug: (name?: string) => () => void;
308
+ }>;
309
+
117
310
  interface CustomSlots<E extends ErrorBase = ErrorBase> {
118
311
  loading?: () => VNode;
119
312
  error?: (props: {
120
313
  error: E;
121
314
  }) => VNode;
315
+ idle?: () => VNode;
122
316
  }
123
317
  /**
124
- * Builds a custom AsyncResultLoader component with predefined slots for loading and error states.
318
+ * Factory function to create a component that displays different content based on an AsyncResult's state. Provides slots for loading, error, idle, and success states and passes the relevant data to each slot, and are typed appropriately.
319
+ * @param slots predefined slots for loading, error, and idle states. Useful for not having to repeat the same template for displaying a framework-specific spinner while in loading state, or a custom error message.
320
+ * @param name Optional internal name for the component
321
+ * @returns An instantiable component that accepts an AsyncResult prop and a default slot for the success state.
125
322
  *
126
- * Useful for creating reusable components with consistent loading and error handling UI (eg. framework-specific spinners, etc...).
323
+ * @example
324
+ * // loaders.ts - Create reusable loader with default loading/error UI
325
+ * const MyLoader = makeAsyncResultLoader({
326
+ * loading: () => h(Spinner),
327
+ * error: ({ error }) => h(ErrorDisplay, { error }),
328
+ * idle: () => h('div', 'Ready')
329
+ * });
127
330
  *
128
- * @param slots the custom slots for loading and error states
129
- * @returns a Vue component that uses the provided slots
331
+ * // MyPage.vue - Use the loader with custom success content
332
+ * <MyLoader :result="myAsyncResult">
333
+ * <template #default="{ value }">
334
+ * <UserProfile :user="value" />
335
+ * </template>
336
+ * </MyLoader>
130
337
  */
131
- declare function buildCustomAsyncResultLoader<T, E extends ErrorBase = ErrorBase>(slots: CustomSlots<E>): vue.DefineComponent<vue.ExtractPropTypes<{
338
+ declare function makeAsyncResultLoader<T, E extends ErrorBase = ErrorBase>(slots: CustomSlots<E>, name?: string): vue.DefineComponent<vue.ExtractPropTypes<{
132
339
  result: {
133
340
  type: () => AsyncResult<T, E>;
134
341
  required: true;
135
342
  };
136
343
  }>, () => VNode<vue.RendererNode, vue.RendererElement, {
137
344
  [key: string]: any;
138
- }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
345
+ }> | VNode<vue.RendererNode, vue.RendererElement, {
346
+ [key: string]: any;
347
+ }>[], {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
139
348
  result: {
140
349
  type: () => AsyncResult<T, E>;
141
350
  required: true;
142
351
  };
143
- }>> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
352
+ }>> & Readonly<{}>, {}, SlotsType<CustomSlots<E> & {
353
+ default: {
354
+ value: T;
355
+ };
356
+ }>, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
144
357
 
145
- export { AsyncResultLoader, type LazyActionRef, buildCustomAsyncResultLoader, useAction, useAsyncResultRef, useAsyncResultRefFromPromise, useGenerator, useLazyAction, useLazyGenerator, useReactiveChain, useReactiveGenerator };
358
+ export { type LazyActionRef, makeAsyncResultLoader, useAction, useAsyncResultList, useAsyncResultRef, useAsyncResultRefFromPromise, useGenerator, useLazyAction, useLazyGenerator, useReactiveChain, useReactiveGenerator };