revojs 0.0.88 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +176 -9
- package/dist/index.js +220 -915
- package/dist/vite/index.d.ts +53 -0
- package/dist/vite/index.js +460 -0
- package/package.json +11 -10
- package/src/types/index.d.ts +20 -16
- package/dist/app/index.d.ts +0 -36
- package/dist/html/index.d.ts +0 -110
- package/dist/http/index.d.ts +0 -41
- package/dist/jsx/index.d.ts +0 -371
- package/dist/jsx/index.js +0 -160
- package/dist/locale/index.d.ts +0 -26
- package/dist/radix/index.d.ts +0 -12
- package/dist/router/index.d.ts +0 -45
- package/dist/runtime/index.d.ts +0 -55
- package/dist/schema/index.d.ts +0 -24
- package/dist/signals/index.d.ts +0 -44
package/dist/index.js
CHANGED
|
@@ -1,284 +1,98 @@
|
|
|
1
|
-
//#region src/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const object = structuredClone(input);
|
|
5
|
-
for (const key in base) {
|
|
6
|
-
if (key === "__proto__" || key === "constructor") continue;
|
|
7
|
-
const value = base[key];
|
|
8
|
-
if (value === null || value === void 0) continue;
|
|
9
|
-
if (Array.isArray(value) && Array.isArray(object[key])) object[key] = [...value, ...object[key]];
|
|
10
|
-
else if (typeof value === "object" && typeof object[key] === "object") object[key] = mergeObjects(value, object[key]);
|
|
11
|
-
else object[key] = value;
|
|
12
|
-
}
|
|
13
|
-
return object;
|
|
14
|
-
}
|
|
15
|
-
function createApp(config) {
|
|
16
|
-
return {
|
|
17
|
-
config: mergeObjects(config, {
|
|
18
|
-
modules: [],
|
|
19
|
-
client: {
|
|
20
|
-
entry: "index.html",
|
|
21
|
-
externals: []
|
|
22
|
-
},
|
|
23
|
-
server: {
|
|
24
|
-
entry: "@revojs/bun/runtime",
|
|
25
|
-
externals: []
|
|
26
|
-
},
|
|
27
|
-
dev: { middleware: [] }
|
|
28
|
-
}),
|
|
29
|
-
virtuals: {}
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
const SERVER = "ssr";
|
|
33
|
-
const CLIENT = "client";
|
|
34
|
-
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/jsx/index.ts
|
|
37
|
-
const svgElements = new Set([
|
|
38
|
-
"altGlyph",
|
|
39
|
-
"altGlyphDef",
|
|
40
|
-
"altGlyphItem",
|
|
41
|
-
"animate",
|
|
42
|
-
"animateColor",
|
|
43
|
-
"animateMotion",
|
|
44
|
-
"animateTransform",
|
|
45
|
-
"circle",
|
|
46
|
-
"clipPath",
|
|
47
|
-
"color-profile",
|
|
48
|
-
"cursor",
|
|
49
|
-
"defs",
|
|
50
|
-
"desc",
|
|
51
|
-
"ellipse",
|
|
52
|
-
"feBlend",
|
|
53
|
-
"feColorMatrix",
|
|
54
|
-
"feComponentTransfer",
|
|
55
|
-
"feComposite",
|
|
56
|
-
"feConvolveMatrix",
|
|
57
|
-
"feDiffuseLighting",
|
|
58
|
-
"feDisplacementMap",
|
|
59
|
-
"feDistantLight",
|
|
60
|
-
"feDropShadow",
|
|
61
|
-
"feFlood",
|
|
62
|
-
"feFuncA",
|
|
63
|
-
"feFuncB",
|
|
64
|
-
"feFuncG",
|
|
65
|
-
"feFuncR",
|
|
66
|
-
"feGaussianBlur",
|
|
67
|
-
"feImage",
|
|
68
|
-
"feMerge",
|
|
69
|
-
"feMergeNode",
|
|
70
|
-
"feMorphology",
|
|
71
|
-
"feOffset",
|
|
72
|
-
"fePointLight",
|
|
73
|
-
"feSpecularLighting",
|
|
74
|
-
"feSpotLight",
|
|
75
|
-
"feTile",
|
|
76
|
-
"feTurbulence",
|
|
77
|
-
"filter",
|
|
78
|
-
"font",
|
|
79
|
-
"font-face",
|
|
80
|
-
"font-face-format",
|
|
81
|
-
"font-face-name",
|
|
82
|
-
"font-face-src",
|
|
83
|
-
"font-face-uri",
|
|
84
|
-
"foreignObject",
|
|
85
|
-
"g",
|
|
86
|
-
"glyph",
|
|
87
|
-
"glyphRef",
|
|
88
|
-
"hkern",
|
|
89
|
-
"image",
|
|
90
|
-
"line",
|
|
91
|
-
"linearGradient",
|
|
92
|
-
"marker",
|
|
93
|
-
"mask",
|
|
94
|
-
"metadata",
|
|
95
|
-
"missing-glyph",
|
|
96
|
-
"mpath",
|
|
97
|
-
"path",
|
|
98
|
-
"pattern",
|
|
99
|
-
"polygon",
|
|
100
|
-
"polyline",
|
|
101
|
-
"radialGradient",
|
|
102
|
-
"rect",
|
|
103
|
-
"set",
|
|
104
|
-
"stop",
|
|
105
|
-
"svg",
|
|
106
|
-
"switch",
|
|
107
|
-
"symbol",
|
|
108
|
-
"text",
|
|
109
|
-
"textPath",
|
|
110
|
-
"tref",
|
|
111
|
-
"tspan",
|
|
112
|
-
"use",
|
|
113
|
-
"view",
|
|
114
|
-
"vkern"
|
|
115
|
-
]);
|
|
116
|
-
function namespace(tag) {
|
|
117
|
-
return svgElements.has(tag) ? "http://www.w3.org/2000/svg" : "http://www.w3.org/1999/xhtml";
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/schema/index.ts
|
|
122
|
-
function isFailure(result) {
|
|
123
|
-
return "issues" in result;
|
|
124
|
-
}
|
|
125
|
-
function parseSchema(scope, schema, value) {
|
|
126
|
-
const result = schema["~standard"].validate(value);
|
|
127
|
-
if (isFailure(result)) throw sendBadRequest(scope, result.issues.map((issue) => issue.message).join(", "));
|
|
128
|
-
return result.value;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
//#endregion
|
|
132
|
-
//#region src/signals/index.ts
|
|
133
|
-
var StopEvent = class extends Event {
|
|
1
|
+
//#region src/server/index.ts
|
|
2
|
+
var Radix = class {
|
|
3
|
+
rootNode;
|
|
134
4
|
constructor() {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
parentScope;
|
|
140
|
-
context;
|
|
141
|
-
constructor(parentScope) {
|
|
142
|
-
super();
|
|
143
|
-
this.parentScope = parentScope;
|
|
144
|
-
this.parentScope?.onStop(() => this.stop());
|
|
145
|
-
this.context = /* @__PURE__ */ new Map();
|
|
5
|
+
this.rootNode = {
|
|
6
|
+
type: "PATH",
|
|
7
|
+
children: {}
|
|
8
|
+
};
|
|
146
9
|
}
|
|
147
|
-
|
|
148
|
-
let
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
|
|
10
|
+
use(path, value) {
|
|
11
|
+
let node = this.rootNode;
|
|
12
|
+
for (const segment of path.split("/")) {
|
|
13
|
+
if (segment.startsWith(WILDCARD)) {
|
|
14
|
+
let childNode$1 = node.children[WILDCARD];
|
|
15
|
+
childNode$1 ??= {
|
|
16
|
+
type: "WILDCARD",
|
|
17
|
+
parameter: segment.substring(WILDCARD.length),
|
|
18
|
+
children: {}
|
|
19
|
+
};
|
|
20
|
+
node.children[WILDCARD] ??= childNode$1;
|
|
21
|
+
node = childNode$1;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (segment.startsWith(PARAMETER)) {
|
|
25
|
+
let childNode$1 = node.children[PARAMETER];
|
|
26
|
+
childNode$1 ??= {
|
|
27
|
+
type: "PARAMETER",
|
|
28
|
+
parameter: segment.substring(PARAMETER.length),
|
|
29
|
+
children: {}
|
|
30
|
+
};
|
|
31
|
+
node.children[PARAMETER] ??= childNode$1;
|
|
32
|
+
node = childNode$1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
let childNode = node.children[segment];
|
|
36
|
+
childNode ??= {
|
|
37
|
+
type: "PATH",
|
|
38
|
+
children: {}
|
|
39
|
+
};
|
|
40
|
+
node.children[segment] ??= childNode;
|
|
41
|
+
node = childNode;
|
|
152
42
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
setContext(input, value) {
|
|
156
|
-
this.context.set(input, value);
|
|
157
|
-
}
|
|
158
|
-
onStop(input) {
|
|
159
|
-
this.addEventListener("stop", input, { once: true });
|
|
160
|
-
}
|
|
161
|
-
stop() {
|
|
162
|
-
return this.dispatchEvent(new StopEvent());
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
var Compute = class extends Scope {
|
|
166
|
-
invoke;
|
|
167
|
-
constructor(parentScope, invoke) {
|
|
168
|
-
super(parentScope);
|
|
169
|
-
this.invoke = invoke;
|
|
170
|
-
}
|
|
171
|
-
run() {
|
|
172
|
-
this.stop();
|
|
173
|
-
return this.invoke(this);
|
|
43
|
+
node.value = value;
|
|
44
|
+
return node;
|
|
174
45
|
}
|
|
175
46
|
};
|
|
176
|
-
var
|
|
177
|
-
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
47
|
+
var Router = class extends Radix {
|
|
48
|
+
fetch(scope, next) {
|
|
49
|
+
const { request } = useServer(scope);
|
|
50
|
+
const { pathname } = useUrl(scope);
|
|
51
|
+
const context = {
|
|
52
|
+
route: this.rootNode,
|
|
53
|
+
segments: (request.method.toUpperCase() + pathname).split("/"),
|
|
54
|
+
parameters: {}
|
|
55
|
+
};
|
|
56
|
+
const invoke = (node, index) => {
|
|
57
|
+
if (index === context.segments.length) return node.value;
|
|
58
|
+
const segment = context.segments[index];
|
|
59
|
+
if (node.children[segment]) {
|
|
60
|
+
const route$1 = invoke(node.children[segment], index + 1);
|
|
61
|
+
if (route$1) return route$1;
|
|
62
|
+
}
|
|
63
|
+
if (node.children[PARAMETER]) {
|
|
64
|
+
const parameterNode = node.children[PARAMETER];
|
|
65
|
+
const route$1 = invoke(parameterNode, index + 1);
|
|
66
|
+
if (route$1) {
|
|
67
|
+
context.parameters[parameterNode.parameter] = segment;
|
|
68
|
+
return route$1;
|
|
189
69
|
}
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
const value = Reflect.get(target, key);
|
|
193
|
-
if (value) {
|
|
194
|
-
if (typeof value === "function" && !value.prototype) return value.bind(target);
|
|
195
|
-
if (typeof value === "object") {
|
|
196
|
-
const tag = Object.prototype.toString.call(value);
|
|
197
|
-
if (tag === "[object Object]" || tag === "[object Array]" || tag === "[object Map]" || tag === "[object Set]" || tag === "[object WeakMap]" || tag === "[object WeakSet]") return new Proxy(value, new Handler());
|
|
198
70
|
}
|
|
71
|
+
if (node.children[WILDCARD]) {
|
|
72
|
+
const wildcardNode = node.children[WILDCARD];
|
|
73
|
+
context.parameters[wildcardNode.parameter] = segment;
|
|
74
|
+
return wildcardNode.value ?? invoke(wildcardNode, segment.length);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const route = invoke(this.rootNode, 0);
|
|
78
|
+
if (route) {
|
|
79
|
+
scope.setContext(ROUTER_CONTEXT, context);
|
|
80
|
+
return route.fetch(scope);
|
|
199
81
|
}
|
|
200
|
-
return
|
|
201
|
-
}
|
|
202
|
-
set(target, key, value) {
|
|
203
|
-
const result = Reflect.set(target, key, value);
|
|
204
|
-
for (const compute of targets.get(target)?.get(key) ?? []) compute.run();
|
|
205
|
-
return result;
|
|
82
|
+
return next?.();
|
|
206
83
|
}
|
|
207
84
|
};
|
|
208
|
-
function
|
|
209
|
-
return
|
|
210
|
-
}
|
|
211
|
-
function createCompute(scope, invoke) {
|
|
212
|
-
let previous = activeCompute;
|
|
213
|
-
activeCompute = new Compute(scope, invoke);
|
|
214
|
-
const result = invoke(activeCompute);
|
|
215
|
-
if (result instanceof Promise) return result.finally(() => activeCompute = previous);
|
|
216
|
-
activeCompute = previous;
|
|
217
|
-
return result;
|
|
218
|
-
}
|
|
219
|
-
function createMemo(scope, invoke) {
|
|
220
|
-
let state;
|
|
221
|
-
const compute = createCompute(scope, (scope$1) => {
|
|
222
|
-
const value = invoke(scope$1);
|
|
223
|
-
if (typeof state === "object") state.value = value;
|
|
224
|
-
return value;
|
|
225
|
-
});
|
|
226
|
-
state = createState(compute);
|
|
227
|
-
return state;
|
|
228
|
-
}
|
|
229
|
-
function fromValue(value) {
|
|
230
|
-
if (value instanceof Function) return fromValue(value());
|
|
231
|
-
return value;
|
|
232
|
-
}
|
|
233
|
-
function untrack(invoke) {
|
|
234
|
-
let previous = activeCompute;
|
|
235
|
-
activeCompute = void 0;
|
|
236
|
-
const result = invoke();
|
|
237
|
-
if (result instanceof Promise) return result.finally(() => activeCompute = previous);
|
|
238
|
-
activeCompute = previous;
|
|
239
|
-
return result;
|
|
240
|
-
}
|
|
241
|
-
function defineContext(key) {
|
|
242
|
-
return key;
|
|
243
|
-
}
|
|
244
|
-
let activeCompute;
|
|
245
|
-
const targets = /* @__PURE__ */ new WeakMap();
|
|
246
|
-
|
|
247
|
-
//#endregion
|
|
248
|
-
//#region src/http/index.ts
|
|
249
|
-
function sendText(scope, text) {
|
|
250
|
-
const { response } = useRuntime(scope);
|
|
251
|
-
response.headers.set("Content-Type", "text/plain");
|
|
252
|
-
return new Response(text, response);
|
|
253
|
-
}
|
|
254
|
-
function sendHtml(scope, text) {
|
|
255
|
-
const { response } = useRuntime(scope);
|
|
256
|
-
response.headers.set("Content-Type", "text/html");
|
|
257
|
-
return new Response(text, response);
|
|
258
|
-
}
|
|
259
|
-
function sendJson(scope, value) {
|
|
260
|
-
const { response } = useRuntime(scope);
|
|
261
|
-
response.headers.set("Content-Type", "application/json");
|
|
262
|
-
return new Response(JSON.stringify(value), response);
|
|
263
|
-
}
|
|
264
|
-
function sendRedirect(scope, path) {
|
|
265
|
-
const { response } = useRuntime(scope);
|
|
266
|
-
response.status = 302;
|
|
267
|
-
response.headers.set("Location", path);
|
|
268
|
-
return new Response(null, response);
|
|
85
|
+
function defineRoute(route) {
|
|
86
|
+
return route;
|
|
269
87
|
}
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
response.status = 400;
|
|
273
|
-
return new Response(text, response);
|
|
88
|
+
function defineMiddleware(middleware) {
|
|
89
|
+
return middleware;
|
|
274
90
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
277
|
-
response.status = 401;
|
|
278
|
-
return new Response(null, response);
|
|
91
|
+
function useServer(scope) {
|
|
92
|
+
return scope.getContext(SERVER_CONTEXT);
|
|
279
93
|
}
|
|
280
94
|
function useUrl(scope, base) {
|
|
281
|
-
const { request } =
|
|
95
|
+
const { request } = useServer(scope);
|
|
282
96
|
return new URL(request?.url ?? window?.location.href, base);
|
|
283
97
|
}
|
|
284
98
|
function useQuery(scope, schema) {
|
|
@@ -286,23 +100,8 @@ function useQuery(scope, schema) {
|
|
|
286
100
|
const entries = Object.fromEntries(searchParams);
|
|
287
101
|
return schema ? parseSchema(scope, schema, entries) : entries;
|
|
288
102
|
}
|
|
289
|
-
function useCookie(scope, name, schema, options) {
|
|
290
|
-
const cookies = useCookies(scope);
|
|
291
|
-
const state = createState(parseSchema(scope, schema, cookies[name]));
|
|
292
|
-
createCompute(scope, () => {
|
|
293
|
-
switch (typeof state.value) {
|
|
294
|
-
case "string":
|
|
295
|
-
case "number":
|
|
296
|
-
case "bigint":
|
|
297
|
-
case "boolean":
|
|
298
|
-
case "symbol": return setCookie(scope, name, state.value.toString(), options);
|
|
299
|
-
case "object": return setCookie(scope, name, JSON.stringify(state.value), options);
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
return state;
|
|
303
|
-
}
|
|
304
103
|
function useCookies(scope, schema) {
|
|
305
|
-
const { request } =
|
|
104
|
+
const { request } = useServer(scope);
|
|
306
105
|
const entries = (isClient() ? document.cookie : request.headers.get("Cookie") ?? "").split("; ").reduce((result, cookie) => {
|
|
307
106
|
const [name, value] = cookie.split("=");
|
|
308
107
|
if (name && value) result[name] = decodeURIComponent(value);
|
|
@@ -311,7 +110,7 @@ function useCookies(scope, schema) {
|
|
|
311
110
|
return schema ? parseSchema(scope, schema, entries) : entries;
|
|
312
111
|
}
|
|
313
112
|
function useSetCookies(scope, schema) {
|
|
314
|
-
const { request } =
|
|
113
|
+
const { request } = useServer(scope);
|
|
315
114
|
const entries = request.headers.getSetCookie().reduce((result, cookie) => {
|
|
316
115
|
const [name, value] = cookie.split("=");
|
|
317
116
|
if (name && value) result[name] = decodeURIComponent(value);
|
|
@@ -320,7 +119,7 @@ function useSetCookies(scope, schema) {
|
|
|
320
119
|
return schema ? parseSchema(scope, schema, entries) : entries;
|
|
321
120
|
}
|
|
322
121
|
function setCookie(scope, name, value, options) {
|
|
323
|
-
const { response } =
|
|
122
|
+
const { response } = useServer(scope);
|
|
324
123
|
let cookie = name + "=" + encodeURIComponent(value);
|
|
325
124
|
if (options?.domain) cookie += `; Domain=${options.domain}`;
|
|
326
125
|
if (options?.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
@@ -333,10 +132,77 @@ function setCookie(scope, name, value, options) {
|
|
|
333
132
|
if (isClient()) document.cookie = cookie;
|
|
334
133
|
else response.headers.append("Set-Cookie", cookie);
|
|
335
134
|
}
|
|
135
|
+
function sendText(scope, text, config) {
|
|
136
|
+
const { response } = useServer(scope);
|
|
137
|
+
response.headers.set("Content-Type", "text/plain");
|
|
138
|
+
return new Response(text, mergeObjects(response, config));
|
|
139
|
+
}
|
|
140
|
+
function sendHtml(scope, text, config) {
|
|
141
|
+
const { response } = useServer(scope);
|
|
142
|
+
response.headers.set("Content-Type", "text/html");
|
|
143
|
+
return new Response(text, mergeObjects(response, config));
|
|
144
|
+
}
|
|
145
|
+
function sendJson(scope, value, config) {
|
|
146
|
+
const { response } = useServer(scope);
|
|
147
|
+
response.headers.set("Content-Type", "application/json");
|
|
148
|
+
return new Response(JSON.stringify(value), mergeObjects(response, config));
|
|
149
|
+
}
|
|
150
|
+
function sendRedirect(scope, path, config) {
|
|
151
|
+
const { response } = useServer(scope);
|
|
152
|
+
response.status = 302;
|
|
153
|
+
response.headers.set("Location", path);
|
|
154
|
+
return new Response(null, mergeObjects(response, config));
|
|
155
|
+
}
|
|
156
|
+
function sendBadRequest(scope, text, config) {
|
|
157
|
+
const { response } = useServer(scope);
|
|
158
|
+
response.status = 400;
|
|
159
|
+
return new Response(text, mergeObjects(response, config));
|
|
160
|
+
}
|
|
161
|
+
function sendUnauthorized(scope, config) {
|
|
162
|
+
const { response } = useServer(scope);
|
|
163
|
+
response.status = 401;
|
|
164
|
+
return new Response(null, mergeObjects(response, config));
|
|
165
|
+
}
|
|
336
166
|
function mimeType(file) {
|
|
337
167
|
const extension = /\.([a-zA-Z0-9]+?)$/.exec(file)?.at(1);
|
|
338
168
|
return mimeTypes[extension ?? ""] ?? "text/plain";
|
|
339
169
|
}
|
|
170
|
+
function toRoutePath(path) {
|
|
171
|
+
const result = ("/" + path).replaceAll(/\/index/g, "").replaceAll(/\[\.\.\.(.*?)\]/g, (_, value) => WILDCARD + value).replaceAll(/\[(.*?)\]/g, (_, value) => PARAMETER + value);
|
|
172
|
+
return (result.startsWith("/") ? result : "/" + result).split(".");
|
|
173
|
+
}
|
|
174
|
+
async function createServer() {
|
|
175
|
+
const router = new Router();
|
|
176
|
+
const pipeline = new Array();
|
|
177
|
+
const middlewares = await import("#virtual/middlewares").then((module) => Object.entries(module.default));
|
|
178
|
+
for (const [_, middleware] of middlewares) pipeline.push(middleware);
|
|
179
|
+
const assets = await import("#virtual/assets").then((module) => Object.entries(module.default));
|
|
180
|
+
for (const [path, asset] of assets) router.use(`GET/${path}`, defineRoute({ async fetch(scope) {
|
|
181
|
+
const { response } = useServer(scope);
|
|
182
|
+
response.headers.set("Content-Type", mimeType(path));
|
|
183
|
+
return new Response(asset, response);
|
|
184
|
+
} }));
|
|
185
|
+
const routes = await import("#virtual/routes").then((module) => Object.entries(module.default));
|
|
186
|
+
for (const [path, route] of routes) {
|
|
187
|
+
const [name, method] = toRoutePath(path);
|
|
188
|
+
router.use(method?.toUpperCase() + name, route);
|
|
189
|
+
}
|
|
190
|
+
pipeline.push(router);
|
|
191
|
+
const invoke = (scope, index) => {
|
|
192
|
+
return pipeline.at(index)?.fetch(scope, () => invoke(scope, index + 1));
|
|
193
|
+
};
|
|
194
|
+
return {
|
|
195
|
+
router,
|
|
196
|
+
pipeline,
|
|
197
|
+
async fetch(scope) {
|
|
198
|
+
return await invoke(scope, 0) ?? sendText(scope, "NOT_FOUND", { status: 404 });
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const ROUTER_CONTEXT = defineContext("ROUTER_CONTEXT");
|
|
203
|
+
const SERVER_CONTEXT = defineContext("SERVER_CONTEXT");
|
|
204
|
+
const WILDCARD = "$";
|
|
205
|
+
const PARAMETER = ":";
|
|
340
206
|
const mimeTypes = {
|
|
341
207
|
txt: "text/plain",
|
|
342
208
|
css: "text/css",
|
|
@@ -384,520 +250,41 @@ const mimeTypes = {
|
|
|
384
250
|
};
|
|
385
251
|
|
|
386
252
|
//#endregion
|
|
387
|
-
//#region src/
|
|
388
|
-
var
|
|
389
|
-
value;
|
|
390
|
-
input;
|
|
391
|
-
children;
|
|
392
|
-
constructor(input) {
|
|
393
|
-
this.input = input;
|
|
394
|
-
this.children = {};
|
|
395
|
-
}
|
|
396
|
-
insert(path, value) {
|
|
397
|
-
let node = this;
|
|
398
|
-
for (let segment of path.split("/")) {
|
|
399
|
-
let input;
|
|
400
|
-
if (segment.startsWith(":")) {
|
|
401
|
-
input = segment.substring(1);
|
|
402
|
-
segment = ":";
|
|
403
|
-
}
|
|
404
|
-
let childNode = node.children[segment];
|
|
405
|
-
if (childNode === void 0) {
|
|
406
|
-
childNode = new Radix(input);
|
|
407
|
-
node.children[segment] = childNode;
|
|
408
|
-
}
|
|
409
|
-
node = childNode;
|
|
410
|
-
}
|
|
411
|
-
node.value = value;
|
|
412
|
-
return this;
|
|
413
|
-
}
|
|
414
|
-
match(path) {
|
|
415
|
-
let node = this;
|
|
416
|
-
const match = { inputs: {} };
|
|
417
|
-
for (const segment of path.split("/")) {
|
|
418
|
-
node = node?.children[segment] ?? node?.children[":"];
|
|
419
|
-
if (node?.input) match.inputs[node.input] = segment;
|
|
420
|
-
}
|
|
421
|
-
match.value = node?.value;
|
|
422
|
-
return match;
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
|
|
426
|
-
//#endregion
|
|
427
|
-
//#region src/runtime/index.ts
|
|
428
|
-
function isRoute(value) {
|
|
429
|
-
return !!value && typeof value === "object" && "fetch" in value;
|
|
430
|
-
}
|
|
431
|
-
function useRuntime(scope) {
|
|
432
|
-
return scope.getContext(RUNTIME_CONTEXT);
|
|
433
|
-
}
|
|
434
|
-
function useRoute(scope) {
|
|
435
|
-
return scope.getContext(ROUTE_CONTEXT);
|
|
436
|
-
}
|
|
437
|
-
async function useRoutes() {
|
|
438
|
-
return await import("#virtual/routes").then((module) => module.default);
|
|
439
|
-
}
|
|
440
|
-
async function useAssets() {
|
|
441
|
-
return await import("#virtual/assets").then((module) => module.default);
|
|
442
|
-
}
|
|
443
|
-
async function useLocales() {
|
|
444
|
-
return await import("#virtual/locales").then((module) => module.default);
|
|
445
|
-
}
|
|
446
|
-
function defineRoute(route) {
|
|
447
|
-
return route;
|
|
448
|
-
}
|
|
449
|
-
function defineMiddleware(middleware) {
|
|
450
|
-
return middleware;
|
|
451
|
-
}
|
|
452
|
-
function fileName(path) {
|
|
453
|
-
return path.split("/").pop()?.split(".").slice(0, -1).join(".");
|
|
454
|
-
}
|
|
455
|
-
function toPath(value) {
|
|
456
|
-
const path = (value.startsWith("/") ? value : "/" + value).replaceAll(/\/index/g, "").replaceAll(/\[(.*?)\]/g, (_, name) => ":" + name);
|
|
457
|
-
const route = path.startsWith("/") ? path : "/" + path;
|
|
458
|
-
const split = route.split(".");
|
|
459
|
-
return split.length === 3 ? [split.at(0), split.at(1)] : [split.at(0)];
|
|
460
|
-
}
|
|
461
|
-
async function $fetch(scope, input, options) {
|
|
462
|
-
const { request, variables } = useRuntime(scope);
|
|
463
|
-
let response;
|
|
464
|
-
if (request) {
|
|
465
|
-
const next = new Scope();
|
|
466
|
-
const url = new URL(input.toString(), request.url);
|
|
467
|
-
next.setContext(RUNTIME_CONTEXT, {
|
|
468
|
-
tasks: [],
|
|
469
|
-
states: {},
|
|
470
|
-
request: new Request(url, options),
|
|
471
|
-
response: { headers: new Headers() },
|
|
472
|
-
variables
|
|
473
|
-
});
|
|
474
|
-
const previous = new URL(request.url);
|
|
475
|
-
if (url.origin === previous.origin) response = await (await import("#virtual/runtime")).runtime.fetch(next);
|
|
476
|
-
}
|
|
477
|
-
response ??= await fetch(input, options);
|
|
478
|
-
if (response.ok === false) throw response;
|
|
479
|
-
const contentType = response.headers.get("Content-Type")?.split(";").shift() ?? "";
|
|
480
|
-
switch (contentType) {
|
|
481
|
-
case "application/json": return response.json();
|
|
482
|
-
default: return response;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
function useState(scope, name, value) {
|
|
486
|
-
const state = createState(value);
|
|
487
|
-
if (isClient()) {
|
|
488
|
-
if (STATES === void 0) {
|
|
489
|
-
const element = document.getElementById("STATES");
|
|
490
|
-
STATES = element?.textContent ? JSON.parse(element.textContent) : {};
|
|
491
|
-
}
|
|
492
|
-
state.value = STATES[name];
|
|
493
|
-
createCompute(scope, () => STATES && (STATES[name] = state.value));
|
|
494
|
-
}
|
|
495
|
-
if (isServer()) {
|
|
496
|
-
const { states } = useRuntime(scope);
|
|
497
|
-
states[name] = state;
|
|
498
|
-
}
|
|
499
|
-
return state;
|
|
500
|
-
}
|
|
501
|
-
function useAsync(scope, name, invoke, defaultOptions) {
|
|
502
|
-
const { tasks } = useRuntime(scope);
|
|
503
|
-
const state = useState(scope, name);
|
|
504
|
-
const isLoading = createState(false);
|
|
505
|
-
const execute = async (options) => {
|
|
506
|
-
const onCatch = options?.catch ?? defaultOptions?.catch;
|
|
507
|
-
const viewTransition = options?.viewTransition ?? defaultOptions?.viewTransition;
|
|
508
|
-
isLoading.value = true;
|
|
509
|
-
try {
|
|
510
|
-
const result = await invoke();
|
|
511
|
-
if (JSON.stringify(state.value ?? {}) !== JSON.stringify(result)) if (viewTransition) await startViewTransition(viewTransition, () => state.value = result);
|
|
512
|
-
else state.value = result;
|
|
513
|
-
} catch (error) {
|
|
514
|
-
onCatch?.(error);
|
|
515
|
-
} finally {
|
|
516
|
-
isLoading.value = false;
|
|
517
|
-
}
|
|
518
|
-
return state.value;
|
|
519
|
-
};
|
|
520
|
-
const task = execute(defaultOptions);
|
|
521
|
-
if (isServer()) tasks.push(task);
|
|
522
|
-
return {
|
|
523
|
-
state,
|
|
524
|
-
isLoading,
|
|
525
|
-
execute
|
|
526
|
-
};
|
|
527
|
-
}
|
|
528
|
-
function useFetch(scope, input, options) {
|
|
529
|
-
return useAsync(scope, input.toString(), () => $fetch(scope, input, options), options);
|
|
530
|
-
}
|
|
531
|
-
async function createRuntime() {
|
|
532
|
-
const radix = new Radix();
|
|
533
|
-
const middlewares = new Array();
|
|
534
|
-
const routes = await useRoutes();
|
|
535
|
-
for (const path in routes) {
|
|
536
|
-
const [name, method] = toPath(path);
|
|
537
|
-
radix.insert((method ?? "GET").toUpperCase() + name, defineRoute({ fetch: async (scope) => {
|
|
538
|
-
const route = routes[path];
|
|
539
|
-
if (isRoute(route)) return route.fetch(scope);
|
|
540
|
-
const { states } = useRuntime(scope);
|
|
541
|
-
const content = await renderToString(scope, await import("#virtual/client").then((module) => module.client), { head: { children: ["<!--STATES-->"] } });
|
|
542
|
-
const entries = Object.entries(states).reduce((states$1, [name$1, state]) => {
|
|
543
|
-
return {
|
|
544
|
-
...states$1,
|
|
545
|
-
[name$1]: state.value
|
|
546
|
-
};
|
|
547
|
-
}, {});
|
|
548
|
-
return sendHtml(scope, content.replace("<!--STATES-->", await renderToString(scope, {
|
|
549
|
-
tag: "script",
|
|
550
|
-
attributes: {
|
|
551
|
-
id: "STATES",
|
|
552
|
-
type: "application/json"
|
|
553
|
-
},
|
|
554
|
-
children: [JSON.stringify(entries)]
|
|
555
|
-
})));
|
|
556
|
-
} }));
|
|
557
|
-
}
|
|
558
|
-
const assets = await useAssets();
|
|
559
|
-
for (const path in assets) radix.insert("GET/" + path, defineRoute({ fetch: async (scope) => {
|
|
560
|
-
const { response } = useRuntime(scope);
|
|
561
|
-
let content = assets[path];
|
|
562
|
-
if (content) {
|
|
563
|
-
if (path.endsWith(".png")) {
|
|
564
|
-
const [_, base64] = content.split(",");
|
|
565
|
-
const binary = atob(base64.replace(/-/g, "+").replace(/_/g, "/"));
|
|
566
|
-
const bytes = new Uint8Array(binary.length);
|
|
567
|
-
for (let index = 0; index < binary.length; index++) bytes[index] = binary.charCodeAt(index);
|
|
568
|
-
content = bytes;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
response.headers.set("Content-Type", mimeType(path));
|
|
572
|
-
return new Response(content, response);
|
|
573
|
-
} }));
|
|
574
|
-
const invoke = (scope, route, index) => {
|
|
575
|
-
return middlewares.at(index)?.fetch(scope, () => invoke(scope, route, index + 1)) ?? route.fetch(scope);
|
|
576
|
-
};
|
|
577
|
-
return {
|
|
578
|
-
radix,
|
|
579
|
-
middlewares,
|
|
580
|
-
fetch: async (scope) => {
|
|
581
|
-
const { request } = useRuntime(scope);
|
|
582
|
-
const { pathname } = useUrl(scope);
|
|
583
|
-
const { value: route, inputs } = radix.match(request.method + pathname);
|
|
584
|
-
try {
|
|
585
|
-
scope.setContext(ROUTE_CONTEXT, { inputs: createState(inputs) });
|
|
586
|
-
if (route) {
|
|
587
|
-
const response = await invoke(scope, route, 0);
|
|
588
|
-
if (response) return response;
|
|
589
|
-
}
|
|
590
|
-
return sendText(scope, "NOT_FOUND");
|
|
591
|
-
} catch (exception) {
|
|
592
|
-
if (exception instanceof Response) return exception;
|
|
593
|
-
throw exception;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
|
-
let STATES;
|
|
599
|
-
const RUNTIME_CONTEXT = defineContext("RUNTIME_CONTEXT");
|
|
600
|
-
const ROUTE_CONTEXT = defineContext("ROUTE_CONTEXT");
|
|
601
|
-
|
|
602
|
-
//#endregion
|
|
603
|
-
//#region src/html/index.ts
|
|
604
|
-
var MountedEvent = class extends Event {
|
|
253
|
+
//#region src/shared/index.ts
|
|
254
|
+
var StopEvent = class extends Event {
|
|
605
255
|
constructor() {
|
|
606
|
-
super("
|
|
256
|
+
super("stop");
|
|
607
257
|
}
|
|
608
258
|
};
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
}
|
|
618
|
-
function useHost(scope) {
|
|
619
|
-
return scope.getContext(HOST_CONTEXT);
|
|
620
|
-
}
|
|
621
|
-
function createElement(input, attributes, ...children) {
|
|
622
|
-
if (isComponent(input)) return {
|
|
623
|
-
tag: input.$name,
|
|
624
|
-
attributes: attributes ?? {},
|
|
625
|
-
children
|
|
626
|
-
};
|
|
627
|
-
if (typeof input === "string") return {
|
|
628
|
-
tag: input,
|
|
629
|
-
attributes: attributes ?? {},
|
|
630
|
-
children
|
|
631
|
-
};
|
|
632
|
-
return input?.({
|
|
633
|
-
...attributes,
|
|
634
|
-
children
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
function toString(slot) {
|
|
638
|
-
switch (typeof slot) {
|
|
639
|
-
case "string":
|
|
640
|
-
case "number":
|
|
641
|
-
case "bigint":
|
|
642
|
-
case "boolean":
|
|
643
|
-
case "symbol": return slot.toString();
|
|
644
|
-
case "object": return JSON.stringify(slot);
|
|
645
|
-
case "function": return toString(slot());
|
|
646
|
-
default: return "";
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
function toArray(hydration) {
|
|
650
|
-
if (Array.isArray(hydration)) return hydration.reduce((items, child) => items.concat(toArray(child)), []);
|
|
651
|
-
return [hydration];
|
|
652
|
-
}
|
|
653
|
-
function toRange(hydration) {
|
|
654
|
-
const items = toArray(hydration);
|
|
655
|
-
const range = document.createRange();
|
|
656
|
-
const firstNode = items.at(0);
|
|
657
|
-
if (firstNode) range.setStartBefore(firstNode);
|
|
658
|
-
const lastNode = items.at(-1);
|
|
659
|
-
if (lastNode) range.setEndAfter(lastNode);
|
|
660
|
-
return range;
|
|
661
|
-
}
|
|
662
|
-
function toFragment(hydration) {
|
|
663
|
-
return toArray(hydration).reduce((fragment, node) => {
|
|
664
|
-
fragment.appendChild(node);
|
|
665
|
-
return fragment;
|
|
666
|
-
}, document.createDocumentFragment());
|
|
667
|
-
}
|
|
668
|
-
function hydrate(scope, parentNode, slot, index, previous) {
|
|
669
|
-
let hydration = parentNode.childNodes.item(index);
|
|
670
|
-
if (Array.isArray(slot)) {
|
|
671
|
-
const items = new Array();
|
|
672
|
-
for (const [index$1, childSlot] of slot.entries()) items.push(hydrate(scope, parentNode, childSlot, index$1, previous));
|
|
673
|
-
if (items.length) hydration = items;
|
|
674
|
-
else if (previous || !(hydration instanceof Comment)) hydration = document.createComment("");
|
|
675
|
-
}
|
|
676
|
-
if (typeof slot === "function") {
|
|
677
|
-
let previous$1;
|
|
678
|
-
createCompute(scope, (scope$1) => {
|
|
679
|
-
let input = slot;
|
|
680
|
-
while (typeof input === "function") input = input();
|
|
681
|
-
hydration = hydrate(scope$1, parentNode, input, index, previous$1);
|
|
682
|
-
if (previous$1 && hydration !== previous$1) if (Array.isArray(hydration)) if (Array.isArray(previous$1)) {
|
|
683
|
-
const range = toRange(previous$1);
|
|
684
|
-
range.deleteContents();
|
|
685
|
-
range.collapse(true);
|
|
686
|
-
range.insertNode(toFragment(hydration));
|
|
687
|
-
} else if (parentNode.contains(previous$1)) parentNode.replaceChild(toFragment(hydration), previous$1);
|
|
688
|
-
else parentNode.replaceChild(toFragment(hydration), parentNode.childNodes.item(index));
|
|
689
|
-
else if (Array.isArray(previous$1)) {
|
|
690
|
-
const range = toRange(previous$1);
|
|
691
|
-
range.deleteContents();
|
|
692
|
-
range.collapse(true);
|
|
693
|
-
range.insertNode(hydration);
|
|
694
|
-
} else if (parentNode.contains(previous$1)) parentNode.replaceChild(hydration, previous$1);
|
|
695
|
-
else parentNode.replaceChild(hydration, parentNode.childNodes.item(index));
|
|
696
|
-
previous$1 = hydration;
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
if ((slot === null || slot === void 0) && (previous || !(hydration instanceof Comment))) hydration = document.createComment("");
|
|
700
|
-
if (typeof slot === "number" || typeof slot === "bigint" || typeof slot === "boolean" || typeof slot === "string" || typeof slot === "symbol") {
|
|
701
|
-
const textContent = slot.toString();
|
|
702
|
-
if (previous || !(hydration instanceof Text)) hydration = document.createTextNode(textContent);
|
|
703
|
-
else if (textContent !== hydration.textContent) hydration = parentNode.replaceChild(document.createTextNode(textContent), hydration);
|
|
704
|
-
}
|
|
705
|
-
if (isTemplate(slot)) {
|
|
706
|
-
const Component = components.get(slot.tag);
|
|
707
|
-
if (Component) registerComponent(Component);
|
|
708
|
-
if (previous || !(hydration instanceof Element && hydration.tagName.toUpperCase() === slot.tag.toUpperCase())) hydration = document.createElementNS(namespace(slot.tag), slot.tag);
|
|
709
|
-
for (const [name, value] of Object.entries(slot.attributes)) createCompute(scope, (scope$1) => {
|
|
710
|
-
const target = hydration;
|
|
711
|
-
if (name.startsWith("on")) {
|
|
712
|
-
const event = name.substring(2).toLowerCase();
|
|
713
|
-
useEvent(scope$1, target, event, value);
|
|
714
|
-
} else {
|
|
715
|
-
const set = toString(value);
|
|
716
|
-
if (set === "" || set === "false") return target.removeAttribute(name);
|
|
717
|
-
return target.setAttribute(name, set);
|
|
718
|
-
}
|
|
719
|
-
});
|
|
720
|
-
let index$1 = 0;
|
|
721
|
-
for (const childSlot of slot.children) {
|
|
722
|
-
const nodes = toArray(hydrate(scope, hydration, childSlot, index$1));
|
|
723
|
-
index$1 += nodes.length || 1;
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
hydration ??= document.createComment("");
|
|
727
|
-
if (parentNode.childNodes.item(index) === null) parentNode.appendChild(toFragment(hydration));
|
|
728
|
-
return hydration;
|
|
729
|
-
}
|
|
730
|
-
async function renderToString(scope, slot, defaults) {
|
|
731
|
-
const { tasks } = useRuntime(scope);
|
|
732
|
-
if (typeof slot === "number" || typeof slot === "bigint" || typeof slot === "boolean" || typeof slot === "string" || typeof slot === "symbol") return slot.toString();
|
|
733
|
-
if (typeof slot === "function") {
|
|
734
|
-
let input = slot;
|
|
735
|
-
while (typeof input === "function") input = await input();
|
|
736
|
-
return await renderToString(scope, input, defaults);
|
|
737
|
-
}
|
|
738
|
-
if (Array.isArray(slot)) {
|
|
739
|
-
let items = "";
|
|
740
|
-
for (const childSlot of slot) items += await renderToString(scope, childSlot, defaults);
|
|
741
|
-
if (items === "") return "<!---->";
|
|
742
|
-
return items;
|
|
743
|
-
}
|
|
744
|
-
if (isTemplate(slot)) {
|
|
745
|
-
const merge = mergeObjects(slot, defaults?.[slot.tag]);
|
|
746
|
-
const CustomElement = components.get(merge.tag);
|
|
747
|
-
const prefix = Object.entries(merge.attributes).reduce((chunks, [name, value]) => {
|
|
748
|
-
if (value && !name.startsWith("on")) chunks.push(`${name}='${toString(value)}'`);
|
|
749
|
-
return chunks;
|
|
750
|
-
}, [merge.tag]).join(" ");
|
|
751
|
-
let content = `<${prefix}>`;
|
|
752
|
-
if (CustomElement) {
|
|
753
|
-
const element = new CustomElement(merge.attributes, scope);
|
|
754
|
-
const result = element.setup();
|
|
755
|
-
while (tasks.length) await tasks.shift();
|
|
756
|
-
const template = await renderToString(element.scope, result, defaults);
|
|
757
|
-
if (element.shadowRoot) {
|
|
758
|
-
const shadow = {
|
|
759
|
-
tag: "template",
|
|
760
|
-
attributes: { shadowRootMode: element.shadowRoot.mode },
|
|
761
|
-
children: [template]
|
|
762
|
-
};
|
|
763
|
-
content += await renderToString(element.scope, shadow, defaults);
|
|
764
|
-
} else content += template;
|
|
765
|
-
}
|
|
766
|
-
for (const childSlot of merge.children) content += await renderToString(scope, childSlot, defaults);
|
|
767
|
-
content += `</${merge.tag}>`;
|
|
768
|
-
return content;
|
|
259
|
+
var Scope = class extends EventTarget {
|
|
260
|
+
parentScope;
|
|
261
|
+
context;
|
|
262
|
+
constructor(parentScope) {
|
|
263
|
+
super();
|
|
264
|
+
this.parentScope = parentScope;
|
|
265
|
+
this.parentScope?.onStop(() => this.stop());
|
|
266
|
+
this.context = {};
|
|
769
267
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
static $events = options.events ?? {};
|
|
776
|
-
static $attributes = options.attributes ?? {};
|
|
777
|
-
scope;
|
|
778
|
-
events;
|
|
779
|
-
attributes;
|
|
780
|
-
shadowRoot;
|
|
781
|
-
constructor(input, parentScope) {
|
|
782
|
-
this.scope = new Scope(parentScope);
|
|
783
|
-
this.events = Object.keys(options.events ?? {}).reduce((output, name) => {
|
|
784
|
-
Reflect.set(output, name, input?.[name], output);
|
|
785
|
-
return output;
|
|
786
|
-
}, {});
|
|
787
|
-
this.attributes = Object.entries(options.attributes ?? {}).reduce((attributes, [name, attribute]) => {
|
|
788
|
-
Reflect.set(attributes.value, name, fromValue(input?.[name]) ?? attribute.default, attributes.value);
|
|
789
|
-
return attributes;
|
|
790
|
-
}, createState({}));
|
|
791
|
-
this.shadowRoot = options.shadowRoot;
|
|
268
|
+
getContext(input) {
|
|
269
|
+
let scope = this;
|
|
270
|
+
while (scope) {
|
|
271
|
+
if (scope.context[input]) return scope.context[input];
|
|
272
|
+
scope = scope.parentScope;
|
|
792
273
|
}
|
|
793
|
-
|
|
274
|
+
return {};
|
|
794
275
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
function toCustomElement(Component) {
|
|
799
|
-
return class extends HTMLElement {
|
|
800
|
-
static formAssociated = true;
|
|
801
|
-
component;
|
|
802
|
-
constructor() {
|
|
803
|
-
super();
|
|
804
|
-
this.component = new Component();
|
|
805
|
-
this.component.scope.setContext(HOST_CONTEXT, {
|
|
806
|
-
host: this,
|
|
807
|
-
internals: this.attachInternals()
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
connectedCallback() {
|
|
811
|
-
let rootNode = this;
|
|
812
|
-
const findParentScope = (node) => {
|
|
813
|
-
if (node) {
|
|
814
|
-
if (isCustomElement(node)) return node.component.scope;
|
|
815
|
-
if (node instanceof ShadowRoot) return findParentScope(node.host);
|
|
816
|
-
return findParentScope(node.parentNode);
|
|
817
|
-
}
|
|
818
|
-
};
|
|
819
|
-
this.component.scope.parentScope = findParentScope(this.parentNode);
|
|
820
|
-
if (this.component.shadowRoot) rootNode = this.shadowRoot ?? this.attachShadow(this.component.shadowRoot);
|
|
821
|
-
for (const [name, event] of Object.entries(Component.$events)) Reflect.set(this.component.events, name, (value) => {
|
|
822
|
-
if (value instanceof Event) return;
|
|
823
|
-
this.dispatchEvent(new CustomEvent(name.substring(2).toLowerCase(), {
|
|
824
|
-
...event,
|
|
825
|
-
detail: value
|
|
826
|
-
}));
|
|
827
|
-
});
|
|
828
|
-
hydrate(this.component.scope, rootNode, untrack(this.component.setup), 0);
|
|
829
|
-
requestAnimationFrame(() => this.dispatchEvent(new MountedEvent()));
|
|
830
|
-
}
|
|
831
|
-
attributeChangedCallback(name, oldValue, value) {
|
|
832
|
-
if (value === oldValue) return;
|
|
833
|
-
const attribute = Component.$attributes?.[name];
|
|
834
|
-
if (attribute) {
|
|
835
|
-
let convertedValue;
|
|
836
|
-
if (value) switch (attribute.type) {
|
|
837
|
-
case String:
|
|
838
|
-
convertedValue = value;
|
|
839
|
-
break;
|
|
840
|
-
case Number:
|
|
841
|
-
convertedValue = Number(value);
|
|
842
|
-
break;
|
|
843
|
-
case Boolean:
|
|
844
|
-
convertedValue = value.toLowerCase() === "true";
|
|
845
|
-
break;
|
|
846
|
-
case Object:
|
|
847
|
-
convertedValue = JSON.parse(value);
|
|
848
|
-
break;
|
|
849
|
-
}
|
|
850
|
-
Reflect.set(this.component.attributes.value, name, convertedValue ?? attribute.default, this.component.attributes.value);
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
disconnectedCallback() {
|
|
854
|
-
this.component.scope.stop();
|
|
855
|
-
}
|
|
856
|
-
static get observedAttributes() {
|
|
857
|
-
return Object.keys(Component.$attributes ?? {});
|
|
858
|
-
}
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
|
-
function registerComponent(component) {
|
|
862
|
-
if (isClient()) {
|
|
863
|
-
const previous = customElements.get(component.$name);
|
|
864
|
-
if (previous === void 0) customElements.define(component.$name, toCustomElement(component));
|
|
276
|
+
setContext(input, value) {
|
|
277
|
+
this.context[input] = value;
|
|
865
278
|
}
|
|
866
|
-
|
|
867
|
-
}
|
|
868
|
-
function useEvent(scope, target, event, input, options) {
|
|
869
|
-
const controller = new AbortController();
|
|
870
|
-
target?.addEventListener(event, (event$1) => {
|
|
871
|
-
if (Array.isArray(input)) for (const target$1 of input) target$1?.(event$1);
|
|
872
|
-
else input?.(event$1);
|
|
873
|
-
}, {
|
|
874
|
-
signal: controller.signal,
|
|
875
|
-
...options
|
|
876
|
-
});
|
|
877
|
-
scope.onStop(() => controller.abort());
|
|
878
|
-
}
|
|
879
|
-
function onMounted(scope, event) {
|
|
880
|
-
if (isClient()) {
|
|
881
|
-
const { host } = useHost(scope);
|
|
882
|
-
useEvent(scope, host, "mounted", event);
|
|
279
|
+
onStop(input) {
|
|
280
|
+
this.addEventListener("stop", input, { once: true });
|
|
883
281
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
if (isClient() && document.startViewTransition !== void 0) {
|
|
887
|
-
await activeViewTransition.value?.update;
|
|
888
|
-
const update = document.startViewTransition(invoke).finished.finally(() => activeViewTransition.value = void 0);
|
|
889
|
-
activeViewTransition.value = {
|
|
890
|
-
name,
|
|
891
|
-
update
|
|
892
|
-
};
|
|
893
|
-
return update;
|
|
282
|
+
stop() {
|
|
283
|
+
return this.dispatchEvent(new StopEvent());
|
|
894
284
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
return () => {
|
|
899
|
-
if (activeViewTransition.value?.name === name && isClient()) return value instanceof Function ? value(name) : value;
|
|
900
|
-
};
|
|
285
|
+
};
|
|
286
|
+
function defineContext(name) {
|
|
287
|
+
return name;
|
|
901
288
|
}
|
|
902
289
|
function isClient() {
|
|
903
290
|
return typeof window !== "undefined";
|
|
@@ -905,140 +292,58 @@ function isClient() {
|
|
|
905
292
|
function isServer() {
|
|
906
293
|
return typeof window === "undefined";
|
|
907
294
|
}
|
|
908
|
-
function
|
|
909
|
-
|
|
910
|
-
}
|
|
911
|
-
function stopPropagation(event) {
|
|
912
|
-
event.stopPropagation();
|
|
295
|
+
function isFailure(result) {
|
|
296
|
+
return "issues" in result;
|
|
913
297
|
}
|
|
914
|
-
function
|
|
915
|
-
|
|
298
|
+
function parseSchema(scope, schema, value) {
|
|
299
|
+
const result = schema["~standard"].validate(value);
|
|
300
|
+
if (isFailure(result)) throw sendBadRequest(scope, result.issues.map((issue) => issue.message).join(", "));
|
|
301
|
+
return result.value;
|
|
916
302
|
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
const
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
};
|
|
928
|
-
var AfterNavigateEvent = class extends Event {
|
|
929
|
-
constructor() {
|
|
930
|
-
super("afterNavigate");
|
|
931
|
-
}
|
|
932
|
-
};
|
|
933
|
-
function provideRouterContext(scope, options) {
|
|
934
|
-
const url = createState();
|
|
935
|
-
const route = createState();
|
|
936
|
-
const radix = new Radix();
|
|
937
|
-
const navigator = new EventTarget();
|
|
938
|
-
for (const path in options.routes) {
|
|
939
|
-
const [name] = toPath(path);
|
|
940
|
-
if (name) {
|
|
941
|
-
const value = options.routes[path];
|
|
942
|
-
if (value) radix.insert(name, value);
|
|
943
|
-
}
|
|
303
|
+
function mergeObjects(base, input) {
|
|
304
|
+
if (input === null || input === void 0) return mergeObjects(base, {});
|
|
305
|
+
const object = structuredClone(input);
|
|
306
|
+
for (const key in base) {
|
|
307
|
+
if (key === "__proto__" || key === "constructor") continue;
|
|
308
|
+
const value = base[key];
|
|
309
|
+
if (value === null || value === void 0) continue;
|
|
310
|
+
if (Array.isArray(value) && Array.isArray(object[key])) object[key] = [...value, ...object[key]];
|
|
311
|
+
else if (typeof value === "object" && typeof object[key] === "object") object[key] = mergeObjects(value, object[key]);
|
|
312
|
+
else object[key] = value;
|
|
944
313
|
}
|
|
945
|
-
|
|
946
|
-
const { request } = useRuntime(scope);
|
|
947
|
-
const { inputs } = useRoute(scope);
|
|
948
|
-
var next = new URL(request?.url ?? window?.location.href);
|
|
949
|
-
if (next.toString() !== url.value?.toString()) {
|
|
950
|
-
const match = radix.match(next.pathname);
|
|
951
|
-
url.value = next;
|
|
952
|
-
inputs.value = match.inputs;
|
|
953
|
-
route.value = match.value;
|
|
954
|
-
navigator.dispatchEvent(new AfterNavigateEvent());
|
|
955
|
-
}
|
|
956
|
-
};
|
|
957
|
-
scope.setContext(ROUTE_CONTEXT, { inputs: createState() });
|
|
958
|
-
scope.setContext(ROUTER_CONTEXT, {
|
|
959
|
-
options,
|
|
960
|
-
navigator,
|
|
961
|
-
url,
|
|
962
|
-
radix,
|
|
963
|
-
route
|
|
964
|
-
});
|
|
965
|
-
fetch$1();
|
|
966
|
-
useEvent(scope, navigator, "navigate", () => startViewTransition("navigate", fetch$1));
|
|
967
|
-
if (isClient()) useEvent(scope, window, "popstate", fetch$1);
|
|
968
|
-
return useRouter(scope);
|
|
969
|
-
}
|
|
970
|
-
function useRouter(scope, context) {
|
|
971
|
-
const { url, route, navigator, options, radix } = scope.getContext(context ?? ROUTER_CONTEXT);
|
|
972
|
-
const navigate = (path) => {
|
|
973
|
-
if (isClient()) {
|
|
974
|
-
if (window.location.pathname != path) window.history.pushState(window.history.state, "", path);
|
|
975
|
-
navigator.dispatchEvent(new NavigateEvent());
|
|
976
|
-
}
|
|
977
|
-
if (isServer()) throw sendRedirect(scope, path);
|
|
978
|
-
};
|
|
979
|
-
const anchorNavigate = (event) => {
|
|
980
|
-
event.preventDefault();
|
|
981
|
-
navigate(event.currentTarget?.getAttribute("href") ?? "/");
|
|
982
|
-
};
|
|
983
|
-
return {
|
|
984
|
-
url,
|
|
985
|
-
route,
|
|
986
|
-
navigator,
|
|
987
|
-
options,
|
|
988
|
-
radix,
|
|
989
|
-
navigate,
|
|
990
|
-
anchorNavigate
|
|
991
|
-
};
|
|
314
|
+
return object;
|
|
992
315
|
}
|
|
993
|
-
const Page = defineComponent({
|
|
994
|
-
name: "x-page",
|
|
995
|
-
setup: ({ scope }) => {
|
|
996
|
-
const { route } = useRouter(scope);
|
|
997
|
-
return () => route.value;
|
|
998
|
-
}
|
|
999
|
-
});
|
|
1000
|
-
const ROUTER_CONTEXT = defineContext("ROUTER_CONTEXT");
|
|
1001
316
|
|
|
1002
317
|
//#endregion
|
|
1003
|
-
//#region src/
|
|
1004
|
-
function
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
318
|
+
//#region src/app/index.ts
|
|
319
|
+
function createApp(inputConfig) {
|
|
320
|
+
let config = mergeObjects(inputConfig, {
|
|
321
|
+
modules: [],
|
|
322
|
+
sources: {
|
|
323
|
+
assets: {
|
|
324
|
+
match: "**/*",
|
|
325
|
+
entries: ["./public"],
|
|
326
|
+
suffix: "?raw"
|
|
327
|
+
},
|
|
328
|
+
routes: {
|
|
329
|
+
match: "**/*.{js,ts}",
|
|
330
|
+
entries: ["./routes"]
|
|
331
|
+
},
|
|
332
|
+
middlewares: {
|
|
333
|
+
match: "**/*.{js,ts}",
|
|
334
|
+
entries: ["./middlewares"]
|
|
335
|
+
}
|
|
336
|
+
}
|
|
1021
337
|
});
|
|
1022
|
-
|
|
1023
|
-
}
|
|
1024
|
-
function useLocale(scope, context) {
|
|
1025
|
-
const { locale, messages, options } = scope.getContext(context ?? LOCALE_CONTEXT);
|
|
1026
|
-
const $ = (key) => {
|
|
1027
|
-
return () => messages.value?.[key] ?? key;
|
|
1028
|
-
};
|
|
1029
|
-
const $date = (date, options$1) => {
|
|
1030
|
-
const format = new Intl.DateTimeFormat(locale.value, options$1);
|
|
1031
|
-
if (date) return format.format(date);
|
|
1032
|
-
};
|
|
338
|
+
for (const module of config.modules) config = mergeObjects(config, module.config);
|
|
1033
339
|
return {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
$,
|
|
1038
|
-
$date
|
|
340
|
+
config,
|
|
341
|
+
virtuals: {},
|
|
342
|
+
alias: {}
|
|
1039
343
|
};
|
|
1040
344
|
}
|
|
1041
|
-
const
|
|
345
|
+
const SERVER = "ssr";
|
|
346
|
+
const CLIENT = "client";
|
|
1042
347
|
|
|
1043
348
|
//#endregion
|
|
1044
|
-
export {
|
|
349
|
+
export { CLIENT, PARAMETER, ROUTER_CONTEXT, Radix, Router, SERVER, SERVER_CONTEXT, Scope, StopEvent, WILDCARD, createApp, createServer, defineContext, defineMiddleware, defineRoute, isClient, isFailure, isServer, mergeObjects, mimeType, mimeTypes, parseSchema, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, toRoutePath, useCookies, useQuery, useServer, useSetCookies, useUrl };
|