@typed/async-data 0.13.1 → 1.0.0-beta.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 ADDED
@@ -0,0 +1,159 @@
1
+ # @typed/async-data
2
+
3
+ > **Beta:** This package is in beta; APIs may change.
4
+
5
+ `@typed/async-data` provides a typed model for async data state: **NoData**, **Loading**, **Success**, **Failure**, and **Optimistic** (plus **Refreshing** as Success/Failure with progress). It integrates with Effect Schema for codecs and offers pattern matching and transformers (map, flatMap, mapError). Use it for UI state that represents remote data, loading indicators, and optimistic updates.
6
+
7
+ ## Dependencies
8
+
9
+ - `effect`
10
+
11
+ ## API overview
12
+
13
+ - **Type:** `AsyncData<A, E>` — union of NoData | Loading | Success\<A\> | Failure\<E\> | Optimistic\<A, E\>.
14
+ - **Schema:** `AsyncData(A, E)` — builds an Effect Schema codec for `AsyncData` given value and error schemas.
15
+ - **Constructors:** `NoData`, `loading(progress?)`, `success(value, progress?)`, `failure(cause, progress?)`, `optimistic(previous, value)`.
16
+ - **Guards:** `isNoData`, `isLoading`, `isSuccess`, `isFailure`, `isOptimistic`, `isPending`, `isRefreshing`, `isAsyncData`.
17
+ - **Pattern matching:** `match(data, { NoData, Loading, Success, Failure, Optimistic })`.
18
+ - **Helpers:** `startLoading`, `stopLoading`; `getSuccess`, `getCause`, `getError`.
19
+ - **Transformers:** `map`, `flatMap`, `mapError`; `fromExit`, `fromResult`.
20
+
21
+ ## API reference
22
+
23
+ ### Types
24
+
25
+ - **`Progress`** — `{ readonly loaded: number; readonly total?: number }`. Used for loading/refresh progress.
26
+ - **`NoData`** — `{ readonly _tag: "NoData" }`. Initial state before any load.
27
+ - **`Loading`** — `{ readonly _tag: "Loading"; readonly progress?: Progress }`. Load in progress.
28
+ - **`Success<A>`** — `{ readonly _tag: "Success"; readonly value: A; readonly progress?: Progress }`. Loaded value; optional progress when refreshing.
29
+ - **`Failure<E>`** — `{ readonly _tag: "Failure"; readonly cause: Cause.Cause<E>; readonly progress?: Progress }`. Error state; optional progress when refreshing.
30
+ - **`Optimistic<A, E>`** — `{ readonly _tag: "Optimistic"; readonly value: A; readonly previous: AsyncData<A, E> }`. Optimistic value with previous state.
31
+ - **`AsyncData<A, E>`** — `NoData | Loading | Success<A> | Failure<E> | Optimistic<A, E>`.
32
+ - **`Refreshing<A, E>`** — `(Success<A> | Failure<E>) & { readonly progress: Progress }`. Success or Failure that is currently refreshing.
33
+
34
+ ### Schema
35
+
36
+ ```ts
37
+ AsyncData(A, E): Schema.Codec<AsyncData<A, E>, ...>
38
+ ```
39
+
40
+ Builds an Effect Schema codec for `AsyncData` given value schema `A` and error schema `E`.
41
+
42
+ ### Constructors
43
+
44
+ ```ts
45
+ NoData: NoData
46
+ loading(progress?: Progress): Loading
47
+ success<A>(value: A, progress?: Progress): Success<A>
48
+ failure<E>(cause: Cause.Cause<E>, progress?: Progress): Failure<E>
49
+ optimistic<A, E>(previous: AsyncData<A, E>, value: A): Optimistic<A, E>
50
+ ```
51
+
52
+ ### Guards
53
+
54
+ ```ts
55
+ isNoData<A, E>(asyncData: AsyncData<A, E>): asyncData is NoData
56
+ isLoading<A, E>(asyncData: AsyncData<A, E>): asyncData is Loading
57
+ isSuccess<A, E>(asyncData: AsyncData<A, E>): asyncData is Success<A>
58
+ isFailure<A, E>(asyncData: AsyncData<A, E>): asyncData is Failure<E>
59
+ isOptimistic<A, E>(asyncData: AsyncData<A, E>): asyncData is Optimistic<A, E>
60
+ isAsyncData<A, E>(u: unknown): u is AsyncData<A, E>
61
+ isRefreshing<A, E>(asyncData: AsyncData<A, E>): asyncData is Refreshing<A, E>
62
+ isPending<A, E>(asyncData: AsyncData<A, E>): asyncData is Loading | Refreshing<A, E>
63
+ ```
64
+
65
+ ### Pattern matching
66
+
67
+ ```ts
68
+ data.pipe(
69
+ AsyncData.match({
70
+ NoData: (data) => R1,
71
+ Loading: (data) => R2,
72
+ Failure: (cause, data) => R3,
73
+ Success: (value, data) => R4,
74
+ Optimistic: (value, data) => R5,
75
+ })
76
+ )
77
+ ```
78
+
79
+ Returns a unified result type from the matching branch. Callbacks receive the variant payload (and full variant for `Failure`/`Success`/`Optimistic`).
80
+
81
+ ### Helpers
82
+
83
+ ```ts
84
+ startLoading<A, E>(data: AsyncData<A, E>, progress?: Progress): AsyncData<A, E>
85
+ ```
86
+
87
+ Puts data into a loading/refreshing state: Success/Failure become refreshing with optional progress; Optimistic recurs on `previous`; NoData/Loading become Loading (with optional progress).
88
+
89
+ ```ts
90
+ stopLoading<A, E>(data: AsyncData<A, E>): AsyncData<A, E>
91
+ ```
92
+
93
+ Removes progress from Success/Failure/Optimistic (stops refreshing); NoData/Loading unchanged.
94
+
95
+ ```ts
96
+ getSuccess<A, E>(data: AsyncData<A, E>): Option.Option<A>
97
+ getCause<A, E>(data: AsyncData<A, E>): Option.Option<Cause.Cause<E>>
98
+ getError<A, E>(data: AsyncData<A, E>): Option.Option<E>
99
+ ```
100
+
101
+ Extract the success value, failure cause, or first error from the variant (or `Option.none` when not applicable).
102
+
103
+ ### Transformers
104
+
105
+ ```ts
106
+ data.pipe(AsyncData.map((a: A) => B))
107
+ ```
108
+
109
+ Maps the success/optimistic value; NoData, Loading, and Failure are unchanged.
110
+
111
+ ```ts
112
+ data.pipe(
113
+ AsyncData.flatMap((value: A, data: Success<A> | Optimistic<A, E>) => AsyncData<B, E2>)
114
+ )
115
+ ```
116
+
117
+ Chains on success or optimistic; NoData, Loading, and Failure are unchanged.
118
+
119
+ ```ts
120
+ data.pipe(AsyncData.mapError((e: E) => E2))
121
+ ```
122
+
123
+ Maps the failure error type; Success, NoData, Loading unchanged; Optimistic recurs on `previous`.
124
+
125
+ ```ts
126
+ fromExit<A, E>(exit: Exit.Exit<A, E>): AsyncData<A, E>
127
+ fromResult<A, E>(result: Result.Result<A, E>): AsyncData<A, E>
128
+ ```
129
+
130
+ Convert an Effect `Exit` or `Result` to `AsyncData`.
131
+
132
+ ## Example
133
+
134
+ ```ts
135
+ import { Option } from "effect";
136
+ import * as AsyncData from "@typed/async-data";
137
+
138
+ // Success and match
139
+ const data = AsyncData.success({ id: 1, name: "Alice" });
140
+ const message = data.pipe(
141
+ AsyncData.match({
142
+ NoData: () => "no data",
143
+ Loading: () => "loading...",
144
+ Failure: (cause) => `error: ${cause}`,
145
+ Success: (user) => `user: ${user.name}`,
146
+ Optimistic: (user) => `optimistic: ${user.name}`,
147
+ })
148
+ );
149
+ // message === "user: Alice"
150
+
151
+ // From Result and getSuccess
152
+ const result = { _tag: "Success" as const, success: { id: 2, name: "Bob" } };
153
+ const data2 = AsyncData.fromResult(result);
154
+ const name = AsyncData.getSuccess(data2).pipe(
155
+ Option.map((u) => u.name),
156
+ Option.getOrElse(() => "unknown"),
157
+ );
158
+ // name === "Bob"
159
+ ```
package/dist/index.d.ts CHANGED
@@ -1,4 +1,92 @@
1
- export * from './AsyncData.js';
2
- export * from './LazyRef.js';
3
- export * from './Progress.js';
4
- export * from './TypeId.js';
1
+ import * as Cause from "effect/Cause";
2
+ import * as Exit from "effect/Exit";
3
+ import * as Option from "effect/Option";
4
+ import * as Result from "effect/Result";
5
+ import * as Schema from "effect/Schema";
6
+ import type { Unify } from "effect/Unify";
7
+ export interface Progress {
8
+ readonly loaded: number;
9
+ readonly total?: number | undefined;
10
+ }
11
+ export interface NoData {
12
+ readonly _tag: "NoData";
13
+ }
14
+ export interface Loading {
15
+ readonly _tag: "Loading";
16
+ readonly progress?: Progress | undefined;
17
+ }
18
+ export interface Success<A> {
19
+ readonly _tag: "Success";
20
+ readonly value: A;
21
+ readonly progress?: Progress | undefined;
22
+ }
23
+ export interface Failure<E> {
24
+ readonly _tag: "Failure";
25
+ readonly cause: Cause.Cause<E>;
26
+ readonly progress?: Progress | undefined;
27
+ }
28
+ export interface Optimistic<A, E> {
29
+ readonly _tag: "Optimistic";
30
+ readonly value: A;
31
+ readonly previous: AsyncData<A, E>;
32
+ }
33
+ export type AsyncData<A, E> = NoData | Loading | Success<A> | Failure<E> | Optimistic<A, E>;
34
+ export type Refreshing<A, E> = (Success<A> | Failure<E>) & {
35
+ readonly progress: Progress;
36
+ };
37
+ export declare const AsyncData: <const A extends Schema.Top, E extends Schema.Top>(A: A, E: E) => Schema.Codec<AsyncData<A["Type"], E["Type"]>, AsyncData<A["Encoded"], E["Encoded"]>, A["DecodingServices"] | E["DecodingServices"], A["EncodingServices"] | E["EncodingServices"]>;
38
+ export declare const isNoData: <A, E>(asyncData: AsyncData<A, E>) => asyncData is NoData;
39
+ export declare const isLoading: <A, E>(asyncData: AsyncData<A, E>) => asyncData is Loading;
40
+ export declare const isSuccess: <A, E>(asyncData: AsyncData<A, E>) => asyncData is Success<A>;
41
+ export declare const isFailure: <A, E>(asyncData: AsyncData<A, E>) => asyncData is Failure<E>;
42
+ export declare const isOptimistic: <A, E>(asyncData: AsyncData<A, E>) => asyncData is Optimistic<A, E>;
43
+ export declare const isAsyncData: <A, E>(u: unknown) => u is AsyncData<A, E>;
44
+ export declare const isRefreshing: <A, E>(asyncData: AsyncData<A, E>) => asyncData is Refreshing<A, E>;
45
+ export declare const isPending: <A, E>(asyncData: AsyncData<A, E>) => asyncData is Loading | Refreshing<A, E>;
46
+ export declare const NoData: NoData;
47
+ export declare const loading: (progress?: Progress) => Loading;
48
+ export declare const success: <A>(value: A, progress?: Progress) => Success<A>;
49
+ export declare const failure: <E>(cause: Cause.Cause<E>, progress?: Progress) => Failure<E>;
50
+ export declare const optimistic: <A, E>(previous: AsyncData<A, E>, value: A) => Optimistic<A, E>;
51
+ export declare const startLoading: <A, E>(data: AsyncData<A, E>, progress?: Progress) => AsyncData<A, E>;
52
+ export declare const stopLoading: <A, E>(data: AsyncData<A, E>) => AsyncData<A, E>;
53
+ export declare const match: {
54
+ <A, E, R1, R2, R3, R4, R5>(matchers: {
55
+ NoData: (data: NoData) => R1;
56
+ Loading: (data: Loading) => R2;
57
+ Failure: (cause: Cause.Cause<E>, data: Failure<E>) => R3;
58
+ Success: (value: A, data: Success<A>) => R4;
59
+ Optimistic: (value: A, data: Optimistic<A, E>) => R5;
60
+ }): (data: AsyncData<A, E>) => Unify<R1 | R2 | R3 | R4 | R5>;
61
+ <A, E, R1, R2, R3, R4, R5>(data: AsyncData<A, E>, matchers: {
62
+ NoData: (data: NoData) => R1;
63
+ Loading: (data: Loading) => R2;
64
+ Failure: (cause: Cause.Cause<E>, data: Failure<E>) => R3;
65
+ Success: (value: A, data: Success<A>) => R4;
66
+ Optimistic: (value: A, data: Optimistic<A, E>) => R5;
67
+ }): Unify<R1 | R2 | R3 | R4 | R5>;
68
+ };
69
+ export declare function getSuccess<A, E>(data: AsyncData<A, E>): Option.Option<A>;
70
+ /**
71
+ * @since 1.0.0
72
+ */
73
+ export declare function getCause<A, E>(data: AsyncData<A, E>): Option.Option<Cause.Cause<E>>;
74
+ /**
75
+ * @since 1.0.0
76
+ */
77
+ export declare function getError<A, E>(data: AsyncData<A, E>): Option.Option<E>;
78
+ export declare const map: {
79
+ <A, B>(f: (a: A) => B): <E>(data: AsyncData<A, E>) => AsyncData<B, E>;
80
+ <A, E, B>(data: AsyncData<A, E>, f: (a: A) => B): AsyncData<B, E>;
81
+ };
82
+ export declare const flatMap: {
83
+ <A, E, B, E2>(f: (a: A, data: Success<A> | Optimistic<A, E>) => AsyncData<B, E2>): (data: AsyncData<A, E>) => AsyncData<B, E | E2>;
84
+ <A, E, B, E2>(data: AsyncData<A, E>, f: (a: A, data: Success<A> | Optimistic<A, E>) => AsyncData<B, E>): AsyncData<B, E | E2>;
85
+ };
86
+ export declare const mapError: {
87
+ <A, E, E2>(f: (e: E) => E2): (data: AsyncData<A, E>) => AsyncData<A, E2>;
88
+ <A, E, E2>(data: AsyncData<A, E>, f: (e: E) => E2): AsyncData<A, E2>;
89
+ };
90
+ export declare const fromExit: <A, E>(exit: Exit.Exit<A, E>) => AsyncData<A, E>;
91
+ export declare const fromResult: <A, E>(result: Result.Result<A, E>) => AsyncData<A, E>;
92
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,169 @@
1
- export * from './AsyncData.js';
2
- export * from './LazyRef.js';
3
- export * from './Progress.js';
4
- export * from './TypeId.js';
5
- //# sourceMappingURL=index.js.map
1
+ import * as Cause from "effect/Cause";
2
+ import * as Exit from "effect/Exit";
3
+ import { dual } from "effect/Function";
4
+ import * as Option from "effect/Option";
5
+ import { hasProperty, isObject, isString } from "effect/Predicate";
6
+ import * as Result from "effect/Result";
7
+ import * as Schema from "effect/Schema";
8
+ export const AsyncData = (A, E) => {
9
+ const Progress = Schema.Struct({ loaded: Schema.Number, total: Schema.optional(Schema.Number) });
10
+ const NoData = Schema.Struct({ _tag: Schema.tag("NoData") });
11
+ const Loading = Schema.Struct({
12
+ _tag: Schema.tag("Loading"),
13
+ progress: Schema.optional(Progress),
14
+ });
15
+ const Success = Schema.Struct({
16
+ _tag: Schema.tag("Success"),
17
+ value: A,
18
+ progress: Schema.optional(Progress),
19
+ });
20
+ const Failure = Schema.Struct({
21
+ _tag: Schema.tag("Failure"),
22
+ cause: E,
23
+ progress: Schema.optional(Progress),
24
+ });
25
+ const Optimistic = Schema.Struct({
26
+ _tag: Schema.tag("Optimistic"),
27
+ value: A,
28
+ previous: Schema.suspend(() => AsyncData),
29
+ });
30
+ const AsyncData = Schema.Union([NoData, Loading, Success, Failure, Optimistic]);
31
+ return AsyncData;
32
+ };
33
+ export const isNoData = (asyncData) => asyncData._tag === "NoData";
34
+ export const isLoading = (asyncData) => asyncData._tag === "Loading";
35
+ export const isSuccess = (asyncData) => asyncData._tag === "Success";
36
+ export const isFailure = (asyncData) => asyncData._tag === "Failure";
37
+ export const isOptimistic = (asyncData) => asyncData._tag === "Optimistic";
38
+ const TAGS = new Set(["NoData", "Loading", "Success", "Failure", "Optimistic"]);
39
+ export const isAsyncData = (u) => isObject(u) && hasProperty(u, "_tag") && isString(u._tag) && TAGS.has(u._tag);
40
+ export const isRefreshing = (asyncData) => (asyncData._tag === "Success" || asyncData._tag === "Failure") &&
41
+ asyncData.progress !== undefined;
42
+ export const isPending = (asyncData) => asyncData._tag === "Loading" || isRefreshing(asyncData);
43
+ export const NoData = { _tag: "NoData" };
44
+ export const loading = (progress) => ({ _tag: "Loading", progress });
45
+ export const success = (value, progress) => ({
46
+ _tag: "Success",
47
+ value,
48
+ progress,
49
+ });
50
+ export const failure = (cause, progress) => ({
51
+ _tag: "Failure",
52
+ cause,
53
+ progress,
54
+ });
55
+ export const optimistic = (previous, value) => ({
56
+ _tag: "Optimistic",
57
+ value,
58
+ previous,
59
+ });
60
+ export const startLoading = (data, progress) => {
61
+ if (isSuccess(data)) {
62
+ return success(data.value, progress);
63
+ }
64
+ else if (isFailure(data)) {
65
+ return failure(data.cause, progress);
66
+ }
67
+ else if (isOptimistic(data)) {
68
+ return optimistic(startLoading(data.previous, progress), data.value);
69
+ }
70
+ else {
71
+ return loading(progress);
72
+ }
73
+ };
74
+ export const stopLoading = (data) => {
75
+ if (isSuccess(data)) {
76
+ return success(data.value);
77
+ }
78
+ else if (isFailure(data)) {
79
+ return failure(data.cause);
80
+ }
81
+ else if (isOptimistic(data)) {
82
+ return optimistic(stopLoading(data.previous), data.value);
83
+ }
84
+ else {
85
+ return data;
86
+ }
87
+ };
88
+ export const match = dual(2, (data, matchers) => {
89
+ if (isSuccess(data)) {
90
+ return matchers.Success(data.value, data);
91
+ }
92
+ else if (isFailure(data)) {
93
+ return matchers.Failure(data.cause, data);
94
+ }
95
+ else if (isLoading(data)) {
96
+ return matchers.Loading(data);
97
+ }
98
+ else if (isNoData(data)) {
99
+ return matchers.NoData(data);
100
+ }
101
+ else {
102
+ return matchers.Optimistic(data.value, data);
103
+ }
104
+ });
105
+ export function getSuccess(data) {
106
+ return match(data, {
107
+ NoData: Option.none,
108
+ Loading: Option.none,
109
+ Failure: Option.none,
110
+ Success: Option.some,
111
+ Optimistic: Option.some,
112
+ });
113
+ }
114
+ /**
115
+ * @since 1.0.0
116
+ */
117
+ export function getCause(data) {
118
+ return match(data, {
119
+ NoData: Option.none,
120
+ Loading: Option.none,
121
+ Failure: Option.some,
122
+ Success: Option.none,
123
+ Optimistic: Option.none,
124
+ });
125
+ }
126
+ /**
127
+ * @since 1.0.0
128
+ */
129
+ export function getError(data) {
130
+ return match(data, {
131
+ NoData: Option.none,
132
+ Loading: Option.none,
133
+ Failure: Cause.findErrorOption,
134
+ Success: Option.none,
135
+ Optimistic: Option.none,
136
+ });
137
+ }
138
+ export const map = dual(2, function map(data, f) {
139
+ if (isSuccess(data)) {
140
+ return success(f(data.value), data.progress);
141
+ }
142
+ else if (isOptimistic(data)) {
143
+ return optimistic(map(data.previous, f), f(data.value));
144
+ }
145
+ else {
146
+ return data;
147
+ }
148
+ });
149
+ export const flatMap = dual(2, function (data, f) {
150
+ if (isSuccess(data) || isOptimistic(data)) {
151
+ return f(data.value, data);
152
+ }
153
+ else {
154
+ return data;
155
+ }
156
+ });
157
+ export const mapError = dual(2, function mapError(data, f) {
158
+ if (isFailure(data)) {
159
+ return failure(Cause.map(data.cause, f), data.progress);
160
+ }
161
+ else if (isOptimistic(data)) {
162
+ return optimistic(mapError(data.previous, f), data.value);
163
+ }
164
+ else {
165
+ return data;
166
+ }
167
+ });
168
+ export const fromExit = (exit) => Exit.isSuccess(exit) ? success(exit.value) : failure(exit.cause);
169
+ export const fromResult = (result) => Result.isSuccess(result) ? success(result.success) : failure(Cause.fail(result.failure));
package/package.json CHANGED
@@ -1,39 +1,29 @@
1
1
  {
2
2
  "name": "@typed/async-data",
3
- "version": "0.13.1",
4
- "description": "Async Data for Effect",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
3
+ "version": "1.0.0-beta.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
7
  "type": "module",
8
- "keywords": [
9
- "async",
10
- "data",
11
- "effect",
12
- "typescript"
13
- ],
14
- "author": "Tylor Steinberger <tlsteinberger167@gmail.com>",
15
- "license": "MIT",
16
- "dependencies": {
17
- "@typed/lazy-ref": "^0.3.2",
18
- "effect": "^3.11.9"
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./*": {
14
+ "types": "./dist/*.d.ts",
15
+ "import": "./dist/*.js"
16
+ }
19
17
  },
20
- "peerDependencies": {
21
- "@typed/lazy-ref": "^0.3.2",
22
- "effect": "^3.11.9"
18
+ "dependencies": {
19
+ "effect": "4.0.0-beta.4"
23
20
  },
24
21
  "devDependencies": {
25
- "@biomejs/biome": "^1.9.4",
26
- "@effect/vitest": "^0.16.0",
27
- "@types/node": "^22.10.2",
28
- "typescript": "^5.4.2",
29
- "vitest": "^2.1.8"
22
+ "typescript": "5.9.3",
23
+ "vitest": "4.0.18"
30
24
  },
31
25
  "scripts": {
32
26
  "build": "tsc",
33
- "dev": "tsc --watch",
34
- "lint": "biome lint --write",
35
- "test:watch": "vitest --typecheck",
36
- "test": "vitest run --typecheck",
37
- "typecheck": "tsc --noEmit"
27
+ "test": "vitest run --passWithNoTests"
38
28
  }
39
29
  }