@rikalabs/effect-react 0.0.1

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 (167) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +179 -0
  3. package/dist/actions/http.d.ts +18 -0
  4. package/dist/actions/index.d.ts +4 -0
  5. package/dist/actions/react.d.ts +7 -0
  6. package/dist/actions/service.d.ts +18 -0
  7. package/dist/actions/types.d.ts +33 -0
  8. package/dist/boundary/codecs.d.ts +40 -0
  9. package/dist/boundary/errors.d.ts +22 -0
  10. package/dist/boundary/index.d.ts +2 -0
  11. package/dist/chunk-2GIUCKL2.js +16 -0
  12. package/dist/chunk-2GIUCKL2.js.map +1 -0
  13. package/dist/chunk-2TG7YEVD.js +11 -0
  14. package/dist/chunk-2TG7YEVD.js.map +1 -0
  15. package/dist/chunk-6FI4ROTW.js +152 -0
  16. package/dist/chunk-6FI4ROTW.js.map +1 -0
  17. package/dist/chunk-C5JI7D7W.js +213 -0
  18. package/dist/chunk-C5JI7D7W.js.map +1 -0
  19. package/dist/chunk-EEYASTXR.js +99 -0
  20. package/dist/chunk-EEYASTXR.js.map +1 -0
  21. package/dist/chunk-H7MOLKTU.js +301 -0
  22. package/dist/chunk-H7MOLKTU.js.map +1 -0
  23. package/dist/chunk-IVIYY6S5.js +77 -0
  24. package/dist/chunk-IVIYY6S5.js.map +1 -0
  25. package/dist/chunk-JKN75OYC.js +87 -0
  26. package/dist/chunk-JKN75OYC.js.map +1 -0
  27. package/dist/chunk-M2CJG6T7.js +24 -0
  28. package/dist/chunk-M2CJG6T7.js.map +1 -0
  29. package/dist/chunk-MDGEGQZB.js +206 -0
  30. package/dist/chunk-MDGEGQZB.js.map +1 -0
  31. package/dist/chunk-NI2GNZ7S.js +78 -0
  32. package/dist/chunk-NI2GNZ7S.js.map +1 -0
  33. package/dist/chunk-O7XTA7H3.js +423 -0
  34. package/dist/chunk-O7XTA7H3.js.map +1 -0
  35. package/dist/chunk-S67FHWAR.js +88 -0
  36. package/dist/chunk-S67FHWAR.js.map +1 -0
  37. package/dist/chunk-SKC3HMF3.js +17 -0
  38. package/dist/chunk-SKC3HMF3.js.map +1 -0
  39. package/dist/chunk-TUJZ6XJY.js +127 -0
  40. package/dist/chunk-TUJZ6XJY.js.map +1 -0
  41. package/dist/chunk-WPV3WFMS.js +38 -0
  42. package/dist/chunk-WPV3WFMS.js.map +1 -0
  43. package/dist/chunk-XIBEKS5A.js +301 -0
  44. package/dist/chunk-XIBEKS5A.js.map +1 -0
  45. package/dist/chunk-YG22YP5K.js +68 -0
  46. package/dist/chunk-YG22YP5K.js.map +1 -0
  47. package/dist/chunk-ZMZQBREU.js +262 -0
  48. package/dist/chunk-ZMZQBREU.js.map +1 -0
  49. package/dist/client/index.cjs +191 -0
  50. package/dist/client/index.cjs.map +1 -0
  51. package/dist/client/index.d.ts +8 -0
  52. package/dist/client/index.js +14 -0
  53. package/dist/client/index.js.map +1 -0
  54. package/dist/config/index.cjs +63 -0
  55. package/dist/config/index.cjs.map +1 -0
  56. package/dist/config/index.d.ts +32 -0
  57. package/dist/config/index.js +9 -0
  58. package/dist/config/index.js.map +1 -0
  59. package/dist/data/index.d.ts +3 -0
  60. package/dist/data/react.d.ts +10 -0
  61. package/dist/data/service.d.ts +20 -0
  62. package/dist/data/types.d.ts +31 -0
  63. package/dist/devtools/events.d.ts +37 -0
  64. package/dist/devtools/index.cjs +149 -0
  65. package/dist/devtools/index.cjs.map +1 -0
  66. package/dist/devtools/index.d.ts +2 -0
  67. package/dist/devtools/index.js +18 -0
  68. package/dist/devtools/index.js.map +1 -0
  69. package/dist/devtools/react.d.ts +8 -0
  70. package/dist/form/index.cjs +301 -0
  71. package/dist/form/index.cjs.map +1 -0
  72. package/dist/form/index.d.ts +3 -0
  73. package/dist/form/index.js +14 -0
  74. package/dist/form/index.js.map +1 -0
  75. package/dist/form/react.d.ts +9 -0
  76. package/dist/form/service.d.ts +3 -0
  77. package/dist/form/types.d.ts +41 -0
  78. package/dist/framework/app.d.ts +21 -0
  79. package/dist/framework/cache.d.ts +10 -0
  80. package/dist/framework/contracts.d.ts +32 -0
  81. package/dist/framework/index.cjs +1006 -0
  82. package/dist/framework/index.cjs.map +1 -0
  83. package/dist/framework/index.d.ts +4 -0
  84. package/dist/framework/index.js +35 -0
  85. package/dist/framework/index.js.map +1 -0
  86. package/dist/framework/manifest.d.ts +12 -0
  87. package/dist/framework/vite.d.ts +13 -0
  88. package/dist/framework-vite/index.cjs +163 -0
  89. package/dist/framework-vite/index.cjs.map +1 -0
  90. package/dist/framework-vite/index.d.ts +1 -0
  91. package/dist/framework-vite/index.js +125 -0
  92. package/dist/framework-vite/index.js.map +1 -0
  93. package/dist/grid/grid.d.ts +8 -0
  94. package/dist/grid/index.cjs +238 -0
  95. package/dist/grid/index.cjs.map +1 -0
  96. package/dist/grid/index.d.ts +2 -0
  97. package/dist/grid/index.js +19 -0
  98. package/dist/grid/index.js.map +1 -0
  99. package/dist/grid/types.d.ts +35 -0
  100. package/dist/index.cjs +2512 -0
  101. package/dist/index.cjs.map +1 -0
  102. package/dist/index.d.ts +13 -0
  103. package/dist/index.js +207 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/kernel/app.d.ts +26 -0
  106. package/dist/kernel/index.d.ts +3 -0
  107. package/dist/kernel/runtime.d.ts +5 -0
  108. package/dist/kernel/telemetry.d.ts +37 -0
  109. package/dist/navigation/index.d.ts +4 -0
  110. package/dist/navigation/matcher.d.ts +13 -0
  111. package/dist/navigation/react.d.ts +12 -0
  112. package/dist/navigation/service.d.ts +23 -0
  113. package/dist/navigation/types.d.ts +65 -0
  114. package/dist/query/index.cjs +361 -0
  115. package/dist/query/index.cjs.map +1 -0
  116. package/dist/query/index.d.ts +3 -0
  117. package/dist/query/index.js +30 -0
  118. package/dist/query/index.js.map +1 -0
  119. package/dist/query/react.d.ts +27 -0
  120. package/dist/query/service.d.ts +10 -0
  121. package/dist/query/types.d.ts +5 -0
  122. package/dist/react/index.d.ts +1 -0
  123. package/dist/react/provider.d.ts +10 -0
  124. package/dist/realtime/channel.d.ts +15 -0
  125. package/dist/realtime/index.cjs +117 -0
  126. package/dist/realtime/index.cjs.map +1 -0
  127. package/dist/realtime/index.d.ts +2 -0
  128. package/dist/realtime/index.js +15 -0
  129. package/dist/realtime/index.js.map +1 -0
  130. package/dist/realtime/presence.d.ts +22 -0
  131. package/dist/render/hydration.d.ts +24 -0
  132. package/dist/render/index.d.ts +2 -0
  133. package/dist/render/ssr.d.ts +13 -0
  134. package/dist/router/helpers.d.ts +26 -0
  135. package/dist/router/index.cjs +236 -0
  136. package/dist/router/index.cjs.map +1 -0
  137. package/dist/router/index.d.ts +4 -0
  138. package/dist/router/index.js +40 -0
  139. package/dist/router/index.js.map +1 -0
  140. package/dist/router/react.d.ts +5 -0
  141. package/dist/router/service.d.ts +5 -0
  142. package/dist/router/types.d.ts +1 -0
  143. package/dist/server/index.cjs +174 -0
  144. package/dist/server/index.cjs.map +1 -0
  145. package/dist/server/index.d.ts +16 -0
  146. package/dist/server/index.js +12 -0
  147. package/dist/server/index.js.map +1 -0
  148. package/dist/state/index.cjs +128 -0
  149. package/dist/state/index.cjs.map +1 -0
  150. package/dist/state/index.d.ts +2 -0
  151. package/dist/state/index.js +36 -0
  152. package/dist/state/index.js.map +1 -0
  153. package/dist/state/react.d.ts +3 -0
  154. package/dist/state/service.d.ts +28 -0
  155. package/dist/testing/index.cjs +970 -0
  156. package/dist/testing/index.cjs.map +1 -0
  157. package/dist/testing/index.d.ts +2 -0
  158. package/dist/testing/index.js +13 -0
  159. package/dist/testing/index.js.map +1 -0
  160. package/dist/virtual/index.cjs +160 -0
  161. package/dist/virtual/index.cjs.map +1 -0
  162. package/dist/virtual/index.d.ts +2 -0
  163. package/dist/virtual/index.js +21 -0
  164. package/dist/virtual/index.js.map +1 -0
  165. package/dist/virtual/types.d.ts +25 -0
  166. package/dist/virtual/virtual.d.ts +9 -0
  167. package/package.json +156 -0
