@davidsouther/jiffies 2026.24.0 → 2026.24.2

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.
Files changed (226) hide show
  1. package/lib/esm/assert.d.ts +26 -0
  2. package/lib/esm/assert.js +38 -0
  3. package/lib/esm/awaitable.js +1 -0
  4. package/lib/esm/case.d.ts +1 -0
  5. package/lib/esm/case.js +5 -0
  6. package/lib/esm/components/accordion.d.ts +5 -0
  7. package/lib/esm/components/accordion.js +9 -0
  8. package/lib/esm/components/alert.d.ts +7 -0
  9. package/lib/esm/components/alert.js +31 -0
  10. package/lib/esm/components/button_bar.d.ts +8 -0
  11. package/lib/esm/components/button_bar.js +25 -0
  12. package/lib/esm/components/card.d.ts +8 -0
  13. package/lib/esm/components/card.js +31 -0
  14. package/lib/esm/components/children.d.ts +2 -0
  15. package/{src/components/children.ts → lib/esm/components/children.js} +2 -6
  16. package/lib/esm/components/form.d.ts +5 -0
  17. package/lib/esm/components/form.js +13 -0
  18. package/{src/components/index.ts → lib/esm/components/index.d.ts} +2 -15
  19. package/lib/esm/components/index.js +10 -0
  20. package/lib/esm/components/inline_edit.d.ts +12 -0
  21. package/lib/esm/components/inline_edit.js +48 -0
  22. package/lib/esm/components/link.d.ts +5 -0
  23. package/lib/esm/components/link.js +11 -0
  24. package/lib/esm/components/logger.d.ts +6 -0
  25. package/lib/esm/components/logger.js +22 -0
  26. package/lib/esm/components/modal.d.ts +2 -0
  27. package/{src/components/modal.ts → lib/esm/components/modal.js} +3 -8
  28. package/lib/esm/components/nav.d.ts +11 -0
  29. package/lib/esm/components/nav.js +27 -0
  30. package/lib/esm/components/property.d.ts +9 -0
  31. package/lib/esm/components/property.js +16 -0
  32. package/lib/esm/components/select.d.ts +10 -0
  33. package/lib/esm/components/select.js +3 -0
  34. package/lib/esm/components/tabs.d.ts +20 -0
  35. package/lib/esm/components/tabs.js +45 -0
  36. package/lib/esm/components/virtual_scroll.d.ts +42 -0
  37. package/lib/esm/components/virtual_scroll.js +94 -0
  38. package/lib/esm/debounce.d.ts +1 -0
  39. package/lib/esm/debounce.js +11 -0
  40. package/lib/esm/diff.d.ts +15 -0
  41. package/lib/esm/diff.js +50 -0
  42. package/lib/esm/display.d.ts +5 -0
  43. package/lib/esm/display.js +11 -0
  44. package/lib/esm/dom/css/border.d.ts +11 -0
  45. package/lib/esm/dom/css/border.js +27 -0
  46. package/lib/esm/dom/css/constants.d.ts +31 -0
  47. package/lib/esm/dom/css/constants.js +28 -0
  48. package/lib/esm/dom/css/core.d.ts +5 -0
  49. package/lib/esm/dom/css/core.js +24 -0
  50. package/lib/esm/dom/css/fstyle.d.ts +5 -0
  51. package/lib/esm/dom/css/fstyle.js +32 -0
  52. package/lib/esm/dom/css/sizing.d.ts +5 -0
  53. package/lib/esm/dom/css/sizing.js +10 -0
  54. package/lib/esm/dom/dom.d.ts +36 -0
  55. package/lib/esm/dom/dom.js +217 -0
  56. package/lib/esm/dom/fc.d.ts +10 -0
  57. package/lib/esm/dom/fc.js +32 -0
  58. package/lib/esm/dom/form/form.app.d.ts +1 -0
  59. package/lib/esm/dom/form/form.app.js +19 -0
  60. package/lib/esm/dom/form/form.d.ts +27 -0
  61. package/lib/esm/dom/form/form.js +65 -0
  62. package/lib/esm/dom/html.d.ts +112 -0
  63. package/{src/dom/html.ts → lib/esm/dom/html.js} +2 -14
  64. package/lib/esm/dom/hydrate.d.ts +39 -0
  65. package/lib/esm/dom/hydrate.js +187 -0
  66. package/lib/esm/dom/index.js +2 -0
  67. package/lib/esm/dom/navigation/index.d.ts +76 -0
  68. package/lib/esm/dom/navigation/index.js +292 -0
  69. package/lib/esm/dom/observable.d.ts +2 -0
  70. package/lib/esm/dom/observable.js +6 -0
  71. package/lib/esm/dom/provide.d.ts +3 -0
  72. package/lib/esm/dom/provide.js +7 -0
  73. package/lib/esm/dom/render.d.ts +8 -0
  74. package/lib/esm/dom/render.js +28 -0
  75. package/lib/esm/dom/router/link.d.ts +6 -0
  76. package/lib/esm/dom/router/link.js +3 -0
  77. package/lib/esm/dom/router/router.d.ts +13 -0
  78. package/lib/esm/dom/router/router.js +52 -0
  79. package/lib/esm/dom/svg.d.ts +64 -0
  80. package/{src/dom/svg.ts → lib/esm/dom/svg.js} +2 -19
  81. package/lib/esm/dom/types/css.d.ts +6590 -0
  82. package/lib/esm/dom/types/css.js +1 -0
  83. package/lib/esm/dom/types/dom.js +1 -0
  84. package/lib/esm/dom/types/html.d.ts +614 -0
  85. package/lib/esm/dom/types/html.js +1 -0
  86. package/lib/esm/dom/xml.d.ts +1 -0
  87. package/lib/esm/dom/xml.js +4 -0
  88. package/lib/esm/equal.d.ts +11 -0
  89. package/lib/esm/equal.js +43 -0
  90. package/lib/esm/fs.d.ts +72 -0
  91. package/lib/esm/fs.js +227 -0
  92. package/lib/esm/fs_node.d.ts +15 -0
  93. package/lib/esm/fs_node.js +45 -0
  94. package/lib/esm/generator.d.ts +1 -0
  95. package/lib/esm/generator.js +10 -0
  96. package/lib/esm/lock.d.ts +1 -0
  97. package/lib/esm/lock.js +23 -0
  98. package/lib/esm/log.d.ts +69 -0
  99. package/lib/esm/log.js +211 -0
  100. package/lib/esm/observable/event.d.ts +35 -0
  101. package/lib/esm/observable/event.js +46 -0
  102. package/lib/esm/observable/observable.d.ts +134 -0
  103. package/lib/esm/observable/observable.js +349 -0
  104. package/lib/esm/range.d.ts +1 -0
  105. package/lib/esm/range.js +7 -0
  106. package/lib/esm/result.d.ts +31 -0
  107. package/lib/esm/result.js +66 -0
  108. package/lib/esm/safe.d.ts +1 -0
  109. package/lib/esm/safe.js +10 -0
  110. package/lib/esm/server/http/apps.d.ts +5 -0
  111. package/lib/esm/server/http/apps.js +23 -0
  112. package/lib/esm/server/http/css.d.ts +5 -0
  113. package/lib/esm/server/http/css.js +43 -0
  114. package/lib/esm/server/http/index.d.ts +16 -0
  115. package/lib/esm/server/http/index.js +78 -0
  116. package/lib/esm/server/http/response.d.ts +4 -0
  117. package/lib/esm/server/http/response.js +43 -0
  118. package/lib/esm/server/http/sitemap.d.ts +2 -0
  119. package/lib/esm/server/http/sitemap.js +22 -0
  120. package/lib/esm/server/http/static.d.ts +2 -0
  121. package/lib/esm/server/http/static.js +22 -0
  122. package/lib/esm/server/http/typescript.d.ts +5 -0
  123. package/lib/esm/server/http/typescript.js +40 -0
  124. package/lib/esm/server/live-reload.d.ts +46 -0
  125. package/lib/esm/server/live-reload.js +161 -0
  126. package/lib/esm/server/main.d.ts +2 -0
  127. package/{src/server/main.ts → lib/esm/server/main.js} +8 -15
  128. package/lib/esm/server/ws/frame.d.ts +2 -0
  129. package/lib/esm/server/ws/frame.js +35 -0
  130. package/lib/esm/server/ws/handshake.d.ts +4 -0
  131. package/lib/esm/server/ws/handshake.js +32 -0
  132. package/lib/esm/server/ws/index.d.ts +14 -0
  133. package/lib/esm/server/ws/index.js +68 -0
  134. package/lib/esm/ssg/bundle.d.ts +14 -0
  135. package/lib/esm/ssg/bundle.js +73 -0
  136. package/lib/esm/ssg/copy-public.d.ts +6 -0
  137. package/lib/esm/ssg/copy-public.js +34 -0
  138. package/lib/esm/ssg/discover.d.ts +15 -0
  139. package/lib/esm/ssg/discover.js +117 -0
  140. package/lib/esm/ssg/main.d.ts +2 -0
  141. package/lib/esm/ssg/main.js +122 -0
  142. package/lib/esm/ssg/rewrite.d.ts +9 -0
  143. package/{src/ssg/rewrite.ts → lib/esm/ssg/rewrite.js} +6 -9
  144. package/lib/esm/ssg/ssg.d.ts +26 -0
  145. package/lib/esm/ssg/ssg.js +84 -0
  146. package/lib/esm/transpile.d.mts +3 -0
  147. package/lib/esm/transpile.mjs +12 -0
  148. package/package.json +11 -7
  149. package/src/404.html +0 -14
  150. package/src/assert.ts +0 -56
  151. package/src/case.ts +0 -5
  152. package/src/components/_notes +0 -33
  153. package/src/components/accordion.ts +0 -25
  154. package/src/components/alert.ts +0 -47
  155. package/src/components/button_bar.ts +0 -42
  156. package/src/components/card.ts +0 -54
  157. package/src/components/form.ts +0 -25
  158. package/src/components/inline_edit.ts +0 -78
  159. package/src/components/link.ts +0 -22
  160. package/src/components/logger.ts +0 -35
  161. package/src/components/nav.ts +0 -42
  162. package/src/components/property.ts +0 -32
  163. package/src/components/select.ts +0 -22
  164. package/src/components/tabs.ts +0 -82
  165. package/src/components/virtual_scroll.ts +0 -199
  166. package/src/debounce.ts +0 -14
  167. package/src/diff.ts +0 -82
  168. package/src/display.ts +0 -18
  169. package/src/dom/README.md +0 -107
  170. package/src/dom/SKILL.md +0 -201
  171. package/src/dom/css/border.ts +0 -47
  172. package/src/dom/css/constants.ts +0 -34
  173. package/src/dom/css/core.ts +0 -28
  174. package/src/dom/css/fstyle.ts +0 -42
  175. package/src/dom/css/sizing.ts +0 -11
  176. package/src/dom/dom.ts +0 -327
  177. package/src/dom/fc.ts +0 -81
  178. package/src/dom/form/form.app.ts +0 -44
  179. package/src/dom/form/form.ts +0 -151
  180. package/src/dom/form/index.html +0 -15
  181. package/src/dom/hydrate.ts +0 -206
  182. package/src/dom/navigation/index.ts +0 -349
  183. package/src/dom/observable.ts +0 -11
  184. package/src/dom/provide.ts +0 -11
  185. package/src/dom/render.ts +0 -41
  186. package/src/dom/router/link.ts +0 -14
  187. package/src/dom/router/router.ts +0 -72
  188. package/src/dom/types/css.ts +0 -10088
  189. package/src/dom/types/html.ts +0 -629
  190. package/src/dom/xml.ts +0 -11
  191. package/src/equal.ts +0 -66
  192. package/src/favicon.ico +0 -0
  193. package/src/fs.ts +0 -300
  194. package/src/fs_node.ts +0 -57
  195. package/src/generator.ts +0 -12
  196. package/src/hooks/_notes +0 -6
  197. package/src/lock.ts +0 -23
  198. package/src/log.ts +0 -307
  199. package/src/observable/_notes +0 -26
  200. package/src/observable/event.ts +0 -93
  201. package/src/observable/observable.ts +0 -484
  202. package/src/range.ts +0 -7
  203. package/src/result.ts +0 -107
  204. package/src/safe.ts +0 -12
  205. package/src/server/http/apps.ts +0 -26
  206. package/src/server/http/css.ts +0 -49
  207. package/src/server/http/index.ts +0 -127
  208. package/src/server/http/response.ts +0 -60
  209. package/src/server/http/sitemap.ts +0 -24
  210. package/src/server/http/static.ts +0 -28
  211. package/src/server/http/typescript.ts +0 -46
  212. package/src/server/live-reload.ts +0 -208
  213. package/src/server/ws/frame.ts +0 -36
  214. package/src/server/ws/handshake.ts +0 -42
  215. package/src/server/ws/index.ts +0 -100
  216. package/src/ssg/bundle.ts +0 -85
  217. package/src/ssg/copy-public.ts +0 -44
  218. package/src/ssg/discover.ts +0 -143
  219. package/src/ssg/main.ts +0 -168
  220. package/src/ssg/ssg.ts +0 -134
  221. package/src/transpile.mjs +0 -16
  222. package/src/zip/spec.txt +0 -3260
  223. package/tsconfig.json +0 -34
  224. /package/{src/awaitable.ts → lib/esm/awaitable.d.ts} +0 -0
  225. /package/{src/dom/index.ts → lib/esm/dom/index.d.ts} +0 -0
  226. /package/{src/dom/types/dom.ts → lib/esm/dom/types/dom.d.ts} +0 -0
