htmx-router 1.0.5 → 1.0.6

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.
@@ -20,8 +20,11 @@ export async function Resolve(request, tree, config) {
20
20
  : res;
21
21
  // Override with context headers
22
22
  if (response.headers !== ctx.headers) {
23
- for (const [key, value] of ctx.headers)
23
+ for (const [key, value] of ctx.headers) {
24
+ if (key === "content-type")
25
+ continue;
24
26
  response.headers.set(key, value);
27
+ }
25
28
  }
26
29
  }
27
30
  catch (e) {
@@ -2,3 +2,4 @@ export declare function QuickHash(input: string): string;
2
2
  export declare function CutString(str: string, pivot: string, offset?: number): [string, string];
3
3
  export declare function Singleton<T>(name: string, cb: () => T): T;
4
4
  export declare function ServerOnlyWarning(context: string): void;
5
+ export declare function AssertUnreachable(x: never): never;
package/internal/util.js CHANGED
@@ -47,3 +47,7 @@ export function ServerOnlyWarning(context) {
47
47
  console.warn(`Warn: Server-side only htmx-router feature ${context} has leaked to client code`);
48
48
  console.log(typeof document, typeof process);
49
49
  }
50
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
51
+ export function AssertUnreachable(x) {
52
+ throw new Error("Unreachable code path reachable");
53
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "htmx-router",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "A lightweight SSR framework with server+client islands",
5
5
  "keywords": [
6
6
  "htmx",
package/response.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export declare function text(text: string, init?: ResponseInit): Response;
2
- export declare function html(text: string, init?: ResponseInit): Response;
1
+ export declare function text(text: BodyInit, init?: ResponseInit): Response;
2
+ export declare function html(text: BodyInit, init?: ResponseInit): Response;
3
3
  export type TypedResponse<T> = Omit<Response, "json"> & {
4
4
  json(): Promise<T>;
5
5
  };
package/router.js CHANGED
@@ -1,10 +1,12 @@
1
- import { ServerOnlyWarning } from "./internal/util.js";
1
+ import { AssertUnreachable, ServerOnlyWarning } from "./internal/util.js";
2
2
  ServerOnlyWarning("router");
3
+ import { MakeStatus } from "./status.js";
3
4
  // builtin routes
4
5
  import * as endpoint from './endpoint.js';
5
6
  import * as dynamic from './defer.js';
6
7
  import * as mount from './internal/mount.js';
7
8
  import * as css from './css.js';
9
+ import { html } from "./response.js";
8
10
  export function GenerateRouteTree(props) {
9
11
  if (!props.scope.endsWith("/"))
10
12
  props.scope += "/";
@@ -134,7 +136,7 @@ export class RouteTree {
134
136
  return res;
135
137
  if (res === null)
136
138
  return null;
137
- return new Response(res, { headers: ctx.headers });
139
+ AssertUnreachable(res);
138
140
  }
139
141
  async resolveNext(fragments, ctx) {
140
142
  if (fragments.length < 1)
@@ -161,22 +163,12 @@ export class RouteTree {
161
163
  return res;
162
164
  if (res === null)
163
165
  return null;
164
- return new Response(res, { headers: ctx.headers });
166
+ AssertUnreachable(res);
165
167
  }
166
- async unwrap(ctx, res) {
168
+ unwrap(ctx, res) {
167
169
  if (!this.slug)
168
170
  throw res;
169
- const caught = await this.slug.error(ctx, res);
170
- if (caught instanceof Response) {
171
- caught.headers.set("X-Caught", "true");
172
- return caught;
173
- }
174
- ctx.headers.set("X-Caught", "true");
175
- return new Response(caught, res instanceof Response ? res : {
176
- status: 500,
177
- statusText: "Internal Server Error",
178
- headers: ctx.headers
179
- });
171
+ return this.slug.error(ctx, res);
180
172
  }
181
173
  }
182
174
  class RouteLeaf {
@@ -185,20 +177,28 @@ class RouteLeaf {
185
177
  this.module = module;
186
178
  }
187
179
  async resolve(ctx) {
188
- const res = await this.response(ctx);
189
- if (res === null)
180
+ const jsx = await this.response(ctx);
181
+ if (jsx === null)
190
182
  return null;
183
+ if (jsx instanceof Response)
184
+ return jsx;
185
+ const res = await ctx.render(jsx, ctx.headers);
191
186
  if (res instanceof Response)
192
187
  return res;
193
- return await ctx.render(res, ctx.headers);
188
+ return html(res, { headers: ctx.headers });
194
189
  }
195
190
  async error(ctx, e) {
196
191
  if (!this.module.error)
197
192
  throw e;
198
- const res = await this.module.error(ctx, e);
199
- if (res instanceof Response)
200
- return res;
201
- return await ctx.render(res, ctx.headers);
193
+ let jsx = await this.module.error(ctx, e);
194
+ const caught = jsx instanceof Response ? jsx
195
+ : await ctx.render(jsx, ctx.headers);
196
+ if (caught instanceof Response) {
197
+ caught.headers.set("X-Caught", "true");
198
+ return caught;
199
+ }
200
+ ctx.headers.set("X-Caught", "true");
201
+ return html(caught, e instanceof Response ? e : MakeStatus("Internal Server Error", ctx.headers));
202
202
  }
203
203
  async response(ctx) {
204
204
  try {
@@ -213,7 +213,7 @@ class RouteLeaf {
213
213
  }
214
214
  if (this.module.action)
215
215
  return await this.module.action(context);
216
- throw new Response("Method not Allowed", { status: 405, statusText: "Method not Allowed", headers: ctx.headers });
216
+ throw new Response("Method not Allowed", MakeStatus("Method Not Allowed", ctx.headers));
217
217
  }
218
218
  catch (e) {
219
219
  return await this.error(ctx, e);