hyperspan 1.0.0-alpha.7 → 1.0.0-alpha.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/package.json +4 -4
- package/src/index.ts +16 -4
- package/src/server.ts +86 -59
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hyperspan",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.9",
|
|
4
4
|
"description": "Hyperspan CLI - for @hyperspan/framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"public": true,
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"test": "bun test"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@hyperspan/framework": "^1.0.0-alpha
|
|
35
|
+
"@hyperspan/framework": "^1.0.0-alpha",
|
|
36
|
+
"bun-plugin-tailwind": "^0.1.2",
|
|
36
37
|
"commander": "^14.0.2",
|
|
37
38
|
"degit": "^2.8.4"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@types/bun": "^1.3.2",
|
|
41
42
|
"@types/degit": "^2.8.6",
|
|
42
|
-
"@types/node": "^24.10.0"
|
|
43
|
-
"bun-plugin-tailwind": "^0.1.2"
|
|
43
|
+
"@types/node": "^24.10.0"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/index.ts
CHANGED
|
@@ -43,9 +43,19 @@ program
|
|
|
43
43
|
*/
|
|
44
44
|
program
|
|
45
45
|
.command('start')
|
|
46
|
+
.alias('dev')
|
|
46
47
|
.option('--dir <path>', 'directory of your hyperspan project', './')
|
|
47
48
|
.description('Start the server')
|
|
48
|
-
.action(async (options)
|
|
49
|
+
.action(async function (options) {
|
|
50
|
+
|
|
51
|
+
const IS_DEV_MODE = process.argv.includes('dev');
|
|
52
|
+
|
|
53
|
+
// Developer mode (extra logging, etc.)
|
|
54
|
+
if (IS_DEV_MODE) {
|
|
55
|
+
console.log('[Hyperspan] Developer mode enabled 🛠️');
|
|
56
|
+
process.env.NODE_ENV = 'development';
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
// Ensure we are in a hyperspan project
|
|
50
60
|
const serverFile = `${options.dir}/app/routes`;
|
|
51
61
|
|
|
@@ -59,11 +69,13 @@ program
|
|
|
59
69
|
console.log('\n========================================');
|
|
60
70
|
console.log('[Hyperspan] Starting...');
|
|
61
71
|
|
|
62
|
-
const server = await startServer({ development:
|
|
72
|
+
const server = await startServer({ development: IS_DEV_MODE });
|
|
63
73
|
|
|
64
74
|
const routes: Record<string, (request: Request) => Promise<Response>> = {};
|
|
65
75
|
for (const route of server._routes) {
|
|
66
|
-
routes[route._path()] = (request: Request) =>
|
|
76
|
+
routes[route._path()] = (request: Request) => {
|
|
77
|
+
return route.fetch(request);
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
const httpServer = Bun.serve({
|
|
@@ -108,7 +120,7 @@ program
|
|
|
108
120
|
|
|
109
121
|
const server = await import(serverFile);
|
|
110
122
|
|
|
111
|
-
|
|
123
|
+
// @TODO: Build the project for SSG...
|
|
112
124
|
});
|
|
113
125
|
|
|
114
126
|
program.parse();
|
package/src/server.ts
CHANGED
|
@@ -59,81 +59,108 @@ export async function addDirectoryAsRoutes(
|
|
|
59
59
|
const buildDir = join(CWD, '.build');
|
|
60
60
|
const cssPublicDir = join(CWD, server._config.publicDir, CSS_PUBLIC_PATH);
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
try {
|
|
63
|
+
// Scan directory for TypeScript files
|
|
64
|
+
for await (const file of routesGlob.scan(directoryPath)) {
|
|
65
|
+
const filePath = join(directoryPath, file);
|
|
66
|
+
|
|
67
|
+
// Hidden directories and files start with a double underscore.
|
|
68
|
+
// These do not get added to the routes. Nothing nested under them gets added to the routes either.
|
|
69
|
+
if (filePath.includes('/__')) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
files.push(filePath);
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(`[Hyperspan] Directory not found: ${directoryPath}`);
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
const routeMap: { route: string; file: string }[] = [];
|
|
76
80
|
const routes: Array<HS.Route> = (await Promise.all(
|
|
77
81
|
files.map(async (filePath) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const module = await import(filePath);
|
|
83
|
-
const route = getRunnableRoute(module);
|
|
84
|
-
const parsedPath = parsePath(relativeFilePath);
|
|
85
|
-
|
|
86
|
-
// If route has a _path() method that returns a meaningful path, use it
|
|
87
|
-
// Otherwise, parse path from file path
|
|
88
|
-
let path = parsedPath.path;
|
|
89
|
-
if (typeof route._path === 'function') {
|
|
90
|
-
const routePath = route._path();
|
|
91
|
-
// If _path() returns a meaningful path (not just '/'), use it
|
|
92
|
-
if (routePath && routePath !== '/') {
|
|
93
|
-
path = routePath;
|
|
82
|
+
try {
|
|
83
|
+
const relativeFilePath = filePath.split(relativeAppPath).pop() || '';
|
|
84
|
+
if (!isValidRoutePath(relativeFilePath)) {
|
|
85
|
+
return null;
|
|
94
86
|
}
|
|
95
|
-
|
|
87
|
+
const module = await import(filePath);
|
|
96
88
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// Move CSS files to the public directory
|
|
113
|
-
for (const output of buildResult.outputs) {
|
|
114
|
-
if (output.path.endsWith('.css')) {
|
|
115
|
-
const cssFileName = output.path.split('/').pop()!;
|
|
116
|
-
await Bun.write(join(cssPublicDir, cssFileName), Bun.file(output.path));
|
|
117
|
-
cssFiles.push(cssFileName);
|
|
89
|
+
const route = getRunnableRoute(module);
|
|
90
|
+
|
|
91
|
+
const parsedPath = parsePath(relativeFilePath);
|
|
92
|
+
|
|
93
|
+
// If route has a _path() method that returns a meaningful path, use it
|
|
94
|
+
// Otherwise, parse path from file path
|
|
95
|
+
let path = parsedPath.path;
|
|
96
|
+
if (typeof route._path === 'function') {
|
|
97
|
+
const routePath = route._path();
|
|
98
|
+
// If _path() returns a meaningful path (not just '/'), use it
|
|
99
|
+
if (routePath && routePath !== '/') {
|
|
100
|
+
path = routePath;
|
|
101
|
+
}
|
|
118
102
|
}
|
|
119
|
-
}
|
|
120
103
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
route
|
|
124
|
-
|
|
104
|
+
let cssFiles: string[] = [];
|
|
105
|
+
|
|
106
|
+
// Build the route just for the CSS files (expensive, but easiest way to do CSS compilation by route)
|
|
107
|
+
// @TODO: Optimize this at some later date... This is O(n) for each route and doesn't scale well for large projects.
|
|
108
|
+
// @TODO: This will also currently re-compile the same CSS file(s) that are included in multiple routes, which is dumb.
|
|
109
|
+
const buildResult = await Bun.build({
|
|
110
|
+
plugins: [tailwind],
|
|
111
|
+
entrypoints: [filePath],
|
|
112
|
+
outdir: buildDir,
|
|
113
|
+
naming: `${relativeAppPath}/${path.endsWith('/') ? path + 'index' : path}-[hash].[ext]`,
|
|
114
|
+
minify: IS_PROD,
|
|
115
|
+
format: 'esm',
|
|
116
|
+
target: 'node',
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Move CSS files to the public directory
|
|
120
|
+
for (const output of buildResult.outputs) {
|
|
121
|
+
if (output.path.endsWith('.css')) {
|
|
122
|
+
const cssFileName = output.path.split('/').pop()!;
|
|
123
|
+
await Bun.write(join(cssPublicDir, cssFileName), Bun.file(output.path));
|
|
124
|
+
cssFiles.push(cssFileName);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
125
127
|
|
|
126
|
-
|
|
127
|
-
route._config.
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
// Set route path based on the file path (if not already set)
|
|
129
|
+
if (!route._config.path) {
|
|
130
|
+
route._config.path = path;
|
|
131
|
+
|
|
132
|
+
// Initialize params object if it doesn't exist
|
|
133
|
+
if (parsedPath.params.length > 0) {
|
|
134
|
+
const params = route._config.params ?? {};
|
|
135
|
+
parsedPath.params.forEach(param => {
|
|
136
|
+
params[param] = undefined;
|
|
137
|
+
});
|
|
138
|
+
route._config.params = params;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (cssFiles.length > 0) {
|
|
143
|
+
route._config.cssImports = cssFiles;
|
|
144
|
+
CSS_ROUTE_MAP.set(path, cssFiles);
|
|
145
|
+
}
|
|
130
146
|
|
|
131
|
-
|
|
147
|
+
routeMap.push({ route: path, file: filePath.replace(CWD, '') });
|
|
132
148
|
|
|
133
|
-
|
|
149
|
+
return route;
|
|
150
|
+
|
|
151
|
+
} catch (error) {
|
|
152
|
+
console.error(`[Hyperspan] Error loading route: ${filePath}`);
|
|
153
|
+
console.error(error);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
134
156
|
})
|
|
135
157
|
)).filter((route) => route !== null);
|
|
136
158
|
|
|
159
|
+
if (routeMap.length === 0) {
|
|
160
|
+
console.log(`[Hyperspan] No routes found in ${relativeDirectory}`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
137
164
|
if (startConfig.development) {
|
|
138
165
|
console.table(routeMap);
|
|
139
166
|
}
|