vorzelajs 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/README.md +188 -0
- package/bin/vorzelajs.mjs +2 -0
- package/dist/analytics.d.ts +132 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +690 -0
- package/dist/cli/build.d.ts +2 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +22 -0
- package/dist/cli/dev.d.ts +2 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/dev.js +93 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +29 -0
- package/dist/cli/serve.d.ts +2 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +43 -0
- package/dist/cookie.d.ts +33 -0
- package/dist/cookie.d.ts.map +1 -0
- package/dist/cookie.js +198 -0
- package/dist/debug/error-stack.d.ts +14 -0
- package/dist/debug/error-stack.d.ts.map +1 -0
- package/dist/debug/error-stack.js +52 -0
- package/dist/internal/document.d.ts +12 -0
- package/dist/internal/document.d.ts.map +1 -0
- package/dist/internal/document.jsx +56 -0
- package/dist/internal/entry-client.d.ts +2 -0
- package/dist/internal/entry-client.d.ts.map +1 -0
- package/dist/internal/entry-client.jsx +8 -0
- package/dist/internal/entry-server.d.ts +14 -0
- package/dist/internal/entry-server.d.ts.map +1 -0
- package/dist/internal/entry-server.jsx +71 -0
- package/dist/runtime/create-route.d.ts +8 -0
- package/dist/runtime/create-route.d.ts.map +1 -0
- package/dist/runtime/create-route.js +18 -0
- package/dist/runtime/head.d.ts +10 -0
- package/dist/runtime/head.d.ts.map +1 -0
- package/dist/runtime/head.js +111 -0
- package/dist/runtime/index.d.ts +6 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.jsx +4 -0
- package/dist/runtime/navigation.d.ts +36 -0
- package/dist/runtime/navigation.d.ts.map +1 -0
- package/dist/runtime/navigation.js +70 -0
- package/dist/runtime/path.d.ts +11 -0
- package/dist/runtime/path.d.ts.map +1 -0
- package/dist/runtime/path.js +80 -0
- package/dist/runtime/resolve.d.ts +11 -0
- package/dist/runtime/resolve.d.ts.map +1 -0
- package/dist/runtime/resolve.js +449 -0
- package/dist/runtime/runtime.d.ts +40 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/runtime.jsx +779 -0
- package/dist/runtime/search.d.ts +23 -0
- package/dist/runtime/search.d.ts.map +1 -0
- package/dist/runtime/search.js +178 -0
- package/dist/runtime/server.d.ts +10 -0
- package/dist/runtime/server.d.ts.map +1 -0
- package/dist/runtime/server.js +5 -0
- package/dist/runtime/types.d.ts +248 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +1 -0
- package/dist/seo.d.ts +16 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +69 -0
- package/dist/server/index.d.ts +53 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +268 -0
- package/dist/session.d.ts +23 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +58 -0
- package/dist/vite/index.d.ts +13 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +174 -0
- package/dist/vite/routes-plugin.d.ts +4 -0
- package/dist/vite/routes-plugin.d.ts.map +1 -0
- package/dist/vite/routes-plugin.js +345 -0
- package/dist/vite/server-only.d.ts +3 -0
- package/dist/vite/server-only.d.ts.map +1 -0
- package/dist/vite/server-only.js +342 -0
- package/package.json +76 -0
- package/templates/bare/README.md +22 -0
- package/templates/bare/src/components/counter-card.tsx +19 -0
- package/templates/bare/src/routes/__root.tsx +24 -0
- package/templates/bare/src/routes/index.tsx +36 -0
- package/templates/base/gitignore +4 -0
- package/templates/base/public/favicon.svg +5 -0
- package/templates/base/tsconfig.json +18 -0
- package/templates/modern/README.md +28 -0
- package/templates/modern/src/components/counter-card.tsx +19 -0
- package/templates/modern/src/routes/__root.tsx +42 -0
- package/templates/modern/src/routes/about.tsx +55 -0
- package/templates/modern/src/routes/index.tsx +51 -0
- package/templates/styling/css/styles.css +269 -0
- package/templates/styling/css-modules/styles.css +269 -0
- package/templates/styling/tailwind/styles.css +271 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { serveStatic } from '@hono/node-server/serve-static';
|
|
3
|
+
import { Hono } from 'hono';
|
|
4
|
+
import { DEFAULT_ANALYTICS_ENDPOINT, handleAnalyticsRequest } from '../analytics';
|
|
5
|
+
import { formatParsedStack, parseErrorStack } from '../debug/error-stack';
|
|
6
|
+
import { isRedirect } from '../runtime/navigation';
|
|
7
|
+
import { defaultRobotsConfig, renderRobotsTxt } from '../seo';
|
|
8
|
+
function logDevRequest(kind, request, status, startedAt, isProd, meta = {}) {
|
|
9
|
+
if (isProd)
|
|
10
|
+
return;
|
|
11
|
+
const url = new URL(request.url);
|
|
12
|
+
const duration = Date.now() - startedAt;
|
|
13
|
+
const suffix = Object.entries(meta)
|
|
14
|
+
.filter(([, value]) => value !== undefined && value !== null && value !== '')
|
|
15
|
+
.map(([key, value]) => `${key}=${String(value)}`)
|
|
16
|
+
.join(' ');
|
|
17
|
+
console.info(`[VorzelaJs][dev] ${kind.padEnd(9)} ${request.method.padEnd(6)} ${String(status).padStart(3)} ${url.pathname}${url.search} ${duration}ms${suffix ? ` ${suffix}` : ''}`);
|
|
18
|
+
}
|
|
19
|
+
function logDevError(scope, error, isProd, meta = {}) {
|
|
20
|
+
if (isProd)
|
|
21
|
+
return;
|
|
22
|
+
const parsedStack = parseErrorStack(error);
|
|
23
|
+
console.groupCollapsed(`[VorzelaJs][dev:${scope}] ${error instanceof Error ? error.message : 'Unexpected error'}`);
|
|
24
|
+
console.info(meta);
|
|
25
|
+
if (parsedStack) {
|
|
26
|
+
const lines = formatParsedStack(parsedStack);
|
|
27
|
+
if (lines.length > 0) {
|
|
28
|
+
console.info(lines.join('\n'));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
console.error(error);
|
|
32
|
+
console.groupEnd();
|
|
33
|
+
}
|
|
34
|
+
function escapeXml(value) {
|
|
35
|
+
return value
|
|
36
|
+
.replace(/&/gu, '&')
|
|
37
|
+
.replace(/</gu, '<')
|
|
38
|
+
.replace(/>/gu, '>')
|
|
39
|
+
.replace(/"/gu, '"')
|
|
40
|
+
.replace(/'/gu, ''');
|
|
41
|
+
}
|
|
42
|
+
export function createVorzelaApp(options) {
|
|
43
|
+
const { assets, isProd, loadEntry, staticRoot, vite } = options;
|
|
44
|
+
const app = new Hono();
|
|
45
|
+
// Static asset serving
|
|
46
|
+
if (isProd && staticRoot) {
|
|
47
|
+
app.use('/assets/*', serveStatic({ root: './dist/client' }));
|
|
48
|
+
app.use('/favicon.svg', serveStatic({ root: './dist/client' }));
|
|
49
|
+
}
|
|
50
|
+
if (!isProd) {
|
|
51
|
+
app.use('/favicon.svg', serveStatic({ root: './public' }));
|
|
52
|
+
}
|
|
53
|
+
const assetNotFound = (request) => {
|
|
54
|
+
const startedAt = Date.now();
|
|
55
|
+
logDevRequest('asset', request, 404, startedAt, isProd, { reason: 'missing-static-asset' });
|
|
56
|
+
return new Response('Asset Not Found', {
|
|
57
|
+
headers: {
|
|
58
|
+
'Cache-Control': 'no-store',
|
|
59
|
+
'Content-Type': 'text/plain; charset=utf-8',
|
|
60
|
+
},
|
|
61
|
+
status: 404,
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
if (isProd) {
|
|
65
|
+
app.all('/assets/*', (c) => assetNotFound(c.req.raw));
|
|
66
|
+
}
|
|
67
|
+
// Security headers
|
|
68
|
+
app.use('*', async (c, next) => {
|
|
69
|
+
const cspNonce = randomBytes(16).toString('base64');
|
|
70
|
+
c.set('cspNonce', cspNonce);
|
|
71
|
+
await next();
|
|
72
|
+
c.res.headers.set('X-Content-Type-Options', 'nosniff');
|
|
73
|
+
c.res.headers.set('X-Frame-Options', 'DENY');
|
|
74
|
+
c.res.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
75
|
+
c.res.headers.set('Cross-Origin-Opener-Policy', 'same-origin');
|
|
76
|
+
c.res.headers.set('Cross-Origin-Resource-Policy', 'same-origin');
|
|
77
|
+
c.res.headers.set('Permissions-Policy', 'accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()');
|
|
78
|
+
c.res.headers.set('X-Robots-Tag', 'index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1');
|
|
79
|
+
c.res.headers.set('Content-Security-Policy', isProd
|
|
80
|
+
? `default-src 'self'; script-src 'self' 'nonce-${cspNonce}'; style-src 'self'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'`
|
|
81
|
+
: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'");
|
|
82
|
+
if (isProd) {
|
|
83
|
+
c.res.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
// Favicon redirect
|
|
87
|
+
app.get('/favicon.ico', (c) => c.redirect('/favicon.svg', 302));
|
|
88
|
+
// Analytics
|
|
89
|
+
const analyticsHandler = async (request) => {
|
|
90
|
+
const startedAt = Date.now();
|
|
91
|
+
const entry = await loadEntry();
|
|
92
|
+
if (!entry.analytics) {
|
|
93
|
+
const response = new Response(JSON.stringify({ message: 'Not Found' }), {
|
|
94
|
+
headers: { 'Content-Type': 'application/json; charset=utf-8' },
|
|
95
|
+
status: 404,
|
|
96
|
+
});
|
|
97
|
+
logDevRequest('analytics', request, response.status, startedAt, isProd);
|
|
98
|
+
return response;
|
|
99
|
+
}
|
|
100
|
+
const response = await handleAnalyticsRequest(request, entry.analytics);
|
|
101
|
+
logDevRequest('analytics', request, response.status, startedAt, isProd);
|
|
102
|
+
return response;
|
|
103
|
+
};
|
|
104
|
+
app.options(DEFAULT_ANALYTICS_ENDPOINT, async (c) => analyticsHandler(c.req.raw));
|
|
105
|
+
app.post(DEFAULT_ANALYTICS_ENDPOINT, async (c) => analyticsHandler(c.req.raw));
|
|
106
|
+
// Robots.txt
|
|
107
|
+
app.get('/robots.txt', async (c) => {
|
|
108
|
+
const startedAt = Date.now();
|
|
109
|
+
const entry = await loadEntry();
|
|
110
|
+
const config = entry.robotsConfig ?? defaultRobotsConfig();
|
|
111
|
+
const body = renderRobotsTxt(config);
|
|
112
|
+
c.header('Content-Type', 'text/plain; charset=utf-8');
|
|
113
|
+
c.header('Cache-Control', 'public, max-age=3600');
|
|
114
|
+
logDevRequest('robots', c.req.raw, 200, startedAt, isProd);
|
|
115
|
+
return c.text(body);
|
|
116
|
+
});
|
|
117
|
+
// Sitemap
|
|
118
|
+
app.get('/sitemap.xml', async (c) => {
|
|
119
|
+
const startedAt = Date.now();
|
|
120
|
+
const entry = await loadEntry();
|
|
121
|
+
const entries = entry.getSitemapEntries ? await entry.getSitemapEntries() : [];
|
|
122
|
+
const items = entries.map((item) => {
|
|
123
|
+
const parts = [` <loc>${escapeXml(item.loc)}</loc>`];
|
|
124
|
+
if (item.lastmod)
|
|
125
|
+
parts.push(` <lastmod>${escapeXml(item.lastmod)}</lastmod>`);
|
|
126
|
+
if (item.changefreq)
|
|
127
|
+
parts.push(` <changefreq>${escapeXml(item.changefreq)}</changefreq>`);
|
|
128
|
+
if (item.priority !== undefined)
|
|
129
|
+
parts.push(` <priority>${item.priority}</priority>`);
|
|
130
|
+
return ` <url>\n${parts.join('\n')}\n </url>`;
|
|
131
|
+
});
|
|
132
|
+
const xml = [
|
|
133
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
134
|
+
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
135
|
+
...items,
|
|
136
|
+
'</urlset>',
|
|
137
|
+
].join('\n');
|
|
138
|
+
c.header('Content-Type', 'application/xml; charset=utf-8');
|
|
139
|
+
c.header('Cache-Control', 'public, max-age=3600');
|
|
140
|
+
logDevRequest('sitemap', c.req.raw, 200, startedAt, isProd, { entries: entries.length });
|
|
141
|
+
return c.text(xml);
|
|
142
|
+
});
|
|
143
|
+
// Payload endpoint (client navigation)
|
|
144
|
+
app.get('/__vorzela/payload', async (c) => {
|
|
145
|
+
const startedAt = Date.now();
|
|
146
|
+
const navigationHeader = c.req.header('X-Vorzela-Navigation');
|
|
147
|
+
if (navigationHeader !== 'payload') {
|
|
148
|
+
logDevRequest('payload', c.req.raw, 403, startedAt, isProd, { reason: 'missing-navigation-header' });
|
|
149
|
+
return c.json({ message: 'Forbidden' }, 403);
|
|
150
|
+
}
|
|
151
|
+
if (isProd) {
|
|
152
|
+
const origin = c.req.header('Origin');
|
|
153
|
+
const referer = c.req.header('Referer');
|
|
154
|
+
const host = c.req.header('Host');
|
|
155
|
+
if (origin) {
|
|
156
|
+
try {
|
|
157
|
+
const originHost = new URL(origin).host;
|
|
158
|
+
if (host && originHost !== host) {
|
|
159
|
+
logDevRequest('payload', c.req.raw, 403, startedAt, isProd, { reason: 'origin-mismatch' });
|
|
160
|
+
return c.json({ message: 'Forbidden' }, 403);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
logDevRequest('payload', c.req.raw, 403, startedAt, isProd, { reason: 'invalid-origin' });
|
|
165
|
+
return c.json({ message: 'Forbidden' }, 403);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else if (referer) {
|
|
169
|
+
try {
|
|
170
|
+
const refererHost = new URL(referer).host;
|
|
171
|
+
if (host && refererHost !== host) {
|
|
172
|
+
logDevRequest('payload', c.req.raw, 403, startedAt, isProd, { reason: 'referer-mismatch' });
|
|
173
|
+
return c.json({ message: 'Forbidden' }, 403);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
logDevRequest('payload', c.req.raw, 403, startedAt, isProd, { reason: 'invalid-referer' });
|
|
178
|
+
return c.json({ message: 'Forbidden' }, 403);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
logDevRequest('payload', c.req.raw, 403, startedAt, isProd, { reason: 'missing-origin-and-referer' });
|
|
183
|
+
return c.json({ message: 'Forbidden' }, 403);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const routePath = c.req.query('path') ?? '/';
|
|
188
|
+
const entry = await loadEntry();
|
|
189
|
+
const payload = await entry.renderPayload({
|
|
190
|
+
path: routePath,
|
|
191
|
+
request: c.req.raw,
|
|
192
|
+
});
|
|
193
|
+
c.header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0, private');
|
|
194
|
+
c.header('Pragma', 'no-cache');
|
|
195
|
+
c.header('Expires', '0');
|
|
196
|
+
if (payload.responseHeaders) {
|
|
197
|
+
for (const [key, value] of payload.responseHeaders) {
|
|
198
|
+
c.header(key, value, { append: true });
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const { responseHeaders: _, ...jsonPayload } = payload;
|
|
202
|
+
logDevRequest('payload', c.req.raw, payload.status, startedAt, isProd, {
|
|
203
|
+
path: routePath,
|
|
204
|
+
status: payload.status,
|
|
205
|
+
});
|
|
206
|
+
return c.json(jsonPayload, { status: payload.status });
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
if (isRedirect(error)) {
|
|
210
|
+
c.header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0, private');
|
|
211
|
+
c.header('Pragma', 'no-cache');
|
|
212
|
+
c.header('Expires', '0');
|
|
213
|
+
logDevRequest('payload', c.req.raw, error.status, startedAt, isProd, {
|
|
214
|
+
redirect: error.to,
|
|
215
|
+
});
|
|
216
|
+
return c.json({
|
|
217
|
+
redirect: {
|
|
218
|
+
replace: error.replace,
|
|
219
|
+
status: error.status,
|
|
220
|
+
to: error.to,
|
|
221
|
+
},
|
|
222
|
+
}, { status: error.status });
|
|
223
|
+
}
|
|
224
|
+
if (!isProd && vite) {
|
|
225
|
+
vite.ssrFixStacktrace(error);
|
|
226
|
+
}
|
|
227
|
+
logDevError('payload', error, isProd, {
|
|
228
|
+
path: c.req.query('path') ?? '/',
|
|
229
|
+
});
|
|
230
|
+
console.error(error);
|
|
231
|
+
c.header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0, private');
|
|
232
|
+
c.header('Pragma', 'no-cache');
|
|
233
|
+
c.header('Expires', '0');
|
|
234
|
+
logDevRequest('payload', c.req.raw, 500, startedAt, isProd);
|
|
235
|
+
return c.json({ message: 'Internal Server Error' }, 500);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
// Document SSR (catch-all)
|
|
239
|
+
app.get('*', async (c) => {
|
|
240
|
+
const startedAt = Date.now();
|
|
241
|
+
try {
|
|
242
|
+
const entry = await loadEntry();
|
|
243
|
+
const response = await entry.renderDocument({
|
|
244
|
+
request: c.req.raw,
|
|
245
|
+
assets,
|
|
246
|
+
nonce: c.get('cspNonce'),
|
|
247
|
+
});
|
|
248
|
+
logDevRequest('document', c.req.raw, response.status, startedAt, isProd);
|
|
249
|
+
return response;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
if (isRedirect(error)) {
|
|
253
|
+
logDevRequest('document', c.req.raw, error.status, startedAt, isProd, { redirect: error.to });
|
|
254
|
+
return c.redirect(error.to, error.status);
|
|
255
|
+
}
|
|
256
|
+
if (!isProd && vite) {
|
|
257
|
+
vite.ssrFixStacktrace(error);
|
|
258
|
+
}
|
|
259
|
+
logDevError('document', error, isProd, {
|
|
260
|
+
path: new URL(c.req.raw.url).pathname,
|
|
261
|
+
});
|
|
262
|
+
console.error(error);
|
|
263
|
+
logDevRequest('document', c.req.raw, 500, startedAt, isProd);
|
|
264
|
+
return c.text('Internal Server Error', 500);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
return app;
|
|
268
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CookieOptions, VorzelaCookie } from './cookie';
|
|
2
|
+
export interface SessionData {
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
}
|
|
5
|
+
export interface VorzelaSession {
|
|
6
|
+
data: SessionData;
|
|
7
|
+
get<T = unknown>(key: string): T | undefined;
|
|
8
|
+
has(key: string): boolean;
|
|
9
|
+
set(key: string, value: unknown): void;
|
|
10
|
+
unset(key: string): void;
|
|
11
|
+
flash(key: string, value: unknown): void;
|
|
12
|
+
}
|
|
13
|
+
export interface SessionStorage {
|
|
14
|
+
commitSession(session: VorzelaSession): Promise<string>;
|
|
15
|
+
destroySession(session: VorzelaSession): Promise<string>;
|
|
16
|
+
getSession(cookieHeader: string | null): Promise<VorzelaSession>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createCookieSessionStorage(options?: {
|
|
19
|
+
cookie?: VorzelaCookie | (CookieOptions & {
|
|
20
|
+
name?: string;
|
|
21
|
+
});
|
|
22
|
+
}): SessionStorage;
|
|
23
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAG5D,MAAM,WAAW,WAAW;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAA;IACjB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAA;IAC5C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;IACtC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACvD,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACxD,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;CACjE;AA0CD,wBAAgB,0BAA0B,CAAC,OAAO,GAAE;IAClD,MAAM,CAAC,EAAE,aAAa,GAAG,CAAC,aAAa,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACxD,GAAG,cAAc,CAiCtB"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createCookie } from './cookie';
|
|
2
|
+
const FLASH_PREFIX = '__flash_';
|
|
3
|
+
function createSession(data = {}) {
|
|
4
|
+
const sessionData = { ...data };
|
|
5
|
+
return {
|
|
6
|
+
get data() {
|
|
7
|
+
return { ...sessionData };
|
|
8
|
+
},
|
|
9
|
+
get(key) {
|
|
10
|
+
const flashKey = `${FLASH_PREFIX}${key}`;
|
|
11
|
+
if (flashKey in sessionData) {
|
|
12
|
+
const value = sessionData[flashKey];
|
|
13
|
+
delete sessionData[flashKey];
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
return sessionData[key];
|
|
17
|
+
},
|
|
18
|
+
has(key) {
|
|
19
|
+
return key in sessionData || `${FLASH_PREFIX}${key}` in sessionData;
|
|
20
|
+
},
|
|
21
|
+
set(key, value) {
|
|
22
|
+
sessionData[key] = value;
|
|
23
|
+
},
|
|
24
|
+
unset(key) {
|
|
25
|
+
delete sessionData[key];
|
|
26
|
+
},
|
|
27
|
+
flash(key, value) {
|
|
28
|
+
sessionData[`${FLASH_PREFIX}${key}`] = value;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function createCookieSessionStorage(options = {}) {
|
|
33
|
+
const cookie = options.cookie && 'parse' in options.cookie
|
|
34
|
+
? options.cookie
|
|
35
|
+
: createCookie(options.cookie?.name ?? '__session', options.cookie ?? {});
|
|
36
|
+
return {
|
|
37
|
+
async getSession(cookieHeader) {
|
|
38
|
+
const raw = await cookie.parse(cookieHeader);
|
|
39
|
+
if (!raw) {
|
|
40
|
+
return createSession();
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const data = JSON.parse(raw);
|
|
44
|
+
return createSession(data);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return createSession();
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
async commitSession(session) {
|
|
51
|
+
const serialized = JSON.stringify(session.data);
|
|
52
|
+
return cookie.serialize(serialized);
|
|
53
|
+
},
|
|
54
|
+
async destroySession(_session) {
|
|
55
|
+
return cookie.destroy();
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Plugin, UserConfig } from 'vite';
|
|
2
|
+
export interface VorzelaPluginOptions {
|
|
3
|
+
/** Override the Solid plugin. Pass `false` to disable auto-detection. */
|
|
4
|
+
solid?: false | Plugin;
|
|
5
|
+
/** Override the Tailwind plugin. Pass `false` to disable auto-detection. */
|
|
6
|
+
tailwind?: false | Plugin;
|
|
7
|
+
}
|
|
8
|
+
export declare function vorzelaPlugin(options?: VorzelaPluginOptions): Plugin[];
|
|
9
|
+
export declare function resolveVorzelaConfig(appRoot: string, options?: VorzelaPluginOptions): Promise<UserConfig>;
|
|
10
|
+
export declare function resolveVorzelalBuildConfig(appRoot: string, mode: 'client' | 'server'): UserConfig;
|
|
11
|
+
export { generateRoutes, vorzelaRoutesPlugin } from './routes-plugin';
|
|
12
|
+
export { vorzelaServerOnlyPlugin } from './server-only';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAiB9C,MAAM,WAAW,oBAAoB;IACnC,yEAAyE;IACzE,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;CAC1B;AAoFD,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,EAAE,CAO1E;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,UAAU,CAAC,CAoCrB;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ,GAAG,QAAQ,GACxB,UAAU,CAqCZ;AAED,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import url from 'node:url';
|
|
3
|
+
import { vorzelaRoutesPlugin } from './routes-plugin';
|
|
4
|
+
const VIRTUAL_ROUTES = 'virtual:vorzela/routes';
|
|
5
|
+
const VIRTUAL_HYDRATION = 'virtual:vorzela/hydration';
|
|
6
|
+
const VIRTUAL_STYLES = 'virtual:vorzela/styles';
|
|
7
|
+
const VIRTUAL_ENTRY_CLIENT = 'virtual:vorzela/entry-client';
|
|
8
|
+
const VIRTUAL_ENTRY_SERVER = 'virtual:vorzela/entry-server';
|
|
9
|
+
const RESOLVED_VIRTUAL_ROUTES = `\0${VIRTUAL_ROUTES}`;
|
|
10
|
+
const RESOLVED_VIRTUAL_HYDRATION = `\0${VIRTUAL_HYDRATION}`;
|
|
11
|
+
const RESOLVED_VIRTUAL_STYLES = `\0${VIRTUAL_STYLES}`;
|
|
12
|
+
const RESOLVED_VIRTUAL_ENTRY_CLIENT = `\0${VIRTUAL_ENTRY_CLIENT}`;
|
|
13
|
+
const RESOLVED_VIRTUAL_ENTRY_SERVER = `\0${VIRTUAL_ENTRY_SERVER}`;
|
|
14
|
+
function resolveFrameworkDir() {
|
|
15
|
+
const thisFile = url.fileURLToPath(import.meta.url);
|
|
16
|
+
// In built form: dist/vite/index.js -> dist/
|
|
17
|
+
// In source form: src/vite/index.ts -> src/
|
|
18
|
+
return path.resolve(path.dirname(thisFile), '..');
|
|
19
|
+
}
|
|
20
|
+
function tryRequirePlugin(name) {
|
|
21
|
+
try {
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
23
|
+
const mod = require(name);
|
|
24
|
+
return typeof mod === 'function' ? mod() : typeof mod.default === 'function' ? mod.default() : null;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function tryImportPlugin(name) {
|
|
31
|
+
try {
|
|
32
|
+
const mod = await import(name);
|
|
33
|
+
const fn = mod.default ?? mod;
|
|
34
|
+
return typeof fn === 'function' ? fn() : null;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function vorzelaVirtualModulesPlugin() {
|
|
41
|
+
let appRoot = process.cwd();
|
|
42
|
+
let frameworkDir = resolveFrameworkDir();
|
|
43
|
+
return {
|
|
44
|
+
name: 'vorzelajs-virtual-modules',
|
|
45
|
+
enforce: 'pre',
|
|
46
|
+
configResolved(config) {
|
|
47
|
+
appRoot = config.root;
|
|
48
|
+
},
|
|
49
|
+
resolveId(id) {
|
|
50
|
+
switch (id) {
|
|
51
|
+
case VIRTUAL_ROUTES:
|
|
52
|
+
return RESOLVED_VIRTUAL_ROUTES;
|
|
53
|
+
case VIRTUAL_HYDRATION:
|
|
54
|
+
return RESOLVED_VIRTUAL_HYDRATION;
|
|
55
|
+
case VIRTUAL_STYLES:
|
|
56
|
+
return RESOLVED_VIRTUAL_STYLES;
|
|
57
|
+
case VIRTUAL_ENTRY_CLIENT:
|
|
58
|
+
return RESOLVED_VIRTUAL_ENTRY_CLIENT;
|
|
59
|
+
case VIRTUAL_ENTRY_SERVER:
|
|
60
|
+
return RESOLVED_VIRTUAL_ENTRY_SERVER;
|
|
61
|
+
default:
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
load(id) {
|
|
66
|
+
switch (id) {
|
|
67
|
+
case RESOLVED_VIRTUAL_ROUTES: {
|
|
68
|
+
const routeTreePath = path.resolve(appRoot, 'src/routeTree.gen.ts');
|
|
69
|
+
return `export * from ${JSON.stringify(routeTreePath)}`;
|
|
70
|
+
}
|
|
71
|
+
case RESOLVED_VIRTUAL_HYDRATION: {
|
|
72
|
+
const hydrationPath = path.resolve(appRoot, 'src/routeHydration.gen.ts');
|
|
73
|
+
return `export * from ${JSON.stringify(hydrationPath)}`;
|
|
74
|
+
}
|
|
75
|
+
case RESOLVED_VIRTUAL_STYLES: {
|
|
76
|
+
const stylesPath = path.resolve(appRoot, 'src/styles.css');
|
|
77
|
+
return `import ${JSON.stringify(stylesPath)}`;
|
|
78
|
+
}
|
|
79
|
+
case RESOLVED_VIRTUAL_ENTRY_CLIENT: {
|
|
80
|
+
const entryPath = path.resolve(frameworkDir, 'internal/entry-client.tsx');
|
|
81
|
+
return `export * from ${JSON.stringify(entryPath)}`;
|
|
82
|
+
}
|
|
83
|
+
case RESOLVED_VIRTUAL_ENTRY_SERVER: {
|
|
84
|
+
const entryPath = path.resolve(frameworkDir, 'internal/entry-server.tsx');
|
|
85
|
+
return `export * from ${JSON.stringify(entryPath)}`;
|
|
86
|
+
}
|
|
87
|
+
default:
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export function vorzelaPlugin(options = {}) {
|
|
94
|
+
const plugins = [
|
|
95
|
+
vorzelaVirtualModulesPlugin(),
|
|
96
|
+
vorzelaRoutesPlugin(),
|
|
97
|
+
];
|
|
98
|
+
return plugins;
|
|
99
|
+
}
|
|
100
|
+
export async function resolveVorzelaConfig(appRoot, options = {}) {
|
|
101
|
+
const plugins = [...vorzelaPlugin(options)];
|
|
102
|
+
// Auto-detect Solid plugin
|
|
103
|
+
if (options.solid !== false) {
|
|
104
|
+
if (options.solid) {
|
|
105
|
+
plugins.push(options.solid);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const solidPlugin = await tryImportPlugin('vite-plugin-solid');
|
|
109
|
+
if (solidPlugin) {
|
|
110
|
+
plugins.push(solidPlugin);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Auto-detect Tailwind plugin
|
|
115
|
+
if (options.tailwind !== false) {
|
|
116
|
+
if (options.tailwind) {
|
|
117
|
+
plugins.push(options.tailwind);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const tailwindPlugin = await tryImportPlugin('@tailwindcss/vite');
|
|
121
|
+
if (tailwindPlugin) {
|
|
122
|
+
plugins.push(tailwindPlugin);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
root: appRoot,
|
|
128
|
+
resolve: {
|
|
129
|
+
alias: {
|
|
130
|
+
'~': path.resolve(appRoot, 'src'),
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
plugins,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export function resolveVorzelalBuildConfig(appRoot, mode) {
|
|
137
|
+
if (mode === 'server') {
|
|
138
|
+
return {
|
|
139
|
+
build: {
|
|
140
|
+
outDir: 'dist/server',
|
|
141
|
+
emptyOutDir: false,
|
|
142
|
+
copyPublicDir: false,
|
|
143
|
+
ssr: true,
|
|
144
|
+
rollupOptions: {
|
|
145
|
+
input: VIRTUAL_ENTRY_SERVER,
|
|
146
|
+
output: {
|
|
147
|
+
entryFileNames: 'entry-server.js',
|
|
148
|
+
chunkFileNames: 'chunks/[name]-[hash].js',
|
|
149
|
+
assetFileNames: 'assets/[name]-[hash][extname]',
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
build: {
|
|
157
|
+
cssCodeSplit: false,
|
|
158
|
+
outDir: 'dist/client',
|
|
159
|
+
emptyOutDir: true,
|
|
160
|
+
copyPublicDir: true,
|
|
161
|
+
manifest: true,
|
|
162
|
+
rollupOptions: {
|
|
163
|
+
input: VIRTUAL_ENTRY_CLIENT,
|
|
164
|
+
output: {
|
|
165
|
+
entryFileNames: 'assets/[name]-[hash].js',
|
|
166
|
+
chunkFileNames: 'assets/[name]-[hash].js',
|
|
167
|
+
assetFileNames: 'assets/[name]-[hash][extname]',
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
export { generateRoutes, vorzelaRoutesPlugin } from './routes-plugin';
|
|
174
|
+
export { vorzelaServerOnlyPlugin } from './server-only';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes-plugin.d.ts","sourceRoot":"","sources":["../../src/vite/routes-plugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AA+VlC,wBAAsB,cAAc,CAAC,WAAW,SAAgB,iBA2B/D;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CA2C5C"}
|