glashjs 0.13.0 → 0.13.2
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/bin/glash.mjs +20 -3
- package/package.json +1 -1
- package/src/server/server.mjs +17 -3
package/bin/glash.mjs
CHANGED
|
@@ -12,7 +12,10 @@ import { createProject } from '../src/create.mjs';
|
|
|
12
12
|
import { generateTypedRoutes } from '../src/typed-routes.mjs';
|
|
13
13
|
|
|
14
14
|
const VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
15
|
-
|
|
15
|
+
let [, , cmd, ...rest] = process.argv;
|
|
16
|
+
if (cmd === 'run') {
|
|
17
|
+
cmd = rest.shift() || 'dev';
|
|
18
|
+
}
|
|
16
19
|
|
|
17
20
|
function arg(name, fallback) {
|
|
18
21
|
const i = rest.indexOf(name);
|
|
@@ -55,11 +58,12 @@ function lanAddresses() {
|
|
|
55
58
|
async function serve(dev) {
|
|
56
59
|
const root = arg('--root', process.cwd());
|
|
57
60
|
const { listen, cfg, routes } = await createGlashServer({ root, dev });
|
|
58
|
-
const
|
|
59
|
-
await listen
|
|
61
|
+
const preferredPort = Number(arg('--port', cfg.port || 3000));
|
|
62
|
+
const port = await listenOnAvailablePort(listen, preferredPort);
|
|
60
63
|
const pages = routes.filter((r) => !r.isApi).length;
|
|
61
64
|
const apis = routes.filter((r) => r.isApi).length;
|
|
62
65
|
console.log(`\nglashjs ${dev ? 'dev' : 'serve'} — "${cfg.name}"`);
|
|
66
|
+
if (port !== preferredPort) console.log(` Port ${preferredPort} is in use; using ${port} instead.`);
|
|
63
67
|
console.log(` ${pages} page route(s), ${apis} api route(s)`);
|
|
64
68
|
routes.forEach((r) => console.log(` ${r.isApi ? 'api ' : 'page'} ${r.pattern}`));
|
|
65
69
|
console.log('');
|
|
@@ -69,6 +73,18 @@ async function serve(dev) {
|
|
|
69
73
|
console.log('');
|
|
70
74
|
}
|
|
71
75
|
|
|
76
|
+
async function listenOnAvailablePort(listen, preferredPort) {
|
|
77
|
+
for (let port = preferredPort; port < preferredPort + 20; port += 1) {
|
|
78
|
+
try {
|
|
79
|
+
await listen(port);
|
|
80
|
+
return port;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (error?.code !== 'EADDRINUSE') throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`No available port found from ${preferredPort} to ${preferredPort + 19}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
72
88
|
async function main() {
|
|
73
89
|
switch (cmd) {
|
|
74
90
|
case 'create':
|
|
@@ -144,6 +160,7 @@ async function main() {
|
|
|
144
160
|
console.log(`glashjs — fast, offline-capable, hard-to-hack sites
|
|
145
161
|
|
|
146
162
|
Usage: (run as "glashjs <cmd>"; "glash <cmd>" also works unless the glashdb deploy CLI owns that name)
|
|
163
|
+
glashjs run dev Alias for glashjs dev (also: glash run dev)
|
|
147
164
|
glashjs create [name] Create a new Glash project (interactive)
|
|
148
165
|
glashjs dev [--port 3000] Run the dev server (routing, SSR, API, live reload) + Network preview URL
|
|
149
166
|
glashjs serve [--port 3000] Run the production server over routes/ + built assets
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glashjs",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "glashjs — The Postgres-native full-stack framework for builders who want to ship without DevOps. Framework, hosting, database, auth, and deploy in one GlashDB-native runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/server/server.mjs
CHANGED
|
@@ -34,6 +34,7 @@ export async function createGlashServer({ root = process.cwd(), dev = false } =
|
|
|
34
34
|
const cfg = await loadConfig(root);
|
|
35
35
|
const routesDir = path.resolve(root, cfg.routesDir || 'routes');
|
|
36
36
|
const outDir = path.resolve(root, cfg.outDir);
|
|
37
|
+
const publicDir = path.resolve(root, cfg.publicDir || 'public');
|
|
37
38
|
const secHeaders = securityHeaders(cfg.security);
|
|
38
39
|
let routes = await discoverRoutes(routesDir);
|
|
39
40
|
|
|
@@ -72,6 +73,7 @@ export async function createGlashServer({ root = process.cwd(), dev = false } =
|
|
|
72
73
|
// Static first: in production this serves prebuilt /_glash/<id>.js bundles
|
|
73
74
|
// (written by `glash build`) — no runtime esbuild needed.
|
|
74
75
|
if (await serveStatic(res, outDir, pathname, req, secHeaders)) return;
|
|
76
|
+
if (dev && publicDir !== outDir && await serveStatic(res, publicDir, pathname, req, secHeaders)) return;
|
|
75
77
|
// Dynamic hydration bundles (dev, or when not prebuilt): /_glash/<routeId>.js
|
|
76
78
|
if (pathname.startsWith('/_glash/')) {
|
|
77
79
|
const id = pathname.slice('/_glash/'.length).replace(/\.js$/, '');
|
|
@@ -120,9 +122,21 @@ export async function createGlashServer({ root = process.cwd(), dev = false } =
|
|
|
120
122
|
});
|
|
121
123
|
|
|
122
124
|
const listen = (port = cfg.port || 3000, host = '0.0.0.0') =>
|
|
123
|
-
new Promise((resolve
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
new Promise((resolve, reject) => {
|
|
126
|
+
const onError = (error) => {
|
|
127
|
+
server.off('listening', onListening);
|
|
128
|
+
reject(error);
|
|
129
|
+
};
|
|
130
|
+
const onListening = () => {
|
|
131
|
+
server.off('error', onError);
|
|
132
|
+
resolve({ port, host });
|
|
133
|
+
};
|
|
134
|
+
server.once('error', onError);
|
|
135
|
+
server.once('listening', onListening);
|
|
136
|
+
server.listen(port, host);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return { server, listen, cfg, routes, routesDir, outDir, publicDir };
|
|
126
140
|
}
|
|
127
141
|
|
|
128
142
|
async function handleApi(res, mod, req, ctx, secHeaders) {
|