@hyperspan/framework 1.0.0-alpha.5 → 1.0.0-alpha.7
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 +1 -5
- package/src/index.ts +1 -1
- package/src/server.ts +1 -60
- package/src/utils.ts +61 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperspan/framework",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.7",
|
|
4
4
|
"description": "Hyperspan Web Framework",
|
|
5
5
|
"main": "src/server.ts",
|
|
6
6
|
"types": "src/server.ts",
|
|
@@ -21,10 +21,6 @@
|
|
|
21
21
|
"types": "./src/middleware.ts",
|
|
22
22
|
"default": "./src/middleware.ts"
|
|
23
23
|
},
|
|
24
|
-
"./middleware/zod": {
|
|
25
|
-
"types": "./src/middleware/zod.ts",
|
|
26
|
-
"default": "./src/middleware/zod.ts"
|
|
27
|
-
},
|
|
28
24
|
"./utils": {
|
|
29
25
|
"types": "./src/utils.ts",
|
|
30
26
|
"default": "./src/utils.ts"
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createConfig, createContext, createRoute, createServer, getRunnableRoute, StreamResponse } from './server';
|
|
1
|
+
export { createConfig, createContext, createRoute, createServer, getRunnableRoute, StreamResponse, IS_PROD } from './server';
|
|
2
2
|
export type { Hyperspan } from './types';
|
package/src/server.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { HSHtml, html, isHSHtml, renderStream, renderAsync, render } from '@hype
|
|
|
2
2
|
import { executeMiddleware } from './middleware';
|
|
3
3
|
import type { Hyperspan as HS } from './types';
|
|
4
4
|
import { clientJSPlugin } from './plugins';
|
|
5
|
+
import { parsePath } from './utils';
|
|
5
6
|
export type { HS as Hyperspan };
|
|
6
7
|
|
|
7
8
|
export const IS_PROD = process.env.NODE_ENV === 'production';
|
|
@@ -368,16 +369,6 @@ export function isRunnableRoute(route: unknown): boolean {
|
|
|
368
369
|
return typeof obj?._kind === 'string' && 'fetch' in obj;
|
|
369
370
|
}
|
|
370
371
|
|
|
371
|
-
/**
|
|
372
|
-
* Is valid route path to add to server?
|
|
373
|
-
*/
|
|
374
|
-
export function isValidRoutePath(path: string): boolean {
|
|
375
|
-
const isHiddenRoute = path.includes('/__');
|
|
376
|
-
const isTestFile = path.includes('.test') || path.includes('.spec');
|
|
377
|
-
|
|
378
|
-
return !isHiddenRoute && !isTestFile && Boolean(path);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
372
|
/**
|
|
382
373
|
* Basic error handling
|
|
383
374
|
* @TODO: Should check for and load user-customizeable template with special name (app/__error.ts ?)
|
|
@@ -473,53 +464,3 @@ export function createReadableStreamFromAsyncGenerator(output: AsyncGenerator) {
|
|
|
473
464
|
},
|
|
474
465
|
});
|
|
475
466
|
}
|
|
476
|
-
|
|
477
|
-
/**
|
|
478
|
-
* Normalize URL path
|
|
479
|
-
* Removes trailing slash and lowercases path
|
|
480
|
-
*/
|
|
481
|
-
const ROUTE_SEGMENT_REGEX = /(\[[a-zA-Z_\.]+\])/g;
|
|
482
|
-
export function parsePath(urlPath: string): { path: string, params: string[] } {
|
|
483
|
-
const params: string[] = [];
|
|
484
|
-
urlPath = urlPath.replace('index', '').replace('.ts', '').replace('.js', '');
|
|
485
|
-
|
|
486
|
-
if (urlPath.startsWith('/')) {
|
|
487
|
-
urlPath = urlPath.substring(1);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
if (urlPath.endsWith('/')) {
|
|
491
|
-
urlPath = urlPath.substring(0, urlPath.length - 1);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
if (!urlPath) {
|
|
495
|
-
return { path: '/', params: [] };
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// Dynamic params
|
|
499
|
-
if (ROUTE_SEGMENT_REGEX.test(urlPath)) {
|
|
500
|
-
urlPath = urlPath.replace(ROUTE_SEGMENT_REGEX, (match: string) => {
|
|
501
|
-
const paramName = match.replace(/[^a-zA-Z_\.]+/g, '');
|
|
502
|
-
params.push(paramName);
|
|
503
|
-
|
|
504
|
-
if (match.includes('...')) {
|
|
505
|
-
return '*';
|
|
506
|
-
} else {
|
|
507
|
-
return ':' + paramName;
|
|
508
|
-
}
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// Only lowercase non-param segments (do not lowercase after ':')
|
|
513
|
-
return {
|
|
514
|
-
path: (
|
|
515
|
-
'/' +
|
|
516
|
-
urlPath
|
|
517
|
-
.split('/')
|
|
518
|
-
.map((segment) =>
|
|
519
|
-
segment.startsWith(':') || segment === '*' ? segment : segment.toLowerCase()
|
|
520
|
-
)
|
|
521
|
-
.join('/')
|
|
522
|
-
),
|
|
523
|
-
params,
|
|
524
|
-
};
|
|
525
|
-
}
|
package/src/utils.ts
CHANGED
|
@@ -8,6 +8,67 @@ export function randomHash(): string {
|
|
|
8
8
|
return createHash('md5').update(randomBytes(32).toString('hex')).digest('hex');
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Normalize URL path
|
|
14
|
+
* Removes trailing slash and lowercases path
|
|
15
|
+
*/
|
|
16
|
+
const ROUTE_SEGMENT_REGEX = /(\[[a-zA-Z_\.]+\])/g;
|
|
17
|
+
export function parsePath(urlPath: string): { path: string, params: string[] } {
|
|
18
|
+
const params: string[] = [];
|
|
19
|
+
urlPath = urlPath.replace('index', '').replace('.ts', '').replace('.js', '');
|
|
20
|
+
|
|
21
|
+
if (urlPath.startsWith('/')) {
|
|
22
|
+
urlPath = urlPath.substring(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (urlPath.endsWith('/')) {
|
|
26
|
+
urlPath = urlPath.substring(0, urlPath.length - 1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!urlPath) {
|
|
30
|
+
return { path: '/', params: [] };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Dynamic params
|
|
34
|
+
if (ROUTE_SEGMENT_REGEX.test(urlPath)) {
|
|
35
|
+
urlPath = urlPath.replace(ROUTE_SEGMENT_REGEX, (match: string) => {
|
|
36
|
+
const paramName = match.replace(/[^a-zA-Z_\.]+/g, '');
|
|
37
|
+
params.push(paramName);
|
|
38
|
+
|
|
39
|
+
if (match.includes('...')) {
|
|
40
|
+
return '*';
|
|
41
|
+
} else {
|
|
42
|
+
return ':' + paramName;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Only lowercase non-param segments (do not lowercase after ':')
|
|
48
|
+
return {
|
|
49
|
+
path: (
|
|
50
|
+
'/' +
|
|
51
|
+
urlPath
|
|
52
|
+
.split('/')
|
|
53
|
+
.map((segment) =>
|
|
54
|
+
segment.startsWith(':') || segment === '*' ? segment : segment.toLowerCase()
|
|
55
|
+
)
|
|
56
|
+
.join('/')
|
|
57
|
+
),
|
|
58
|
+
params,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Is valid route path to add to server?
|
|
64
|
+
*/
|
|
65
|
+
export function isValidRoutePath(path: string): boolean {
|
|
66
|
+
const isHiddenRoute = path.includes('/__');
|
|
67
|
+
const isTestFile = path.includes('.test') || path.includes('.spec');
|
|
68
|
+
|
|
69
|
+
return !isHiddenRoute && !isTestFile && Boolean(path);
|
|
70
|
+
}
|
|
71
|
+
|
|
11
72
|
/**
|
|
12
73
|
* Return JSON data structure for a given FormData or URLSearchParams object
|
|
13
74
|
* Accounts for array fields (e.g. name="options[]" or <select multiple>)
|