zero-query 0.9.7 → 0.9.9
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 +55 -4
- package/cli/commands/build.js +50 -3
- package/cli/commands/create.js +58 -11
- package/cli/help.js +4 -0
- package/cli/scaffold/default/app/app.js +211 -0
- package/cli/scaffold/default/app/components/about.js +201 -0
- package/cli/scaffold/default/app/components/api-demo.js +143 -0
- package/cli/scaffold/default/app/components/contact-card.js +231 -0
- package/cli/scaffold/default/app/components/contacts/contacts.css +706 -0
- package/cli/scaffold/default/app/components/contacts/contacts.html +200 -0
- package/cli/scaffold/default/app/components/contacts/contacts.js +196 -0
- package/cli/scaffold/default/app/components/counter.js +127 -0
- package/cli/scaffold/default/app/components/home.js +249 -0
- package/cli/scaffold/{app → default/app}/components/not-found.js +2 -2
- package/cli/scaffold/default/app/components/playground/playground.css +116 -0
- package/cli/scaffold/default/app/components/playground/playground.html +162 -0
- package/cli/scaffold/default/app/components/playground/playground.js +117 -0
- package/cli/scaffold/default/app/components/todos.js +225 -0
- package/cli/scaffold/default/app/components/toolkit/toolkit.css +97 -0
- package/cli/scaffold/default/app/components/toolkit/toolkit.html +146 -0
- package/cli/scaffold/default/app/components/toolkit/toolkit.js +280 -0
- package/cli/scaffold/default/app/routes.js +15 -0
- package/cli/scaffold/{app → default/app}/store.js +15 -10
- package/cli/scaffold/{global.css → default/global.css} +238 -252
- package/cli/scaffold/{index.html → default/index.html} +35 -0
- package/cli/scaffold/{app → minimal/app}/app.js +37 -39
- package/cli/scaffold/minimal/app/components/about.js +68 -0
- package/cli/scaffold/minimal/app/components/counter.js +122 -0
- package/cli/scaffold/minimal/app/components/home.js +68 -0
- package/cli/scaffold/minimal/app/components/not-found.js +16 -0
- package/cli/scaffold/minimal/app/routes.js +9 -0
- package/cli/scaffold/minimal/app/store.js +36 -0
- package/cli/scaffold/minimal/assets/.gitkeep +0 -0
- package/cli/scaffold/minimal/global.css +291 -0
- package/cli/scaffold/minimal/index.html +44 -0
- package/cli/scaffold/ssr/app/app.js +30 -0
- package/cli/scaffold/ssr/app/components/about.js +28 -0
- package/cli/scaffold/ssr/app/components/home.js +37 -0
- package/cli/scaffold/ssr/app/components/not-found.js +15 -0
- package/cli/scaffold/ssr/app/routes.js +6 -0
- package/cli/scaffold/ssr/global.css +113 -0
- package/cli/scaffold/ssr/index.html +31 -0
- package/cli/scaffold/ssr/package.json +8 -0
- package/cli/scaffold/ssr/server/index.js +118 -0
- package/dist/zquery.dist.zip +0 -0
- package/dist/zquery.js +2006 -1933
- package/dist/zquery.min.js +2 -2
- package/index.d.ts +20 -1
- package/index.js +8 -5
- package/package.json +8 -2
- package/src/component.js +6 -3
- package/src/diff.js +15 -2
- package/src/errors.js +59 -5
- package/src/package.json +1 -0
- package/src/ssr.js +116 -22
- package/tests/cli.test.js +304 -0
- package/tests/errors.test.js +423 -145
- package/tests/ssr.test.js +435 -3
- package/types/errors.d.ts +34 -2
- package/types/ssr.d.ts +21 -1
- package/cli/scaffold/app/components/about.js +0 -131
- package/cli/scaffold/app/components/api-demo.js +0 -103
- package/cli/scaffold/app/components/contacts/contacts.css +0 -246
- package/cli/scaffold/app/components/contacts/contacts.html +0 -140
- package/cli/scaffold/app/components/contacts/contacts.js +0 -153
- package/cli/scaffold/app/components/counter.js +0 -85
- package/cli/scaffold/app/components/home.js +0 -137
- package/cli/scaffold/app/components/todos.js +0 -131
- package/cli/scaffold/app/routes.js +0 -13
- /package/cli/scaffold/{LICENSE → default/LICENSE} +0 -0
- /package/cli/scaffold/{assets → default/assets}/.gitkeep +0 -0
- /package/cli/scaffold/{favicon.ico → default/favicon.ico} +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// server/index.js — SSR HTTP server
|
|
2
|
+
//
|
|
3
|
+
// Renders routes to HTML with zQuery SSR and serves them over HTTP.
|
|
4
|
+
// Components are imported from app/components/ — the same definitions
|
|
5
|
+
// the client uses.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// node server/index.js
|
|
9
|
+
// PORT=8080 node server/index.js
|
|
10
|
+
|
|
11
|
+
import { createServer } from 'node:http';
|
|
12
|
+
import { readFile } from 'node:fs/promises';
|
|
13
|
+
import { join, extname, resolve } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { createSSRApp } from 'zero-query/ssr';
|
|
16
|
+
|
|
17
|
+
// Shared component definitions — same ones the client registers
|
|
18
|
+
import { homePage } from '../app/components/home.js';
|
|
19
|
+
import { aboutPage } from '../app/components/about.js';
|
|
20
|
+
import { notFound } from '../app/components/not-found.js';
|
|
21
|
+
import { routes } from '../app/routes.js';
|
|
22
|
+
|
|
23
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
24
|
+
const ROOT = join(__dirname, '..');
|
|
25
|
+
const PORT = parseInt(process.env.PORT || '3000', 10);
|
|
26
|
+
|
|
27
|
+
// --- SSR app ----------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
const app = createSSRApp();
|
|
30
|
+
app.component('home-page', homePage);
|
|
31
|
+
app.component('about-page', aboutPage);
|
|
32
|
+
app.component('not-found', notFound);
|
|
33
|
+
|
|
34
|
+
// --- Route matching ---------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
function matchRoute(pathname) {
|
|
37
|
+
const route = routes.find(r => r.path === pathname);
|
|
38
|
+
return route ? route.component : 'not-found';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// --- Render a full HTML page ------------------------------------------------
|
|
42
|
+
|
|
43
|
+
async function render(pathname) {
|
|
44
|
+
const component = matchRoute(pathname);
|
|
45
|
+
const body = await app.renderToString(component);
|
|
46
|
+
|
|
47
|
+
return `<!DOCTYPE html>
|
|
48
|
+
<html lang="en">
|
|
49
|
+
<head>
|
|
50
|
+
<meta charset="UTF-8">
|
|
51
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
52
|
+
<title>{{NAME}}</title>
|
|
53
|
+
<link rel="stylesheet" href="/global.css">
|
|
54
|
+
</head>
|
|
55
|
+
<body>
|
|
56
|
+
<nav class="navbar">
|
|
57
|
+
<span class="brand">⚡ {{NAME}}</span>
|
|
58
|
+
<div class="nav-links">
|
|
59
|
+
${routes.map(r =>
|
|
60
|
+
` <a href="${r.path}" class="nav-link${r.path === pathname ? ' active' : ''}">${
|
|
61
|
+
r.path === '/' ? 'Home' : r.path.slice(1)[0].toUpperCase() + r.path.slice(2)
|
|
62
|
+
}</a>`).join('\n')}
|
|
63
|
+
</div>
|
|
64
|
+
</nav>
|
|
65
|
+
<main id="app">${body}</main>
|
|
66
|
+
<footer class="footer"><small>Built with zQuery · SSR</small></footer>
|
|
67
|
+
</body>
|
|
68
|
+
</html>`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// --- Static files -----------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
const MIME = {
|
|
74
|
+
'.css': 'text/css', '.js': 'text/javascript', '.json': 'application/json',
|
|
75
|
+
'.png': 'image/png', '.jpg': 'image/jpeg', '.svg': 'image/svg+xml',
|
|
76
|
+
'.ico': 'image/x-icon', '.woff2': 'font/woff2',
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
async function serveStatic(res, pathname) {
|
|
80
|
+
const ext = extname(pathname);
|
|
81
|
+
if (!MIME[ext]) return false;
|
|
82
|
+
|
|
83
|
+
const filePath = join(ROOT, pathname);
|
|
84
|
+
if (!resolve(filePath).startsWith(resolve(ROOT))) return false;
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const data = await readFile(filePath);
|
|
88
|
+
res.writeHead(200, { 'Content-Type': MIME[ext] });
|
|
89
|
+
res.end(data);
|
|
90
|
+
return true;
|
|
91
|
+
} catch { return false; }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// --- HTTP server ------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
createServer(async (req, res) => {
|
|
97
|
+
const { pathname } = new URL(req.url, `http://localhost:${PORT}`);
|
|
98
|
+
|
|
99
|
+
// Static assets (CSS, images, etc.)
|
|
100
|
+
if (pathname !== '/' && await serveStatic(res, pathname)) return;
|
|
101
|
+
|
|
102
|
+
// SSR route
|
|
103
|
+
try {
|
|
104
|
+
const html = await render(pathname);
|
|
105
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
106
|
+
res.end(html);
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error('SSR error:', err);
|
|
109
|
+
if (!res.headersSent) {
|
|
110
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
111
|
+
}
|
|
112
|
+
res.end('Internal Server Error');
|
|
113
|
+
}
|
|
114
|
+
}).listen(PORT, () => {
|
|
115
|
+
console.log(`\n ⚡ SSR server → http://localhost:${PORT}\n`);
|
|
116
|
+
routes.forEach(r => console.log(` ${r.path.padEnd(10)} → ${r.component}`));
|
|
117
|
+
console.log(` * → not-found\n`);
|
|
118
|
+
});
|
package/dist/zquery.dist.zip
CHANGED
|
Binary file
|