htmx-router 1.0.9 → 1.0.10

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/css.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare function GetSheetUrl(): string;
14
14
  /**
15
15
  * RouteTree mounting point
16
16
  */
17
- export declare const path = "_/style/$hash";
17
+ export declare const path = "/_/style/$hash";
18
18
  export declare const parameters: {
19
19
  hash: StringConstructor;
20
20
  };
package/css.js CHANGED
@@ -45,7 +45,7 @@ export function GetSheetUrl() {
45
45
  /**
46
46
  * RouteTree mounting point
47
47
  */
48
- export const path = "_/style/$hash";
48
+ export const path = "/_/style/$hash";
49
49
  export const parameters = {
50
50
  hash: String
51
51
  };
package/defer.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare function Deferral<T extends ParameterShaper>(func: RenderFunction
6
6
  /**
7
7
  * RouteTree mounting point
8
8
  */
9
- export declare const path = "_/defer/$";
9
+ export declare const path = "/_/defer/$";
10
10
  export declare const parameters: {
11
11
  $: StringConstructor;
12
12
  };
package/defer.js CHANGED
@@ -52,7 +52,7 @@ export function Deferral(func, params) {
52
52
  /**
53
53
  * RouteTree mounting point
54
54
  */
55
- export const path = "_/defer/$";
55
+ export const path = "/_/defer/$";
56
56
  export const parameters = {
57
57
  "$": String
58
58
  };
@@ -69,7 +69,7 @@ export async function loader(ctx) {
69
69
  return null;
70
70
  }
71
71
  ctx.headers.set("X-Partial", "true");
72
- const forward = new RouteContext(ctx, prelude, entry.shape);
72
+ const forward = new RouteContext(ctx, prelude, entry.shape, "");
73
73
  return await endpoint(forward);
74
74
  }
75
75
  export const action = loader;
package/endpoint.d.ts CHANGED
@@ -12,7 +12,7 @@ export declare class Endpoint {
12
12
  /**
13
13
  * RouteTree mounting point
14
14
  */
15
- export declare const path = "_/endpoint/$";
15
+ export declare const path = "/_/endpoint/$";
16
16
  export declare const parameters: {
17
17
  $: StringConstructor;
18
18
  };
package/endpoint.js CHANGED
@@ -22,7 +22,7 @@ export class Endpoint {
22
22
  /**
23
23
  * RouteTree mounting point
24
24
  */
25
- export const path = "_/endpoint/$";
25
+ export const path = "/_/endpoint/$";
26
26
  export const parameters = {
27
27
  "$": String
28
28
  };
@@ -3,7 +3,7 @@ export declare function GetMountUrl(): string;
3
3
  /**
4
4
  * RouteTree mounting point
5
5
  */
6
- export declare const path = "_/mount/$hash";
6
+ export declare const path = "/_/mount/$hash";
7
7
  export declare const parameters: {
8
8
  hash: StringConstructor;
9
9
  };
package/internal/mount.js CHANGED
@@ -110,7 +110,7 @@ export function GetMountUrl() {
110
110
  /**
111
111
  * RouteTree mounting point
112
112
  */
113
- export const path = "_/mount/$hash";
113
+ export const path = "/_/mount/$hash";
114
114
  export const parameters = {
115
115
  hash: String
116
116
  };
@@ -12,6 +12,6 @@ export declare class GenericContext {
12
12
  url: URL;
13
13
  render: (res: JSX.Element, headers: Headers) => Promise<Rendered> | Rendered;
14
14
  constructor(request: GenericContext["request"], url: GenericContext["url"], renderer: GenericContext["render"]);
15
- shape<T extends ParameterShaper>(shape: T): RouteContext<T>;
15
+ shape<T extends ParameterShaper>(shape: T, path: string): RouteContext<T>;
16
16
  }
17
17
  export {};
@@ -19,7 +19,7 @@ export class GenericContext {
19
19
  this.headers.set("x-powered-by", "htmx-router");
20
20
  this.headers.set("content-type", "text/html");
21
21
  }
22
- shape(shape) {
23
- return new RouteContext(this, this.params, shape);
22
+ shape(shape, path) {
23
+ return new RouteContext(this, this.params, shape, path);
24
24
  }
25
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "htmx-router",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "A lightweight SSR framework with server+client islands",
5
5
  "keywords": [
6
6
  "htmx",
package/router.d.ts CHANGED
@@ -7,13 +7,14 @@ export declare function GenerateRouteTree(props: {
7
7
  scope: string;
8
8
  }): RouteTree;
9
9
  export declare class RouteContext<T extends ParameterShaper = {}> {
10
+ readonly path: string;
10
11
  readonly request: Request;
11
12
  readonly headers: Headers;
12
13
  readonly cookie: Cookies;
13
14
  readonly params: Parameterized<T>;
14
15
  readonly url: URL;
15
16
  render: GenericContext["render"];
16
- constructor(base: GenericContext | RouteContext, params: ParameterPrelude<T>, shape: T);
17
+ constructor(base: GenericContext | RouteContext, params: ParameterPrelude<T>, shape: T, path: string);
17
18
  }
18
19
  export declare class RouteTree {
19
20
  private nested;
@@ -22,7 +23,7 @@ export declare class RouteTree {
22
23
  private wild;
23
24
  private wildCard;
24
25
  constructor();
25
- ingest(path: string | string[], module: RouteModule<any>): void;
26
+ ingest(node: RouteLeaf, path?: string[]): void;
26
27
  resolve(fragments: string[], ctx: GenericContext): Promise<Response | null>;
27
28
  private _resolve;
28
29
  private resolveIndex;
@@ -31,3 +32,12 @@ export declare class RouteTree {
31
32
  private resolveSlug;
32
33
  private unwrap;
33
34
  }
35
+ declare class RouteLeaf {
36
+ private module;
37
+ readonly path: string;
38
+ constructor(module: RouteModule<any>, path: string);
39
+ resolve(ctx: GenericContext): Promise<Response | null>;
40
+ error(ctx: GenericContext, e: unknown): Promise<Response>;
41
+ private response;
42
+ }
43
+ export {};
package/router.js CHANGED
@@ -13,27 +13,32 @@ export function GenerateRouteTree(props) {
13
13
  const tree = new RouteTree();
14
14
  for (const path in props.modules) {
15
15
  const mod = props.modules[path];
16
- const tail = path.lastIndexOf(".");
17
- const url = path.slice(props.scope.length, tail);
18
- tree.ingest(url, mod);
16
+ let tail = path.lastIndexOf(".");
17
+ if (path.endsWith("/_index", tail))
18
+ tail -= "/_index".length;
19
+ const url = path.slice(props.scope.length - 1, tail);
20
+ const leaf = new RouteLeaf(mod, url);
21
+ tree.ingest(leaf);
19
22
  if (mod.route)
20
23
  mod.route(url);
21
24
  }
22
25
  // ingest router builtins
23
- tree.ingest(endpoint.path, endpoint);
24
- tree.ingest(dynamic.path, dynamic);
25
- tree.ingest(mount.path, mount);
26
- tree.ingest(css.path, css);
26
+ tree.ingest(new RouteLeaf(endpoint, endpoint.path));
27
+ tree.ingest(new RouteLeaf(dynamic, dynamic.path));
28
+ tree.ingest(new RouteLeaf(mount, mount.path));
29
+ tree.ingest(new RouteLeaf(css, css.path));
27
30
  return tree;
28
31
  }
29
32
  export class RouteContext {
33
+ path;
30
34
  request;
31
35
  headers; // response headers
32
36
  cookie;
33
37
  params;
34
38
  url;
35
39
  render;
36
- constructor(base, params, shape) {
40
+ constructor(base, params, shape, path) {
41
+ this.path = path;
37
42
  this.cookie = base.cookie;
38
43
  this.headers = base.headers;
39
44
  this.request = base.request;
@@ -67,15 +72,15 @@ export class RouteTree {
67
72
  this.wild = null;
68
73
  this.slug = null;
69
74
  }
70
- ingest(path, module) {
71
- if (!Array.isArray(path))
72
- path = path.split("/");
73
- if (path.length === 0 || (path.length == 1 && path[0] === "_index")) {
74
- this.index = new RouteLeaf(module);
75
+ ingest(node, path) {
76
+ if (!path)
77
+ path = node.path.length === 0 ? [] : node.path.slice(1).split("/");
78
+ if (path.length === 0) {
79
+ this.index = node;
75
80
  return;
76
81
  }
77
82
  if (path[0] === "$") {
78
- this.slug = new RouteLeaf(module);
83
+ this.slug = node;
79
84
  return;
80
85
  }
81
86
  if (path[0][0] === "$") {
@@ -88,8 +93,7 @@ export class RouteTree {
88
93
  else if (wildCard !== this.wildCard) {
89
94
  throw new Error(`Redefinition of wild card ${this.wildCard} to ${wildCard}`);
90
95
  }
91
- path.splice(0, 1);
92
- this.wild.ingest(path, module);
96
+ this.wild.ingest(node, path.slice(1));
93
97
  return;
94
98
  }
95
99
  let next = this.nested.get(path[0]);
@@ -97,8 +101,7 @@ export class RouteTree {
97
101
  next = new RouteTree();
98
102
  this.nested.set(path[0], next);
99
103
  }
100
- path.splice(0, 1);
101
- next.ingest(path, module);
104
+ next.ingest(node, path.slice(1));
102
105
  }
103
106
  async resolve(fragments, ctx) {
104
107
  if (!this.slug)
@@ -173,8 +176,10 @@ export class RouteTree {
173
176
  }
174
177
  class RouteLeaf {
175
178
  module;
176
- constructor(module) {
179
+ path;
180
+ constructor(module, path) {
177
181
  this.module = module;
182
+ this.path = path;
178
183
  }
179
184
  async resolve(ctx) {
180
185
  const jsx = await this.response(ctx);
@@ -190,7 +195,7 @@ class RouteLeaf {
190
195
  async error(ctx, e) {
191
196
  if (!this.module.error)
192
197
  throw e;
193
- let jsx = await this.module.error(ctx, e);
198
+ let jsx = await this.module.error(ctx.shape({}, this.path), e);
194
199
  const caught = jsx instanceof Response ? jsx
195
200
  : await ctx.render(jsx, ctx.headers);
196
201
  if (caught instanceof Response) {
@@ -204,7 +209,7 @@ class RouteLeaf {
204
209
  try {
205
210
  if (!this.module.loader && !this.module.action)
206
211
  return null;
207
- const context = ctx.shape(this.module.parameters || {});
212
+ const context = ctx.shape(this.module.parameters || {}, this.path);
208
213
  if (ctx.request.method === "HEAD" || ctx.request.method === "GET") {
209
214
  if (this.module.loader)
210
215
  return await this.module.loader(context);