revojs 0.0.2 → 0.0.3
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/app/index.d.ts +24 -10
- package/dist/hooks/index.d.ts +8 -0
- package/dist/html/index.d.ts +27 -12
- package/dist/http/index.d.ts +37 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +457 -146
- package/dist/jsx/index.d.ts +362 -3
- package/dist/jsx/index.js +83 -1
- package/dist/presets/bun.js +6 -1
- package/dist/presets/cloudflare.d.ts +1 -1
- package/dist/presets/cloudflare.js +6 -1
- package/dist/router/index.d.ts +2 -3
- package/dist/runtime/index.d.ts +14 -15
- package/dist/signals/index.d.ts +23 -14
- package/package.json +3 -3
- package/dist/event/index.d.ts +0 -19
package/dist/index.js
CHANGED
|
@@ -1,118 +1,249 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { defu } from "defu";
|
|
2
2
|
import { h } from "revojs/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/app/index.ts
|
|
5
|
+
const defineContent = (key) => {
|
|
6
|
+
return Object.assign(String(key), { key });
|
|
7
|
+
};
|
|
5
8
|
const getContent = async (key) => {
|
|
6
|
-
return await import("#virtual/content").then((module) => module.index[key]);
|
|
9
|
+
return await import("#virtual/content").then((module) => module.index[key.toString()]);
|
|
7
10
|
};
|
|
8
11
|
const createApp = (config) => {
|
|
9
12
|
return {
|
|
10
|
-
config: defu
|
|
13
|
+
config: defu(config, {
|
|
11
14
|
client: { entry: "./index.html" },
|
|
12
15
|
server: { entry: "revojs/presets/node" },
|
|
13
16
|
content: {
|
|
14
|
-
|
|
17
|
+
[STATIC_CONTENT]: {
|
|
15
18
|
type: "static",
|
|
16
19
|
source: "./dist/client",
|
|
17
20
|
include: ["**/*.*"]
|
|
18
21
|
},
|
|
19
|
-
|
|
22
|
+
[PAGES_CONTENT]: {
|
|
20
23
|
type: "asset",
|
|
21
24
|
source: "./routes",
|
|
22
25
|
include: [
|
|
23
26
|
"**/*.js",
|
|
24
27
|
"**/*.ts",
|
|
25
28
|
"**/*.jsx",
|
|
26
|
-
"**/*.tsx"
|
|
29
|
+
"**/*.tsx",
|
|
30
|
+
"!**/*.*.js",
|
|
31
|
+
"!**/*.*.ts",
|
|
32
|
+
"!**/*.*.jsx",
|
|
33
|
+
"!**/*.*.tsx"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
[ROUTES_CONTENT]: {
|
|
37
|
+
type: "asset",
|
|
38
|
+
source: "./routes",
|
|
39
|
+
include: [
|
|
40
|
+
"**/*.*.js",
|
|
41
|
+
"**/*.*.ts",
|
|
42
|
+
"**/*.*.jsx",
|
|
43
|
+
"**/*.*.tsx"
|
|
27
44
|
]
|
|
28
45
|
}
|
|
29
46
|
},
|
|
30
|
-
markdown: {}
|
|
47
|
+
markdown: {},
|
|
48
|
+
dev: { middleware: [] }
|
|
31
49
|
}),
|
|
32
50
|
virtuals: {}
|
|
33
51
|
};
|
|
34
52
|
};
|
|
53
|
+
const STATIC_CONTENT = defineContent("STATIC");
|
|
54
|
+
const PAGES_CONTENT = defineContent("PAGES");
|
|
55
|
+
const ROUTES_CONTENT = defineContent("ROUTES");
|
|
35
56
|
|
|
36
57
|
//#endregion
|
|
37
|
-
//#region src/
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
//#region src/jsx/index.ts
|
|
59
|
+
const svgElements = new Set([
|
|
60
|
+
"altGlyph",
|
|
61
|
+
"altGlyphDef",
|
|
62
|
+
"altGlyphItem",
|
|
63
|
+
"animate",
|
|
64
|
+
"animateColor",
|
|
65
|
+
"animateMotion",
|
|
66
|
+
"animateTransform",
|
|
67
|
+
"circle",
|
|
68
|
+
"clipPath",
|
|
69
|
+
"color-profile",
|
|
70
|
+
"cursor",
|
|
71
|
+
"defs",
|
|
72
|
+
"desc",
|
|
73
|
+
"ellipse",
|
|
74
|
+
"feBlend",
|
|
75
|
+
"feColorMatrix",
|
|
76
|
+
"feComponentTransfer",
|
|
77
|
+
"feComposite",
|
|
78
|
+
"feConvolveMatrix",
|
|
79
|
+
"feDiffuseLighting",
|
|
80
|
+
"feDisplacementMap",
|
|
81
|
+
"feDistantLight",
|
|
82
|
+
"feDropShadow",
|
|
83
|
+
"feFlood",
|
|
84
|
+
"feFuncA",
|
|
85
|
+
"feFuncB",
|
|
86
|
+
"feFuncG",
|
|
87
|
+
"feFuncR",
|
|
88
|
+
"feGaussianBlur",
|
|
89
|
+
"feImage",
|
|
90
|
+
"feMerge",
|
|
91
|
+
"feMergeNode",
|
|
92
|
+
"feMorphology",
|
|
93
|
+
"feOffset",
|
|
94
|
+
"fePointLight",
|
|
95
|
+
"feSpecularLighting",
|
|
96
|
+
"feSpotLight",
|
|
97
|
+
"feTile",
|
|
98
|
+
"feTurbulence",
|
|
99
|
+
"filter",
|
|
100
|
+
"font",
|
|
101
|
+
"font-face",
|
|
102
|
+
"font-face-format",
|
|
103
|
+
"font-face-name",
|
|
104
|
+
"font-face-src",
|
|
105
|
+
"font-face-uri",
|
|
106
|
+
"foreignObject",
|
|
107
|
+
"g",
|
|
108
|
+
"glyph",
|
|
109
|
+
"glyphRef",
|
|
110
|
+
"hkern",
|
|
111
|
+
"image",
|
|
112
|
+
"line",
|
|
113
|
+
"linearGradient",
|
|
114
|
+
"marker",
|
|
115
|
+
"mask",
|
|
116
|
+
"metadata",
|
|
117
|
+
"missing-glyph",
|
|
118
|
+
"mpath",
|
|
119
|
+
"path",
|
|
120
|
+
"pattern",
|
|
121
|
+
"polygon",
|
|
122
|
+
"polyline",
|
|
123
|
+
"radialGradient",
|
|
124
|
+
"rect",
|
|
125
|
+
"set",
|
|
126
|
+
"stop",
|
|
127
|
+
"svg",
|
|
128
|
+
"switch",
|
|
129
|
+
"symbol",
|
|
130
|
+
"text",
|
|
131
|
+
"textPath",
|
|
132
|
+
"tref",
|
|
133
|
+
"tspan",
|
|
134
|
+
"use",
|
|
135
|
+
"view",
|
|
136
|
+
"vkern"
|
|
137
|
+
]);
|
|
138
|
+
const namespace = (tag) => {
|
|
139
|
+
return svgElements.has(tag) ? "http://www.w3.org/2000/svg" : "http://www.w3.org/1999/xhtml";
|
|
57
140
|
};
|
|
58
141
|
|
|
59
142
|
//#endregion
|
|
60
143
|
//#region src/signals/index.ts
|
|
144
|
+
var Scope = class {
|
|
145
|
+
dispose;
|
|
146
|
+
constructor() {
|
|
147
|
+
this.dispose = new Array();
|
|
148
|
+
}
|
|
149
|
+
run(invoke) {
|
|
150
|
+
let previous = activeScope;
|
|
151
|
+
activeScope = this;
|
|
152
|
+
try {
|
|
153
|
+
return invoke();
|
|
154
|
+
} finally {
|
|
155
|
+
activeScope = previous;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
stop() {
|
|
159
|
+
while (this.dispose.length) this.dispose.pop()?.(this);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
var Compute = class {
|
|
163
|
+
invoke;
|
|
164
|
+
scope;
|
|
165
|
+
constructor(invoke) {
|
|
166
|
+
this.invoke = invoke;
|
|
167
|
+
this.scope = new Scope();
|
|
168
|
+
}
|
|
169
|
+
run() {
|
|
170
|
+
this.scope.stop();
|
|
171
|
+
return this.scope.run(this.invoke);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
61
174
|
var Handler = class Handler {
|
|
62
|
-
get
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
175
|
+
get(target, key) {
|
|
176
|
+
const compute = activeCompute;
|
|
177
|
+
if (compute) {
|
|
178
|
+
const computes = targets.get(target) ?? new Map();
|
|
179
|
+
const set = computes.get(key) ?? new Set();
|
|
180
|
+
computes.set(key, set.add(compute));
|
|
181
|
+
targets.set(target, computes);
|
|
182
|
+
onCleanUp(() => {
|
|
183
|
+
compute.scope.stop();
|
|
184
|
+
set.delete(compute);
|
|
185
|
+
});
|
|
69
186
|
}
|
|
70
|
-
const value = Reflect.get(target,
|
|
71
|
-
if (value
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
set = (target, path, value) => {
|
|
75
|
-
const result = Reflect.set(target, path, value);
|
|
76
|
-
for (const effect of targets.get(target)?.get(path) ?? []) {
|
|
77
|
-
while (effect.cleanUps.length) effect.cleanUps.pop()?.(effect);
|
|
78
|
-
effect.invoke();
|
|
187
|
+
const value = Reflect.get(target, key);
|
|
188
|
+
if (value) {
|
|
189
|
+
if (typeof value === "function") return value.bind(target);
|
|
190
|
+
if (typeof value === "object") return new Proxy(value, new Handler());
|
|
79
191
|
}
|
|
192
|
+
return value;
|
|
193
|
+
}
|
|
194
|
+
set(target, key, value) {
|
|
195
|
+
const result = Reflect.set(target, key, value);
|
|
196
|
+
for (const compute of targets.get(target)?.get(key) ?? []) compute.run();
|
|
80
197
|
return result;
|
|
81
|
-
}
|
|
198
|
+
}
|
|
82
199
|
};
|
|
83
|
-
|
|
200
|
+
function createState(value) {
|
|
84
201
|
return new Proxy({ value }, new Handler());
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
cleanUps: []
|
|
90
|
-
});
|
|
91
|
-
};
|
|
92
|
-
const runCompute = (compute) => {
|
|
93
|
-
compute.previous = runningCompute;
|
|
94
|
-
runningCompute = compute;
|
|
202
|
+
}
|
|
203
|
+
function createCompute(invoke) {
|
|
204
|
+
let previous = activeCompute;
|
|
205
|
+
activeCompute = new Compute(invoke);
|
|
95
206
|
try {
|
|
96
|
-
return
|
|
207
|
+
return invoke();
|
|
97
208
|
} finally {
|
|
98
|
-
|
|
209
|
+
activeCompute = previous;
|
|
99
210
|
}
|
|
100
|
-
}
|
|
101
|
-
|
|
211
|
+
}
|
|
212
|
+
function createMemo(invoke) {
|
|
213
|
+
let state;
|
|
214
|
+
const compute = createCompute(() => {
|
|
215
|
+
const value = invoke();
|
|
216
|
+
if (typeof state === "object") state.value = value;
|
|
217
|
+
return value;
|
|
218
|
+
});
|
|
219
|
+
state = createState(compute);
|
|
220
|
+
return state;
|
|
221
|
+
}
|
|
222
|
+
function onCleanUp(invoke) {
|
|
223
|
+
activeScope?.dispose.push(invoke);
|
|
224
|
+
}
|
|
225
|
+
function fromValue(value) {
|
|
102
226
|
if (value) {
|
|
103
227
|
if (value instanceof Function) return fromValue(value());
|
|
104
228
|
if (value instanceof Object) return value.value;
|
|
105
229
|
}
|
|
106
230
|
return value;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
};
|
|
231
|
+
}
|
|
232
|
+
let activeScope;
|
|
233
|
+
let activeCompute;
|
|
111
234
|
const targets = new WeakMap();
|
|
112
|
-
let runningCompute;
|
|
113
235
|
|
|
114
236
|
//#endregion
|
|
115
237
|
//#region src/html/index.ts
|
|
238
|
+
const isTemplate = (value) => {
|
|
239
|
+
return "tag" in value && "attributes" in value && "children" in value;
|
|
240
|
+
};
|
|
241
|
+
const descriptor = (descriptor$1) => {
|
|
242
|
+
return (typeof descriptor$1 === "object" ? descriptor$1.key : descriptor$1).toString();
|
|
243
|
+
};
|
|
244
|
+
const defineContext = (description) => {
|
|
245
|
+
return { key: Symbol(description) };
|
|
246
|
+
};
|
|
116
247
|
const createElement = (input, attributes, ...children) => {
|
|
117
248
|
return {
|
|
118
249
|
tag: typeof input === "function" ? input.$name : input,
|
|
@@ -132,59 +263,85 @@ const toString = (slot) => {
|
|
|
132
263
|
default: return "";
|
|
133
264
|
}
|
|
134
265
|
};
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
266
|
+
const toFragment = (nodes) => {
|
|
267
|
+
const fragment = document.createDocumentFragment();
|
|
268
|
+
fragment.replaceChildren(...nodes);
|
|
269
|
+
return fragment;
|
|
270
|
+
};
|
|
271
|
+
const renderToString = async (slot, context) => {
|
|
272
|
+
if (typeof slot === "number" || typeof slot === "bigint" || typeof slot === "boolean" || typeof slot === "string" || typeof slot === "symbol") return slot.toString();
|
|
273
|
+
if (typeof slot === "function") return await renderToString(await slot(), context);
|
|
139
274
|
if (typeof slot === "object") {
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
275
|
+
if (Array.isArray(slot)) return await Promise.all(slot.map((slot$1) => renderToString(slot$1, context))).then((chunks) => chunks.join(""));
|
|
276
|
+
if (isTemplate(slot)) {
|
|
277
|
+
const customElement = components.get(slot.tag);
|
|
278
|
+
const prefix = Object.entries(slot.attributes).reduce((chunks, [name, value]) => {
|
|
279
|
+
if (!name.startsWith("on")) chunks.push(`${name}='${toString(value)}'`);
|
|
280
|
+
return chunks;
|
|
281
|
+
}, [slot.tag]).join(" ");
|
|
282
|
+
const children = await renderToString(slot.children, context);
|
|
283
|
+
if (customElement) {
|
|
284
|
+
const element = new customElement(slot.attributes, context);
|
|
285
|
+
const template = await renderToString(await element.setup(), context);
|
|
286
|
+
if (element.shadowRoot) {
|
|
287
|
+
const shadow = await renderToString({
|
|
288
|
+
tag: "template",
|
|
289
|
+
attributes: { shadowRootMode: element.shadowRoot.mode },
|
|
290
|
+
children: [template]
|
|
291
|
+
}, context);
|
|
292
|
+
return `<${prefix}>` + shadow + children + `</${slot.tag}>`;
|
|
293
|
+
}
|
|
294
|
+
return `<${prefix}>` + template + children + `</${slot.tag}>`;
|
|
151
295
|
}
|
|
152
|
-
return `<${prefix}
|
|
296
|
+
return `<${prefix}>` + children + `</${slot.tag}>`;
|
|
153
297
|
}
|
|
154
|
-
return
|
|
298
|
+
return JSON.stringify(slot);
|
|
155
299
|
}
|
|
156
|
-
return "";
|
|
300
|
+
return "<!---->";
|
|
157
301
|
};
|
|
158
|
-
const
|
|
159
|
-
if (Array.isArray(slot)) {
|
|
160
|
-
const fragment = document.createDocumentFragment();
|
|
161
|
-
fragment.replaceChildren(...await Promise.all(slot.map(slotToNode)));
|
|
162
|
-
return fragment;
|
|
163
|
-
}
|
|
302
|
+
const renderToNode = async (slot) => {
|
|
164
303
|
if (typeof slot === "number" || typeof slot === "bigint" || typeof slot === "boolean" || typeof slot === "string" || typeof slot === "symbol") return document.createTextNode(slot.toString());
|
|
165
304
|
if (typeof slot === "function") {
|
|
166
|
-
let
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
305
|
+
let node;
|
|
306
|
+
await createCompute(async () => {
|
|
307
|
+
let input = slot;
|
|
308
|
+
let parentNode = Array.isArray(node) ? node.at(0)?.parentNode : node?.parentNode;
|
|
309
|
+
while (typeof input === "function") input = await input();
|
|
310
|
+
let next = await (Array.isArray(input) ? Promise.all(input.map(renderToNode)) : renderToNode(input));
|
|
311
|
+
if (Array.isArray(next)) if (Array.isArray(node)) {
|
|
312
|
+
if (parentNode) {
|
|
313
|
+
const range = document.createRange();
|
|
314
|
+
const firstNode = node.at(0);
|
|
315
|
+
if (firstNode) range.setStartBefore(firstNode);
|
|
316
|
+
const lastNode = node.at(-1);
|
|
317
|
+
if (lastNode) range.setEndAfter(lastNode);
|
|
318
|
+
range.deleteContents();
|
|
319
|
+
for (const child of next) parentNode?.appendChild(child);
|
|
320
|
+
}
|
|
321
|
+
} else node?.parentNode?.replaceChild(toFragment(next), node);
|
|
322
|
+
else if (Array.isArray(node)) {} else node?.parentNode?.replaceChild(next, node);
|
|
323
|
+
node = next;
|
|
172
324
|
});
|
|
325
|
+
if (Array.isArray(node)) return toFragment(node);
|
|
326
|
+
return node ?? document.createComment("");
|
|
173
327
|
}
|
|
174
328
|
if (typeof slot === "object") {
|
|
175
|
-
if (
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
329
|
+
if (Array.isArray(slot)) return toFragment(await Promise.all(slot.map(renderToNode)));
|
|
330
|
+
if (isTemplate(slot)) {
|
|
331
|
+
const element = document.createElementNS(namespace(slot.tag), slot.tag);
|
|
332
|
+
for (const name in slot.attributes) {
|
|
333
|
+
const value = slot.attributes[name];
|
|
334
|
+
if (value) if (name.startsWith("on") && typeof value === "function") {
|
|
335
|
+
const event = name.substring(2).toLowerCase();
|
|
336
|
+
const controller = new AbortController();
|
|
337
|
+
element.addEventListener(event, value, { signal: controller.signal });
|
|
338
|
+
onCleanUp(() => controller.abort());
|
|
339
|
+
} else createCompute(() => element.setAttribute(name, toString(value)));
|
|
184
340
|
}
|
|
185
|
-
|
|
186
|
-
return
|
|
341
|
+
element.replaceChildren(await renderToNode(slot.children));
|
|
342
|
+
return element;
|
|
187
343
|
}
|
|
344
|
+
return document.createTextNode(JSON.stringify(slot));
|
|
188
345
|
}
|
|
189
346
|
return document.createComment("");
|
|
190
347
|
};
|
|
@@ -196,7 +353,8 @@ const defineComponent = (options) => {
|
|
|
196
353
|
events;
|
|
197
354
|
attributes;
|
|
198
355
|
shadowRoot;
|
|
199
|
-
|
|
356
|
+
context;
|
|
357
|
+
constructor(input, context) {
|
|
200
358
|
this.events = Object.keys(options.events ?? {}).reduce((output, name) => {
|
|
201
359
|
Reflect.set(output, name, input?.[name], output);
|
|
202
360
|
return output;
|
|
@@ -206,34 +364,48 @@ const defineComponent = (options) => {
|
|
|
206
364
|
return output;
|
|
207
365
|
}, createState({}));
|
|
208
366
|
this.shadowRoot = options.shadowRoot ?? { mode: "open" };
|
|
367
|
+
this.context = context ?? {};
|
|
209
368
|
}
|
|
369
|
+
getContext = (input) => {
|
|
370
|
+
return this.context[descriptor(input)];
|
|
371
|
+
};
|
|
372
|
+
setContext = (input, value) => {
|
|
373
|
+
this.context[descriptor(input)] = value;
|
|
374
|
+
};
|
|
210
375
|
setup = () => options.setup(this);
|
|
211
376
|
});
|
|
212
377
|
};
|
|
213
378
|
const toCustomElement = (component) => {
|
|
214
379
|
return class extends HTMLElement {
|
|
380
|
+
static formAssociated = true;
|
|
381
|
+
scope;
|
|
215
382
|
component;
|
|
216
383
|
constructor() {
|
|
217
384
|
super();
|
|
385
|
+
this.scope = new Scope();
|
|
218
386
|
this.component = new component();
|
|
219
387
|
}
|
|
220
388
|
async connectedCallback() {
|
|
221
389
|
let previous = activeElement;
|
|
390
|
+
const parentNode = getCustomElement(this.parentNode);
|
|
222
391
|
activeElement = this;
|
|
223
392
|
try {
|
|
224
393
|
const shadow = this.component.shadowRoot ? this.attachShadow(this.component.shadowRoot) : this;
|
|
225
394
|
for (const [name, event] of Object.entries(component.$events)) Reflect.set(this.component.events, name, (value) => {
|
|
395
|
+
if (value instanceof Event) return;
|
|
226
396
|
this.dispatchEvent(new CustomEvent(name.substring(2).toLowerCase(), {
|
|
227
397
|
...event,
|
|
228
398
|
detail: value
|
|
229
399
|
}));
|
|
230
400
|
}, this.component.events);
|
|
231
|
-
|
|
401
|
+
if (parentNode) for (const key in parentNode.component.context) this.component.setContext(key, parentNode.component.context[key]);
|
|
402
|
+
await this.scope.run(async () => shadow.replaceChildren(await renderToNode(await this.component.setup())));
|
|
232
403
|
} finally {
|
|
233
404
|
activeElement = previous;
|
|
234
405
|
}
|
|
235
406
|
}
|
|
236
|
-
attributeChangedCallback(name,
|
|
407
|
+
attributeChangedCallback(name, oldValue, value) {
|
|
408
|
+
if (value === oldValue) return;
|
|
237
409
|
const attribute = component.$attributes?.[name];
|
|
238
410
|
if (attribute) {
|
|
239
411
|
let convertedValue;
|
|
@@ -254,6 +426,9 @@ const toCustomElement = (component) => {
|
|
|
254
426
|
Reflect.set(this.component.attributes.value, name, convertedValue ?? attribute.default, this.component.attributes.value);
|
|
255
427
|
}
|
|
256
428
|
}
|
|
429
|
+
disconnectedCallback() {
|
|
430
|
+
this.scope.stop();
|
|
431
|
+
}
|
|
257
432
|
static get observedAttributes() {
|
|
258
433
|
return Object.keys(component.$attributes ?? {});
|
|
259
434
|
}
|
|
@@ -281,21 +456,121 @@ const getGlobalStyles = () => {
|
|
|
281
456
|
return sheet;
|
|
282
457
|
});
|
|
283
458
|
};
|
|
284
|
-
|
|
459
|
+
const getCustomElement = (node) => {
|
|
460
|
+
if (node) {
|
|
461
|
+
if ("component" in node) return node;
|
|
462
|
+
return getCustomElement(node.parentNode);
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
const preventDefault = (event) => {
|
|
466
|
+
event.preventDefault();
|
|
467
|
+
};
|
|
468
|
+
const stopPropagation = (event) => {
|
|
469
|
+
event.stopPropagation();
|
|
470
|
+
};
|
|
471
|
+
const stopImmediatePropagation = (event) => {
|
|
472
|
+
event.stopImmediatePropagation();
|
|
473
|
+
};
|
|
285
474
|
let activeElement;
|
|
286
475
|
const components = new Map();
|
|
287
476
|
|
|
477
|
+
//#endregion
|
|
478
|
+
//#region src/hooks/index.ts
|
|
479
|
+
var Hooks = class {
|
|
480
|
+
hooks;
|
|
481
|
+
constructor() {
|
|
482
|
+
this.hooks = new Map();
|
|
483
|
+
}
|
|
484
|
+
on = (input, invoke) => {
|
|
485
|
+
const key = descriptor(input);
|
|
486
|
+
const invokes = this.hooks.get(key) ?? new Set();
|
|
487
|
+
invokes.add(invoke);
|
|
488
|
+
this.hooks.set(key, invokes);
|
|
489
|
+
return onCleanUp(() => invokes.delete(invoke));
|
|
490
|
+
};
|
|
491
|
+
dispatch = (input, value) => {
|
|
492
|
+
const invokes = this.hooks.get(descriptor(input));
|
|
493
|
+
if (invokes) for (const invoke of invokes) invoke(value);
|
|
494
|
+
};
|
|
495
|
+
};
|
|
496
|
+
const defineHook = (description) => {
|
|
497
|
+
return { key: Symbol(description) };
|
|
498
|
+
};
|
|
499
|
+
|
|
288
500
|
//#endregion
|
|
289
501
|
//#region src/http/index.ts
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
502
|
+
const createEvent = (request, context) => {
|
|
503
|
+
return {
|
|
504
|
+
request,
|
|
505
|
+
response: { headers: new Headers() },
|
|
506
|
+
context
|
|
507
|
+
};
|
|
508
|
+
};
|
|
509
|
+
const sendText = (event, text) => {
|
|
510
|
+
event.response.headers.set("Content-Type", "text/plain");
|
|
511
|
+
return new Response(text, event.response);
|
|
512
|
+
};
|
|
513
|
+
const sendHtml = (event, text) => {
|
|
514
|
+
event.response.headers.set("Content-Type", "text/html");
|
|
515
|
+
return new Response(text, event.response);
|
|
516
|
+
};
|
|
517
|
+
const sendJson = (event, value) => {
|
|
518
|
+
event.response.headers.set("Content-Type", "application/json");
|
|
519
|
+
return new Response(JSON.stringify(value), event.response);
|
|
520
|
+
};
|
|
521
|
+
const sendRedirect = (event, path) => {
|
|
522
|
+
event.response.status = 302;
|
|
523
|
+
event.response.headers.set("Location", path);
|
|
524
|
+
return new Response(null, event.response);
|
|
525
|
+
};
|
|
526
|
+
const sendBadRequest = (event, text) => {
|
|
527
|
+
event.response.status = 400;
|
|
528
|
+
return new Response(text, event.response);
|
|
529
|
+
};
|
|
530
|
+
const sendUnauthorized = (event) => {
|
|
531
|
+
event.response.status = 401;
|
|
532
|
+
return new Response(null, event.response);
|
|
533
|
+
};
|
|
534
|
+
const getRequestUrl = (event) => {
|
|
535
|
+
return new URL(event instanceof Request ? event.url : event.request.url);
|
|
536
|
+
};
|
|
537
|
+
const getCookies = (event) => {
|
|
538
|
+
const cookies = event.request.headers.get("Cookie")?.split("; ") ?? [];
|
|
539
|
+
return cookies.reduce((result, cookie) => {
|
|
540
|
+
const [name, value] = cookie.split("=");
|
|
541
|
+
if (name && value) result[name] = decodeURIComponent(value);
|
|
542
|
+
return result;
|
|
543
|
+
}, {});
|
|
544
|
+
};
|
|
545
|
+
const getSetCookies = (event) => {
|
|
546
|
+
const cookies = event.request.headers.getSetCookie();
|
|
547
|
+
return cookies.reduce((result, cookie) => {
|
|
548
|
+
const [name, value] = cookie.split("=");
|
|
549
|
+
if (name && value) result[name] = decodeURIComponent(value);
|
|
550
|
+
return result;
|
|
551
|
+
}, {});
|
|
552
|
+
};
|
|
553
|
+
const setCookie = (event, name, value, options) => {
|
|
554
|
+
let cookie = name + "=" + encodeURIComponent(value);
|
|
555
|
+
if (options?.domain) cookie += `; Domain=${options.domain}`;
|
|
556
|
+
if (options?.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
557
|
+
if (options?.httpOnly) cookie += `; HttpOnly`;
|
|
558
|
+
if (options?.maxAge) cookie += `; Max-Age=${options.maxAge}`;
|
|
559
|
+
if (options?.path) cookie += `; Path=${options.path}`;
|
|
560
|
+
if (options?.priority) cookie += `; Priority=${options.priority}`;
|
|
561
|
+
if (options?.sameSite) cookie += `; SameSite=${options.sameSite}`;
|
|
562
|
+
if (options?.secure) cookie += `; Secure`;
|
|
563
|
+
event.response.headers.append("Set-Cookie", cookie);
|
|
294
564
|
};
|
|
295
565
|
const getMimeType = (file) => {
|
|
296
566
|
const extension = /\.([a-zA-Z0-9]+?)$/.exec(file)?.at(1);
|
|
297
567
|
return mimeTypes[extension ?? ""] ?? "text/plain";
|
|
298
568
|
};
|
|
569
|
+
const mimeTypes = {
|
|
570
|
+
css: "text/css",
|
|
571
|
+
js: "text/javascript",
|
|
572
|
+
txt: "text/plain"
|
|
573
|
+
};
|
|
299
574
|
|
|
300
575
|
//#endregion
|
|
301
576
|
//#region src/markdown/index.ts
|
|
@@ -435,47 +710,79 @@ var Radix = class Radix {
|
|
|
435
710
|
const defineRoute = (route) => {
|
|
436
711
|
return route;
|
|
437
712
|
};
|
|
438
|
-
const defineSocket = (socket) => {
|
|
439
|
-
return socket;
|
|
440
|
-
};
|
|
441
713
|
const fileName = (path) => {
|
|
442
714
|
return path.split("/").pop()?.split(".").slice(0, -1).join(".");
|
|
443
715
|
};
|
|
444
716
|
const toPath = (value) => {
|
|
445
|
-
|
|
717
|
+
const path = (value.startsWith("/") ? value : "/" + value).replaceAll(/\/index/g, "").replaceAll(/\[(.*)\]/g, (_, name) => ":" + name);
|
|
718
|
+
return (path.startsWith("/") ? path : "/" + path).split(".");
|
|
719
|
+
};
|
|
720
|
+
const $fetch = async (input, init) => {
|
|
721
|
+
let response;
|
|
722
|
+
if (activeEvent) {
|
|
723
|
+
const url = new URL(input.toString(), activeEvent.request.url);
|
|
724
|
+
response = await (await import("#virtual/runtime")).runtime.fetch(new Request(url, init), activeEvent.context);
|
|
725
|
+
} else response = await fetch(input, init);
|
|
726
|
+
if (response.ok === false) throw response;
|
|
727
|
+
switch (response.headers.get("Content-Type")) {
|
|
728
|
+
case "application/json": return response.json();
|
|
729
|
+
default: return response;
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
const getVariables = (event) => {
|
|
733
|
+
return event ? event.context.variables : import.meta.env;
|
|
446
734
|
};
|
|
447
735
|
const createRuntime = async () => {
|
|
448
736
|
const radix = new Radix();
|
|
449
|
-
const
|
|
737
|
+
const middlewares = new Array();
|
|
738
|
+
const assets = await getContent(STATIC_CONTENT);
|
|
450
739
|
for (const path in assets) radix.insert("GET/" + path, defineRoute({ fetch: async (event) => {
|
|
451
|
-
|
|
452
|
-
return
|
|
740
|
+
event.response.headers.set("Content-Type", getMimeType(path));
|
|
741
|
+
return new Response(await assets[path]?.(), event.response);
|
|
453
742
|
} }));
|
|
454
|
-
const
|
|
455
|
-
for (const path in
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
743
|
+
const pages = await getContent(PAGES_CONTENT);
|
|
744
|
+
for (const path in pages) {
|
|
745
|
+
const [name] = toPath(path);
|
|
746
|
+
radix.insert("GET" + name, defineRoute({ fetch: async (event) => {
|
|
747
|
+
const slot = await import("#virtual/client").then((module) => module.index);
|
|
748
|
+
return sendHtml(event, await renderToString(slot, {}));
|
|
749
|
+
} }));
|
|
750
|
+
}
|
|
751
|
+
const routes = await getContent(ROUTES_CONTENT);
|
|
752
|
+
for (const path in routes) {
|
|
753
|
+
const [name, method] = toPath(path);
|
|
754
|
+
radix.insert((method ?? "GET").toUpperCase() + name, defineRoute({ fetch: async (event) => {
|
|
755
|
+
const route = await routes[path]?.();
|
|
756
|
+
if (route) return route.fetch(event);
|
|
757
|
+
} }));
|
|
758
|
+
}
|
|
759
|
+
const invoke = (event, next, index) => {
|
|
760
|
+
return middlewares.at(index)?.(event, () => invoke(event, next, index + 1)) ?? next(event);
|
|
761
|
+
};
|
|
762
|
+
return {
|
|
763
|
+
radix,
|
|
764
|
+
middlewares,
|
|
765
|
+
fetch: async (request, context) => {
|
|
766
|
+
const url = getRequestUrl(request);
|
|
767
|
+
const { value: route, inputs } = radix.match(request.method + url.pathname);
|
|
768
|
+
activeEvent = createEvent(request, {
|
|
769
|
+
...context,
|
|
770
|
+
inputs
|
|
771
|
+
});
|
|
772
|
+
try {
|
|
773
|
+
if (route) {
|
|
774
|
+
const response = await invoke(activeEvent, route.fetch, 0);
|
|
775
|
+
if (response) return response;
|
|
776
|
+
}
|
|
777
|
+
return sendText(activeEvent, "Not found");
|
|
778
|
+
} catch (response) {
|
|
779
|
+
if (response instanceof Response) return response;
|
|
780
|
+
throw response;
|
|
781
|
+
} finally {
|
|
782
|
+
activeEvent = undefined;
|
|
462
783
|
}
|
|
463
|
-
return route.fetch(event);
|
|
464
784
|
}
|
|
465
|
-
}
|
|
466
|
-
return { fetch: async (request, context) => {
|
|
467
|
-
const url = new URL(request.url);
|
|
468
|
-
const { value: route, inputs } = radix.match(request.method + url.pathname);
|
|
469
|
-
activeEvent = createEvent(request, {
|
|
470
|
-
...context,
|
|
471
|
-
inputs
|
|
472
|
-
});
|
|
473
|
-
try {
|
|
474
|
-
return await route?.fetch(activeEvent) ?? sendText(activeEvent, "Not found");
|
|
475
|
-
} finally {
|
|
476
|
-
activeEvent = undefined;
|
|
477
|
-
}
|
|
478
|
-
} };
|
|
785
|
+
};
|
|
479
786
|
};
|
|
480
787
|
let activeEvent;
|
|
481
788
|
|
|
@@ -483,10 +790,14 @@ let activeEvent;
|
|
|
483
790
|
//#region src/router/index.tsx
|
|
484
791
|
const Outlet = defineComponent({
|
|
485
792
|
name: "x-outlet",
|
|
793
|
+
shadowRoot: false,
|
|
486
794
|
setup: async () => {
|
|
487
795
|
const radix = new Radix();
|
|
488
|
-
const routes = await getContent(
|
|
489
|
-
for (const path in routes)
|
|
796
|
+
const routes = await getContent(PAGES_CONTENT);
|
|
797
|
+
for (const path in routes) {
|
|
798
|
+
const [name] = toPath(path);
|
|
799
|
+
radix.insert(name, routes[path]);
|
|
800
|
+
}
|
|
490
801
|
const url = createState(new URL(activeEvent ? activeEvent.request.url : window.location.href));
|
|
491
802
|
if (isClient()) {
|
|
492
803
|
const controller = new AbortController();
|
|
@@ -513,4 +824,4 @@ const anchorNavigate = (event) => {
|
|
|
513
824
|
};
|
|
514
825
|
|
|
515
826
|
//#endregion
|
|
516
|
-
export { Handler, Outlet, Radix, activeElement, activeEvent, addStyles, anchorNavigate, components, createApp, createCompute, createElement, createEvent, createRuntime, createState, defineComponent, defineRoute,
|
|
827
|
+
export { $fetch, Compute, Handler, Hooks, Outlet, PAGES_CONTENT, ROUTES_CONTENT, Radix, STATIC_CONTENT, Scope, activeCompute, activeElement, activeEvent, activeScope, addStyles, anchorNavigate, components, createApp, createCompute, createElement, createEvent, createMemo, createRuntime, createState, defineComponent, defineContent, defineContext, defineHook, defineRoute, descriptor, fileName, fromValue, getContent, getCookies, getCustomElement, getGlobalStyles, getMimeType, getRequestUrl, getSetCookies, getVariables, isClient, isServer, isTemplate, markdownToSlot, navigate, onCleanUp, preventDefault, registerComponent, renderToNode, renderToString, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, stopImmediatePropagation, stopPropagation, targets, toCustomElement, toFragment, toPath, toString };
|