@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,174 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/server/index.ts
31
+ var server_exports = {};
32
+ __export(server_exports, {
33
+ createRequestHandler: () => createRequestHandler
34
+ });
35
+ module.exports = __toCommonJS(server_exports);
36
+ var import_effect5 = require("effect");
37
+ var import_react = require("react");
38
+
39
+ // src/navigation/service.ts
40
+ var import_effect = require("effect");
41
+ var Navigation = class extends import_effect.Context.Tag("EffectReact/Navigation")() {
42
+ };
43
+ var navigateTo = (href) => import_effect.Effect.flatMap(Navigation, (service) => service.navigate(href));
44
+
45
+ // src/render/hydration.ts
46
+ var import_effect3 = require("effect");
47
+
48
+ // src/data/service.ts
49
+ var import_effect2 = require("effect");
50
+ var Data = class extends import_effect2.Context.Tag("EffectReact/Data")() {
51
+ };
52
+
53
+ // src/render/hydration.ts
54
+ var QuerySnapshotSchema = import_effect3.Schema.Struct({
55
+ key: import_effect3.Schema.String,
56
+ phase: import_effect3.Schema.Union(
57
+ import_effect3.Schema.Literal("initial"),
58
+ import_effect3.Schema.Literal("loading"),
59
+ import_effect3.Schema.Literal("success"),
60
+ import_effect3.Schema.Literal("failure")
61
+ ),
62
+ data: import_effect3.Schema.NullishOr(import_effect3.Schema.Unknown),
63
+ error: import_effect3.Schema.NullishOr(import_effect3.Schema.Unknown),
64
+ updatedAt: import_effect3.Schema.NullishOr(import_effect3.Schema.Number)
65
+ });
66
+ var HydrationStateSchema = import_effect3.Schema.Struct({
67
+ version: import_effect3.Schema.Literal(1),
68
+ data: import_effect3.Schema.Array(import_effect3.Schema.Tuple(import_effect3.Schema.String, QuerySnapshotSchema)),
69
+ navigationHref: import_effect3.Schema.String
70
+ });
71
+ var escapeForScript = (value) => value.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
72
+ var dehydrateAppState = () => import_effect3.Effect.gen(function* () {
73
+ const data = yield* Data;
74
+ const navigation = yield* Navigation;
75
+ const snapshots = yield* data.getAllSnapshots;
76
+ const navigationSnapshot = yield* navigation.getSnapshot;
77
+ return {
78
+ version: 1,
79
+ data: Array.from(snapshots.entries()),
80
+ navigationHref: navigationSnapshot.href
81
+ };
82
+ });
83
+ var createHydrationScript = (state, globalName = "__effectReactHydration") => {
84
+ const serialized = JSON.stringify(state);
85
+ return `window[${JSON.stringify(globalName)}]=JSON.parse(${JSON.stringify(escapeForScript(serialized))});`;
86
+ };
87
+
88
+ // src/render/ssr.ts
89
+ var import_effect4 = require("effect");
90
+ var ReactDOMServer = __toESM(require("react-dom/server"), 1);
91
+ var htmlResponse = (options) => {
92
+ const headers = new Headers(options.headers);
93
+ if (!headers.has("content-type")) {
94
+ headers.set("content-type", "text/html; charset=utf-8");
95
+ }
96
+ return new Response(options.html, {
97
+ status: options.status,
98
+ headers
99
+ });
100
+ };
101
+ var injectScript = (html, script) => {
102
+ const tag = `<script>${script}</script>`;
103
+ const bodyClose = html.lastIndexOf("</body>");
104
+ if (bodyClose === -1) {
105
+ return `${html}${tag}`;
106
+ }
107
+ return `${html.slice(0, bodyClose)}${tag}${html.slice(bodyClose)}`;
108
+ };
109
+ var toError = (cause) => cause instanceof Error ? cause : new Error(String(cause));
110
+ var createSsrHandler = (options) => (request) => {
111
+ const program = import_effect4.Effect.gen(function* () {
112
+ const element = yield* options.render(request);
113
+ const html = ReactDOMServer.renderToString(element);
114
+ const state = yield* dehydrateAppState();
115
+ const script = createHydrationScript(state, options.hydrationGlobalName);
116
+ return htmlResponse({
117
+ html: injectScript(html, script),
118
+ status: options.status ?? 200,
119
+ ...options.headers !== void 0 ? { headers: options.headers } : {}
120
+ });
121
+ });
122
+ return options.runtime.runPromise(program).catch((cause) => {
123
+ const squashed = toError(cause);
124
+ if (options.onError !== void 0) {
125
+ return options.onError(squashed);
126
+ }
127
+ return new Response(`SSR render failed: ${squashed.message}`, {
128
+ status: 500,
129
+ headers: {
130
+ "content-type": "text/plain; charset=utf-8"
131
+ }
132
+ });
133
+ });
134
+ };
135
+
136
+ // src/server/index.ts
137
+ var defaultNotFoundElement = () => (0, import_react.createElement)("main", void 0, "Not Found");
138
+ var createRequestHandler = (options) => {
139
+ const actionPath = options.actionPath ?? "/_actions";
140
+ const ssrHandler = createSsrHandler({
141
+ runtime: options.app.runtime,
142
+ ...options.hydrationGlobalName !== void 0 ? { hydrationGlobalName: options.hydrationGlobalName } : {},
143
+ ...options.onError !== void 0 ? { onError: options.onError } : {},
144
+ render: (request) => import_effect5.Effect.gen(function* () {
145
+ const url = new URL(request.url);
146
+ const href = `${url.pathname}${url.search}`;
147
+ const page = options.app.matchPage(href);
148
+ if (page === void 0) {
149
+ return defaultNotFoundElement();
150
+ }
151
+ yield* navigateTo(href);
152
+ if (options.render !== void 0) {
153
+ return yield* options.render({ request, page });
154
+ }
155
+ return (0, import_react.createElement)(page.component);
156
+ }).pipe(
157
+ import_effect5.Effect.mapError(
158
+ (error) => error instanceof Error ? error : new Error(String(error))
159
+ )
160
+ )
161
+ });
162
+ return (request) => {
163
+ const url = new URL(request.url);
164
+ if (request.method.toUpperCase() === "POST" && url.pathname === actionPath) {
165
+ return options.app.handleActionRequest(request);
166
+ }
167
+ return ssrHandler(request);
168
+ };
169
+ };
170
+ // Annotate the CommonJS export names for ESM import in node:
171
+ 0 && (module.exports = {
172
+ createRequestHandler
173
+ });
174
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server/index.ts","../../src/navigation/service.ts","../../src/render/hydration.ts","../../src/data/service.ts","../../src/render/ssr.ts"],"sourcesContent":["import { Effect } from \"effect\";\nimport { createElement, type ReactElement } from \"react\";\nimport type { AppServices } from \"../kernel/app\";\nimport { navigateTo } from \"../navigation\";\nimport { createSsrHandler } from \"../render\";\nimport type { AnyPageDefinition } from \"../framework/contracts\";\nimport type { EffectReactApp } from \"../framework/app\";\n\nexport interface CreateRequestHandlerOptions {\n readonly app: EffectReactApp;\n readonly render?: (options: {\n readonly request: Request;\n readonly page: AnyPageDefinition;\n }) => Effect.Effect<ReactElement, unknown, AppServices>;\n readonly actionPath?: string;\n readonly hydrationGlobalName?: string;\n readonly onError?: (error: Error) => Response;\n}\n\nconst defaultNotFoundElement = (): ReactElement =>\n createElement(\"main\", undefined, \"Not Found\");\n\nexport const createRequestHandler = (\n options: CreateRequestHandlerOptions,\n): ((request: Request) => Promise<Response>) => {\n const actionPath = options.actionPath ?? \"/_actions\";\n\n const ssrHandler = createSsrHandler({\n runtime: options.app.runtime,\n ...(options.hydrationGlobalName !== undefined\n ? { hydrationGlobalName: options.hydrationGlobalName }\n : {}),\n ...(options.onError !== undefined ? { onError: options.onError } : {}),\n render: (request) =>\n Effect.gen(function* () {\n const url = new URL(request.url);\n const href = `${url.pathname}${url.search}`;\n const page = options.app.matchPage(href);\n\n if (page === undefined) {\n return defaultNotFoundElement();\n }\n\n yield* navigateTo(href);\n\n if (options.render !== undefined) {\n return yield* options.render({ request, page });\n }\n\n return createElement(page.component);\n }).pipe(\n Effect.mapError((error) =>\n error instanceof Error ? error : new Error(String(error)),\n ),\n ),\n });\n\n return (request) => {\n const url = new URL(request.url);\n if (request.method.toUpperCase() === \"POST\" && url.pathname === actionPath) {\n return options.app.handleActionRequest(request);\n }\n\n return ssrHandler(request);\n };\n};\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 { Effect, Schema } from \"effect\";\nimport { Boundary } from \"../boundary\";\nimport { Data } from \"../data/service\";\nimport type { QuerySnapshot } from \"../data/types\";\nimport { Navigation } from \"../navigation/service\";\nimport { parseHref } from \"../navigation/matcher\";\n\nexport interface HydrationState {\n readonly version: 1;\n readonly data: readonly (readonly [string, QuerySnapshot<unknown, unknown>])[];\n readonly navigationHref: string;\n}\n\nconst QuerySnapshotSchema = Schema.Struct({\n key: Schema.String,\n phase: Schema.Union(\n Schema.Literal(\"initial\"),\n Schema.Literal(\"loading\"),\n Schema.Literal(\"success\"),\n Schema.Literal(\"failure\"),\n ),\n data: Schema.NullishOr(Schema.Unknown),\n error: Schema.NullishOr(Schema.Unknown),\n updatedAt: Schema.NullishOr(Schema.Number),\n});\n\nexport const HydrationStateSchema = Schema.Struct({\n version: Schema.Literal(1),\n data: Schema.Array(Schema.Tuple(Schema.String, QuerySnapshotSchema)),\n navigationHref: Schema.String,\n});\n\nconst escapeForScript = (value: string): string =>\n value\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n\nexport const dehydrateAppState = (): Effect.Effect<HydrationState, never, Data | Navigation> =>\n Effect.gen(function* () {\n const data = yield* Data;\n const navigation = yield* Navigation;\n\n const snapshots = yield* data.getAllSnapshots;\n const navigationSnapshot = yield* navigation.getSnapshot;\n\n return {\n version: 1,\n data: Array.from(snapshots.entries()),\n navigationHref: navigationSnapshot.href,\n } satisfies HydrationState;\n });\n\nexport const createHydrationScript = (\n state: HydrationState,\n globalName = \"__effectReactHydration\",\n): string => {\n const serialized = JSON.stringify(state);\n return `window[${JSON.stringify(globalName)}]=JSON.parse(${JSON.stringify(escapeForScript(serialized))});`;\n};\n\nexport const hydrateAppState = (\n payload: unknown,\n): Effect.Effect<void, unknown, Boundary | Data | Navigation> =>\n Effect.gen(function* () {\n const boundary = yield* Boundary;\n const data = yield* Data;\n const navigation = yield* Navigation;\n\n const decoded = yield* boundary.decodeUnknown({\n source: \"hydration:payload\",\n schema: HydrationStateSchema,\n value: payload,\n });\n\n const mapped = new Map<string, QuerySnapshot<unknown, unknown>>(decoded.data);\n yield* data.hydrateSnapshots(mapped);\n\n const current = yield* navigation.getSnapshot;\n const parsed = parseHref(decoded.navigationHref);\n\n yield* navigation.hydrateSnapshot({\n ...current,\n pathname: parsed.pathname,\n searchText: parsed.searchText,\n href: decoded.navigationHref,\n status: \"success\",\n match: null,\n loaders: {},\n error: undefined,\n });\n });\n","import {\n Cache,\n Context,\n Effect,\n Layer,\n SubscriptionRef,\n type Stream,\n} from \"effect\";\nimport { Boundary, type BoundaryDecodeError } from \"../boundary\";\nimport type { BoundaryProtocolError } from \"../boundary/errors\";\nimport { Telemetry } from \"../kernel/telemetry\";\nimport {\n type QueryDefinition,\n type QueryRunOptions,\n type QueryRuntimeOptions,\n type QuerySnapshot,\n QueryRuntimeError,\n} from \"./types\";\n\nconst defaultRuntimeOptions: Required<QueryRuntimeOptions> = {\n capacity: 2048,\n timeToLive: \"5 minutes\",\n};\n\nconst stableStringify = (value: unknown): string => {\n if (value === null || value === undefined) {\n return String(value);\n }\n\n if (typeof value !== \"object\") {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n\n const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) =>\n a.localeCompare(b),\n );\n return `{${entries.map(([key, nested]) => `${JSON.stringify(key)}:${stableStringify(nested)}`).join(\",\")}}`;\n};\n\nconst initialSnapshot = <Output, E>(key: string): QuerySnapshot<Output, E> => ({\n key,\n phase: \"initial\",\n data: undefined,\n error: undefined,\n updatedAt: null,\n});\n\nexport interface DataService {\n readonly fetch: <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n options?: QueryRunOptions,\n ) => Effect.Effect<Output, E | BoundaryDecodeError | BoundaryProtocolError | QueryRuntimeError, never>;\n readonly prefetch: <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n ) => Effect.Effect<void, E | BoundaryDecodeError | BoundaryProtocolError | QueryRuntimeError, never>;\n readonly invalidate: <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n ) => Effect.Effect<void, QueryRuntimeError, never>;\n readonly getSnapshot: <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n ) => Effect.Effect<QuerySnapshot<Output, E>, never, never>;\n readonly getAllSnapshots: Effect.Effect<ReadonlyMap<string, QuerySnapshot<unknown, unknown>>, never, never>;\n readonly hydrateSnapshots: (\n snapshots: ReadonlyMap<string, QuerySnapshot<unknown, unknown>>,\n ) => Effect.Effect<void, never, never>;\n readonly snapshots: Stream.Stream<ReadonlyMap<string, QuerySnapshot<unknown, unknown>>>;\n}\n\nexport class Data extends Context.Tag(\"EffectReact/Data\")<Data, DataService>() {}\n\nexport const makeDataLayer = (\n options: QueryRuntimeOptions = {},\n): Layer.Layer<Data, never, Boundary | Telemetry> => {\n const merged = {\n ...defaultRuntimeOptions,\n ...options,\n };\n\n return Layer.effect(\n Data,\n Effect.gen(function* () {\n const boundary = yield* Boundary;\n const telemetry = yield* Telemetry;\n const lookups = new Map<string, Effect.Effect<unknown, unknown, never>>();\n const snapshots = yield* SubscriptionRef.make(\n new Map<string, QuerySnapshot<unknown, unknown>>() as ReadonlyMap<\n string,\n QuerySnapshot<unknown, unknown>\n >,\n );\n\n const cache = yield* Cache.make<string, unknown, unknown>({\n capacity: merged.capacity,\n timeToLive: merged.timeToLive,\n lookup: (key) =>\n Effect.suspend(() => {\n const lookup = lookups.get(key);\n if (lookup === undefined) {\n return Effect.fail(new QueryRuntimeError(`No query executor registered for ${key}`));\n }\n return lookup;\n }),\n });\n\n const setSnapshot = <Output, E>(\n key: string,\n update: (previous: QuerySnapshot<Output, E>) => QuerySnapshot<Output, E>,\n ): Effect.Effect<void> =>\n SubscriptionRef.update(snapshots, (current) => {\n const next = new Map(current);\n const previous =\n (next.get(key) as QuerySnapshot<Output, E> | undefined) ?? initialSnapshot<Output, E>(key);\n next.set(key, update(previous));\n return next;\n }).pipe(Effect.asVoid);\n\n const buildKey = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: Input,\n ): string => {\n const base = definition.key ? definition.key(input) : input;\n return `${definition.name}:${stableStringify(base)}`;\n };\n\n const fetch = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n runOptions?: QueryRunOptions,\n ): Effect.Effect<\n Output,\n E | BoundaryDecodeError | BoundaryProtocolError | QueryRuntimeError,\n never\n > =>\n Effect.gen(function* () {\n const decodedInput = yield* boundary.decodeUnknown({\n source: `query:${definition.name}:input`,\n schema: definition.input,\n value: input,\n });\n\n const key = buildKey(definition, decodedInput);\n yield* telemetry.emit({\n _tag: \"query\",\n phase: \"start\",\n key,\n timestamp: Date.now(),\n });\n\n yield* setSnapshot(key, (previous) => ({\n ...previous,\n phase: \"loading\",\n error: undefined,\n }));\n\n lookups.set(\n key,\n definition\n .run(decodedInput)\n .pipe(\n Effect.flatMap((output) =>\n boundary.decodeUnknown({\n source: `query:${definition.name}:output`,\n schema: definition.output,\n value: output,\n }),\n ),\n ) as Effect.Effect<unknown, unknown, never>,\n );\n\n if (runOptions?.forceRefresh === true) {\n yield* cache.refresh(key).pipe(Effect.ignore);\n }\n\n const value = yield* cache.get(key).pipe(\n Effect.mapError(\n (error) =>\n error as E | BoundaryDecodeError | BoundaryProtocolError | QueryRuntimeError,\n ),\n );\n\n yield* setSnapshot(key, () => ({\n key,\n phase: \"success\",\n data: value,\n error: undefined,\n updatedAt: Date.now(),\n }));\n\n yield* telemetry.emit({\n _tag: \"query\",\n phase: \"success\",\n key,\n timestamp: Date.now(),\n });\n\n return value as Output;\n }).pipe(\n Effect.tapError((error) =>\n Effect.gen(function* () {\n const decodedInput = yield* boundary.decodeUnknown({\n source: `query:${definition.name}:input`,\n schema: definition.input,\n value: input,\n });\n const key = buildKey(definition, decodedInput);\n yield* setSnapshot(key, (previous) => ({\n ...previous,\n phase: \"failure\",\n error,\n updatedAt: previous.updatedAt,\n }));\n yield* telemetry.emit({\n _tag: \"query\",\n phase: \"failure\",\n key,\n timestamp: Date.now(),\n detail: error,\n });\n }),\n ),\n );\n\n const prefetch: DataService[\"prefetch\"] = (definition, input) =>\n fetch(definition, input).pipe(Effect.asVoid);\n\n const invalidate: DataService[\"invalidate\"] = (definition, input) =>\n Effect.gen(function* () {\n const key = `${definition.name}:${stableStringify(input)}`;\n yield* cache.invalidate(key);\n yield* SubscriptionRef.update(snapshots, (current) => {\n const next = new Map(current);\n next.delete(key);\n return next;\n }).pipe(Effect.asVoid);\n yield* telemetry.emit({\n _tag: \"query\",\n phase: \"invalidate\",\n key,\n timestamp: Date.now(),\n });\n });\n\n const getSnapshot = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n ): Effect.Effect<QuerySnapshot<Output, E>, never, never> =>\n Effect.gen(function* () {\n const key = `${definition.name}:${stableStringify(input)}`;\n const current = yield* SubscriptionRef.get(snapshots);\n const snapshot = current.get(key);\n if (snapshot === undefined) {\n return initialSnapshot<Output, E>(key);\n }\n return snapshot as QuerySnapshot<Output, E>;\n });\n\n return {\n fetch,\n prefetch,\n invalidate,\n getSnapshot,\n getAllSnapshots: SubscriptionRef.get(snapshots),\n hydrateSnapshots: (nextSnapshots) => SubscriptionRef.set(snapshots, new Map(nextSnapshots)),\n snapshots: snapshots.changes,\n } satisfies DataService;\n }),\n );\n};\n\nexport const fetchQuery = <Name extends string, Input, Output, E>(\n definition: QueryDefinition<Name, Input, Output, E>,\n input: unknown,\n options?: QueryRunOptions,\n): Effect.Effect<Output, E | BoundaryDecodeError | BoundaryProtocolError | QueryRuntimeError, Data> =>\n Effect.flatMap(Data, (service) => service.fetch(definition, input, options));\n","import { Effect } from \"effect\";\nimport type { ReactElement } from \"react\";\nimport * as ReactDOMServer from \"react-dom/server\";\nimport type { AppServices } from \"../kernel/app\";\nimport type { AppManagedRuntime } from \"../kernel/runtime\";\nimport { createHydrationScript, dehydrateAppState, type HydrationState } from \"./hydration\";\n\nexport interface CreateSsrHandlerOptions<E> {\n readonly runtime: AppManagedRuntime<AppServices>;\n readonly render: (request: Request) => Effect.Effect<ReactElement, E, AppServices>;\n readonly status?: number;\n readonly headers?: HeadersInit;\n readonly hydrationGlobalName?: string;\n readonly onError?: (error: E | Error) => Response;\n}\n\nconst htmlResponse = (options: {\n readonly html: string;\n readonly status: number;\n readonly headers?: HeadersInit;\n}): Response => {\n const headers = new Headers(options.headers);\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"text/html; charset=utf-8\");\n }\n return new Response(options.html, {\n status: options.status,\n headers,\n });\n};\n\nconst injectScript = (html: string, script: string): string => {\n const tag = `<script>${script}</script>`;\n const bodyClose = html.lastIndexOf(\"</body>\");\n if (bodyClose === -1) {\n return `${html}${tag}`;\n }\n return `${html.slice(0, bodyClose)}${tag}${html.slice(bodyClose)}`;\n};\n\nconst toError = (cause: unknown): Error =>\n cause instanceof Error ? cause : new Error(String(cause));\n\nexport const createSsrHandler = <E>(options: CreateSsrHandlerOptions<E>) =>\n (request: Request): Promise<Response> => {\n const program = Effect.gen(function* () {\n const element = yield* options.render(request);\n const html = ReactDOMServer.renderToString(element);\n\n const state: HydrationState = yield* dehydrateAppState();\n const script = createHydrationScript(state, options.hydrationGlobalName);\n\n return htmlResponse({\n html: injectScript(html, script),\n status: options.status ?? 200,\n ...(options.headers !== undefined ? { headers: options.headers } : {}),\n });\n });\n\n return options.runtime\n .runPromise(program)\n .catch((cause: unknown) => {\n const squashed = toError(cause);\n if (options.onError !== undefined) {\n return options.onError(squashed as E | Error);\n }\n return new Response(`SSR render failed: ${squashed.message}`, {\n status: 500,\n headers: {\n \"content-type\": \"text/plain; charset=utf-8\",\n },\n });\n });\n };\n"],"mappings":"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","names":["import_effect","import_effect","import_effect","import_effect"]}
@@ -0,0 +1,16 @@
1
+ import { Effect } from "effect";
2
+ import { type ReactElement } from "react";
3
+ import type { AppServices } from "../kernel/app";
4
+ import type { AnyPageDefinition } from "../framework/contracts";
5
+ import type { EffectReactApp } from "../framework/app";
6
+ export interface CreateRequestHandlerOptions {
7
+ readonly app: EffectReactApp;
8
+ readonly render?: (options: {
9
+ readonly request: Request;
10
+ readonly page: AnyPageDefinition;
11
+ }) => Effect.Effect<ReactElement, unknown, AppServices>;
12
+ readonly actionPath?: string;
13
+ readonly hydrationGlobalName?: string;
14
+ readonly onError?: (error: Error) => Response;
15
+ }
16
+ export declare const createRequestHandler: (options: CreateRequestHandlerOptions) => ((request: Request) => Promise<Response>);
@@ -0,0 +1,12 @@
1
+ import {
2
+ createRequestHandler
3
+ } from "../chunk-EEYASTXR.js";
4
+ import "../chunk-IVIYY6S5.js";
5
+ import "../chunk-C5JI7D7W.js";
6
+ import "../chunk-O7XTA7H3.js";
7
+ import "../chunk-YG22YP5K.js";
8
+ import "../chunk-SKC3HMF3.js";
9
+ export {
10
+ createRequestHandler
11
+ };
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/state/index.ts
21
+ var state_exports = {};
22
+ __export(state_exports, {
23
+ changes: () => changes,
24
+ createStore: () => createStore,
25
+ createStoreFromEffect: () => createStoreFromEffect,
26
+ createStoreTag: () => createStoreTag,
27
+ derive: () => derive,
28
+ get: () => get,
29
+ makeStoreLayer: () => makeStoreLayer,
30
+ makeStoreLayerFromEffect: () => makeStoreLayerFromEffect,
31
+ modify: () => modify,
32
+ select: () => select,
33
+ selectChanges: () => selectChanges,
34
+ set: () => set,
35
+ update: () => update,
36
+ useStore: () => useStore,
37
+ useStoreSelector: () => useStoreSelector
38
+ });
39
+ module.exports = __toCommonJS(state_exports);
40
+
41
+ // src/state/service.ts
42
+ var import_effect = require("effect");
43
+ var defaultEquality = (left, right) => Object.is(left, right);
44
+ var createStore = (initial) => import_effect.Effect.map(import_effect.SubscriptionRef.make(initial), (ref) => ({ ref }));
45
+ var createStoreFromEffect = (initial) => import_effect.Effect.flatMap(initial, createStore);
46
+ var createStoreTag = (key) => import_effect.Context.GenericTag(key);
47
+ var makeStoreLayer = (tag, initial) => import_effect.Layer.effect(tag, createStore(initial));
48
+ var makeStoreLayerFromEffect = (tag, initial) => import_effect.Layer.effect(tag, createStoreFromEffect(initial));
49
+ var get = (store) => import_effect.SubscriptionRef.get(store.ref);
50
+ var set = (store, value) => import_effect.SubscriptionRef.set(store.ref, value);
51
+ var update = (store, mutate) => import_effect.SubscriptionRef.update(store.ref, mutate);
52
+ var modify = (store, mutate) => import_effect.SubscriptionRef.modify(store.ref, mutate);
53
+ var select = (store, selector) => import_effect.Effect.map(get(store), selector);
54
+ var changes = (store) => store.ref.changes;
55
+ var selectChanges = (store, selector, options = {}) => {
56
+ const selected = changes(store).pipe(import_effect.Stream.map(selector));
57
+ if (options.distinct === false) {
58
+ return selected;
59
+ }
60
+ return selected.pipe(import_effect.Stream.changesWith(options.equals ?? defaultEquality));
61
+ };
62
+ var derive = (store, selector, options = {}) => ({
63
+ get: select(store, selector),
64
+ changes: selectChanges(store, selector, options)
65
+ });
66
+
67
+ // src/state/react.tsx
68
+ var import_effect2 = require("effect");
69
+ var import_react2 = require("react");
70
+
71
+ // src/react/provider.tsx
72
+ var import_react = require("react");
73
+ var import_jsx_runtime = require("react/jsx-runtime");
74
+ var RuntimeContext = (0, import_react.createContext)(null);
75
+ var useEffectRuntime = () => {
76
+ const runtime = (0, import_react.useContext)(RuntimeContext);
77
+ if (runtime === null) {
78
+ throw new Error("Effect runtime is not available. Wrap your app with <EffectProvider>.");
79
+ }
80
+ return runtime;
81
+ };
82
+
83
+ // src/state/react.tsx
84
+ var defaultEquality2 = (left, right) => Object.is(left, right);
85
+ var useStore = (store) => useStoreSelector(store, (state) => state);
86
+ var useStoreSelector = (store, selector, equals = defaultEquality2) => {
87
+ const runtime = useEffectRuntime();
88
+ const subscribe = (0, import_react2.useCallback)(
89
+ (listener) => {
90
+ const fiber = runtime.runFork(
91
+ import_effect2.Stream.runForEach(
92
+ selectChanges(store, selector, {
93
+ equals
94
+ }),
95
+ () => import_effect2.Effect.sync(listener)
96
+ )
97
+ );
98
+ return () => {
99
+ runtime.runFork(import_effect2.Fiber.interrupt(fiber));
100
+ };
101
+ },
102
+ [equals, runtime, selector, store]
103
+ );
104
+ const getSnapshot = (0, import_react2.useCallback)(
105
+ () => runtime.runSync(select(store, selector)),
106
+ [runtime, selector, store]
107
+ );
108
+ return (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
109
+ };
110
+ // Annotate the CommonJS export names for ESM import in node:
111
+ 0 && (module.exports = {
112
+ changes,
113
+ createStore,
114
+ createStoreFromEffect,
115
+ createStoreTag,
116
+ derive,
117
+ get,
118
+ makeStoreLayer,
119
+ makeStoreLayerFromEffect,
120
+ modify,
121
+ select,
122
+ selectChanges,
123
+ set,
124
+ update,
125
+ useStore,
126
+ useStoreSelector
127
+ });
128
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/state/index.ts","../../src/state/service.ts","../../src/state/react.tsx","../../src/react/provider.tsx"],"sourcesContent":["export * from \"./service\";\nexport * from \"./react\";\n","import { Context, Effect, Layer, Stream, SubscriptionRef } from \"effect\";\n\nexport type Selector<State, Selected> = (state: State) => Selected;\nexport type Equality<Selected> = (left: Selected, right: Selected) => boolean;\n\nconst defaultEquality = <Value>(left: Value, right: Value): boolean => Object.is(left, right);\n\nexport interface Store<State> {\n readonly ref: SubscriptionRef.SubscriptionRef<State>;\n}\n\nexport interface DerivedStore<Selected> {\n readonly get: Effect.Effect<Selected>;\n readonly changes: Stream.Stream<Selected>;\n}\n\nexport interface SelectChangesOptions<Selected> {\n readonly equals?: Equality<Selected>;\n readonly distinct?: boolean;\n}\n\nexport type StoreTag<State> = Context.Tag<Store<State>, Store<State>>;\n\nexport const createStore = <State>(initial: State): Effect.Effect<Store<State>, never, never> =>\n Effect.map(SubscriptionRef.make(initial), (ref) => ({ ref }));\n\nexport const createStoreFromEffect = <State, E, R>(\n initial: Effect.Effect<State, E, R>,\n): Effect.Effect<Store<State>, E, R> =>\n Effect.flatMap(initial, createStore);\n\nexport const createStoreTag = <State>(key: string): StoreTag<State> =>\n Context.GenericTag<Store<State>>(key);\n\nexport const makeStoreLayer = <State>(\n tag: StoreTag<State>,\n initial: State,\n): Layer.Layer<Store<State>, never, never> =>\n Layer.effect(tag, createStore(initial));\n\nexport const makeStoreLayerFromEffect = <State, E, R>(\n tag: StoreTag<State>,\n initial: Effect.Effect<State, E, R>,\n): Layer.Layer<Store<State>, E, R> =>\n Layer.effect(tag, createStoreFromEffect(initial));\n\nexport const get = <State>(store: Store<State>): Effect.Effect<State, never, never> =>\n SubscriptionRef.get(store.ref);\n\nexport const set = <State>(\n store: Store<State>,\n value: State,\n): Effect.Effect<void, never, never> =>\n SubscriptionRef.set(store.ref, value);\n\nexport const update = <State>(\n store: Store<State>,\n mutate: (state: State) => State,\n): Effect.Effect<void, never, never> =>\n SubscriptionRef.update(store.ref, mutate);\n\nexport const modify = <State, Result>(\n store: Store<State>,\n mutate: (state: State) => readonly [Result, State],\n): Effect.Effect<Result, never, never> =>\n SubscriptionRef.modify(store.ref, mutate);\n\nexport const select = <State, Selected>(\n store: Store<State>,\n selector: Selector<State, Selected>,\n): Effect.Effect<Selected, never, never> =>\n Effect.map(get(store), selector);\n\nexport const changes = <State>(store: Store<State>): Stream.Stream<State, never, never> =>\n store.ref.changes;\n\nexport const selectChanges = <State, Selected>(\n store: Store<State>,\n selector: Selector<State, Selected>,\n options: SelectChangesOptions<Selected> = {},\n): Stream.Stream<Selected, never, never> => {\n const selected = changes(store).pipe(Stream.map(selector));\n if (options.distinct === false) {\n return selected;\n }\n return selected.pipe(Stream.changesWith(options.equals ?? defaultEquality<Selected>));\n};\n\nexport const derive = <State, Selected>(\n store: Store<State>,\n selector: Selector<State, Selected>,\n options: SelectChangesOptions<Selected> = {},\n): DerivedStore<Selected> => ({\n get: select(store, selector),\n changes: selectChanges(store, selector, options),\n});\n\n","import { Effect, Fiber, Stream } from \"effect\";\nimport { useCallback, useSyncExternalStore } from \"react\";\nimport { useEffectRuntime } from \"../react/provider\";\nimport { type Equality, select, selectChanges, type Selector, type Store } from \"./service\";\n\nconst defaultEquality = <Value,>(left: Value, right: Value): boolean => Object.is(left, right);\n\nexport const useStore = <State,>(store: Store<State>): State =>\n useStoreSelector(store, (state) => state);\n\nexport const useStoreSelector = <State, Selected,>(\n store: Store<State>,\n selector: Selector<State, Selected>,\n equals: Equality<Selected> = defaultEquality,\n): Selected => {\n const runtime = useEffectRuntime();\n\n const subscribe = useCallback(\n (listener: () => void) => {\n const fiber = runtime.runFork(\n Stream.runForEach(\n selectChanges(store, selector, {\n equals,\n }),\n () => Effect.sync(listener),\n ),\n );\n\n return () => {\n runtime.runFork(Fiber.interrupt(fiber));\n };\n },\n [equals, runtime, selector, store],\n );\n\n const getSnapshot = useCallback(\n () => runtime.runSync(select(store, selector)),\n [runtime, selector, store],\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n};\n","import type { ManagedRuntime } from \"effect\";\nimport { createContext, useContext, useEffect, type ReactNode } from \"react\";\nimport type { AppServices } from \"../kernel/app\";\n\nexport type EffectReactManagedRuntime<R = AppServices> = ManagedRuntime.ManagedRuntime<R, never>;\n\nconst RuntimeContext = createContext<EffectReactManagedRuntime | null>(null);\n\nexport interface EffectProviderProps {\n readonly runtime: EffectReactManagedRuntime;\n readonly children?: ReactNode;\n}\n\nexport const EffectProvider = ({ runtime, children }: EffectProviderProps) => {\n useEffect(\n () => () => {\n void runtime.dispose();\n },\n [runtime],\n );\n\n return <RuntimeContext.Provider value={runtime}>{children}</RuntimeContext.Provider>;\n};\n\nexport const useEffectRuntime = (): EffectReactManagedRuntime => {\n const runtime = useContext(RuntimeContext);\n if (runtime === null) {\n throw new Error(\"Effect runtime is not available. Wrap your app with <EffectProvider>.\");\n }\n return runtime;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAgE;AAKhE,IAAM,kBAAkB,CAAQ,MAAa,UAA0B,OAAO,GAAG,MAAM,KAAK;AAkBrF,IAAM,cAAc,CAAQ,YACjC,qBAAO,IAAI,8BAAgB,KAAK,OAAO,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE;AAEvD,IAAM,wBAAwB,CACnC,YAEA,qBAAO,QAAQ,SAAS,WAAW;AAE9B,IAAM,iBAAiB,CAAQ,QACpC,sBAAQ,WAAyB,GAAG;AAE/B,IAAM,iBAAiB,CAC5B,KACA,YAEA,oBAAM,OAAO,KAAK,YAAY,OAAO,CAAC;AAEjC,IAAM,2BAA2B,CACtC,KACA,YAEA,oBAAM,OAAO,KAAK,sBAAsB,OAAO,CAAC;AAE3C,IAAM,MAAM,CAAQ,UACzB,8BAAgB,IAAI,MAAM,GAAG;AAExB,IAAM,MAAM,CACjB,OACA,UAEA,8BAAgB,IAAI,MAAM,KAAK,KAAK;AAE/B,IAAM,SAAS,CACpB,OACA,WAEA,8BAAgB,OAAO,MAAM,KAAK,MAAM;AAEnC,IAAM,SAAS,CACpB,OACA,WAEA,8BAAgB,OAAO,MAAM,KAAK,MAAM;AAEnC,IAAM,SAAS,CACpB,OACA,aAEA,qBAAO,IAAI,IAAI,KAAK,GAAG,QAAQ;AAE1B,IAAM,UAAU,CAAQ,UAC7B,MAAM,IAAI;AAEL,IAAM,gBAAgB,CAC3B,OACA,UACA,UAA0C,CAAC,MACD;AAC1C,QAAM,WAAW,QAAQ,KAAK,EAAE,KAAK,qBAAO,IAAI,QAAQ,CAAC;AACzD,MAAI,QAAQ,aAAa,OAAO;AAC9B,WAAO;AAAA,EACT;AACA,SAAO,SAAS,KAAK,qBAAO,YAAY,QAAQ,UAAU,eAAyB,CAAC;AACtF;AAEO,IAAM,SAAS,CACpB,OACA,UACA,UAA0C,CAAC,OACf;AAAA,EAC5B,KAAK,OAAO,OAAO,QAAQ;AAAA,EAC3B,SAAS,cAAc,OAAO,UAAU,OAAO;AACjD;;;AC/FA,IAAAA,iBAAsC;AACtC,IAAAC,gBAAkD;;;ACAlD,mBAAqE;AAoB5D;AAfT,IAAM,qBAAiB,4BAAgD,IAAI;AAkBpE,IAAM,mBAAmB,MAAiC;AAC/D,QAAM,cAAU,yBAAW,cAAc;AACzC,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI,MAAM,uEAAuE;AAAA,EACzF;AACA,SAAO;AACT;;;ADzBA,IAAMC,mBAAkB,CAAS,MAAa,UAA0B,OAAO,GAAG,MAAM,KAAK;AAEtF,IAAM,WAAW,CAAS,UAC/B,iBAAiB,OAAO,CAAC,UAAU,KAAK;AAEnC,IAAM,mBAAmB,CAC9B,OACA,UACA,SAA6BA,qBAChB;AACb,QAAM,UAAU,iBAAiB;AAEjC,QAAM,gBAAY;AAAA,IAChB,CAAC,aAAyB;AACxB,YAAM,QAAQ,QAAQ;AAAA,QACpB,sBAAO;AAAA,UACL,cAAc,OAAO,UAAU;AAAA,YAC7B;AAAA,UACF,CAAC;AAAA,UACD,MAAM,sBAAO,KAAK,QAAQ;AAAA,QAC5B;AAAA,MACF;AAEA,aAAO,MAAM;AACX,gBAAQ,QAAQ,qBAAM,UAAU,KAAK,CAAC;AAAA,MACxC;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,SAAS,UAAU,KAAK;AAAA,EACnC;AAEA,QAAM,kBAAc;AAAA,IAClB,MAAM,QAAQ,QAAQ,OAAO,OAAO,QAAQ,CAAC;AAAA,IAC7C,CAAC,SAAS,UAAU,KAAK;AAAA,EAC3B;AAEA,aAAO,oCAAqB,WAAW,aAAa,WAAW;AACjE;","names":["import_effect","import_react","defaultEquality"]}
@@ -0,0 +1,2 @@
1
+ export * from "./service";
2
+ export * from "./react";
@@ -0,0 +1,36 @@
1
+ import {
2
+ changes,
3
+ createStore,
4
+ createStoreFromEffect,
5
+ createStoreTag,
6
+ derive,
7
+ get,
8
+ makeStoreLayer,
9
+ makeStoreLayerFromEffect,
10
+ modify,
11
+ select,
12
+ selectChanges,
13
+ set,
14
+ update,
15
+ useStore,
16
+ useStoreSelector
17
+ } from "../chunk-NI2GNZ7S.js";
18
+ import "../chunk-2GIUCKL2.js";
19
+ export {
20
+ changes,
21
+ createStore,
22
+ createStoreFromEffect,
23
+ createStoreTag,
24
+ derive,
25
+ get,
26
+ makeStoreLayer,
27
+ makeStoreLayerFromEffect,
28
+ modify,
29
+ select,
30
+ selectChanges,
31
+ set,
32
+ update,
33
+ useStore,
34
+ useStoreSelector
35
+ };
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,3 @@
1
+ import { type Equality, type Selector, type Store } from "./service";
2
+ export declare const useStore: <State>(store: Store<State>) => State;
3
+ export declare const useStoreSelector: <State, Selected>(store: Store<State>, selector: Selector<State, Selected>, equals?: Equality<Selected>) => Selected;
@@ -0,0 +1,28 @@
1
+ import { Context, Effect, Layer, Stream, SubscriptionRef } from "effect";
2
+ export type Selector<State, Selected> = (state: State) => Selected;
3
+ export type Equality<Selected> = (left: Selected, right: Selected) => boolean;
4
+ export interface Store<State> {
5
+ readonly ref: SubscriptionRef.SubscriptionRef<State>;
6
+ }
7
+ export interface DerivedStore<Selected> {
8
+ readonly get: Effect.Effect<Selected>;
9
+ readonly changes: Stream.Stream<Selected>;
10
+ }
11
+ export interface SelectChangesOptions<Selected> {
12
+ readonly equals?: Equality<Selected>;
13
+ readonly distinct?: boolean;
14
+ }
15
+ export type StoreTag<State> = Context.Tag<Store<State>, Store<State>>;
16
+ export declare const createStore: <State>(initial: State) => Effect.Effect<Store<State>, never, never>;
17
+ export declare const createStoreFromEffect: <State, E, R>(initial: Effect.Effect<State, E, R>) => Effect.Effect<Store<State>, E, R>;
18
+ export declare const createStoreTag: <State>(key: string) => StoreTag<State>;
19
+ export declare const makeStoreLayer: <State>(tag: StoreTag<State>, initial: State) => Layer.Layer<Store<State>, never, never>;
20
+ export declare const makeStoreLayerFromEffect: <State, E, R>(tag: StoreTag<State>, initial: Effect.Effect<State, E, R>) => Layer.Layer<Store<State>, E, R>;
21
+ export declare const get: <State>(store: Store<State>) => Effect.Effect<State, never, never>;
22
+ export declare const set: <State>(store: Store<State>, value: State) => Effect.Effect<void, never, never>;
23
+ export declare const update: <State>(store: Store<State>, mutate: (state: State) => State) => Effect.Effect<void, never, never>;
24
+ export declare const modify: <State, Result>(store: Store<State>, mutate: (state: State) => readonly [Result, State]) => Effect.Effect<Result, never, never>;
25
+ export declare const select: <State, Selected>(store: Store<State>, selector: Selector<State, Selected>) => Effect.Effect<Selected, never, never>;
26
+ export declare const changes: <State>(store: Store<State>) => Stream.Stream<State, never, never>;
27
+ export declare const selectChanges: <State, Selected>(store: Store<State>, selector: Selector<State, Selected>, options?: SelectChangesOptions<Selected>) => Stream.Stream<Selected, never, never>;
28
+ export declare const derive: <State, Selected>(store: Store<State>, selector: Selector<State, Selected>, options?: SelectChangesOptions<Selected>) => DerivedStore<Selected>;