@hyperspan/framework 1.0.0-alpha.11 → 1.0.0-alpha.12

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperspan/framework",
3
- "version": "1.0.0-alpha.11",
3
+ "version": "1.0.0-alpha.12",
4
4
  "description": "Hyperspan Web Framework",
5
5
  "main": "src/server.ts",
6
6
  "types": "src/server.ts",
@@ -113,7 +113,7 @@ test('createContext() can get and set cookies', () => {
113
113
  expect(setCookieHeader).toBeTruthy();
114
114
  expect(setCookieHeader).toContain('newCookie=newValue');
115
115
 
116
- // Test setting a cookie with options (this will overwrite the previous Set-Cookie header)
116
+ // Test setting a cookie with options (this should NOT overwrite the previous Set-Cookie header)
117
117
  context.res.cookies.set('secureCookie', 'secureValue', {
118
118
  httpOnly: true,
119
119
  secure: true,
@@ -125,13 +125,7 @@ test('createContext() can get and set cookies', () => {
125
125
  setCookieHeader = context.res.headers.get('Set-Cookie');
126
126
  expect(setCookieHeader).toBeTruthy();
127
127
  expect(setCookieHeader).toContain('secureCookie=secureValue');
128
- expect(setCookieHeader).toContain('HttpOnly');
129
- expect(setCookieHeader).toContain('Secure');
130
- expect(setCookieHeader).toContain('SameSite=Strict');
131
- expect(setCookieHeader).toContain('Max-Age=3600');
132
-
133
- // Verify the previous cookie was overwritten
134
- expect(setCookieHeader).not.toContain('newCookie=newValue');
128
+ expect(setCookieHeader).toContain('newCookie=newValue');
135
129
 
136
130
  // Test deleting a cookie
137
131
  context.res.cookies.delete('sessionId');
package/src/server.ts CHANGED
@@ -39,7 +39,15 @@ export function createContext(req: Request, route?: HS.Route): HS.Context {
39
39
  const headers = new Headers(req.headers);
40
40
  const path = route?._path() || '/';
41
41
  // @ts-ignore - Bun will put 'params' on the Request object even though it's not standardized
42
- const params: HS.RouteParamsParser<path> = req?.params || {};
42
+ const params: HS.RouteParamsParser<path> & Record<string, string | undefined> = Object.assign({}, req?.params || {}, route?._config.params || {});
43
+
44
+ // Replace catch-all param with the value from the URL path
45
+ const catchAllParam = Object.keys(params).find(key => key.startsWith('...'));
46
+ if (catchAllParam && path.includes('/*')) {
47
+ const catchAllValue = url.pathname.split(path.replace('/*', '/')).pop();
48
+ params[catchAllParam.replace('...', '')] = catchAllValue;
49
+ delete params[catchAllParam];
50
+ }
43
51
 
44
52
  const merge = (response: Response) => {
45
53
  // Convert headers to plain objects and merge (response headers override context headers)
package/src/types.ts CHANGED
@@ -77,11 +77,7 @@ export namespace Hyperspan {
77
77
 
78
78
  export interface Context {
79
79
  vars: Record<string, any>;
80
- route: {
81
- path: string;
82
- params: Record<string, string>;
83
- cssImports?: string[];
84
- }
80
+ route: RouteConfig;
85
81
  req: HSRequest;
86
82
  res: HSResponse;
87
83
  };
@@ -94,6 +90,7 @@ export namespace Hyperspan {
94
90
  export type RouteConfig = {
95
91
  name?: string;
96
92
  path?: string;
93
+ params?: Record<string, string | undefined>;
97
94
  cssImports?: string[];
98
95
  };
99
96
  export type RouteHandler = (context: Hyperspan.Context) => unknown;
package/src/utils.test.ts CHANGED
@@ -149,13 +149,13 @@ describe('parsePath', () => {
149
149
  test('parsePath handles catch-all param with spread', () => {
150
150
  const result = parsePath('users/[...slug]');
151
151
  expect(result.path).toBe('/users/*');
152
- expect(result.params).toEqual(['slug']);
152
+ expect(result.params).toEqual(['...slug']);
153
153
  });
154
154
 
155
155
  test('parsePath handles catch-all param at root', () => {
156
156
  const result = parsePath('[...slug]');
157
157
  expect(result.path).toBe('/*');
158
- expect(result.params).toEqual(['slug']);
158
+ expect(result.params).toEqual(['...slug']);
159
159
  });
160
160
 
161
161
  test('parsePath preserves param names in path but converts format', () => {
package/src/utils.ts CHANGED
@@ -33,7 +33,7 @@ export function parsePath(urlPath: string): { path: string, params: string[] } {
33
33
  // Dynamic params
34
34
  if (ROUTE_SEGMENT_REGEX.test(urlPath)) {
35
35
  urlPath = urlPath.replace(ROUTE_SEGMENT_REGEX, (match: string) => {
36
- const paramName = match.replace(/[^a-zA-Z_\.]+/g, '').replace('...', '');
36
+ const paramName = match.replace(/[^a-zA-Z_\.]+/g, '');
37
37
  params.push(paramName);
38
38
 
39
39
  if (match.includes('...')) {