@@ -1,26 +0,0 @@
1
- Subscriber
2
- next(t: T)
3
- error(e: E)
4
- complete()
5
-
6
- Observable
7
- ::of(...Ts)
8
- ::combineLatest([...])
9
- ::from(promise|Iterable|Subscribable)
10
- ::fromEvent(element, eventName)
11
- (subscriber) -> subscription
12
- .subscribe(subscriber) -> subscription
13
- .pipe(...operators) -> Observable
14
-
15
- Subject
16
- -> BehaviorSubject(t)
17
- -> ReplaySubject(n)
18
-
19
- operator
20
- filter
21
- first/last
22
- map
23
- publishReplay
24
- reduce
25
- takeUntil
26
- tap
@@ -1,93 +0,0 @@
1
- import { display } from "../display.ts";
2
- import type { Observable } from "./observable.ts";
3
-
4
- export interface Next<T> {
5
- value: T;
6
- completed: false;
7
- failed: false;
8
- }
9
-
10
- export interface Error<E> {
11
- error: E;
12
- completed: false;
13
- failed: true;
14
- }
15
-
16
- export interface Completed {
17
- completed: true;
18
- failed: false;
19
- }
20
-
21
- export interface Failed {
22
- completed: true;
23
- failed: true;
24
- }
25
-
26
- export type Event<T, E> = Next<T> | Error<E> | Completed | Failed;
27
-
28
- export interface EventSubscriber<T, E> {
29
- next(e: Event<T, E>): void;
30
- }
31
-
32
- export const next = <T>(value: T): Next<T> => ({
33
- value,
34
- completed: false,
35
- failed: false,
36
- });
37
- export const error = <E>(e: E): Error<E> => ({
38
- error: e,
39
- completed: false,
40
- failed: true,
41
- });
42
- export const completed = (): Completed => ({ completed: true, failed: false });
43
- export const failed = (): Failed => ({ completed: true, failed: true });
44
-
45
- export const isNext = <T>(event: Event<T, unknown>): event is Next<T> =>
46
- !event.completed && !event.failed && event.value !== undefined;
47
- export const isError = <E>(event: Event<unknown, E>): event is Error<E> =>
48
- event.failed && !event.completed;
49
- export const isCompleted = (
50
- event: Event<unknown, unknown>,
51
- ): event is Completed => event.completed && !event.failed;
52
- export const isFailed = (event: Event<unknown, unknown>): event is Failed =>
53
- event.completed && event.failed;
54
-
55
- export const isEvent = <T, E>(t: T | Event<T, E>): t is Event<T, E> => {
56
- const b = t as Event<unknown, unknown>;
57
- return isNext(b) || isError(b) || isCompleted(b);
58
- };
59
-
60
- export const asEvents = <T, E>(a: (T | Event<T, E>)[]): Event<T, E>[] =>
61
- a.map((e) => (isEvent(e) ? e : next(e)));
62
-
63
- const marble = <T, E>(event: Event<T, E>): string =>
64
- isError(event)
65
- ? "X"
66
- : isFailed(event)
67
- ? "!"
68
- : isCompleted(event)
69
- ? "|"
70
- : `(${display(event.value)})`;
71
-
72
- export const marbles = <T, E>(events: Event<T, E>[]): string =>
73
- `:${events.map(marble).join("-")}`;
74
-
75
- export const collect = <T, E>(input$: Observable<T, E>) => {
76
- const collected: Event<T, E>[] = [];
77
-
78
- const subscription = input$.subscribe({
79
- next: (x: T) => {
80
- collected.push(next(x));
81
- },
82
- error: (e: E) => {
83
- collected.push(error(e));
84
- },
85
- complete: () => {
86
- collected.push(completed());
87
- },
88
- });
89
-
90
- subscription.unsubscribe();
91
-
92
- return collected;
93
- };
@@ -1,484 +0,0 @@
1
- import { assertExists } from "../assert.ts";
2
- import type { Display } from "../display.ts";
3
- import { DEFAULT_LOGGER, type Logger } from "../log.ts";
4
-
5
- export interface FullSubscriber<T, E> {
6
- // (t: T): void | Promise<undefined>;
7
- next?: (t: T) => void | Promise<void>;
8
- error?: (e: E) => void | Promise<void>;
9
- complete?: () => void | Promise<void>;
10
- }
11
-
12
- export type Subscriber<T, E> =
13
- | FullSubscriber<T, E>
14
- // | EventSubscriber<T, E>
15
- | ((t: T) => void | Promise<void>);
16
-
17
- export interface Subscription {
18
- // (): void;
19
- unsubscribe(): void;
20
- }
21
-
22
- export interface Observable<T, E = unknown> {
23
- // (subscriber: Subscriber<T, E>): Subscription;
24
- subscribe(subscriber: Subscriber<T, E>): Subscription;
25
- pipe<T1>(o1: Subscriber<T, E> & Observable<T1, E>): Observable<T1, E>;
26
- pipe<T1, T2>(
27
- o1: Subscriber<T, E> & Observable<T1, E>,
28
- o2: Subscriber<T1, E> & Observable<T2, E>,
29
- ): Observable<T2, E>;
30
- filter(fn: (t: T) => boolean): Observable<T, E>;
31
- distinct(fn?: (t1: T, t2: T) => boolean): Observable<T, E>;
32
- map<U>(fn: (t: T) => U): Observable<U, E>;
33
- reduce<A>(fn: (acc: A, t: T) => A, init: A): Observable<A, E>;
34
- replay(n: number): Observable<T, E>;
35
- tap(s: Subscriber<T, E>): Observable<T, E>;
36
- }
37
-
38
- export const Observable = {
39
- of<T, E>(...ts: T[]): Observable<T, E> {
40
- const subject = new Subject<T, E>();
41
- (async function next() {
42
- if (subject.cold) {
43
- subject.onWarm(next);
44
- return;
45
- }
46
- if (ts.length === 0) {
47
- subject.complete();
48
- return;
49
- }
50
- const t = assertExists(ts.shift());
51
- await subject.next(t);
52
- next();
53
- })();
54
- return subject;
55
- },
56
- combineLatest<T1, T2, E>(
57
- o1: Observable<T1, E>,
58
- o2: Observable<T2, E>,
59
- ): Observable<[T1, T2], E> {
60
- const latestSubject = new Subject<[T1, T2], E>();
61
- let o1LatestSet = false;
62
- let o1Latest: T1;
63
- let o2LatestSet = false;
64
- let o2Latest: T2;
65
-
66
- function next() {
67
- if (o1LatestSet && o2LatestSet) {
68
- latestSubject.next([o1Latest, o2Latest]);
69
- }
70
- }
71
-
72
- function error(e: E) {
73
- latestSubject.error(e);
74
- }
75
-
76
- function complete() {
77
- latestSubject.complete();
78
- o1sub.unsubscribe();
79
- o2sub.unsubscribe();
80
- }
81
-
82
- const o1sub = o1.subscribe({
83
- next(t: T1) {
84
- o1Latest = t;
85
- o1LatestSet = true;
86
- next();
87
- },
88
- error,
89
- complete,
90
- });
91
-
92
- const o2sub = o2.subscribe({
93
- next(t: T2) {
94
- o2Latest = t;
95
- o2LatestSet = true;
96
- next();
97
- },
98
- error,
99
- complete,
100
- });
101
-
102
- return latestSubject;
103
- },
104
- };
105
-
106
- interface Scheduler {
107
- execute(fn: () => (void | Promise<void>)[]): void | Promise<void>;
108
- }
109
-
110
- export const AsyncScheduler: Scheduler = {
111
- execute(fn: () => Promise<void>[]): Promise<void> {
112
- return Promise.all(fn()).then(() => undefined);
113
- },
114
- };
115
-
116
- export const SyncScheduler: Scheduler = {
117
- execute(fn: () => undefined[]): void {
118
- fn();
119
- },
120
- };
121
-
122
- let DefaultScheduler = SyncScheduler;
123
- export function setDefaultScheduler(scheduler: Scheduler) {
124
- DefaultScheduler = scheduler;
125
- }
126
-
127
- export class Subject<T, E = unknown, T2 = T>
128
- implements FullSubscriber<T, E>, Observable<T, E>
129
- {
130
- private readonly scheduler: Scheduler;
131
- #coldWaiters = new Set<CallableFunction>();
132
- #subscribers = new Set<FullSubscriber<T, E>>();
133
- #complete = false;
134
-
135
- get $(): Observable<T, E> {
136
- return this;
137
- }
138
-
139
- get hot(): boolean {
140
- return this.#subscribers.size > 0;
141
- }
142
-
143
- get cold(): boolean {
144
- return !this.hot;
145
- }
146
-
147
- constructor(scheduler: Scheduler = DefaultScheduler) {
148
- this.scheduler = scheduler;
149
- }
150
-
151
- onWarm(fn: CallableFunction) {
152
- if (this.cold) this.#coldWaiters.add(fn);
153
- }
154
-
155
- next(t: T | T2): void | Promise<void> {
156
- if (this.#complete)
157
- throw new Error("Cannot call next on a completed subject");
158
- return this.scheduler.execute(() =>
159
- [...this.#subscribers].map((s) => s.next?.(t as T)),
160
- );
161
- }
162
-
163
- error(e: E): void | Promise<void> {
164
- if (this.#complete)
165
- throw new Error("Cannot call error on a completed subject");
166
- return this.scheduler.execute(() =>
167
- [...this.#subscribers].map((s) => s.error?.(e)),
168
- );
169
- }
170
-
171
- complete(): void | Promise<void> {
172
- if (this.#complete)
173
- throw new Error("Cannot call complete on a completed subject");
174
- this.#complete = true;
175
- const finished = this.scheduler.execute(() =>
176
- [...this.#subscribers].map((s) => s.complete?.()),
177
- );
178
- this.#subscribers.clear(); // Free subscribers for garbage collection
179
- return finished;
180
- }
181
-
182
- subscribe(subscriber: Subscriber<T, E>): Subscription {
183
- if (this.#complete)
184
- throw new Error("Cannot call subscribe on a completed subject");
185
-
186
- if (subscriber instanceof Function) {
187
- subscriber = { next: subscriber };
188
- }
189
-
190
- this.#subscribers.add(subscriber);
191
-
192
- for (const w of this.#coldWaiters) w();
193
- this.#coldWaiters.clear();
194
-
195
- return {
196
- unsubscribe: () =>
197
- this.#subscribers.delete(subscriber as FullSubscriber<T, E>),
198
- };
199
- }
200
-
201
- pipe<T1>(o1: Subscriber<T, E> & Observable<T1, E>): Observable<T1, E>;
202
- pipe<T1, T2>(
203
- o1: Subscriber<T, E> & Observable<T1, E>,
204
- o2: Subscriber<T1, E> & Observable<T2, E>,
205
- ): Observable<T2, E>;
206
- pipe(
207
- ...os: (Subscriber<unknown, unknown> & Observable<unknown, unknown>)[]
208
- ): Observable<unknown, E> {
209
- this.subscribe(os[0]);
210
- for (let i = 1; i < os.length; i++) {
211
- os[i - 1].subscribe(os[i]);
212
- }
213
- return os[os.length - 1];
214
- }
215
-
216
- filter(fn: (t: T) => boolean): Observable<T, E> {
217
- return this.pipe(operator.filter(fn));
218
- }
219
-
220
- distinct(fn: (t1: T, t2: T) => boolean = Object.is): Observable<T, E> {
221
- return this.pipe(operator.distinct(fn));
222
- }
223
-
224
- map<U>(fn: (t: T) => U): Observable<U, E> {
225
- return this.pipe(operator.map(fn));
226
- }
227
-
228
- reduce<A>(fn: (acc: A, t: T) => A, init: A): Observable<A, E> {
229
- return this.pipe(operator.reduce(fn, init));
230
- }
231
-
232
- replay(n: number): Observable<T, E> {
233
- return this.pipe(operator.replay(n));
234
- }
235
-
236
- tap(s: Subscriber<T, E>): Observable<T, E> {
237
- return this.pipe(operator.tap(s));
238
- }
239
- }
240
-
241
- export class BehaviorSubject<T, E = unknown, T2 = T> extends Subject<T, E, T2> {
242
- #current: T;
243
-
244
- constructor(t: T, scheduler?: Scheduler) {
245
- super(scheduler ?? AsyncScheduler);
246
- this.#current = t;
247
- }
248
-
249
- next(t: T | T2) {
250
- this.#current = t as T;
251
- return super.next(t);
252
- }
253
-
254
- subscribe(subscriber: Subscriber<T, E>): Subscription {
255
- if (subscriber instanceof Function) {
256
- subscriber = { next: subscriber };
257
- }
258
- subscriber.next?.(this.#current);
259
- return super.subscribe(subscriber);
260
- }
261
-
262
- get current(): T {
263
- return this.#current;
264
- }
265
- }
266
-
267
- export class ReplaySubject<T, E = unknown> extends Subject<T, E> {
268
- readonly n: number;
269
- #history: T[] = [];
270
-
271
- constructor(n: number, scheduler?: Scheduler) {
272
- super(scheduler ?? SyncScheduler);
273
- this.n = n;
274
- }
275
-
276
- next(t: T) {
277
- this.#history.push(t);
278
- if (this.#history.length > this.n) {
279
- this.#history.shift();
280
- }
281
- return super.next(t);
282
- }
283
-
284
- subscribe(subscriber: Subscriber<T, E>): Subscription {
285
- if (subscriber instanceof Function) {
286
- subscriber = { next: subscriber };
287
- }
288
- const history = [...this.#history];
289
- (function send() {
290
- if (history.length === 0) return;
291
- const t = assertExists(history.shift());
292
- subscriber.next?.(t);
293
- new Promise(send);
294
- })();
295
- return super.subscribe(subscriber);
296
- }
297
- }
298
-
299
- export function eventListener<E extends Event>() {
300
- const observable = new Subject<E, unknown>();
301
- function listener(e: E) {
302
- e.preventDefault();
303
- observable.next(e);
304
- }
305
-
306
- return [observable, listener];
307
- }
308
-
309
- export class EventHandler<E extends Event> extends Subject<E> {
310
- eventFn: (e: E) => void | Promise<void>;
311
-
312
- constructor(eventFn: (e: E) => void | Promise<void>) {
313
- super(AsyncScheduler);
314
- this.eventFn = eventFn;
315
- }
316
-
317
- async next(e: E): Promise<undefined> {
318
- e.preventDefault();
319
- super.next(e);
320
- }
321
- }
322
-
323
- export const watch =
324
- <T extends Display, E extends Display>(logger: Logger = DEFAULT_LOGGER) =>
325
- (observable: Observable<T, E>) => {
326
- observable.tap({
327
- async next(t: T) {
328
- logger.info(t);
329
- },
330
- async complete() {
331
- logger.info("Observable completed");
332
- },
333
- async error(e: E) {
334
- logger.warn(e);
335
- },
336
- });
337
- };
338
-
339
- class MapOperator<T, U, E>
340
- extends Subject<U, E, T>
341
- implements FullSubscriber<T, E>, Observable<U, E>
342
- {
343
- private readonly mapFn: (t: T) => U;
344
- constructor(mapFn: (t: T) => U) {
345
- super(SyncScheduler);
346
- this.mapFn = mapFn;
347
- }
348
-
349
- next(t: T): void | Promise<void> {
350
- return super.next(this.mapFn(t));
351
- }
352
- }
353
-
354
- class FilterOperator<T, E>
355
- extends Subject<T, E>
356
- implements FullSubscriber<T, E>, Observable<T, E>
357
- {
358
- private readonly filterFn: (t: T) => boolean;
359
- constructor(filterFn: (t: T) => boolean) {
360
- super(SyncScheduler);
361
- this.filterFn = filterFn;
362
- }
363
-
364
- next(t: T): void | Promise<void> {
365
- return this.filterFn(t) ? super.next(t) : undefined;
366
- }
367
- }
368
-
369
- class DistinctOperator<T, E>
370
- extends Subject<T, E>
371
- implements FullSubscriber<T, E>, Observable<T, E>
372
- {
373
- #prior: T | undefined = undefined;
374
- private readonly distinctFn: (t1: T, t2: T) => boolean;
375
-
376
- constructor(distinctFn: (t1: T, t2: T) => boolean = Object.is) {
377
- super(SyncScheduler);
378
- this.distinctFn = distinctFn;
379
- }
380
-
381
- next(t: T): void | Promise<void> {
382
- if (this.#prior === undefined) {
383
- this.#prior = t;
384
- return super.next(t);
385
- }
386
- const same = this.distinctFn(assertExists(this.#prior), t);
387
- if (!same) {
388
- this.#prior = t;
389
- return super.next(t);
390
- }
391
- return undefined;
392
- }
393
- }
394
-
395
- class ReduceOperator<A, T, E> extends BehaviorSubject<A, E, T> {
396
- private readonly fn: (acc: A, t: T) => A;
397
- constructor(fn: (acc: A, t: T) => A, init: A) {
398
- super(init);
399
- this.fn = fn;
400
- }
401
-
402
- next(t: T) {
403
- return super.next(this.fn(this.current, t));
404
- }
405
- }
406
-
407
- export class TakeUntilOperator<T, E> extends Subject<T, E> {
408
- constructor(o: Observable<unknown, unknown>) {
409
- super();
410
- o.subscribe(() => this.complete());
411
- }
412
- }
413
- export class TapOperator<T, E> extends Subject<T, E> {
414
- private readonly subscriber: FullSubscriber<T, E>;
415
- constructor(fn: Subscriber<T, E>) {
416
- super();
417
- this.subscriber = fn instanceof Function ? { next: fn } : fn;
418
- }
419
-
420
- next(t: T) {
421
- this.subscriber.next?.(t);
422
- return super.next(t);
423
- }
424
-
425
- error(e: E) {
426
- this.subscriber.error?.(e);
427
- return super.error(e);
428
- }
429
-
430
- complete() {
431
- this.subscriber.complete?.();
432
- return super.complete();
433
- }
434
- }
435
-
436
- class FirstOperator<T, E> extends Subject<T, E> {
437
- next(t: T): void | Promise<void> {
438
- const next = super.next(t);
439
- this.complete();
440
- return next;
441
- }
442
- }
443
-
444
- class LastOperator<T, E = Error> extends Subject<T, E> {
445
- #latest?: T;
446
-
447
- next(t: T) {
448
- this.#latest = t;
449
- }
450
-
451
- complete(): void | Promise<void> {
452
- if (this.#latest !== undefined) {
453
- super.next(this.#latest);
454
- }
455
- return super.complete();
456
- }
457
- }
458
-
459
- export const filter = <T, E>(fn: (t: T) => boolean) =>
460
- new FilterOperator<T, E>(fn);
461
- export const distinct = <T, E>(fn?: (t1: T, t2: T) => boolean) =>
462
- new DistinctOperator<T, E>(fn ?? Object.is);
463
- export const first = <T, E>() => new FirstOperator<T, E>();
464
- export const last = <T, E>() => new LastOperator<T, E>();
465
- export const map = <T1, T2, E>(fn: (t: T1) => T2) =>
466
- new MapOperator<T1, T2, E>(fn);
467
- export const replay = <T, E>(n: number) => new ReplaySubject<T, E>(n);
468
- export const reduce = <A, T, E>(fn: (acc: A, t: T) => A, init: A) =>
469
- new ReduceOperator<A, T, E>(fn, init);
470
- export const takeUntil = <T, E>(o: Observable<unknown, unknown>) =>
471
- new TakeUntilOperator<T, E>(o);
472
- export const tap = <T, E>(fn: Subscriber<T, E>) => new TapOperator<T, E>(fn);
473
-
474
- export const operator = {
475
- filter,
476
- distinct,
477
- first,
478
- last,
479
- map,
480
- replay,
481
- reduce,
482
- takeUntil,
483
- tap,
484
- };
package/src/range.ts DELETED
@@ -1,7 +0,0 @@
1
- export function range(start: number, end: number, stride = 1): number[] {
2
- const range = [];
3
- for (let i = start; i < end; i += stride) {
4
- range.push(i);
5
- }
6
- return range;
7
- }
package/src/result.ts DELETED
@@ -1,107 +0,0 @@
1
- export const isNone = <T>(s: Option<T>): s is None => s === null;
2
- export const isSome = <T>(s: Option<T>): s is Some<T> => s != null;
3
-
4
- export function None<T = unknown>(_?: T): Option<T> {
5
- return null;
6
- }
7
-
8
- export function Some<T>(t: Option<T>): Option<T>;
9
- export function Some<T>(t: T): Option<T>;
10
- export function Some<T>(t: Option<T> | T): Option<T> {
11
- return t;
12
- }
13
-
14
- export const isOk = <T, E>(t: Result<T, E>): t is Ok<T> =>
15
- t && Object.hasOwn(t, "ok");
16
- export const isErr = <T, E>(e: Result<T, E>): e is Err<E> =>
17
- e && Object.hasOwn(e, "err");
18
- export const isResult = <T, E>(t: Result<T, E>): t is Result<T, E> =>
19
- isOk(t) || isErr(t);
20
-
21
- // Beware: Order matters for correct inference.
22
- export function Ok<T, _E = unknown>(ok: Ok<T>): T;
23
- export function Ok<T, _E = unknown>(t?: T): Ok<T>;
24
- export function Ok<T, E = unknown>(t: T | Ok<T>): T | Ok<T> {
25
- return isOk(t as Ok<T>)
26
- ? (t as Ok<T>).ok
27
- : ({
28
- ok: t,
29
- map<U>(fn: (_: typeof t) => Result<U, E>): Result<U, E> {
30
- return fn(Ok(this));
31
- },
32
- } as Ok<T>);
33
- }
34
-
35
- // Beware: Order matters for correct inference.
36
- export function Err<_T, E>(e: Err<E>): E;
37
- export function Err<_T, E>(e: E): Err<E>;
38
- export function Err<_T, E>(e: string): Err<E>;
39
- export function Err<T, E>(e: E | string | Err<E>): E | Err<E> {
40
- return (
41
- ((e as Err<E>).err as E) ??
42
- ({
43
- err: e,
44
- map<U>(this: Result<T, E>, _fn: (t: unknown) => Result<U>): Result<U, E> {
45
- return this as Result<U, E>;
46
- },
47
- } as Err<E>)
48
- );
49
- }
50
-
51
- export function unwrap<T, E>(result: Result<T, E>): T | never;
52
- export function unwrap<O>(some: Option<O>): O | never;
53
- export function unwrap<T, E>(t: Result<T, E> | Option<T> | T): T | never {
54
- if (isNone(t as Option<T>)) {
55
- throw new Error("Attempted to unwrap None");
56
- }
57
- if (isErr(t as Result<T, E>)) {
58
- throw Err(t);
59
- }
60
- if (isOk(t as Result<T, E>)) {
61
- return Ok(t as Ok<T>);
62
- }
63
- return t as T;
64
- }
65
-
66
- export function unwrapOr<T, E>(result: Result<T, E>, def: T): T;
67
- export function unwrapOr<T>(some: Some<T>, def: T): T;
68
- export function unwrapOr<T, E>(t: Some<T> | Result<T, E>, def: T): T {
69
- if (isNone(t as Some<T>)) {
70
- return def;
71
- }
72
- if (isErr(t as Result<T, E>)) {
73
- return def;
74
- }
75
- if (isOk(t as Result<T, E>)) {
76
- return Ok(t as Ok<T>);
77
- }
78
- return t as T;
79
- }
80
-
81
- export function unwrapOrElse<T, E>(result: Result<T, E>, def: () => T): T;
82
- export function unwrapOrElse<T, _E>(some: Some<T>, def: () => T): T;
83
- export function unwrapOrElse<T, E>(t: Result<T, E> | Some<T>, def: () => T): T {
84
- if (isNone(t as Some<T>)) {
85
- return def();
86
- }
87
- if (isErr(t as Err<T>)) {
88
- return def();
89
- }
90
- if (isOk(t as Ok<T>)) {
91
- return Ok(t as Ok<T>);
92
- }
93
- return t as T;
94
- }
95
-
96
- export type None = null;
97
- // biome-ignore lint/suspicious/noRedeclare: This file does trickery with const and type.
98
- export type Some<T> = T;
99
- export type Option<T> = Some<T> | None;
100
- // biome-ignore lint/suspicious/noRedeclare: This file does trickery with const and type.
101
- export type Err<E = Error> = {
102
- err: E;
103
- map: <U>(fn: (t: unknown) => Result<U>) => Result<U>;
104
- };
105
- // biome-ignore lint/suspicious/noRedeclare: This file does trickery with const and type.
106
- export type Ok<T> = { ok: T; map: <U>(fn: (t: T) => Result<U>) => Result<U> };
107
- export type Result<T, E = Error> = Ok<T> | Err<E>;