@@ -0,0 +1,423 @@
1
+ import {
2
+ Boundary
3
+ } from "./chunk-YG22YP5K.js";
4
+ import {
5
+ Telemetry
6
+ } from "./chunk-SKC3HMF3.js";
7
+
8
+ // src/navigation/types.ts
9
+ var defineRoute = (route) => route;
10
+ var defineLoader = (loader) => loader;
11
+ var NavigationRuntimeError = class extends Error {
12
+ constructor(messageText) {
13
+ super(messageText);
14
+ this.messageText = messageText;
15
+ this.name = "NavigationRuntimeError";
16
+ }
17
+ _tag = "NavigationRuntimeError";
18
+ };
19
+ var NavigationCancelledError = class extends Error {
20
+ constructor(pathname) {
21
+ super(`Navigation cancelled for ${pathname}`);
22
+ this.pathname = pathname;
23
+ this.name = "NavigationCancelledError";
24
+ }
25
+ _tag = "NavigationCancelledError";
26
+ };
27
+
28
+ // src/navigation/service.ts
29
+ import {
30
+ Cause,
31
+ Context,
32
+ Effect,
33
+ Fiber,
34
+ Layer,
35
+ Option,
36
+ Ref,
37
+ SubscriptionRef
38
+ } from "effect";
39
+
40
+ // src/navigation/matcher.ts
41
+ var normalizePathname = (pathname) => {
42
+ if (pathname.length === 0) {
43
+ return "/";
44
+ }
45
+ const withSlash = pathname.startsWith("/") ? pathname : `/${pathname}`;
46
+ if (withSlash.length > 1 && withSlash.endsWith("/")) {
47
+ return withSlash.slice(0, -1);
48
+ }
49
+ return withSlash;
50
+ };
51
+ var scoreRoute = (path) => {
52
+ if (path === "/") {
53
+ return 10;
54
+ }
55
+ return path.split("/").filter((segment) => segment.length > 0).reduce((score, segment) => {
56
+ if (segment === "*") {
57
+ return score;
58
+ }
59
+ if (segment.startsWith(":")) {
60
+ return score + 2;
61
+ }
62
+ return score + 5;
63
+ }, 0);
64
+ };
65
+ var splitSegments = (path) => normalizePathname(path).split("/").filter((segment) => segment.length > 0);
66
+ var matchRoutePath = (routePath, pathname) => {
67
+ const routeSegments = splitSegments(routePath);
68
+ const pathSegments = splitSegments(pathname);
69
+ const params = {};
70
+ let i = 0;
71
+ let j = 0;
72
+ while (i < routeSegments.length && j < pathSegments.length) {
73
+ const routeSegment = routeSegments[i];
74
+ const pathSegment = pathSegments[j];
75
+ if (routeSegment === "*") {
76
+ return params;
77
+ }
78
+ if (routeSegment.startsWith(":")) {
79
+ params[routeSegment.slice(1)] = decodeURIComponent(pathSegment);
80
+ i += 1;
81
+ j += 1;
82
+ continue;
83
+ }
84
+ if (routeSegment !== pathSegment) {
85
+ return null;
86
+ }
87
+ i += 1;
88
+ j += 1;
89
+ }
90
+ if (i < routeSegments.length && routeSegments[i] === "*") {
91
+ return params;
92
+ }
93
+ if (i !== routeSegments.length || j !== pathSegments.length) {
94
+ return null;
95
+ }
96
+ return params;
97
+ };
98
+ var matchRoute = ({ routes, pathname, search }) => {
99
+ const normalized = normalizePathname(pathname);
100
+ const sorted = [...routes].sort((a, b) => scoreRoute(b.path) - scoreRoute(a.path));
101
+ for (const route of sorted) {
102
+ const params = matchRoutePath(route.path, normalized);
103
+ if (params !== null) {
104
+ return {
105
+ route,
106
+ pathname: normalized,
107
+ params,
108
+ search
109
+ };
110
+ }
111
+ }
112
+ return null;
113
+ };
114
+ var buildHref = (pathname, searchText) => searchText.length > 0 ? `${normalizePathname(pathname)}${searchText}` : normalizePathname(pathname);
115
+ var normalizeSearchText = (searchText) => {
116
+ if (searchText.length === 0 || searchText === "?") {
117
+ return "";
118
+ }
119
+ return searchText.startsWith("?") ? searchText : `?${searchText}`;
120
+ };
121
+ var parseHref = (href) => {
122
+ const [pathPart, ...searchParts] = href.split("?");
123
+ return {
124
+ pathname: normalizePathname(pathPart ?? "/"),
125
+ searchText: normalizeSearchText(searchParts.length === 0 ? "" : searchParts.join("?"))
126
+ };
127
+ };
128
+
129
+ // src/navigation/service.ts
130
+ var describeUnknown = (value) => {
131
+ if (value instanceof Error) {
132
+ return `${value.name}: ${value.message}`;
133
+ }
134
+ if (typeof value === "string") {
135
+ return value;
136
+ }
137
+ try {
138
+ return JSON.stringify(value);
139
+ } catch {
140
+ return String(value);
141
+ }
142
+ };
143
+ var initialSnapshot = {
144
+ pathname: "/",
145
+ searchText: "",
146
+ href: "/",
147
+ status: "idle",
148
+ match: null,
149
+ loaders: {},
150
+ error: void 0
151
+ };
152
+ var toLoadersByName = (loaders) => new Map(loaders.map((loader) => [loader.name, loader]));
153
+ var planLoaderBatches = (loaders) => {
154
+ const byName = toLoadersByName(loaders);
155
+ const depthByName = /* @__PURE__ */ new Map();
156
+ const visiting = /* @__PURE__ */ new Set();
157
+ const resolveDepth = (name) => {
158
+ const cached = depthByName.get(name);
159
+ if (cached !== void 0) {
160
+ return Effect.succeed(cached);
161
+ }
162
+ if (visiting.has(name)) {
163
+ return Effect.fail(new NavigationRuntimeError(`Cyclic loader dependency detected at ${name}`));
164
+ }
165
+ const loader = byName.get(name);
166
+ if (loader === void 0) {
167
+ return Effect.fail(new NavigationRuntimeError(`Loader dependency '${name}' is not registered`));
168
+ }
169
+ visiting.add(name);
170
+ const dependencies = loader.dependsOn ?? [];
171
+ return Effect.forEach(dependencies, resolveDepth).pipe(
172
+ Effect.map((depths) => {
173
+ const depth = depths.length === 0 ? 0 : Math.max(...depths) + 1;
174
+ depthByName.set(name, depth);
175
+ visiting.delete(name);
176
+ return depth;
177
+ }),
178
+ Effect.catchAll((error) => {
179
+ visiting.delete(name);
180
+ return Effect.fail(error);
181
+ })
182
+ );
183
+ };
184
+ return Effect.gen(function* () {
185
+ const entries = yield* Effect.forEach(
186
+ loaders,
187
+ (loader) => Effect.map(resolveDepth(loader.name), (depth) => [depth, loader])
188
+ );
189
+ const grouped = /* @__PURE__ */ new Map();
190
+ for (const [depth, loader] of entries) {
191
+ const existing = grouped.get(depth);
192
+ if (existing === void 0) {
193
+ grouped.set(depth, [loader]);
194
+ } else {
195
+ existing.push(loader);
196
+ }
197
+ }
198
+ const depths = Array.from(grouped.keys()).sort((a, b) => a - b);
199
+ return depths.map((depth) => grouped.get(depth) ?? []);
200
+ });
201
+ };
202
+ var Navigation = class extends Context.Tag("EffectReact/Navigation")() {
203
+ };
204
+ var makeNavigationLayer = (options) => {
205
+ const loaders = options.loaders ?? [];
206
+ const initial = parseHref(options.initialHref ?? "/");
207
+ return Layer.effect(
208
+ Navigation,
209
+ Effect.gen(function* () {
210
+ const boundary = yield* Boundary;
211
+ const telemetry = yield* Telemetry;
212
+ const snapshotsRef = yield* SubscriptionRef.make({
213
+ ...initialSnapshot,
214
+ pathname: initial.pathname,
215
+ searchText: initial.searchText,
216
+ href: buildHref(initial.pathname, initial.searchText)
217
+ });
218
+ const activeFiberRef = yield* Ref.make(Option.none());
219
+ const runLoaders = (snapshot) => Effect.gen(function* () {
220
+ if (snapshot.match === null) {
221
+ return {};
222
+ }
223
+ const routeLoaders = loaders.filter((loader) => loader.routeId === snapshot.match.route.id);
224
+ if (routeLoaders.length === 0) {
225
+ return {};
226
+ }
227
+ const batches = yield* planLoaderBatches(routeLoaders);
228
+ const results = {};
229
+ const states = {};
230
+ for (const loader of routeLoaders) {
231
+ states[loader.name] = { _tag: "pending" };
232
+ }
233
+ yield* SubscriptionRef.update(snapshotsRef, (current) => ({
234
+ ...current,
235
+ loaders: {
236
+ ...current.loaders,
237
+ ...states
238
+ }
239
+ }));
240
+ for (const batch of batches) {
241
+ const exits = yield* Effect.all(
242
+ batch.map((loader) => {
243
+ const base = loader.run({
244
+ route: snapshot.match.route,
245
+ pathname: snapshot.pathname,
246
+ searchText: snapshot.searchText,
247
+ params: snapshot.match.params,
248
+ search: snapshot.match.search,
249
+ dependencyResults: results
250
+ });
251
+ const withRetry = loader.retry ? Effect.retry(base, loader.retry) : base;
252
+ return Effect.exit(withRetry).pipe(Effect.map((exit) => [loader, exit]));
253
+ }),
254
+ {
255
+ concurrency: "unbounded"
256
+ }
257
+ );
258
+ for (const [loader, exit] of exits) {
259
+ if (exit._tag === "Success") {
260
+ results[loader.name] = exit.value;
261
+ states[loader.name] = {
262
+ _tag: "success",
263
+ value: exit.value
264
+ };
265
+ continue;
266
+ }
267
+ const failure = Cause.failureOption(exit.cause);
268
+ states[loader.name] = {
269
+ _tag: "failure",
270
+ error: failure._tag === "Some" ? failure.value : Cause.pretty(exit.cause)
271
+ };
272
+ yield* SubscriptionRef.update(snapshotsRef, (current) => ({
273
+ ...current,
274
+ status: "failure",
275
+ loaders: {
276
+ ...current.loaders,
277
+ ...states
278
+ },
279
+ error: states[loader.name]
280
+ }));
281
+ return yield* Effect.fail(
282
+ new NavigationRuntimeError(`Loader '${loader.name}' failed for route '${snapshot.match.route.id}'`)
283
+ );
284
+ }
285
+ yield* SubscriptionRef.update(snapshotsRef, (current) => ({
286
+ ...current,
287
+ loaders: {
288
+ ...current.loaders,
289
+ ...states
290
+ }
291
+ }));
292
+ }
293
+ return states;
294
+ });
295
+ const performNavigation = (href) => Effect.gen(function* () {
296
+ const { pathname, searchText } = parseHref(href);
297
+ const searchParams = new URLSearchParams(searchText);
298
+ const candidate = options.routes.find((route) => matchRoute({
299
+ routes: [route],
300
+ pathname,
301
+ search: {}
302
+ }) !== null);
303
+ const decodedSearch = candidate?.search === void 0 ? Effect.succeed({}) : boundary.decodeUnknown({
304
+ source: `route:${candidate.id}:search`,
305
+ schema: candidate.search,
306
+ value: Object.fromEntries(searchParams.entries())
307
+ });
308
+ const search = yield* decodedSearch;
309
+ const matched = matchRoute({
310
+ routes: options.routes,
311
+ pathname,
312
+ search
313
+ });
314
+ if (matched === null) {
315
+ return yield* Effect.fail(
316
+ new NavigationRuntimeError(`No route matched pathname '${pathname}'`)
317
+ );
318
+ }
319
+ yield* telemetry.emit({
320
+ _tag: "navigation",
321
+ phase: "start",
322
+ pathname,
323
+ routeId: matched.route.id,
324
+ timestamp: Date.now()
325
+ });
326
+ const loadingSnapshot = {
327
+ pathname,
328
+ searchText: normalizeSearchText(searchText),
329
+ href: buildHref(pathname, normalizeSearchText(searchText)),
330
+ status: "loading",
331
+ match: matched,
332
+ loaders: {},
333
+ error: void 0
334
+ };
335
+ yield* SubscriptionRef.set(snapshotsRef, loadingSnapshot);
336
+ const loaderStates = yield* runLoaders(loadingSnapshot);
337
+ const completed = {
338
+ ...loadingSnapshot,
339
+ status: "success",
340
+ loaders: loaderStates,
341
+ error: void 0
342
+ };
343
+ yield* SubscriptionRef.set(snapshotsRef, completed);
344
+ yield* telemetry.emit({
345
+ _tag: "navigation",
346
+ phase: "success",
347
+ pathname,
348
+ routeId: matched.route.id,
349
+ timestamp: Date.now()
350
+ });
351
+ return completed;
352
+ });
353
+ const navigate = (href) => Effect.gen(function* () {
354
+ const previous = yield* Ref.getAndSet(activeFiberRef, Option.none());
355
+ if (Option.isSome(previous)) {
356
+ yield* Fiber.interrupt(previous.value);
357
+ yield* telemetry.emit({
358
+ _tag: "navigation",
359
+ phase: "cancel",
360
+ pathname: href,
361
+ timestamp: Date.now()
362
+ });
363
+ }
364
+ const fiber = yield* Effect.fork(performNavigation(href));
365
+ yield* Ref.set(activeFiberRef, Option.some(fiber));
366
+ const exit = yield* Effect.exit(Fiber.join(fiber));
367
+ const current = yield* Ref.get(activeFiberRef);
368
+ if (Option.isSome(current) && current.value === fiber) {
369
+ yield* Ref.set(activeFiberRef, Option.none());
370
+ }
371
+ if (exit._tag === "Success") {
372
+ return exit.value;
373
+ }
374
+ if (Cause.isInterruptedOnly(exit.cause)) {
375
+ return yield* Effect.fail(new NavigationCancelledError(href));
376
+ }
377
+ const failure = Cause.failureOption(exit.cause);
378
+ if (failure._tag === "Some") {
379
+ return yield* Effect.fail(
380
+ failure.value instanceof NavigationRuntimeError ? failure.value : new NavigationRuntimeError(describeUnknown(failure.value))
381
+ );
382
+ }
383
+ return yield* Effect.fail(new NavigationRuntimeError(Cause.pretty(exit.cause)));
384
+ }).pipe(
385
+ Effect.tapError(
386
+ (error) => telemetry.emit({
387
+ _tag: "navigation",
388
+ phase: "failure",
389
+ pathname: href,
390
+ timestamp: Date.now(),
391
+ detail: error
392
+ })
393
+ )
394
+ );
395
+ const revalidate = () => Effect.gen(function* () {
396
+ const snapshot = yield* SubscriptionRef.get(snapshotsRef);
397
+ return yield* navigate(snapshot.href);
398
+ });
399
+ return {
400
+ navigate,
401
+ revalidate,
402
+ getSnapshot: SubscriptionRef.get(snapshotsRef),
403
+ hydrateSnapshot: (snapshot) => SubscriptionRef.set(snapshotsRef, snapshot),
404
+ snapshots: snapshotsRef.changes
405
+ };
406
+ })
407
+ );
408
+ };
409
+ var navigateTo = (href) => Effect.flatMap(Navigation, (service) => service.navigate(href));
410
+
411
+ export {
412
+ defineRoute,
413
+ defineLoader,
414
+ NavigationRuntimeError,
415
+ NavigationCancelledError,
416
+ matchRoute,
417
+ buildHref,
418
+ parseHref,
419
+ Navigation,
420
+ makeNavigationLayer,
421
+ navigateTo
422
+ };
423
+ //# sourceMappingURL=chunk-O7XTA7H3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/navigation/types.ts","../src/navigation/service.ts","../src/navigation/matcher.ts"],"sourcesContent":["import type { Effect, Schedule, Schema } from \"effect\";\nimport type { BoundaryDecodeError } from \"../boundary\";\n\nexport interface RouteDefinition<Path extends string, Search, SearchEncoded = Search> {\n readonly id: string;\n readonly path: Path;\n readonly search?: Schema.Schema<Search, SearchEncoded, never>;\n}\n\nexport const defineRoute = <Path extends string, Search = Record<never, never>, SearchEncoded = Search>(\n route: RouteDefinition<Path, Search, SearchEncoded>,\n): RouteDefinition<Path, Search, SearchEncoded> => route;\n\nexport interface AnyRouteDefinition {\n readonly id: string;\n readonly path: string;\n readonly search?: Schema.Schema.All;\n}\n\nexport interface RouteMatch<TRoute extends AnyRouteDefinition> {\n readonly route: TRoute;\n readonly pathname: string;\n readonly params: Readonly<Record<string, string>>;\n readonly search: unknown;\n}\n\nexport interface LoaderContext<TRoute extends AnyRouteDefinition> {\n readonly route: TRoute;\n readonly pathname: string;\n readonly searchText: string;\n readonly params: Readonly<Record<string, string>>;\n readonly search: unknown;\n readonly dependencyResults: Readonly<Record<string, unknown>>;\n}\n\nexport interface LoaderDefinition<\n Name extends string,\n RouteId extends string,\n Output,\n E,\n TRoute extends AnyRouteDefinition = AnyRouteDefinition,\n> {\n readonly name: Name;\n readonly routeId: RouteId;\n readonly dependsOn?: readonly string[];\n readonly retry?: Schedule.Schedule<unknown, E, never>;\n readonly run: (context: LoaderContext<TRoute>) => Effect.Effect<Output, E, never>;\n}\n\nexport const defineLoader = <\n Name extends string,\n RouteId extends string,\n Output,\n E,\n TRoute extends AnyRouteDefinition = AnyRouteDefinition,\n>(\n loader: LoaderDefinition<Name, RouteId, Output, E, TRoute>,\n): LoaderDefinition<Name, RouteId, Output, E, TRoute> => loader;\n\nexport type AnyLoaderDefinition = LoaderDefinition<string, string, unknown, never, AnyRouteDefinition>;\n\nexport type LoaderSnapshotEntry =\n | {\n readonly _tag: \"pending\";\n }\n | {\n readonly _tag: \"success\";\n readonly value: unknown;\n }\n | {\n readonly _tag: \"failure\";\n readonly error: unknown;\n };\n\nexport interface NavigationSnapshot {\n readonly pathname: string;\n readonly searchText: string;\n readonly href: string;\n readonly status: \"idle\" | \"loading\" | \"success\" | \"failure\";\n readonly match: RouteMatch<AnyRouteDefinition> | null;\n readonly loaders: Readonly<Record<string, LoaderSnapshotEntry>>;\n readonly error: unknown;\n}\n\nexport class NavigationRuntimeError extends Error {\n readonly _tag = \"NavigationRuntimeError\" as const;\n\n constructor(readonly messageText: string) {\n super(messageText);\n this.name = \"NavigationRuntimeError\";\n }\n}\n\nexport class NavigationCancelledError extends Error {\n readonly _tag = \"NavigationCancelledError\" as const;\n\n constructor(readonly pathname: string) {\n super(`Navigation cancelled for ${pathname}`);\n this.name = \"NavigationCancelledError\";\n }\n}\n\nexport type NavigationError =\n | NavigationRuntimeError\n | NavigationCancelledError\n | BoundaryDecodeError;\n","import {\n Cause,\n Context,\n Effect,\n Fiber,\n Layer,\n Option,\n Ref,\n type Schema,\n type Stream,\n SubscriptionRef,\n} from \"effect\";\nimport { Boundary } from \"../boundary\";\nimport { Telemetry } from \"../kernel/telemetry\";\nimport { buildHref, matchRoute, normalizeSearchText, parseHref } from \"./matcher\";\nimport {\n type AnyLoaderDefinition,\n type AnyRouteDefinition,\n type LoaderSnapshotEntry,\n NavigationCancelledError,\n type NavigationSnapshot,\n NavigationRuntimeError,\n} from \"./types\";\nimport type { NavigationError } from \"./types\";\n\nconst describeUnknown = (value: unknown): string => {\n if (value instanceof Error) {\n return `${value.name}: ${value.message}`;\n }\n if (typeof value === \"string\") {\n return value;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n};\n\nconst initialSnapshot: NavigationSnapshot = {\n pathname: \"/\",\n searchText: \"\",\n href: \"/\",\n status: \"idle\",\n match: null,\n loaders: {},\n error: undefined,\n};\n\nconst toLoadersByName = (loaders: readonly AnyLoaderDefinition[]): ReadonlyMap<string, AnyLoaderDefinition> =>\n new Map(loaders.map((loader) => [loader.name, loader] as const));\n\nconst planLoaderBatches = (\n loaders: readonly AnyLoaderDefinition[],\n): Effect.Effect<readonly (readonly AnyLoaderDefinition[])[], NavigationRuntimeError, never> => {\n const byName = toLoadersByName(loaders);\n const depthByName = new Map<string, number>();\n const visiting = new Set<string>();\n\n const resolveDepth = (name: string): Effect.Effect<number, NavigationRuntimeError, never> => {\n const cached = depthByName.get(name);\n if (cached !== undefined) {\n return Effect.succeed(cached);\n }\n\n if (visiting.has(name)) {\n return Effect.fail(new NavigationRuntimeError(`Cyclic loader dependency detected at ${name}`));\n }\n\n const loader = byName.get(name);\n if (loader === undefined) {\n return Effect.fail(new NavigationRuntimeError(`Loader dependency '${name}' is not registered`));\n }\n\n visiting.add(name);\n\n const dependencies = loader.dependsOn ?? [];\n return Effect.forEach(dependencies, resolveDepth).pipe(\n Effect.map((depths) => {\n const depth = depths.length === 0 ? 0 : Math.max(...depths) + 1;\n depthByName.set(name, depth);\n visiting.delete(name);\n return depth;\n }),\n Effect.catchAll((error) => {\n visiting.delete(name);\n return Effect.fail(error);\n }),\n );\n };\n\n return Effect.gen(function* () {\n const entries = yield* Effect.forEach(loaders, (loader) =>\n Effect.map(resolveDepth(loader.name), (depth) => [depth, loader] as const),\n );\n\n const grouped = new Map<number, AnyLoaderDefinition[]>();\n for (const [depth, loader] of entries) {\n const existing = grouped.get(depth);\n if (existing === undefined) {\n grouped.set(depth, [loader]);\n } else {\n existing.push(loader);\n }\n }\n\n const depths = Array.from(grouped.keys()).sort((a, b) => a - b);\n return depths.map((depth) => grouped.get(depth) ?? []);\n });\n};\n\nexport interface NavigationService {\n readonly navigate: (href: string) => Effect.Effect<NavigationSnapshot, NavigationError, never>;\n readonly revalidate: () => Effect.Effect<NavigationSnapshot, NavigationError, never>;\n readonly getSnapshot: Effect.Effect<NavigationSnapshot, never, never>;\n readonly hydrateSnapshot: (snapshot: NavigationSnapshot) => Effect.Effect<void, never, never>;\n readonly snapshots: Stream.Stream<NavigationSnapshot>;\n}\n\nexport class Navigation extends Context.Tag(\"EffectReact/Navigation\")<\n Navigation,\n NavigationService\n>() {}\n\nexport interface MakeNavigationLayerOptions {\n readonly routes: readonly AnyRouteDefinition[];\n readonly loaders?: readonly AnyLoaderDefinition[];\n readonly initialHref?: string;\n}\n\nexport const makeNavigationLayer = (\n options: MakeNavigationLayerOptions,\n): Layer.Layer<Navigation, never, Boundary | Telemetry> => {\n const loaders = options.loaders ?? [];\n const initial = parseHref(options.initialHref ?? \"/\");\n\n return Layer.effect(\n Navigation,\n Effect.gen(function* () {\n const boundary = yield* Boundary;\n const telemetry = yield* Telemetry;\n const snapshotsRef = yield* SubscriptionRef.make<NavigationSnapshot>({\n ...initialSnapshot,\n pathname: initial.pathname,\n searchText: initial.searchText,\n href: buildHref(initial.pathname, initial.searchText),\n });\n const activeFiberRef = yield* Ref.make<Option.Option<Fiber.RuntimeFiber<NavigationSnapshot, NavigationError>>>(Option.none());\n\n const runLoaders = (\n snapshot: NavigationSnapshot,\n ): Effect.Effect<Readonly<Record<string, LoaderSnapshotEntry>>, NavigationRuntimeError, never> =>\n Effect.gen(function* () {\n if (snapshot.match === null) {\n return {};\n }\n\n const routeLoaders = loaders.filter((loader) => loader.routeId === snapshot.match!.route.id);\n if (routeLoaders.length === 0) {\n return {};\n }\n\n const batches = yield* planLoaderBatches(routeLoaders);\n const results: Record<string, unknown> = {};\n const states: Record<string, LoaderSnapshotEntry> = {};\n\n for (const loader of routeLoaders) {\n states[loader.name] = { _tag: \"pending\" };\n }\n\n yield* SubscriptionRef.update(snapshotsRef, (current) => ({\n ...current,\n loaders: {\n ...current.loaders,\n ...states,\n },\n }));\n\n for (const batch of batches) {\n const exits = yield* Effect.all(\n batch.map((loader) => {\n const base = loader.run({\n route: snapshot.match!.route,\n pathname: snapshot.pathname,\n searchText: snapshot.searchText,\n params: snapshot.match!.params,\n search: snapshot.match!.search,\n dependencyResults: results,\n });\n\n const withRetry = loader.retry ? Effect.retry(base, loader.retry) : base;\n return Effect.exit(withRetry).pipe(Effect.map((exit) => [loader, exit] as const));\n }),\n {\n concurrency: \"unbounded\",\n },\n );\n\n for (const [loader, exit] of exits) {\n if (exit._tag === \"Success\") {\n results[loader.name] = exit.value;\n states[loader.name] = {\n _tag: \"success\",\n value: exit.value,\n };\n continue;\n }\n\n const failure = Cause.failureOption(exit.cause);\n states[loader.name] = {\n _tag: \"failure\",\n error: failure._tag === \"Some\" ? failure.value : Cause.pretty(exit.cause),\n };\n\n yield* SubscriptionRef.update(snapshotsRef, (current) => ({\n ...current,\n status: \"failure\",\n loaders: {\n ...current.loaders,\n ...states,\n },\n error: states[loader.name],\n }) satisfies NavigationSnapshot);\n\n return yield* Effect.fail(\n new NavigationRuntimeError(`Loader '${loader.name}' failed for route '${snapshot.match!.route.id}'`),\n );\n }\n\n yield* SubscriptionRef.update(snapshotsRef, (current) => ({\n ...current,\n loaders: {\n ...current.loaders,\n ...states,\n },\n }) satisfies NavigationSnapshot);\n }\n\n return states;\n });\n\n const performNavigation = (\n href: string,\n ): Effect.Effect<NavigationSnapshot, NavigationError, never> =>\n Effect.gen(function* () {\n const { pathname, searchText } = parseHref(href);\n const searchParams = new URLSearchParams(searchText);\n\n const candidate = options.routes.find((route) => matchRoute({\n routes: [route],\n pathname,\n search: {},\n }) !== null);\n\n const decodedSearch =\n candidate?.search === undefined\n ? Effect.succeed({} as unknown)\n : boundary.decodeUnknown({\n source: `route:${candidate.id}:search`,\n schema: candidate.search as Schema.Schema<unknown, unknown, never>,\n value: Object.fromEntries(searchParams.entries()),\n });\n\n const search = yield* decodedSearch;\n const matched = matchRoute({\n routes: options.routes,\n pathname,\n search,\n });\n\n if (matched === null) {\n return yield* Effect.fail(\n new NavigationRuntimeError(`No route matched pathname '${pathname}'`),\n );\n }\n\n yield* telemetry.emit({\n _tag: \"navigation\",\n phase: \"start\",\n pathname,\n routeId: matched.route.id,\n timestamp: Date.now(),\n });\n\n const loadingSnapshot: NavigationSnapshot = {\n pathname,\n searchText: normalizeSearchText(searchText),\n href: buildHref(pathname, normalizeSearchText(searchText)),\n status: \"loading\",\n match: matched,\n loaders: {},\n error: undefined,\n };\n\n yield* SubscriptionRef.set(snapshotsRef, loadingSnapshot);\n\n const loaderStates = yield* runLoaders(loadingSnapshot);\n\n const completed: NavigationSnapshot = {\n ...loadingSnapshot,\n status: \"success\",\n loaders: loaderStates,\n error: undefined,\n };\n\n yield* SubscriptionRef.set(snapshotsRef, completed);\n yield* telemetry.emit({\n _tag: \"navigation\",\n phase: \"success\",\n pathname,\n routeId: matched.route.id,\n timestamp: Date.now(),\n });\n\n return completed;\n });\n\n const navigate: NavigationService[\"navigate\"] = (href) =>\n Effect.gen(function* () {\n const previous = yield* Ref.getAndSet(activeFiberRef, Option.none());\n if (Option.isSome(previous)) {\n yield* Fiber.interrupt(previous.value);\n yield* telemetry.emit({\n _tag: \"navigation\",\n phase: \"cancel\",\n pathname: href,\n timestamp: Date.now(),\n });\n }\n\n const fiber = yield* Effect.fork(performNavigation(href));\n yield* Ref.set(activeFiberRef, Option.some(fiber));\n\n const exit = yield* Effect.exit(Fiber.join(fiber));\n\n const current = yield* Ref.get(activeFiberRef);\n if (Option.isSome(current) && current.value === fiber) {\n yield* Ref.set(activeFiberRef, Option.none());\n }\n\n if (exit._tag === \"Success\") {\n return exit.value;\n }\n\n if (Cause.isInterruptedOnly(exit.cause)) {\n return yield* Effect.fail(new NavigationCancelledError(href));\n }\n\n const failure = Cause.failureOption(exit.cause);\n if (failure._tag === \"Some\") {\n return yield* Effect.fail(\n failure.value instanceof NavigationRuntimeError\n ? failure.value\n : new NavigationRuntimeError(describeUnknown(failure.value)),\n );\n }\n\n return yield* Effect.fail(new NavigationRuntimeError(Cause.pretty(exit.cause)));\n }).pipe(\n Effect.tapError((error) =>\n telemetry.emit({\n _tag: \"navigation\",\n phase: \"failure\",\n pathname: href,\n timestamp: Date.now(),\n detail: error,\n }),\n ),\n );\n\n const revalidate: NavigationService[\"revalidate\"] =\n () =>\n Effect.gen(function* () {\n const snapshot = yield* SubscriptionRef.get(snapshotsRef);\n return yield* navigate(snapshot.href);\n });\n\n return {\n navigate,\n revalidate,\n getSnapshot: SubscriptionRef.get(snapshotsRef),\n hydrateSnapshot: (snapshot) => SubscriptionRef.set(snapshotsRef, snapshot),\n snapshots: snapshotsRef.changes,\n } satisfies NavigationService;\n }),\n );\n};\n\nexport const navigateTo = (\n href: string,\n): Effect.Effect<NavigationSnapshot, NavigationError, Navigation> =>\n Effect.flatMap(Navigation, (service) => service.navigate(href));\n","import type { AnyRouteDefinition, RouteMatch } from \"./types\";\n\nconst normalizePathname = (pathname: string): string => {\n if (pathname.length === 0) {\n return \"/\";\n }\n const withSlash = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n if (withSlash.length > 1 && withSlash.endsWith(\"/\")) {\n return withSlash.slice(0, -1);\n }\n return withSlash;\n};\n\nconst scoreRoute = (path: string): number => {\n if (path === \"/\") {\n return 10;\n }\n return path\n .split(\"/\")\n .filter((segment) => segment.length > 0)\n .reduce((score, segment) => {\n if (segment === \"*\") {\n return score;\n }\n if (segment.startsWith(\":\")) {\n return score + 2;\n }\n return score + 5;\n }, 0);\n};\n\nconst splitSegments = (path: string): readonly string[] =>\n normalizePathname(path)\n .split(\"/\")\n .filter((segment) => segment.length > 0);\n\nconst matchRoutePath = (\n routePath: string,\n pathname: string,\n): Readonly<Record<string, string>> | null => {\n const routeSegments = splitSegments(routePath);\n const pathSegments = splitSegments(pathname);\n\n const params: Record<string, string> = {};\n let i = 0;\n let j = 0;\n\n while (i < routeSegments.length && j < pathSegments.length) {\n const routeSegment = routeSegments[i]!;\n const pathSegment = pathSegments[j]!;\n\n if (routeSegment === \"*\") {\n return params;\n }\n\n if (routeSegment.startsWith(\":\")) {\n params[routeSegment.slice(1)] = decodeURIComponent(pathSegment);\n i += 1;\n j += 1;\n continue;\n }\n\n if (routeSegment !== pathSegment) {\n return null;\n }\n\n i += 1;\n j += 1;\n }\n\n if (i < routeSegments.length && routeSegments[i] === \"*\") {\n return params;\n }\n\n if (i !== routeSegments.length || j !== pathSegments.length) {\n return null;\n }\n\n return params;\n};\n\nexport interface MatchInput {\n readonly routes: readonly AnyRouteDefinition[];\n readonly pathname: string;\n readonly search: unknown;\n}\n\nexport const matchRoute = ({ routes, pathname, search }: MatchInput): RouteMatch<AnyRouteDefinition> | null => {\n const normalized = normalizePathname(pathname);\n const sorted = [...routes].sort((a, b) => scoreRoute(b.path) - scoreRoute(a.path));\n\n for (const route of sorted) {\n const params = matchRoutePath(route.path, normalized);\n if (params !== null) {\n return {\n route,\n pathname: normalized,\n params,\n search,\n };\n }\n }\n\n return null;\n};\n\nexport const buildHref = (pathname: string, searchText: string): string =>\n searchText.length > 0 ? `${normalizePathname(pathname)}${searchText}` : normalizePathname(pathname);\n\nexport const normalizeSearchText = (searchText: string): string => {\n if (searchText.length === 0 || searchText === \"?\") {\n return \"\";\n }\n return searchText.startsWith(\"?\") ? searchText : `?${searchText}`;\n};\n\nexport const parseHref = (href: string): { readonly pathname: string; readonly searchText: string } => {\n const [pathPart, ...searchParts] = href.split(\"?\");\n return {\n pathname: normalizePathname(pathPart ?? \"/\"),\n searchText: normalizeSearchText(searchParts.length === 0 ? \"\" : searchParts.join(\"?\")),\n };\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,88 @@
1
+ import {
2
+ createChannel,
3
+ publish,
4
+ subscribe
5
+ } from "./chunk-JKN75OYC.js";
6
+ import {
7
+ useEffectRuntime
8
+ } from "./chunk-2GIUCKL2.js";
9
+ import {
10
+ Telemetry
11
+ } from "./chunk-SKC3HMF3.js";
12
+
13
+ // src/devtools/events.ts
14
+ import { Effect, Stream } from "effect";
15
+ var emptyRuntimeStream = () => Stream.fromIterable([]);
16
+ var wrapTelemetryEvent = (event) => ({
17
+ _tag: "telemetry",
18
+ timestamp: event.timestamp,
19
+ event
20
+ });
21
+ var wrapRuntimeEvent = (event) => ({
22
+ _tag: "runtime",
23
+ timestamp: event.timestamp,
24
+ event
25
+ });
26
+ var createRuntimeEventSource = () => Effect.map(createChannel(), (channel) => ({
27
+ emit: (event) => publish(channel, event),
28
+ stream: subscribe(channel)
29
+ }));
30
+ var createDevtoolsEventStream = (options) => {
31
+ const telemetry = options.telemetry.pipe(Stream.map(wrapTelemetryEvent));
32
+ const runtime = (options.runtime ?? emptyRuntimeStream()).pipe(Stream.map(wrapRuntimeEvent));
33
+ return {
34
+ stream: Stream.merge(telemetry, runtime)
35
+ };
36
+ };
37
+ var createDevtoolsEventStreamFromTelemetry = (options = {}) => Effect.map(
38
+ Telemetry,
39
+ (telemetry) => createDevtoolsEventStream({
40
+ telemetry: telemetry.stream,
41
+ ...options.runtime !== void 0 ? { runtime: options.runtime } : {}
42
+ })
43
+ );
44
+
45
+ // src/devtools/react.tsx
46
+ import { Effect as Effect2, Fiber, Stream as Stream2 } from "effect";
47
+ import { useEffect, useState } from "react";
48
+ var appendEvent = (current, event, limit) => {
49
+ if (limit <= 0) {
50
+ return current;
51
+ }
52
+ if (current.length < limit) {
53
+ return [...current, event];
54
+ }
55
+ return [...current.slice(current.length - limit + 1), event];
56
+ };
57
+ var useEventStream = (stream, options = {}) => {
58
+ const runtime = useEffectRuntime();
59
+ const limit = options.limit ?? 128;
60
+ const [events, setEvents] = useState([]);
61
+ useEffect(() => {
62
+ if (options.enabled === false || limit <= 0) {
63
+ return;
64
+ }
65
+ const fiber = runtime.runFork(
66
+ Stream2.runForEach(
67
+ stream,
68
+ (event) => Effect2.sync(() => {
69
+ setEvents((current) => appendEvent(current, event, limit));
70
+ })
71
+ )
72
+ );
73
+ return () => {
74
+ runtime.runFork(Fiber.interrupt(fiber));
75
+ };
76
+ }, [runtime, stream, options.enabled, limit]);
77
+ return events;
78
+ };
79
+ var useDevtoolsEvents = (source, options = {}) => useEventStream(source.stream, options);
80
+
81
+ export {
82
+ createRuntimeEventSource,
83
+ createDevtoolsEventStream,
84
+ createDevtoolsEventStreamFromTelemetry,
85
+ useEventStream,
86
+ useDevtoolsEvents
87
+ };
88
+ //# sourceMappingURL=chunk-S67FHWAR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/devtools/events.ts","../src/devtools/react.tsx"],"sourcesContent":["import { Effect, Stream } from \"effect\";\nimport { Telemetry, type TelemetryEvent } from \"../kernel/telemetry\";\nimport { createChannel, publish, subscribe } from \"../realtime\";\n\nexport type RuntimeEvent =\n | {\n readonly phase: \"runtime-created\" | \"runtime-disposed\";\n readonly timestamp: number;\n readonly detail?: unknown;\n }\n | {\n readonly phase: \"run-fork\" | \"run-sync\" | \"run-promise\";\n readonly timestamp: number;\n readonly detail?: unknown;\n };\n\nexport interface RuntimeEventSource {\n readonly emit: (event: RuntimeEvent) => Effect.Effect<void>;\n readonly stream: Stream.Stream<RuntimeEvent>;\n}\n\nexport type DevtoolsEvent =\n | {\n readonly _tag: \"telemetry\";\n readonly timestamp: number;\n readonly event: TelemetryEvent;\n }\n | {\n readonly _tag: \"runtime\";\n readonly timestamp: number;\n readonly event: RuntimeEvent;\n };\n\nexport interface DevtoolsEventStream {\n readonly stream: Stream.Stream<DevtoolsEvent>;\n}\n\nexport interface CreateDevtoolsEventStreamOptions {\n readonly telemetry: Stream.Stream<TelemetryEvent>;\n readonly runtime?: Stream.Stream<RuntimeEvent>;\n}\n\nexport interface CreateDevtoolsEventStreamFromTelemetryOptions {\n readonly runtime?: Stream.Stream<RuntimeEvent>;\n}\n\nconst emptyRuntimeStream = (): Stream.Stream<RuntimeEvent> =>\n Stream.fromIterable<RuntimeEvent>([]);\n\nconst wrapTelemetryEvent = (event: TelemetryEvent): DevtoolsEvent => ({\n _tag: \"telemetry\",\n timestamp: event.timestamp,\n event,\n});\n\nconst wrapRuntimeEvent = (event: RuntimeEvent): DevtoolsEvent => ({\n _tag: \"runtime\",\n timestamp: event.timestamp,\n event,\n});\n\nexport const createRuntimeEventSource = (): Effect.Effect<RuntimeEventSource> =>\n Effect.map(createChannel<RuntimeEvent>(), (channel) => ({\n emit: (event) => publish(channel, event),\n stream: subscribe(channel),\n }));\n\nexport const createDevtoolsEventStream = (\n options: CreateDevtoolsEventStreamOptions,\n): DevtoolsEventStream => {\n const telemetry = options.telemetry.pipe(Stream.map(wrapTelemetryEvent));\n const runtime = (options.runtime ?? emptyRuntimeStream()).pipe(Stream.map(wrapRuntimeEvent));\n\n return {\n stream: Stream.merge(telemetry, runtime),\n };\n};\n\nexport const createDevtoolsEventStreamFromTelemetry = (\n options: CreateDevtoolsEventStreamFromTelemetryOptions = {},\n): Effect.Effect<DevtoolsEventStream, never, Telemetry> =>\n Effect.map(Telemetry, (telemetry) =>\n createDevtoolsEventStream({\n telemetry: telemetry.stream,\n ...(options.runtime !== undefined ? { runtime: options.runtime } : {}),\n }),\n );\n","import { Effect, Fiber, Stream } from \"effect\";\nimport { useEffect, useState } from \"react\";\nimport { useEffectRuntime } from \"../react/provider\";\nimport type { DevtoolsEvent, DevtoolsEventStream } from \"./events\";\n\nexport interface UseEventStreamOptions {\n readonly enabled?: boolean;\n readonly limit?: number;\n}\n\nconst appendEvent = <Event,>(\n current: readonly Event[],\n event: Event,\n limit: number,\n): readonly Event[] => {\n if (limit <= 0) {\n return current;\n }\n if (current.length < limit) {\n return [...current, event];\n }\n return [...current.slice(current.length - limit + 1), event];\n};\n\nexport const useEventStream = <Event,>(\n stream: Stream.Stream<Event>,\n options: UseEventStreamOptions = {},\n): readonly Event[] => {\n const runtime = useEffectRuntime();\n const limit = options.limit ?? 128;\n const [events, setEvents] = useState<readonly Event[]>([]);\n\n useEffect(() => {\n if (options.enabled === false || limit <= 0) {\n return;\n }\n\n const fiber = runtime.runFork(\n Stream.runForEach(stream, (event) =>\n Effect.sync(() => {\n setEvents((current) => appendEvent(current, event, limit));\n }),\n ),\n );\n\n return () => {\n runtime.runFork(Fiber.interrupt(fiber));\n };\n }, [runtime, stream, options.enabled, limit]);\n\n return events;\n};\n\nexport const useDevtoolsEvents = (\n source: DevtoolsEventStream,\n options: UseEventStreamOptions = {},\n): readonly DevtoolsEvent[] => useEventStream(source.stream, options);\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,QAAQ,cAAc;AA8C/B,IAAM,qBAAqB,MACzB,OAAO,aAA2B,CAAC,CAAC;AAEtC,IAAM,qBAAqB,CAAC,WAA0C;AAAA,EACpE,MAAM;AAAA,EACN,WAAW,MAAM;AAAA,EACjB;AACF;AAEA,IAAM,mBAAmB,CAAC,WAAwC;AAAA,EAChE,MAAM;AAAA,EACN,WAAW,MAAM;AAAA,EACjB;AACF;AAEO,IAAM,2BAA2B,MACtC,OAAO,IAAI,cAA4B,GAAG,CAAC,aAAa;AAAA,EACtD,MAAM,CAAC,UAAU,QAAQ,SAAS,KAAK;AAAA,EACvC,QAAQ,UAAU,OAAO;AAC3B,EAAE;AAEG,IAAM,4BAA4B,CACvC,YACwB;AACxB,QAAM,YAAY,QAAQ,UAAU,KAAK,OAAO,IAAI,kBAAkB,CAAC;AACvE,QAAM,WAAW,QAAQ,WAAW,mBAAmB,GAAG,KAAK,OAAO,IAAI,gBAAgB,CAAC;AAE3F,SAAO;AAAA,IACL,QAAQ,OAAO,MAAM,WAAW,OAAO;AAAA,EACzC;AACF;AAEO,IAAM,yCAAyC,CACpD,UAAyD,CAAC,MAE1D,OAAO;AAAA,EAAI;AAAA,EAAW,CAAC,cACrB,0BAA0B;AAAA,IACxB,WAAW,UAAU;AAAA,IACrB,GAAI,QAAQ,YAAY,SAAY,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACtE,CAAC;AACH;;;ACtFF,SAAS,UAAAA,SAAQ,OAAO,UAAAC,eAAc;AACtC,SAAS,WAAW,gBAAgB;AASpC,IAAM,cAAc,CAClB,SACA,OACA,UACqB;AACrB,MAAI,SAAS,GAAG;AACd,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,SAAS,OAAO;AAC1B,WAAO,CAAC,GAAG,SAAS,KAAK;AAAA,EAC3B;AACA,SAAO,CAAC,GAAG,QAAQ,MAAM,QAAQ,SAAS,QAAQ,CAAC,GAAG,KAAK;AAC7D;AAEO,IAAM,iBAAiB,CAC5B,QACA,UAAiC,CAAC,MACb;AACrB,QAAM,UAAU,iBAAiB;AACjC,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA2B,CAAC,CAAC;AAEzD,YAAU,MAAM;AACd,QAAI,QAAQ,YAAY,SAAS,SAAS,GAAG;AAC3C;AAAA,IACF;AAEA,UAAM,QAAQ,QAAQ;AAAA,MACpBC,QAAO;AAAA,QAAW;AAAA,QAAQ,CAAC,UACzBC,QAAO,KAAK,MAAM;AAChB,oBAAU,CAAC,YAAY,YAAY,SAAS,OAAO,KAAK,CAAC;AAAA,QAC3D,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO,MAAM;AACX,cAAQ,QAAQ,MAAM,UAAU,KAAK,CAAC;AAAA,IACxC;AAAA,EACF,GAAG,CAAC,SAAS,QAAQ,QAAQ,SAAS,KAAK,CAAC;AAE5C,SAAO;AACT;AAEO,IAAM,oBAAoB,CAC/B,QACA,UAAiC,CAAC,MACL,eAAe,OAAO,QAAQ,OAAO;","names":["Effect","Stream","Stream","Effect"]}
@@ -0,0 +1,17 @@
1
+ // src/kernel/telemetry.ts
2
+ import { Context, Effect, Layer, PubSub, Stream } from "effect";
3
+ var Telemetry = class extends Context.Tag("EffectReact/Telemetry")() {
4
+ };
5
+ var TelemetryLive = Layer.effect(
6
+ Telemetry,
7
+ Effect.map(PubSub.unbounded(), (pubsub) => ({
8
+ emit: (event) => PubSub.publish(pubsub, event).pipe(Effect.asVoid),
9
+ stream: Stream.fromPubSub(pubsub)
10
+ }))
11
+ );
12
+
13
+ export {
14
+ Telemetry,
15
+ TelemetryLive
16
+ };
17
+ //# sourceMappingURL=chunk-SKC3HMF3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kernel/telemetry.ts"],"sourcesContent":["import { Context, Effect, Layer, PubSub, Stream } from \"effect\";\n\nexport type TelemetryEvent =\n | {\n readonly _tag: \"query\";\n readonly phase: \"start\" | \"success\" | \"failure\" | \"invalidate\";\n readonly key: string;\n readonly timestamp: number;\n readonly detail?: unknown;\n }\n | {\n readonly _tag: \"navigation\";\n readonly phase: \"start\" | \"success\" | \"failure\" | \"cancel\";\n readonly pathname: string;\n readonly routeId?: string;\n readonly timestamp: number;\n readonly detail?: unknown;\n }\n | {\n readonly _tag: \"action\";\n readonly phase: \"start\" | \"success\" | \"failure\" | \"transport\";\n readonly name: string;\n readonly timestamp: number;\n readonly detail?: unknown;\n }\n | {\n readonly _tag: \"boundary\";\n readonly phase: \"decode-failure\" | \"protocol-failure\" | \"transport-failure\";\n readonly source: string;\n readonly timestamp: number;\n readonly detail?: unknown;\n };\n\nexport interface TelemetryService {\n readonly emit: (event: TelemetryEvent) => Effect.Effect<void>;\n readonly stream: Stream.Stream<TelemetryEvent>;\n}\n\nexport class Telemetry extends Context.Tag(\"EffectReact/Telemetry\")<\n Telemetry,\n TelemetryService\n>() {}\n\nexport const TelemetryLive = Layer.effect(\n Telemetry,\n Effect.map(PubSub.unbounded<TelemetryEvent>(), (pubsub) => ({\n emit: (event) => PubSub.publish(pubsub, event).pipe(Effect.asVoid),\n stream: Stream.fromPubSub(pubsub),\n })),\n);\n\nexport const emitTelemetry = (event: TelemetryEvent): Effect.Effect<void, never, Telemetry> =>\n Effect.flatMap(Telemetry, (service) => service.emit(event));\n"],"mappings":";AAAA,SAAS,SAAS,QAAQ,OAAO,QAAQ,cAAc;AAsChD,IAAM,YAAN,cAAwB,QAAQ,IAAI,uBAAuB,EAGhE,EAAE;AAAC;AAEE,IAAM,gBAAgB,MAAM;AAAA,EACjC;AAAA,EACA,OAAO,IAAI,OAAO,UAA0B,GAAG,CAAC,YAAY;AAAA,IAC1D,MAAM,CAAC,UAAU,OAAO,QAAQ,QAAQ,KAAK,EAAE,KAAK,OAAO,MAAM;AAAA,IACjE,QAAQ,OAAO,WAAW,MAAM;AAAA,EAClC,EAAE;AACJ;","names":[]}