@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.
- package/LICENSE +21 -0
- package/README.md +179 -0
- package/dist/actions/http.d.ts +18 -0
- package/dist/actions/index.d.ts +4 -0
- package/dist/actions/react.d.ts +7 -0
- package/dist/actions/service.d.ts +18 -0
- package/dist/actions/types.d.ts +33 -0
- package/dist/boundary/codecs.d.ts +40 -0
- package/dist/boundary/errors.d.ts +22 -0
- package/dist/boundary/index.d.ts +2 -0
- package/dist/chunk-2GIUCKL2.js +16 -0
- package/dist/chunk-2GIUCKL2.js.map +1 -0
- package/dist/chunk-2TG7YEVD.js +11 -0
- package/dist/chunk-2TG7YEVD.js.map +1 -0
- package/dist/chunk-6FI4ROTW.js +152 -0
- package/dist/chunk-6FI4ROTW.js.map +1 -0
- package/dist/chunk-C5JI7D7W.js +213 -0
- package/dist/chunk-C5JI7D7W.js.map +1 -0
- package/dist/chunk-EEYASTXR.js +99 -0
- package/dist/chunk-EEYASTXR.js.map +1 -0
- package/dist/chunk-H7MOLKTU.js +301 -0
- package/dist/chunk-H7MOLKTU.js.map +1 -0
- package/dist/chunk-IVIYY6S5.js +77 -0
- package/dist/chunk-IVIYY6S5.js.map +1 -0
- package/dist/chunk-JKN75OYC.js +87 -0
- package/dist/chunk-JKN75OYC.js.map +1 -0
- package/dist/chunk-M2CJG6T7.js +24 -0
- package/dist/chunk-M2CJG6T7.js.map +1 -0
- package/dist/chunk-MDGEGQZB.js +206 -0
- package/dist/chunk-MDGEGQZB.js.map +1 -0
- package/dist/chunk-NI2GNZ7S.js +78 -0
- package/dist/chunk-NI2GNZ7S.js.map +1 -0
- package/dist/chunk-O7XTA7H3.js +423 -0
- package/dist/chunk-O7XTA7H3.js.map +1 -0
- package/dist/chunk-S67FHWAR.js +88 -0
- package/dist/chunk-S67FHWAR.js.map +1 -0
- package/dist/chunk-SKC3HMF3.js +17 -0
- package/dist/chunk-SKC3HMF3.js.map +1 -0
- package/dist/chunk-TUJZ6XJY.js +127 -0
- package/dist/chunk-TUJZ6XJY.js.map +1 -0
- package/dist/chunk-WPV3WFMS.js +38 -0
- package/dist/chunk-WPV3WFMS.js.map +1 -0
- package/dist/chunk-XIBEKS5A.js +301 -0
- package/dist/chunk-XIBEKS5A.js.map +1 -0
- package/dist/chunk-YG22YP5K.js +68 -0
- package/dist/chunk-YG22YP5K.js.map +1 -0
- package/dist/chunk-ZMZQBREU.js +262 -0
- package/dist/chunk-ZMZQBREU.js.map +1 -0
- package/dist/client/index.cjs +191 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.js +14 -0
- package/dist/client/index.js.map +1 -0
- package/dist/config/index.cjs +63 -0
- package/dist/config/index.cjs.map +1 -0
- package/dist/config/index.d.ts +32 -0
- package/dist/config/index.js +9 -0
- package/dist/config/index.js.map +1 -0
- package/dist/data/index.d.ts +3 -0
- package/dist/data/react.d.ts +10 -0
- package/dist/data/service.d.ts +20 -0
- package/dist/data/types.d.ts +31 -0
- package/dist/devtools/events.d.ts +37 -0
- package/dist/devtools/index.cjs +149 -0
- package/dist/devtools/index.cjs.map +1 -0
- package/dist/devtools/index.d.ts +2 -0
- package/dist/devtools/index.js +18 -0
- package/dist/devtools/index.js.map +1 -0
- package/dist/devtools/react.d.ts +8 -0
- package/dist/form/index.cjs +301 -0
- package/dist/form/index.cjs.map +1 -0
- package/dist/form/index.d.ts +3 -0
- package/dist/form/index.js +14 -0
- package/dist/form/index.js.map +1 -0
- package/dist/form/react.d.ts +9 -0
- package/dist/form/service.d.ts +3 -0
- package/dist/form/types.d.ts +41 -0
- package/dist/framework/app.d.ts +21 -0
- package/dist/framework/cache.d.ts +10 -0
- package/dist/framework/contracts.d.ts +32 -0
- package/dist/framework/index.cjs +1006 -0
- package/dist/framework/index.cjs.map +1 -0
- package/dist/framework/index.d.ts +4 -0
- package/dist/framework/index.js +35 -0
- package/dist/framework/index.js.map +1 -0
- package/dist/framework/manifest.d.ts +12 -0
- package/dist/framework/vite.d.ts +13 -0
- package/dist/framework-vite/index.cjs +163 -0
- package/dist/framework-vite/index.cjs.map +1 -0
- package/dist/framework-vite/index.d.ts +1 -0
- package/dist/framework-vite/index.js +125 -0
- package/dist/framework-vite/index.js.map +1 -0
- package/dist/grid/grid.d.ts +8 -0
- package/dist/grid/index.cjs +238 -0
- package/dist/grid/index.cjs.map +1 -0
- package/dist/grid/index.d.ts +2 -0
- package/dist/grid/index.js +19 -0
- package/dist/grid/index.js.map +1 -0
- package/dist/grid/types.d.ts +35 -0
- package/dist/index.cjs +2512 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +207 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/app.d.ts +26 -0
- package/dist/kernel/index.d.ts +3 -0
- package/dist/kernel/runtime.d.ts +5 -0
- package/dist/kernel/telemetry.d.ts +37 -0
- package/dist/navigation/index.d.ts +4 -0
- package/dist/navigation/matcher.d.ts +13 -0
- package/dist/navigation/react.d.ts +12 -0
- package/dist/navigation/service.d.ts +23 -0
- package/dist/navigation/types.d.ts +65 -0
- package/dist/query/index.cjs +361 -0
- package/dist/query/index.cjs.map +1 -0
- package/dist/query/index.d.ts +3 -0
- package/dist/query/index.js +30 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/react.d.ts +27 -0
- package/dist/query/service.d.ts +10 -0
- package/dist/query/types.d.ts +5 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/provider.d.ts +10 -0
- package/dist/realtime/channel.d.ts +15 -0
- package/dist/realtime/index.cjs +117 -0
- package/dist/realtime/index.cjs.map +1 -0
- package/dist/realtime/index.d.ts +2 -0
- package/dist/realtime/index.js +15 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/presence.d.ts +22 -0
- package/dist/render/hydration.d.ts +24 -0
- package/dist/render/index.d.ts +2 -0
- package/dist/render/ssr.d.ts +13 -0
- package/dist/router/helpers.d.ts +26 -0
- package/dist/router/index.cjs +236 -0
- package/dist/router/index.cjs.map +1 -0
- package/dist/router/index.d.ts +4 -0
- package/dist/router/index.js +40 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/react.d.ts +5 -0
- package/dist/router/service.d.ts +5 -0
- package/dist/router/types.d.ts +1 -0
- package/dist/server/index.cjs +174 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.ts +16 -0
- package/dist/server/index.js +12 -0
- package/dist/server/index.js.map +1 -0
- package/dist/state/index.cjs +128 -0
- package/dist/state/index.cjs.map +1 -0
- package/dist/state/index.d.ts +2 -0
- package/dist/state/index.js +36 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/react.d.ts +3 -0
- package/dist/state/service.d.ts +28 -0
- package/dist/testing/index.cjs +970 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +13 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/virtual/index.cjs +160 -0
- package/dist/virtual/index.cjs.map +1 -0
- package/dist/virtual/index.d.ts +2 -0
- package/dist/virtual/index.js +21 -0
- package/dist/virtual/index.js.map +1 -0
- package/dist/virtual/types.d.ts +25 -0
- package/dist/virtual/virtual.d.ts +9 -0
- package/package.json +156 -0
|
@@ -0,0 +1,1006 @@
|
|
|
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/framework/index.ts
|
|
21
|
+
var framework_exports = {};
|
|
22
|
+
__export(framework_exports, {
|
|
23
|
+
cachePolicy: () => cachePolicy,
|
|
24
|
+
createApp: () => createApp,
|
|
25
|
+
defineAction: () => defineAction,
|
|
26
|
+
defineLayout: () => defineLayout,
|
|
27
|
+
defineLoader: () => defineLoader,
|
|
28
|
+
defineManifest: () => defineManifest,
|
|
29
|
+
defineMiddleware: () => defineMiddleware,
|
|
30
|
+
definePage: () => definePage,
|
|
31
|
+
defineRoute: () => defineRoute,
|
|
32
|
+
loadersFromManifest: () => loadersFromManifest,
|
|
33
|
+
noStore: () => noStore,
|
|
34
|
+
routesFromManifest: () => routesFromManifest
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(framework_exports);
|
|
37
|
+
|
|
38
|
+
// src/actions/types.ts
|
|
39
|
+
var defineAction = (definition) => definition;
|
|
40
|
+
|
|
41
|
+
// src/actions/service.ts
|
|
42
|
+
var import_effect3 = require("effect");
|
|
43
|
+
|
|
44
|
+
// src/boundary/codecs.ts
|
|
45
|
+
var import_effect = require("effect");
|
|
46
|
+
|
|
47
|
+
// src/boundary/errors.ts
|
|
48
|
+
var BoundaryDecodeError = class extends Error {
|
|
49
|
+
constructor(source, messageText, causeValue) {
|
|
50
|
+
super(`Boundary decode failed at ${source}: ${messageText}`);
|
|
51
|
+
this.source = source;
|
|
52
|
+
this.messageText = messageText;
|
|
53
|
+
this.causeValue = causeValue;
|
|
54
|
+
this.name = "BoundaryDecodeError";
|
|
55
|
+
}
|
|
56
|
+
_tag = "BoundaryDecodeError";
|
|
57
|
+
};
|
|
58
|
+
var BoundaryTransportError = class extends Error {
|
|
59
|
+
constructor(source, messageText, causeValue) {
|
|
60
|
+
super(`Boundary transport failed at ${source}: ${messageText}`);
|
|
61
|
+
this.source = source;
|
|
62
|
+
this.messageText = messageText;
|
|
63
|
+
this.causeValue = causeValue;
|
|
64
|
+
this.name = "BoundaryTransportError";
|
|
65
|
+
}
|
|
66
|
+
_tag = "BoundaryTransportError";
|
|
67
|
+
};
|
|
68
|
+
var BoundaryProtocolError = class extends Error {
|
|
69
|
+
constructor(source, messageText) {
|
|
70
|
+
super(`Boundary protocol violation at ${source}: ${messageText}`);
|
|
71
|
+
this.source = source;
|
|
72
|
+
this.messageText = messageText;
|
|
73
|
+
this.name = "BoundaryProtocolError";
|
|
74
|
+
}
|
|
75
|
+
_tag = "BoundaryProtocolError";
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/boundary/codecs.ts
|
|
79
|
+
var Boundary = class extends import_effect.Context.Tag("EffectReact/Boundary")() {
|
|
80
|
+
};
|
|
81
|
+
var parseErrorMessage = (error) => import_effect.Cause.pretty(import_effect.Cause.fail(error)).trim();
|
|
82
|
+
var makeBoundaryService = () => ({
|
|
83
|
+
decodeUnknown: ({ source, schema, value }) => import_effect.Schema.decodeUnknown(schema)(value).pipe(
|
|
84
|
+
import_effect.Effect.mapError(
|
|
85
|
+
(error) => new BoundaryDecodeError(source, parseErrorMessage(error), error)
|
|
86
|
+
)
|
|
87
|
+
),
|
|
88
|
+
decodeTextJson: ({ source, schema, text }) => import_effect.Effect.gen(function* () {
|
|
89
|
+
const payload = yield* import_effect.Effect.try({
|
|
90
|
+
try: () => JSON.parse(text),
|
|
91
|
+
catch: (cause) => new BoundaryTransportError(source, "failed to parse JSON payload", cause)
|
|
92
|
+
});
|
|
93
|
+
return yield* import_effect.Schema.decodeUnknown(schema)(payload).pipe(
|
|
94
|
+
import_effect.Effect.mapError(
|
|
95
|
+
(error) => new BoundaryDecodeError(source, parseErrorMessage(error), error)
|
|
96
|
+
)
|
|
97
|
+
);
|
|
98
|
+
}),
|
|
99
|
+
encode: ({ source, schema, value }) => import_effect.Schema.encode(schema)(value).pipe(
|
|
100
|
+
import_effect.Effect.mapError((error) => new BoundaryProtocolError(source, parseErrorMessage(error)))
|
|
101
|
+
)
|
|
102
|
+
});
|
|
103
|
+
var BoundaryLive = import_effect.Layer.succeed(Boundary, makeBoundaryService());
|
|
104
|
+
|
|
105
|
+
// src/kernel/telemetry.ts
|
|
106
|
+
var import_effect2 = require("effect");
|
|
107
|
+
var Telemetry = class extends import_effect2.Context.Tag("EffectReact/Telemetry")() {
|
|
108
|
+
};
|
|
109
|
+
var TelemetryLive = import_effect2.Layer.effect(
|
|
110
|
+
Telemetry,
|
|
111
|
+
import_effect2.Effect.map(import_effect2.PubSub.unbounded(), (pubsub) => ({
|
|
112
|
+
emit: (event) => import_effect2.PubSub.publish(pubsub, event).pipe(import_effect2.Effect.asVoid),
|
|
113
|
+
stream: import_effect2.Stream.fromPubSub(pubsub)
|
|
114
|
+
}))
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// src/actions/service.ts
|
|
118
|
+
var toFailureDetail = (error) => {
|
|
119
|
+
if (error instanceof Error) {
|
|
120
|
+
return `${error.name}: ${error.message}`;
|
|
121
|
+
}
|
|
122
|
+
return String(error);
|
|
123
|
+
};
|
|
124
|
+
var Actions = class extends import_effect3.Context.Tag("EffectReact/Actions")() {
|
|
125
|
+
};
|
|
126
|
+
var makeActionsLayer = (options) => import_effect3.Layer.effect(
|
|
127
|
+
Actions,
|
|
128
|
+
import_effect3.Effect.gen(function* () {
|
|
129
|
+
const boundary = yield* Boundary;
|
|
130
|
+
const telemetry = yield* Telemetry;
|
|
131
|
+
const actionMap = new Map(
|
|
132
|
+
options.actions.map((action) => [action.name, action])
|
|
133
|
+
);
|
|
134
|
+
const run = (definition, input) => import_effect3.Effect.gen(function* () {
|
|
135
|
+
yield* telemetry.emit({
|
|
136
|
+
_tag: "action",
|
|
137
|
+
phase: "start",
|
|
138
|
+
name: definition.name,
|
|
139
|
+
timestamp: Date.now()
|
|
140
|
+
});
|
|
141
|
+
const decodedInput = yield* boundary.decodeUnknown({
|
|
142
|
+
source: `action:${definition.name}:input`,
|
|
143
|
+
schema: definition.input,
|
|
144
|
+
value: input
|
|
145
|
+
});
|
|
146
|
+
const value = yield* definition.handler(decodedInput);
|
|
147
|
+
const decodedOutput = yield* boundary.decodeUnknown({
|
|
148
|
+
source: `action:${definition.name}:output`,
|
|
149
|
+
schema: definition.output,
|
|
150
|
+
value
|
|
151
|
+
});
|
|
152
|
+
yield* telemetry.emit({
|
|
153
|
+
_tag: "action",
|
|
154
|
+
phase: "success",
|
|
155
|
+
name: definition.name,
|
|
156
|
+
timestamp: Date.now()
|
|
157
|
+
});
|
|
158
|
+
return decodedOutput;
|
|
159
|
+
}).pipe(
|
|
160
|
+
import_effect3.Effect.tapError(
|
|
161
|
+
(error) => telemetry.emit({
|
|
162
|
+
_tag: "action",
|
|
163
|
+
phase: "failure",
|
|
164
|
+
name: definition.name,
|
|
165
|
+
timestamp: Date.now(),
|
|
166
|
+
detail: error
|
|
167
|
+
})
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
const dispatch = (name, input) => import_effect3.Effect.gen(function* () {
|
|
171
|
+
const definition = actionMap.get(name);
|
|
172
|
+
if (definition === void 0) {
|
|
173
|
+
return {
|
|
174
|
+
_tag: "defect",
|
|
175
|
+
message: `Unknown action: ${name}`
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const decodedInput = yield* boundary.decodeUnknown({
|
|
179
|
+
source: `action:${name}:dispatch-input`,
|
|
180
|
+
schema: definition.input,
|
|
181
|
+
value: input
|
|
182
|
+
});
|
|
183
|
+
const handler = definition.handler;
|
|
184
|
+
const result = yield* import_effect3.Effect.exit(handler(decodedInput));
|
|
185
|
+
if (result._tag === "Success") {
|
|
186
|
+
const encoded = yield* boundary.encode({
|
|
187
|
+
source: `action:${name}:wire-success`,
|
|
188
|
+
schema: definition.output,
|
|
189
|
+
value: result.value
|
|
190
|
+
});
|
|
191
|
+
return {
|
|
192
|
+
_tag: "success",
|
|
193
|
+
value: encoded
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const failure = import_effect3.Cause.failureOption(result.cause);
|
|
197
|
+
if (failure._tag === "Some") {
|
|
198
|
+
const value = failure.value;
|
|
199
|
+
if (value instanceof BoundaryDecodeError || value instanceof BoundaryProtocolError) {
|
|
200
|
+
return {
|
|
201
|
+
_tag: "defect",
|
|
202
|
+
message: toFailureDetail(value)
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const encodedError = yield* boundary.encode({
|
|
206
|
+
source: `action:${name}:wire-failure`,
|
|
207
|
+
schema: definition.error,
|
|
208
|
+
value
|
|
209
|
+
}).pipe(
|
|
210
|
+
import_effect3.Effect.catchAll(() => import_effect3.Effect.succeed(value))
|
|
211
|
+
);
|
|
212
|
+
return {
|
|
213
|
+
_tag: "failure",
|
|
214
|
+
error: encodedError
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
_tag: "defect",
|
|
219
|
+
message: import_effect3.Cause.pretty(result.cause)
|
|
220
|
+
};
|
|
221
|
+
}).pipe(
|
|
222
|
+
import_effect3.Effect.catchAll(
|
|
223
|
+
(error) => import_effect3.Effect.succeed({
|
|
224
|
+
_tag: "defect",
|
|
225
|
+
message: toFailureDetail(error)
|
|
226
|
+
})
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
return {
|
|
230
|
+
run,
|
|
231
|
+
dispatch
|
|
232
|
+
};
|
|
233
|
+
})
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
// src/actions/http.ts
|
|
237
|
+
var import_effect4 = require("effect");
|
|
238
|
+
var ActionRequestSchema = import_effect4.Schema.Struct({
|
|
239
|
+
name: import_effect4.Schema.String,
|
|
240
|
+
input: import_effect4.Schema.Unknown
|
|
241
|
+
});
|
|
242
|
+
var ActionWireResultSchema = import_effect4.Schema.Union(
|
|
243
|
+
import_effect4.Schema.Struct({ _tag: import_effect4.Schema.Literal("success"), value: import_effect4.Schema.Unknown }),
|
|
244
|
+
import_effect4.Schema.Struct({ _tag: import_effect4.Schema.Literal("failure"), error: import_effect4.Schema.Unknown }),
|
|
245
|
+
import_effect4.Schema.Struct({ _tag: import_effect4.Schema.Literal("defect"), message: import_effect4.Schema.String })
|
|
246
|
+
);
|
|
247
|
+
var ActionTransportError = class extends Error {
|
|
248
|
+
constructor(messageText, causeValue) {
|
|
249
|
+
super(messageText);
|
|
250
|
+
this.messageText = messageText;
|
|
251
|
+
this.causeValue = causeValue;
|
|
252
|
+
this.name = "ActionTransportError";
|
|
253
|
+
}
|
|
254
|
+
_tag = "ActionTransportError";
|
|
255
|
+
};
|
|
256
|
+
var jsonResponse = (status, body) => new Response(JSON.stringify(body), {
|
|
257
|
+
status,
|
|
258
|
+
headers: {
|
|
259
|
+
"content-type": "application/json"
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
var createActionHttpHandlerEffect = () => (request) => import_effect4.Effect.gen(function* () {
|
|
263
|
+
if (request.method.toUpperCase() !== "POST") {
|
|
264
|
+
return jsonResponse(405, { error: "Method Not Allowed" });
|
|
265
|
+
}
|
|
266
|
+
const rawBody = yield* import_effect4.Effect.tryPromise({
|
|
267
|
+
try: () => request.text(),
|
|
268
|
+
catch: (cause) => new ActionTransportError("Failed to read request body", cause)
|
|
269
|
+
});
|
|
270
|
+
const boundary = yield* Boundary;
|
|
271
|
+
const payload = yield* boundary.decodeTextJson({
|
|
272
|
+
source: "action:http:request",
|
|
273
|
+
schema: ActionRequestSchema,
|
|
274
|
+
text: rawBody
|
|
275
|
+
});
|
|
276
|
+
const actions = yield* Actions;
|
|
277
|
+
const result = yield* actions.dispatch(payload.name, payload.input);
|
|
278
|
+
return jsonResponse(200, result);
|
|
279
|
+
}).pipe(
|
|
280
|
+
import_effect4.Effect.catchAll(
|
|
281
|
+
(error) => import_effect4.Effect.succeed(
|
|
282
|
+
jsonResponse(500, {
|
|
283
|
+
error: error instanceof Error ? error.message : String(error)
|
|
284
|
+
})
|
|
285
|
+
)
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
var createActionHttpHandler = () => {
|
|
289
|
+
const handleEffect = createActionHttpHandlerEffect();
|
|
290
|
+
return (runtimeRun) => (request) => runtimeRun(handleEffect(request));
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// src/kernel/app.ts
|
|
294
|
+
var import_effect8 = require("effect");
|
|
295
|
+
|
|
296
|
+
// src/data/types.ts
|
|
297
|
+
var QueryRuntimeError = class extends Error {
|
|
298
|
+
constructor(messageText) {
|
|
299
|
+
super(messageText);
|
|
300
|
+
this.messageText = messageText;
|
|
301
|
+
this.name = "QueryRuntimeError";
|
|
302
|
+
}
|
|
303
|
+
_tag = "QueryRuntimeError";
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
// src/data/service.ts
|
|
307
|
+
var import_effect5 = require("effect");
|
|
308
|
+
var defaultRuntimeOptions = {
|
|
309
|
+
capacity: 2048,
|
|
310
|
+
timeToLive: "5 minutes"
|
|
311
|
+
};
|
|
312
|
+
var stableStringify = (value) => {
|
|
313
|
+
if (value === null || value === void 0) {
|
|
314
|
+
return String(value);
|
|
315
|
+
}
|
|
316
|
+
if (typeof value !== "object") {
|
|
317
|
+
return JSON.stringify(value);
|
|
318
|
+
}
|
|
319
|
+
if (Array.isArray(value)) {
|
|
320
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
321
|
+
}
|
|
322
|
+
const entries = Object.entries(value).sort(
|
|
323
|
+
([a], [b]) => a.localeCompare(b)
|
|
324
|
+
);
|
|
325
|
+
return `{${entries.map(([key, nested]) => `${JSON.stringify(key)}:${stableStringify(nested)}`).join(",")}}`;
|
|
326
|
+
};
|
|
327
|
+
var initialSnapshot = (key) => ({
|
|
328
|
+
key,
|
|
329
|
+
phase: "initial",
|
|
330
|
+
data: void 0,
|
|
331
|
+
error: void 0,
|
|
332
|
+
updatedAt: null
|
|
333
|
+
});
|
|
334
|
+
var Data = class extends import_effect5.Context.Tag("EffectReact/Data")() {
|
|
335
|
+
};
|
|
336
|
+
var makeDataLayer = (options = {}) => {
|
|
337
|
+
const merged = {
|
|
338
|
+
...defaultRuntimeOptions,
|
|
339
|
+
...options
|
|
340
|
+
};
|
|
341
|
+
return import_effect5.Layer.effect(
|
|
342
|
+
Data,
|
|
343
|
+
import_effect5.Effect.gen(function* () {
|
|
344
|
+
const boundary = yield* Boundary;
|
|
345
|
+
const telemetry = yield* Telemetry;
|
|
346
|
+
const lookups = /* @__PURE__ */ new Map();
|
|
347
|
+
const snapshots = yield* import_effect5.SubscriptionRef.make(
|
|
348
|
+
/* @__PURE__ */ new Map()
|
|
349
|
+
);
|
|
350
|
+
const cache = yield* import_effect5.Cache.make({
|
|
351
|
+
capacity: merged.capacity,
|
|
352
|
+
timeToLive: merged.timeToLive,
|
|
353
|
+
lookup: (key) => import_effect5.Effect.suspend(() => {
|
|
354
|
+
const lookup = lookups.get(key);
|
|
355
|
+
if (lookup === void 0) {
|
|
356
|
+
return import_effect5.Effect.fail(new QueryRuntimeError(`No query executor registered for ${key}`));
|
|
357
|
+
}
|
|
358
|
+
return lookup;
|
|
359
|
+
})
|
|
360
|
+
});
|
|
361
|
+
const setSnapshot = (key, update) => import_effect5.SubscriptionRef.update(snapshots, (current) => {
|
|
362
|
+
const next = new Map(current);
|
|
363
|
+
const previous = next.get(key) ?? initialSnapshot(key);
|
|
364
|
+
next.set(key, update(previous));
|
|
365
|
+
return next;
|
|
366
|
+
}).pipe(import_effect5.Effect.asVoid);
|
|
367
|
+
const buildKey = (definition, input) => {
|
|
368
|
+
const base = definition.key ? definition.key(input) : input;
|
|
369
|
+
return `${definition.name}:${stableStringify(base)}`;
|
|
370
|
+
};
|
|
371
|
+
const fetch2 = (definition, input, runOptions) => import_effect5.Effect.gen(function* () {
|
|
372
|
+
const decodedInput = yield* boundary.decodeUnknown({
|
|
373
|
+
source: `query:${definition.name}:input`,
|
|
374
|
+
schema: definition.input,
|
|
375
|
+
value: input
|
|
376
|
+
});
|
|
377
|
+
const key = buildKey(definition, decodedInput);
|
|
378
|
+
yield* telemetry.emit({
|
|
379
|
+
_tag: "query",
|
|
380
|
+
phase: "start",
|
|
381
|
+
key,
|
|
382
|
+
timestamp: Date.now()
|
|
383
|
+
});
|
|
384
|
+
yield* setSnapshot(key, (previous) => ({
|
|
385
|
+
...previous,
|
|
386
|
+
phase: "loading",
|
|
387
|
+
error: void 0
|
|
388
|
+
}));
|
|
389
|
+
lookups.set(
|
|
390
|
+
key,
|
|
391
|
+
definition.run(decodedInput).pipe(
|
|
392
|
+
import_effect5.Effect.flatMap(
|
|
393
|
+
(output) => boundary.decodeUnknown({
|
|
394
|
+
source: `query:${definition.name}:output`,
|
|
395
|
+
schema: definition.output,
|
|
396
|
+
value: output
|
|
397
|
+
})
|
|
398
|
+
)
|
|
399
|
+
)
|
|
400
|
+
);
|
|
401
|
+
if (runOptions?.forceRefresh === true) {
|
|
402
|
+
yield* cache.refresh(key).pipe(import_effect5.Effect.ignore);
|
|
403
|
+
}
|
|
404
|
+
const value = yield* cache.get(key).pipe(
|
|
405
|
+
import_effect5.Effect.mapError(
|
|
406
|
+
(error) => error
|
|
407
|
+
)
|
|
408
|
+
);
|
|
409
|
+
yield* setSnapshot(key, () => ({
|
|
410
|
+
key,
|
|
411
|
+
phase: "success",
|
|
412
|
+
data: value,
|
|
413
|
+
error: void 0,
|
|
414
|
+
updatedAt: Date.now()
|
|
415
|
+
}));
|
|
416
|
+
yield* telemetry.emit({
|
|
417
|
+
_tag: "query",
|
|
418
|
+
phase: "success",
|
|
419
|
+
key,
|
|
420
|
+
timestamp: Date.now()
|
|
421
|
+
});
|
|
422
|
+
return value;
|
|
423
|
+
}).pipe(
|
|
424
|
+
import_effect5.Effect.tapError(
|
|
425
|
+
(error) => import_effect5.Effect.gen(function* () {
|
|
426
|
+
const decodedInput = yield* boundary.decodeUnknown({
|
|
427
|
+
source: `query:${definition.name}:input`,
|
|
428
|
+
schema: definition.input,
|
|
429
|
+
value: input
|
|
430
|
+
});
|
|
431
|
+
const key = buildKey(definition, decodedInput);
|
|
432
|
+
yield* setSnapshot(key, (previous) => ({
|
|
433
|
+
...previous,
|
|
434
|
+
phase: "failure",
|
|
435
|
+
error,
|
|
436
|
+
updatedAt: previous.updatedAt
|
|
437
|
+
}));
|
|
438
|
+
yield* telemetry.emit({
|
|
439
|
+
_tag: "query",
|
|
440
|
+
phase: "failure",
|
|
441
|
+
key,
|
|
442
|
+
timestamp: Date.now(),
|
|
443
|
+
detail: error
|
|
444
|
+
});
|
|
445
|
+
})
|
|
446
|
+
)
|
|
447
|
+
);
|
|
448
|
+
const prefetch = (definition, input) => fetch2(definition, input).pipe(import_effect5.Effect.asVoid);
|
|
449
|
+
const invalidate = (definition, input) => import_effect5.Effect.gen(function* () {
|
|
450
|
+
const key = `${definition.name}:${stableStringify(input)}`;
|
|
451
|
+
yield* cache.invalidate(key);
|
|
452
|
+
yield* import_effect5.SubscriptionRef.update(snapshots, (current) => {
|
|
453
|
+
const next = new Map(current);
|
|
454
|
+
next.delete(key);
|
|
455
|
+
return next;
|
|
456
|
+
}).pipe(import_effect5.Effect.asVoid);
|
|
457
|
+
yield* telemetry.emit({
|
|
458
|
+
_tag: "query",
|
|
459
|
+
phase: "invalidate",
|
|
460
|
+
key,
|
|
461
|
+
timestamp: Date.now()
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
const getSnapshot = (definition, input) => import_effect5.Effect.gen(function* () {
|
|
465
|
+
const key = `${definition.name}:${stableStringify(input)}`;
|
|
466
|
+
const current = yield* import_effect5.SubscriptionRef.get(snapshots);
|
|
467
|
+
const snapshot = current.get(key);
|
|
468
|
+
if (snapshot === void 0) {
|
|
469
|
+
return initialSnapshot(key);
|
|
470
|
+
}
|
|
471
|
+
return snapshot;
|
|
472
|
+
});
|
|
473
|
+
return {
|
|
474
|
+
fetch: fetch2,
|
|
475
|
+
prefetch,
|
|
476
|
+
invalidate,
|
|
477
|
+
getSnapshot,
|
|
478
|
+
getAllSnapshots: import_effect5.SubscriptionRef.get(snapshots),
|
|
479
|
+
hydrateSnapshots: (nextSnapshots) => import_effect5.SubscriptionRef.set(snapshots, new Map(nextSnapshots)),
|
|
480
|
+
snapshots: snapshots.changes
|
|
481
|
+
};
|
|
482
|
+
})
|
|
483
|
+
);
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
// src/navigation/types.ts
|
|
487
|
+
var defineRoute = (route) => route;
|
|
488
|
+
var defineLoader = (loader) => loader;
|
|
489
|
+
var NavigationRuntimeError = class extends Error {
|
|
490
|
+
constructor(messageText) {
|
|
491
|
+
super(messageText);
|
|
492
|
+
this.messageText = messageText;
|
|
493
|
+
this.name = "NavigationRuntimeError";
|
|
494
|
+
}
|
|
495
|
+
_tag = "NavigationRuntimeError";
|
|
496
|
+
};
|
|
497
|
+
var NavigationCancelledError = class extends Error {
|
|
498
|
+
constructor(pathname) {
|
|
499
|
+
super(`Navigation cancelled for ${pathname}`);
|
|
500
|
+
this.pathname = pathname;
|
|
501
|
+
this.name = "NavigationCancelledError";
|
|
502
|
+
}
|
|
503
|
+
_tag = "NavigationCancelledError";
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// src/navigation/matcher.ts
|
|
507
|
+
var normalizePathname = (pathname) => {
|
|
508
|
+
if (pathname.length === 0) {
|
|
509
|
+
return "/";
|
|
510
|
+
}
|
|
511
|
+
const withSlash = pathname.startsWith("/") ? pathname : `/${pathname}`;
|
|
512
|
+
if (withSlash.length > 1 && withSlash.endsWith("/")) {
|
|
513
|
+
return withSlash.slice(0, -1);
|
|
514
|
+
}
|
|
515
|
+
return withSlash;
|
|
516
|
+
};
|
|
517
|
+
var scoreRoute = (path) => {
|
|
518
|
+
if (path === "/") {
|
|
519
|
+
return 10;
|
|
520
|
+
}
|
|
521
|
+
return path.split("/").filter((segment) => segment.length > 0).reduce((score, segment) => {
|
|
522
|
+
if (segment === "*") {
|
|
523
|
+
return score;
|
|
524
|
+
}
|
|
525
|
+
if (segment.startsWith(":")) {
|
|
526
|
+
return score + 2;
|
|
527
|
+
}
|
|
528
|
+
return score + 5;
|
|
529
|
+
}, 0);
|
|
530
|
+
};
|
|
531
|
+
var splitSegments = (path) => normalizePathname(path).split("/").filter((segment) => segment.length > 0);
|
|
532
|
+
var matchRoutePath = (routePath, pathname) => {
|
|
533
|
+
const routeSegments = splitSegments(routePath);
|
|
534
|
+
const pathSegments = splitSegments(pathname);
|
|
535
|
+
const params = {};
|
|
536
|
+
let i = 0;
|
|
537
|
+
let j = 0;
|
|
538
|
+
while (i < routeSegments.length && j < pathSegments.length) {
|
|
539
|
+
const routeSegment = routeSegments[i];
|
|
540
|
+
const pathSegment = pathSegments[j];
|
|
541
|
+
if (routeSegment === "*") {
|
|
542
|
+
return params;
|
|
543
|
+
}
|
|
544
|
+
if (routeSegment.startsWith(":")) {
|
|
545
|
+
params[routeSegment.slice(1)] = decodeURIComponent(pathSegment);
|
|
546
|
+
i += 1;
|
|
547
|
+
j += 1;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (routeSegment !== pathSegment) {
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
i += 1;
|
|
554
|
+
j += 1;
|
|
555
|
+
}
|
|
556
|
+
if (i < routeSegments.length && routeSegments[i] === "*") {
|
|
557
|
+
return params;
|
|
558
|
+
}
|
|
559
|
+
if (i !== routeSegments.length || j !== pathSegments.length) {
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
return params;
|
|
563
|
+
};
|
|
564
|
+
var matchRoute = ({ routes, pathname, search }) => {
|
|
565
|
+
const normalized = normalizePathname(pathname);
|
|
566
|
+
const sorted = [...routes].sort((a, b) => scoreRoute(b.path) - scoreRoute(a.path));
|
|
567
|
+
for (const route of sorted) {
|
|
568
|
+
const params = matchRoutePath(route.path, normalized);
|
|
569
|
+
if (params !== null) {
|
|
570
|
+
return {
|
|
571
|
+
route,
|
|
572
|
+
pathname: normalized,
|
|
573
|
+
params,
|
|
574
|
+
search
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
return null;
|
|
579
|
+
};
|
|
580
|
+
var buildHref = (pathname, searchText) => searchText.length > 0 ? `${normalizePathname(pathname)}${searchText}` : normalizePathname(pathname);
|
|
581
|
+
var normalizeSearchText = (searchText) => {
|
|
582
|
+
if (searchText.length === 0 || searchText === "?") {
|
|
583
|
+
return "";
|
|
584
|
+
}
|
|
585
|
+
return searchText.startsWith("?") ? searchText : `?${searchText}`;
|
|
586
|
+
};
|
|
587
|
+
var parseHref = (href) => {
|
|
588
|
+
const [pathPart, ...searchParts] = href.split("?");
|
|
589
|
+
return {
|
|
590
|
+
pathname: normalizePathname(pathPart ?? "/"),
|
|
591
|
+
searchText: normalizeSearchText(searchParts.length === 0 ? "" : searchParts.join("?"))
|
|
592
|
+
};
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
// src/navigation/service.ts
|
|
596
|
+
var import_effect6 = require("effect");
|
|
597
|
+
var describeUnknown = (value) => {
|
|
598
|
+
if (value instanceof Error) {
|
|
599
|
+
return `${value.name}: ${value.message}`;
|
|
600
|
+
}
|
|
601
|
+
if (typeof value === "string") {
|
|
602
|
+
return value;
|
|
603
|
+
}
|
|
604
|
+
try {
|
|
605
|
+
return JSON.stringify(value);
|
|
606
|
+
} catch {
|
|
607
|
+
return String(value);
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
var initialSnapshot2 = {
|
|
611
|
+
pathname: "/",
|
|
612
|
+
searchText: "",
|
|
613
|
+
href: "/",
|
|
614
|
+
status: "idle",
|
|
615
|
+
match: null,
|
|
616
|
+
loaders: {},
|
|
617
|
+
error: void 0
|
|
618
|
+
};
|
|
619
|
+
var toLoadersByName = (loaders) => new Map(loaders.map((loader) => [loader.name, loader]));
|
|
620
|
+
var planLoaderBatches = (loaders) => {
|
|
621
|
+
const byName = toLoadersByName(loaders);
|
|
622
|
+
const depthByName = /* @__PURE__ */ new Map();
|
|
623
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
624
|
+
const resolveDepth = (name) => {
|
|
625
|
+
const cached = depthByName.get(name);
|
|
626
|
+
if (cached !== void 0) {
|
|
627
|
+
return import_effect6.Effect.succeed(cached);
|
|
628
|
+
}
|
|
629
|
+
if (visiting.has(name)) {
|
|
630
|
+
return import_effect6.Effect.fail(new NavigationRuntimeError(`Cyclic loader dependency detected at ${name}`));
|
|
631
|
+
}
|
|
632
|
+
const loader = byName.get(name);
|
|
633
|
+
if (loader === void 0) {
|
|
634
|
+
return import_effect6.Effect.fail(new NavigationRuntimeError(`Loader dependency '${name}' is not registered`));
|
|
635
|
+
}
|
|
636
|
+
visiting.add(name);
|
|
637
|
+
const dependencies = loader.dependsOn ?? [];
|
|
638
|
+
return import_effect6.Effect.forEach(dependencies, resolveDepth).pipe(
|
|
639
|
+
import_effect6.Effect.map((depths) => {
|
|
640
|
+
const depth = depths.length === 0 ? 0 : Math.max(...depths) + 1;
|
|
641
|
+
depthByName.set(name, depth);
|
|
642
|
+
visiting.delete(name);
|
|
643
|
+
return depth;
|
|
644
|
+
}),
|
|
645
|
+
import_effect6.Effect.catchAll((error) => {
|
|
646
|
+
visiting.delete(name);
|
|
647
|
+
return import_effect6.Effect.fail(error);
|
|
648
|
+
})
|
|
649
|
+
);
|
|
650
|
+
};
|
|
651
|
+
return import_effect6.Effect.gen(function* () {
|
|
652
|
+
const entries = yield* import_effect6.Effect.forEach(
|
|
653
|
+
loaders,
|
|
654
|
+
(loader) => import_effect6.Effect.map(resolveDepth(loader.name), (depth) => [depth, loader])
|
|
655
|
+
);
|
|
656
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
657
|
+
for (const [depth, loader] of entries) {
|
|
658
|
+
const existing = grouped.get(depth);
|
|
659
|
+
if (existing === void 0) {
|
|
660
|
+
grouped.set(depth, [loader]);
|
|
661
|
+
} else {
|
|
662
|
+
existing.push(loader);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
const depths = Array.from(grouped.keys()).sort((a, b) => a - b);
|
|
666
|
+
return depths.map((depth) => grouped.get(depth) ?? []);
|
|
667
|
+
});
|
|
668
|
+
};
|
|
669
|
+
var Navigation = class extends import_effect6.Context.Tag("EffectReact/Navigation")() {
|
|
670
|
+
};
|
|
671
|
+
var makeNavigationLayer = (options) => {
|
|
672
|
+
const loaders = options.loaders ?? [];
|
|
673
|
+
const initial = parseHref(options.initialHref ?? "/");
|
|
674
|
+
return import_effect6.Layer.effect(
|
|
675
|
+
Navigation,
|
|
676
|
+
import_effect6.Effect.gen(function* () {
|
|
677
|
+
const boundary = yield* Boundary;
|
|
678
|
+
const telemetry = yield* Telemetry;
|
|
679
|
+
const snapshotsRef = yield* import_effect6.SubscriptionRef.make({
|
|
680
|
+
...initialSnapshot2,
|
|
681
|
+
pathname: initial.pathname,
|
|
682
|
+
searchText: initial.searchText,
|
|
683
|
+
href: buildHref(initial.pathname, initial.searchText)
|
|
684
|
+
});
|
|
685
|
+
const activeFiberRef = yield* import_effect6.Ref.make(import_effect6.Option.none());
|
|
686
|
+
const runLoaders = (snapshot) => import_effect6.Effect.gen(function* () {
|
|
687
|
+
if (snapshot.match === null) {
|
|
688
|
+
return {};
|
|
689
|
+
}
|
|
690
|
+
const routeLoaders = loaders.filter((loader) => loader.routeId === snapshot.match.route.id);
|
|
691
|
+
if (routeLoaders.length === 0) {
|
|
692
|
+
return {};
|
|
693
|
+
}
|
|
694
|
+
const batches = yield* planLoaderBatches(routeLoaders);
|
|
695
|
+
const results = {};
|
|
696
|
+
const states = {};
|
|
697
|
+
for (const loader of routeLoaders) {
|
|
698
|
+
states[loader.name] = { _tag: "pending" };
|
|
699
|
+
}
|
|
700
|
+
yield* import_effect6.SubscriptionRef.update(snapshotsRef, (current) => ({
|
|
701
|
+
...current,
|
|
702
|
+
loaders: {
|
|
703
|
+
...current.loaders,
|
|
704
|
+
...states
|
|
705
|
+
}
|
|
706
|
+
}));
|
|
707
|
+
for (const batch of batches) {
|
|
708
|
+
const exits = yield* import_effect6.Effect.all(
|
|
709
|
+
batch.map((loader) => {
|
|
710
|
+
const base = loader.run({
|
|
711
|
+
route: snapshot.match.route,
|
|
712
|
+
pathname: snapshot.pathname,
|
|
713
|
+
searchText: snapshot.searchText,
|
|
714
|
+
params: snapshot.match.params,
|
|
715
|
+
search: snapshot.match.search,
|
|
716
|
+
dependencyResults: results
|
|
717
|
+
});
|
|
718
|
+
const withRetry = loader.retry ? import_effect6.Effect.retry(base, loader.retry) : base;
|
|
719
|
+
return import_effect6.Effect.exit(withRetry).pipe(import_effect6.Effect.map((exit) => [loader, exit]));
|
|
720
|
+
}),
|
|
721
|
+
{
|
|
722
|
+
concurrency: "unbounded"
|
|
723
|
+
}
|
|
724
|
+
);
|
|
725
|
+
for (const [loader, exit] of exits) {
|
|
726
|
+
if (exit._tag === "Success") {
|
|
727
|
+
results[loader.name] = exit.value;
|
|
728
|
+
states[loader.name] = {
|
|
729
|
+
_tag: "success",
|
|
730
|
+
value: exit.value
|
|
731
|
+
};
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
const failure = import_effect6.Cause.failureOption(exit.cause);
|
|
735
|
+
states[loader.name] = {
|
|
736
|
+
_tag: "failure",
|
|
737
|
+
error: failure._tag === "Some" ? failure.value : import_effect6.Cause.pretty(exit.cause)
|
|
738
|
+
};
|
|
739
|
+
yield* import_effect6.SubscriptionRef.update(snapshotsRef, (current) => ({
|
|
740
|
+
...current,
|
|
741
|
+
status: "failure",
|
|
742
|
+
loaders: {
|
|
743
|
+
...current.loaders,
|
|
744
|
+
...states
|
|
745
|
+
},
|
|
746
|
+
error: states[loader.name]
|
|
747
|
+
}));
|
|
748
|
+
return yield* import_effect6.Effect.fail(
|
|
749
|
+
new NavigationRuntimeError(`Loader '${loader.name}' failed for route '${snapshot.match.route.id}'`)
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
yield* import_effect6.SubscriptionRef.update(snapshotsRef, (current) => ({
|
|
753
|
+
...current,
|
|
754
|
+
loaders: {
|
|
755
|
+
...current.loaders,
|
|
756
|
+
...states
|
|
757
|
+
}
|
|
758
|
+
}));
|
|
759
|
+
}
|
|
760
|
+
return states;
|
|
761
|
+
});
|
|
762
|
+
const performNavigation = (href) => import_effect6.Effect.gen(function* () {
|
|
763
|
+
const { pathname, searchText } = parseHref(href);
|
|
764
|
+
const searchParams = new URLSearchParams(searchText);
|
|
765
|
+
const candidate = options.routes.find((route) => matchRoute({
|
|
766
|
+
routes: [route],
|
|
767
|
+
pathname,
|
|
768
|
+
search: {}
|
|
769
|
+
}) !== null);
|
|
770
|
+
const decodedSearch = candidate?.search === void 0 ? import_effect6.Effect.succeed({}) : boundary.decodeUnknown({
|
|
771
|
+
source: `route:${candidate.id}:search`,
|
|
772
|
+
schema: candidate.search,
|
|
773
|
+
value: Object.fromEntries(searchParams.entries())
|
|
774
|
+
});
|
|
775
|
+
const search = yield* decodedSearch;
|
|
776
|
+
const matched = matchRoute({
|
|
777
|
+
routes: options.routes,
|
|
778
|
+
pathname,
|
|
779
|
+
search
|
|
780
|
+
});
|
|
781
|
+
if (matched === null) {
|
|
782
|
+
return yield* import_effect6.Effect.fail(
|
|
783
|
+
new NavigationRuntimeError(`No route matched pathname '${pathname}'`)
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
yield* telemetry.emit({
|
|
787
|
+
_tag: "navigation",
|
|
788
|
+
phase: "start",
|
|
789
|
+
pathname,
|
|
790
|
+
routeId: matched.route.id,
|
|
791
|
+
timestamp: Date.now()
|
|
792
|
+
});
|
|
793
|
+
const loadingSnapshot = {
|
|
794
|
+
pathname,
|
|
795
|
+
searchText: normalizeSearchText(searchText),
|
|
796
|
+
href: buildHref(pathname, normalizeSearchText(searchText)),
|
|
797
|
+
status: "loading",
|
|
798
|
+
match: matched,
|
|
799
|
+
loaders: {},
|
|
800
|
+
error: void 0
|
|
801
|
+
};
|
|
802
|
+
yield* import_effect6.SubscriptionRef.set(snapshotsRef, loadingSnapshot);
|
|
803
|
+
const loaderStates = yield* runLoaders(loadingSnapshot);
|
|
804
|
+
const completed = {
|
|
805
|
+
...loadingSnapshot,
|
|
806
|
+
status: "success",
|
|
807
|
+
loaders: loaderStates,
|
|
808
|
+
error: void 0
|
|
809
|
+
};
|
|
810
|
+
yield* import_effect6.SubscriptionRef.set(snapshotsRef, completed);
|
|
811
|
+
yield* telemetry.emit({
|
|
812
|
+
_tag: "navigation",
|
|
813
|
+
phase: "success",
|
|
814
|
+
pathname,
|
|
815
|
+
routeId: matched.route.id,
|
|
816
|
+
timestamp: Date.now()
|
|
817
|
+
});
|
|
818
|
+
return completed;
|
|
819
|
+
});
|
|
820
|
+
const navigate = (href) => import_effect6.Effect.gen(function* () {
|
|
821
|
+
const previous = yield* import_effect6.Ref.getAndSet(activeFiberRef, import_effect6.Option.none());
|
|
822
|
+
if (import_effect6.Option.isSome(previous)) {
|
|
823
|
+
yield* import_effect6.Fiber.interrupt(previous.value);
|
|
824
|
+
yield* telemetry.emit({
|
|
825
|
+
_tag: "navigation",
|
|
826
|
+
phase: "cancel",
|
|
827
|
+
pathname: href,
|
|
828
|
+
timestamp: Date.now()
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
const fiber = yield* import_effect6.Effect.fork(performNavigation(href));
|
|
832
|
+
yield* import_effect6.Ref.set(activeFiberRef, import_effect6.Option.some(fiber));
|
|
833
|
+
const exit = yield* import_effect6.Effect.exit(import_effect6.Fiber.join(fiber));
|
|
834
|
+
const current = yield* import_effect6.Ref.get(activeFiberRef);
|
|
835
|
+
if (import_effect6.Option.isSome(current) && current.value === fiber) {
|
|
836
|
+
yield* import_effect6.Ref.set(activeFiberRef, import_effect6.Option.none());
|
|
837
|
+
}
|
|
838
|
+
if (exit._tag === "Success") {
|
|
839
|
+
return exit.value;
|
|
840
|
+
}
|
|
841
|
+
if (import_effect6.Cause.isInterruptedOnly(exit.cause)) {
|
|
842
|
+
return yield* import_effect6.Effect.fail(new NavigationCancelledError(href));
|
|
843
|
+
}
|
|
844
|
+
const failure = import_effect6.Cause.failureOption(exit.cause);
|
|
845
|
+
if (failure._tag === "Some") {
|
|
846
|
+
return yield* import_effect6.Effect.fail(
|
|
847
|
+
failure.value instanceof NavigationRuntimeError ? failure.value : new NavigationRuntimeError(describeUnknown(failure.value))
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
return yield* import_effect6.Effect.fail(new NavigationRuntimeError(import_effect6.Cause.pretty(exit.cause)));
|
|
851
|
+
}).pipe(
|
|
852
|
+
import_effect6.Effect.tapError(
|
|
853
|
+
(error) => telemetry.emit({
|
|
854
|
+
_tag: "navigation",
|
|
855
|
+
phase: "failure",
|
|
856
|
+
pathname: href,
|
|
857
|
+
timestamp: Date.now(),
|
|
858
|
+
detail: error
|
|
859
|
+
})
|
|
860
|
+
)
|
|
861
|
+
);
|
|
862
|
+
const revalidate = () => import_effect6.Effect.gen(function* () {
|
|
863
|
+
const snapshot = yield* import_effect6.SubscriptionRef.get(snapshotsRef);
|
|
864
|
+
return yield* navigate(snapshot.href);
|
|
865
|
+
});
|
|
866
|
+
return {
|
|
867
|
+
navigate,
|
|
868
|
+
revalidate,
|
|
869
|
+
getSnapshot: import_effect6.SubscriptionRef.get(snapshotsRef),
|
|
870
|
+
hydrateSnapshot: (snapshot) => import_effect6.SubscriptionRef.set(snapshotsRef, snapshot),
|
|
871
|
+
snapshots: snapshotsRef.changes
|
|
872
|
+
};
|
|
873
|
+
})
|
|
874
|
+
);
|
|
875
|
+
};
|
|
876
|
+
|
|
877
|
+
// src/kernel/runtime.ts
|
|
878
|
+
var import_effect7 = require("effect");
|
|
879
|
+
var createManagedRuntime = (layer) => import_effect7.ManagedRuntime.make(layer);
|
|
880
|
+
|
|
881
|
+
// src/kernel/app.ts
|
|
882
|
+
var createAppLayer = (options) => {
|
|
883
|
+
const boundaryLayer = BoundaryLive;
|
|
884
|
+
const telemetryLayer = TelemetryLive;
|
|
885
|
+
const dataLayer = makeDataLayer(options.data).pipe(
|
|
886
|
+
import_effect8.Layer.provide([boundaryLayer, telemetryLayer])
|
|
887
|
+
);
|
|
888
|
+
const actionsLayer = makeActionsLayer({
|
|
889
|
+
actions: options.actions ?? []
|
|
890
|
+
}).pipe(import_effect8.Layer.provide([boundaryLayer, telemetryLayer]));
|
|
891
|
+
const navigationLayer = makeNavigationLayer({
|
|
892
|
+
routes: options.routes,
|
|
893
|
+
...options.loaders !== void 0 ? { loaders: options.loaders } : {},
|
|
894
|
+
...options.initialHref !== void 0 ? { initialHref: options.initialHref } : {}
|
|
895
|
+
}).pipe(import_effect8.Layer.provide([boundaryLayer, telemetryLayer]));
|
|
896
|
+
return import_effect8.Layer.mergeAll(boundaryLayer, telemetryLayer, dataLayer, actionsLayer, navigationLayer);
|
|
897
|
+
};
|
|
898
|
+
var createAppRuntime = (options) => createManagedRuntime(createAppLayer(options));
|
|
899
|
+
|
|
900
|
+
// src/framework/manifest.ts
|
|
901
|
+
var defineManifest = (manifest) => manifest;
|
|
902
|
+
var routesFromManifest = (manifest) => manifest.pages.map((page) => page.route);
|
|
903
|
+
var loadersFromManifest = (manifest) => {
|
|
904
|
+
const pageLoaders = manifest.pages.map((page) => page.loader).filter((loader) => loader !== void 0);
|
|
905
|
+
const layoutLoaders = (manifest.layouts ?? []).map((layout) => layout.loader).filter((loader) => loader !== void 0);
|
|
906
|
+
return [...pageLoaders, ...layoutLoaders];
|
|
907
|
+
};
|
|
908
|
+
|
|
909
|
+
// src/config/index.ts
|
|
910
|
+
var defaultConfig = {
|
|
911
|
+
appDir: "app",
|
|
912
|
+
adapters: ["node", "bun"],
|
|
913
|
+
ssr: {
|
|
914
|
+
streaming: true
|
|
915
|
+
},
|
|
916
|
+
cache: {
|
|
917
|
+
defaultPolicy: "no-store",
|
|
918
|
+
routeSegmentDefaults: "explicit"
|
|
919
|
+
},
|
|
920
|
+
strict: {
|
|
921
|
+
boundarySchemas: true,
|
|
922
|
+
typedErrors: true
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
var resolveConfig = (config = {}) => ({
|
|
926
|
+
appDir: config.appDir ?? defaultConfig.appDir,
|
|
927
|
+
adapters: config.adapters ?? defaultConfig.adapters,
|
|
928
|
+
ssr: {
|
|
929
|
+
streaming: config.ssr?.streaming ?? defaultConfig.ssr.streaming
|
|
930
|
+
},
|
|
931
|
+
cache: {
|
|
932
|
+
defaultPolicy: config.cache?.defaultPolicy ?? defaultConfig.cache.defaultPolicy,
|
|
933
|
+
routeSegmentDefaults: config.cache?.routeSegmentDefaults ?? defaultConfig.cache.routeSegmentDefaults
|
|
934
|
+
},
|
|
935
|
+
strict: {
|
|
936
|
+
boundarySchemas: config.strict?.boundarySchemas ?? defaultConfig.strict.boundarySchemas,
|
|
937
|
+
typedErrors: config.strict?.typedErrors ?? defaultConfig.strict.typedErrors
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
|
|
941
|
+
// src/framework/app.ts
|
|
942
|
+
var createPageMatcher = (pages) => {
|
|
943
|
+
const routes = pages.map((page) => page.route);
|
|
944
|
+
return (href) => {
|
|
945
|
+
const parsed = parseHref(href);
|
|
946
|
+
const matched = matchRoute({
|
|
947
|
+
routes,
|
|
948
|
+
pathname: parsed.pathname,
|
|
949
|
+
search: {}
|
|
950
|
+
});
|
|
951
|
+
if (matched === null) {
|
|
952
|
+
return void 0;
|
|
953
|
+
}
|
|
954
|
+
return pages.find((page) => page.route.id === matched.route.id);
|
|
955
|
+
};
|
|
956
|
+
};
|
|
957
|
+
var createApp = (options) => {
|
|
958
|
+
const manifest = options.manifest;
|
|
959
|
+
const routes = routesFromManifest(manifest);
|
|
960
|
+
const loaders = loadersFromManifest(manifest);
|
|
961
|
+
const actions = manifest.actions ?? [];
|
|
962
|
+
const runtime = createAppRuntime({
|
|
963
|
+
routes,
|
|
964
|
+
actions,
|
|
965
|
+
loaders,
|
|
966
|
+
...options.initialHref !== void 0 ? { initialHref: options.initialHref } : {}
|
|
967
|
+
});
|
|
968
|
+
const actionHandlerFactory = createActionHttpHandler();
|
|
969
|
+
const handleActionRequest = actionHandlerFactory((effect) => runtime.runPromise(effect));
|
|
970
|
+
return {
|
|
971
|
+
manifest,
|
|
972
|
+
config: resolveConfig(options.config),
|
|
973
|
+
runtime,
|
|
974
|
+
actions,
|
|
975
|
+
matchPage: createPageMatcher(manifest.pages),
|
|
976
|
+
handleActionRequest,
|
|
977
|
+
dispose: () => runtime.dispose()
|
|
978
|
+
};
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
// src/framework/cache.ts
|
|
982
|
+
var cachePolicy = (policy) => policy;
|
|
983
|
+
var noStore = () => ({
|
|
984
|
+
mode: "no-store"
|
|
985
|
+
});
|
|
986
|
+
|
|
987
|
+
// src/framework/contracts.ts
|
|
988
|
+
var definePage = (page) => page;
|
|
989
|
+
var defineLayout = (layout) => layout;
|
|
990
|
+
var defineMiddleware = (middleware) => middleware;
|
|
991
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
992
|
+
0 && (module.exports = {
|
|
993
|
+
cachePolicy,
|
|
994
|
+
createApp,
|
|
995
|
+
defineAction,
|
|
996
|
+
defineLayout,
|
|
997
|
+
defineLoader,
|
|
998
|
+
defineManifest,
|
|
999
|
+
defineMiddleware,
|
|
1000
|
+
definePage,
|
|
1001
|
+
defineRoute,
|
|
1002
|
+
loadersFromManifest,
|
|
1003
|
+
noStore,
|
|
1004
|
+
routesFromManifest
|
|
1005
|
+
});
|
|
1006
|
+
//# sourceMappingURL=index.cjs.map
|