@nlozgachev/pipelined 0.63.0 → 0.65.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/dist/types.mjs CHANGED
@@ -1,199 +1,195 @@
1
- // src/Types/Brand.ts
2
- var Brand = {
3
- /**
4
- * Returns a constructor that wraps a value of type T in brand K.
5
- * The resulting function performs an unchecked cast — only use when the raw
6
- * value is known to satisfy the brand's invariants.
7
- *
8
- * @example
9
- * ```ts
10
- * type PositiveNumber = Brand<"PositiveNumber", number>;
11
- * const toPositiveNumber = Brand.wrap<"PositiveNumber", number>();
12
- *
13
- * const n: PositiveNumber = toPositiveNumber(42);
14
- * ```
15
- */
16
- wrap: () => (value) => value,
17
- /**
18
- * Strips the brand and returns the underlying value.
19
- * Since Brand<K, T> extends T this is rarely needed, but can improve readability.
20
- *
21
- * @example
22
- * ```ts
23
- * type UserId = Brand<"UserId", string>;
24
- * const toUserId = Brand.wrap<"UserId", string>();
25
- * const userId: UserId = toUserId("user-123");
26
- * const raw: string = Brand.unwrap(userId); // "user-123"
27
- * ```
28
- */
29
- unwrap: (branded) => branded
1
+ //#region src/Types/Brand.ts
2
+ const Brand = {
3
+ /**
4
+ * Returns a constructor that wraps a value of type T in brand K.
5
+ * The resulting function performs an unchecked cast — only use when the raw
6
+ * value is known to satisfy the brand's invariants.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * type PositiveNumber = Brand<"PositiveNumber", number>;
11
+ * const toPositiveNumber = Brand.wrap<"PositiveNumber", number>();
12
+ *
13
+ * const n: PositiveNumber = toPositiveNumber(42);
14
+ * ```
15
+ */
16
+ wrap: () => (value) => value,
17
+ /**
18
+ * Strips the brand and returns the underlying value.
19
+ * Since Brand<K, T> extends T this is rarely needed, but can improve readability.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * type UserId = Brand<"UserId", string>;
24
+ * const toUserId = Brand.wrap<"UserId", string>();
25
+ * const userId: UserId = toUserId("user-123");
26
+ * const raw: string = Brand.unwrap(userId); // "user-123"
27
+ * ```
28
+ */
29
+ unwrap: (branded) => branded
30
30
  };
31
-
32
- // src/Types/Duration.ts
33
- var wrap = Brand.wrap();
34
- var Duration = {
35
- /**
36
- * Creates a Duration from milliseconds.
37
- *
38
- * @example
39
- * ```ts
40
- * Duration.milliseconds(500); // 500ms Duration
41
- * ```
42
- */
43
- milliseconds: (ms) => wrap(ms),
44
- /**
45
- * Creates a Duration from seconds.
46
- *
47
- * @example
48
- * ```ts
49
- * Duration.seconds(2); // 2000ms Duration
50
- * ```
51
- */
52
- seconds: (s) => wrap(s * 1e3),
53
- /**
54
- * Creates a Duration from minutes.
55
- *
56
- * @example
57
- * ```ts
58
- * Duration.minutes(5); // 300000ms Duration
59
- * ```
60
- */
61
- minutes: (m) => wrap(m * 60 * 1e3),
62
- /**
63
- * Creates a Duration from hours.
64
- *
65
- * @example
66
- * ```ts
67
- * Duration.hours(1); // 3600000ms Duration
68
- * ```
69
- */
70
- hours: (h) => wrap(h * 60 * 60 * 1e3),
71
- /**
72
- * Creates a Duration from days.
73
- *
74
- * @example
75
- * ```ts
76
- * Duration.days(1); // 86400000ms Duration
77
- * ```
78
- */
79
- days: (d) => wrap(d * 24 * 60 * 60 * 1e3),
80
- // --- to ---
81
- to: {
82
- /**
83
- * Converts a Duration back to raw milliseconds.
84
- *
85
- * @example
86
- * ```ts
87
- * Duration.to.milliseconds(Duration.seconds(2)); // 2000
88
- * ```
89
- */
90
- milliseconds: (d) => Brand.unwrap(d),
91
- /**
92
- * Converts a Duration to seconds.
93
- *
94
- * @example
95
- * ```ts
96
- * Duration.to.seconds(Duration.milliseconds(2500)); // 2.5
97
- * ```
98
- */
99
- seconds: (d) => Brand.unwrap(d) / 1e3,
100
- /**
101
- * Converts a Duration to minutes.
102
- *
103
- * @example
104
- * ```ts
105
- * Duration.to.minutes(Duration.seconds(120)); // 2
106
- * ```
107
- */
108
- minutes: (d) => Brand.unwrap(d) / (60 * 1e3),
109
- /**
110
- * Converts a Duration to hours.
111
- *
112
- * @example
113
- * ```ts
114
- * Duration.to.hours(Duration.minutes(90)); // 1.5
115
- * ```
116
- */
117
- hours: (d) => Brand.unwrap(d) / (60 * 60 * 1e3),
118
- /**
119
- * Converts a Duration to days.
120
- *
121
- * @example
122
- * ```ts
123
- * Duration.to.days(Duration.hours(36)); // 1.5
124
- * ```
125
- */
126
- days: (d) => Brand.unwrap(d) / (24 * 60 * 60 * 1e3)
127
- },
128
- /**
129
- * Adds two Durations together.
130
- *
131
- * @example
132
- * ```ts
133
- * pipe(Duration.seconds(1), Duration.add(Duration.milliseconds(500))); // 1500ms
134
- * ```
135
- */
136
- add: (other) => (self) => wrap(Brand.unwrap(self) + Brand.unwrap(other)),
137
- /**
138
- * Subtracts the other Duration from this one.
139
- *
140
- * @example
141
- * ```ts
142
- * pipe(Duration.seconds(1), Duration.subtract(Duration.milliseconds(500))); // 500ms
143
- * ```
144
- */
145
- subtract: (other) => (self) => wrap(Brand.unwrap(self) - Brand.unwrap(other))
31
+ //#endregion
32
+ //#region src/Types/RetryPolicy.ts
33
+ const RetryPolicy = {
34
+ /**
35
+ * Creates a RetryPolicy with a constant delay between retry attempts.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const policy = RetryPolicy.constant({
40
+ * attempts: 3,
41
+ * delay: Duration.seconds(1),
42
+ * });
43
+ * ```
44
+ */
45
+ constant: (options) => ({
46
+ attempts: Math.max(1, options.attempts),
47
+ getDelay: () => options.delay
48
+ }),
49
+ /**
50
+ * Creates a RetryPolicy with exponential backoff delays between attempts.
51
+ * An optional `factor` (default 2) controls the growth rate.
52
+ * An optional `jitter` (default false) adds randomized variance to prevent thundering herd problems.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * const policy = RetryPolicy.exponential({
57
+ * attempts: 5,
58
+ * initial: Duration.milliseconds(100),
59
+ * factor: 2,
60
+ * jitter: true,
61
+ * });
62
+ * ```
63
+ */
64
+ exponential: (options) => {
65
+ const attempts = Math.max(1, options.attempts);
66
+ const initialMs = Duration.to.milliseconds(options.initial);
67
+ const factor = options.factor ?? 2;
68
+ const jitter = options.jitter ?? false;
69
+ return {
70
+ attempts,
71
+ getDelay: (attempt) => {
72
+ const rawMs = initialMs * factor ** Math.max(0, attempt - 1);
73
+ const finalMs = jitter ? Math.random() * rawMs : rawMs;
74
+ return Duration.milliseconds(finalMs);
75
+ }
76
+ };
77
+ }
146
78
  };
147
-
148
- // src/Types/RetryPolicy.ts
149
- var RetryPolicy = {
150
- /**
151
- * Creates a RetryPolicy with a constant delay between retry attempts.
152
- *
153
- * @example
154
- * ```ts
155
- * const policy = RetryPolicy.constant({
156
- * attempts: 3,
157
- * delay: Duration.seconds(1),
158
- * });
159
- * ```
160
- */
161
- constant: (options) => ({
162
- attempts: Math.max(1, options.attempts),
163
- getDelay: () => options.delay
164
- }),
165
- /**
166
- * Creates a RetryPolicy with exponential backoff delays between attempts.
167
- * An optional `factor` (default 2) controls the growth rate.
168
- * An optional `jitter` (default false) adds randomized variance to prevent thundering herd problems.
169
- *
170
- * @example
171
- * ```ts
172
- * const policy = RetryPolicy.exponential({
173
- * attempts: 5,
174
- * initial: Duration.milliseconds(100),
175
- * factor: 2,
176
- * jitter: true,
177
- * });
178
- * ```
179
- */
180
- exponential: (options) => {
181
- const attempts = Math.max(1, options.attempts);
182
- const initialMs = Duration.to.milliseconds(options.initial);
183
- const factor = options.factor ?? 2;
184
- const jitter = options.jitter ?? false;
185
- return {
186
- attempts,
187
- getDelay: (attempt) => {
188
- const rawMs = initialMs * factor ** Math.max(0, attempt - 1);
189
- const finalMs = jitter ? Math.random() * rawMs : rawMs;
190
- return Duration.milliseconds(finalMs);
191
- }
192
- };
193
- }
194
- };
195
- export {
196
- Brand,
197
- Duration,
198
- RetryPolicy
79
+ //#endregion
80
+ //#region src/Types/Duration.ts
81
+ const wrap = Brand.wrap();
82
+ const Duration = {
83
+ /**
84
+ * Creates a Duration from milliseconds.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * Duration.milliseconds(500); // 500ms Duration
89
+ * ```
90
+ */
91
+ milliseconds: (ms) => wrap(ms),
92
+ /**
93
+ * Creates a Duration from seconds.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * Duration.seconds(2); // 2000ms Duration
98
+ * ```
99
+ */
100
+ seconds: (s) => wrap(s * 1e3),
101
+ /**
102
+ * Creates a Duration from minutes.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * Duration.minutes(5); // 300000ms Duration
107
+ * ```
108
+ */
109
+ minutes: (m) => wrap(m * 60 * 1e3),
110
+ /**
111
+ * Creates a Duration from hours.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * Duration.hours(1); // 3600000ms Duration
116
+ * ```
117
+ */
118
+ hours: (h) => wrap(h * 60 * 60 * 1e3),
119
+ /**
120
+ * Creates a Duration from days.
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * Duration.days(1); // 86400000ms Duration
125
+ * ```
126
+ */
127
+ days: (d) => wrap(d * 24 * 60 * 60 * 1e3),
128
+ to: {
129
+ /**
130
+ * Converts a Duration back to raw milliseconds.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * Duration.to.milliseconds(Duration.seconds(2)); // 2000
135
+ * ```
136
+ */
137
+ milliseconds: (d) => Brand.unwrap(d),
138
+ /**
139
+ * Converts a Duration to seconds.
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * Duration.to.seconds(Duration.milliseconds(2500)); // 2.5
144
+ * ```
145
+ */
146
+ seconds: (d) => Brand.unwrap(d) / 1e3,
147
+ /**
148
+ * Converts a Duration to minutes.
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * Duration.to.minutes(Duration.seconds(120)); // 2
153
+ * ```
154
+ */
155
+ minutes: (d) => Brand.unwrap(d) / 6e4,
156
+ /**
157
+ * Converts a Duration to hours.
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * Duration.to.hours(Duration.minutes(90)); // 1.5
162
+ * ```
163
+ */
164
+ hours: (d) => Brand.unwrap(d) / 36e5,
165
+ /**
166
+ * Converts a Duration to days.
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * Duration.to.days(Duration.hours(36)); // 1.5
171
+ * ```
172
+ */
173
+ days: (d) => Brand.unwrap(d) / 864e5
174
+ },
175
+ /**
176
+ * Adds two Durations together.
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * pipe(Duration.seconds(1), Duration.add(Duration.milliseconds(500))); // 1500ms
181
+ * ```
182
+ */
183
+ add: (other) => (self) => wrap(Brand.unwrap(self) + Brand.unwrap(other)),
184
+ /**
185
+ * Subtracts the other Duration from this one.
186
+ *
187
+ * @example
188
+ * ```ts
189
+ * pipe(Duration.seconds(1), Duration.subtract(Duration.milliseconds(500))); // 500ms
190
+ * ```
191
+ */
192
+ subtract: (other) => (self) => wrap(Brand.unwrap(self) - Brand.unwrap(other))
199
193
  };
194
+ //#endregion
195
+ export { Brand, Duration, RetryPolicy };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nlozgachev/pipelined",
3
- "version": "0.63.0",
3
+ "version": "0.65.0",
4
4
  "description": "Opinionated functional abstractions for TypeScript",
5
5
  "license": "BSD-3-Clause",
6
6
  "homepage": "https://pipelined.lozgachev.dev",
@@ -74,7 +74,7 @@
74
74
  }
75
75
  },
76
76
  "scripts": {
77
- "build": "tsup",
77
+ "build": "tsdown",
78
78
  "test": "vitest run",
79
79
  "test:coverage": "vitest run --coverage",
80
80
  "bench": "vitest bench",
@@ -85,21 +85,24 @@
85
85
  "format": "dprint fmt && dprint fmt --config dprint.md.json \"docs/**/*.md\" \"docs/**/*.mdx\" \"README.md\"",
86
86
  "format:check": "dprint check && dprint check --config dprint.md.json \"docs/**/*.md\" \"docs/**/*.mdx\" \"README.md\"",
87
87
  "docs:dev": "pnpm --filter pipelined-docs dev",
88
- "docs:build": "pnpm --filter pipelined-docs build"
88
+ "docs:build": "pnpm --filter pipelined-docs build",
89
+ "check": "pnpm typecheck && pnpm lint && pnpm format:check"
89
90
  },
90
91
  "devDependencies": {
91
- "@size-limit/esbuild": "13.0.3",
92
- "@size-limit/file": "13.0.3",
93
- "@types/node": "26.2.0",
94
- "@vitest/coverage-v8": "4.1.10",
95
- "dprint": "0.55.2",
92
+ "@arethetypeswrong/core": "0.18.5",
93
+ "@size-limit/esbuild": "14.1.0",
94
+ "@size-limit/file": "14.1.0",
95
+ "@types/node": "26.6.4",
96
+ "@vitest/coverage-v8": "5.0.3",
97
+ "dprint": "0.60.1",
96
98
  "esbuild": "0.28.2",
97
- "fast-check": "4.9.0",
98
- "oxlint": "1.78.0",
99
- "size-limit": "13.0.3",
100
- "tsup": "8.5.1",
99
+ "fast-check": "4.10.2",
100
+ "oxlint": "1.87.0",
101
+ "publint": "0.3.24",
102
+ "size-limit": "14.1.0",
103
+ "tsdown": "0.23.0",
101
104
  "typescript": "6.0.3",
102
- "vitest": "4.1.10"
105
+ "vitest": "5.0.3"
103
106
  },
104
107
  "size-limit": [
105
108
  {
@@ -108,7 +111,10 @@
108
111
  "path": "dist/index.mjs",
109
112
  "limit": "18 KB",
110
113
  "gzip": true,
111
- "ignore": ["util", "node:util"]
114
+ "ignore": [
115
+ "util",
116
+ "node:util"
117
+ ]
112
118
  },
113
119
  {
114
120
  "name": "Core (import * as Core)",
@@ -130,7 +136,10 @@
130
136
  "path": "dist/composition.mjs",
131
137
  "limit": "2 KB",
132
138
  "gzip": true,
133
- "ignore": ["util", "node:util"]
139
+ "ignore": [
140
+ "util",
141
+ "node:util"
142
+ ]
134
143
  },
135
144
  {
136
145
  "name": "Types (import * as Types)",
@@ -1,181 +0,0 @@
1
- declare const _brand: unique symbol;
2
- /**
3
- * Brand<K, T> creates a nominal type by tagging T with a phantom brand K.
4
- * Prevents accidentally mixing up values that share the same underlying type.
5
- *
6
- * @example
7
- * ```ts
8
- * type UserId = Brand<"UserId", string>;
9
- * type ProductId = Brand<"ProductId", string>;
10
- *
11
- * const toUserId = Brand.wrap<"UserId", string>();
12
- * const toProductId = Brand.wrap<"ProductId", string>();
13
- *
14
- * const userId: UserId = toUserId("user-123");
15
- * const productId: ProductId = toProductId("prod-456");
16
- *
17
- * // Type error: ProductId is not assignable to UserId
18
- * // const wrong: UserId = productId;
19
- * ```
20
- */
21
- type Brand<K extends string, T> = T & {
22
- readonly [_brand]: K;
23
- };
24
- declare const Brand: {
25
- /**
26
- * Returns a constructor that wraps a value of type T in brand K.
27
- * The resulting function performs an unchecked cast — only use when the raw
28
- * value is known to satisfy the brand's invariants.
29
- *
30
- * @example
31
- * ```ts
32
- * type PositiveNumber = Brand<"PositiveNumber", number>;
33
- * const toPositiveNumber = Brand.wrap<"PositiveNumber", number>();
34
- *
35
- * const n: PositiveNumber = toPositiveNumber(42);
36
- * ```
37
- */
38
- wrap: <K extends string, T>() => (value: T) => Brand<K, T>;
39
- /**
40
- * Strips the brand and returns the underlying value.
41
- * Since Brand<K, T> extends T this is rarely needed, but can improve readability.
42
- *
43
- * @example
44
- * ```ts
45
- * type UserId = Brand<"UserId", string>;
46
- * const toUserId = Brand.wrap<"UserId", string>();
47
- * const userId: UserId = toUserId("user-123");
48
- * const raw: string = Brand.unwrap(userId); // "user-123"
49
- * ```
50
- */
51
- unwrap: <K extends string, T>(branded: Brand<K, T>) => T;
52
- };
53
-
54
- /**
55
- * A branded nominal type representing a duration of time in milliseconds.
56
- * Use Duration to ensure safe time-based operators and clear unit conversions.
57
- *
58
- * @example
59
- * ```ts
60
- * const halfSecond = Duration.milliseconds(500);
61
- * const twoSeconds = Duration.seconds(2);
62
- * const total = pipe(halfSecond, Duration.add(twoSeconds));
63
- *
64
- * Duration.to.seconds(total); // 2.5
65
- * ```
66
- */
67
- type Duration = Brand<"Duration", number>;
68
- declare const Duration: {
69
- /**
70
- * Creates a Duration from milliseconds.
71
- *
72
- * @example
73
- * ```ts
74
- * Duration.milliseconds(500); // 500ms Duration
75
- * ```
76
- */
77
- milliseconds: (ms: number) => Duration;
78
- /**
79
- * Creates a Duration from seconds.
80
- *
81
- * @example
82
- * ```ts
83
- * Duration.seconds(2); // 2000ms Duration
84
- * ```
85
- */
86
- seconds: (s: number) => Duration;
87
- /**
88
- * Creates a Duration from minutes.
89
- *
90
- * @example
91
- * ```ts
92
- * Duration.minutes(5); // 300000ms Duration
93
- * ```
94
- */
95
- minutes: (m: number) => Duration;
96
- /**
97
- * Creates a Duration from hours.
98
- *
99
- * @example
100
- * ```ts
101
- * Duration.hours(1); // 3600000ms Duration
102
- * ```
103
- */
104
- hours: (h: number) => Duration;
105
- /**
106
- * Creates a Duration from days.
107
- *
108
- * @example
109
- * ```ts
110
- * Duration.days(1); // 86400000ms Duration
111
- * ```
112
- */
113
- days: (d: number) => Duration;
114
- to: {
115
- /**
116
- * Converts a Duration back to raw milliseconds.
117
- *
118
- * @example
119
- * ```ts
120
- * Duration.to.milliseconds(Duration.seconds(2)); // 2000
121
- * ```
122
- */
123
- milliseconds: (d: Duration) => number;
124
- /**
125
- * Converts a Duration to seconds.
126
- *
127
- * @example
128
- * ```ts
129
- * Duration.to.seconds(Duration.milliseconds(2500)); // 2.5
130
- * ```
131
- */
132
- seconds: (d: Duration) => number;
133
- /**
134
- * Converts a Duration to minutes.
135
- *
136
- * @example
137
- * ```ts
138
- * Duration.to.minutes(Duration.seconds(120)); // 2
139
- * ```
140
- */
141
- minutes: (d: Duration) => number;
142
- /**
143
- * Converts a Duration to hours.
144
- *
145
- * @example
146
- * ```ts
147
- * Duration.to.hours(Duration.minutes(90)); // 1.5
148
- * ```
149
- */
150
- hours: (d: Duration) => number;
151
- /**
152
- * Converts a Duration to days.
153
- *
154
- * @example
155
- * ```ts
156
- * Duration.to.days(Duration.hours(36)); // 1.5
157
- * ```
158
- */
159
- days: (d: Duration) => number;
160
- };
161
- /**
162
- * Adds two Durations together.
163
- *
164
- * @example
165
- * ```ts
166
- * pipe(Duration.seconds(1), Duration.add(Duration.milliseconds(500))); // 1500ms
167
- * ```
168
- */
169
- add: (other: Duration) => (self: Duration) => Duration;
170
- /**
171
- * Subtracts the other Duration from this one.
172
- *
173
- * @example
174
- * ```ts
175
- * pipe(Duration.seconds(1), Duration.subtract(Duration.milliseconds(500))); // 500ms
176
- * ```
177
- */
178
- subtract: (other: Duration) => (self: Duration) => Duration;
179
- };
180
-
181
- export { Brand as B, Duration as D };