@richie-router/server 0.1.6 → 0.1.8

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.
@@ -40,6 +40,7 @@ var __export = (target, all) => {
40
40
  var exports_src = {};
41
41
  __export(exports_src, {
42
42
  matchesSpaPath: () => matchesSpaPath,
43
+ matchesPassthroughPath: () => matchesPassthroughPath,
43
44
  handleSpaRequest: () => handleSpaRequest,
44
45
  handleRequest: () => handleRequest,
45
46
  handleHeadTagRequest: () => handleHeadTagRequest,
@@ -236,6 +237,15 @@ function resolveSpaRoutes(spaRoutesManifest) {
236
237
  }
237
238
  return spaRoutes;
238
239
  }
240
+ function resolveHostedRouting(options) {
241
+ if ("routeManifest" in options) {
242
+ return import_core.resolveHostedRoutingConfig(options.routeManifest.hostedRouting);
243
+ }
244
+ return import_core.resolveHostedRoutingConfig(options.spaRoutesManifest.hostedRouting);
245
+ }
246
+ function matchesPassthroughLocation(options, location) {
247
+ return resolveHostedRouting(options).passthrough.some((route) => import_core.matchPathname(route, location.pathname) !== null);
248
+ }
239
249
  function matchesSpaLocation(options, location) {
240
250
  if ("routeManifest" in options) {
241
251
  return buildMatches(options.routeManifest, location).length > 0;
@@ -249,9 +259,16 @@ function matchesSpaPath(path, options) {
249
259
  }
250
260
  return matchesSpaLocation(options, documentRequest.location);
251
261
  }
262
+ function matchesPassthroughPath(path, options) {
263
+ const documentRequest = resolveDocumentPath(path, options.basePath);
264
+ if (documentRequest === null) {
265
+ return false;
266
+ }
267
+ return matchesPassthroughLocation(options, documentRequest.location);
268
+ }
252
269
  async function executeHeadTag(request, headTags, routeId, params, rawSearch) {
253
270
  const definition = headTags.definitions[routeId];
254
- const schemaEntry = headTags.routerSchema[routeId];
271
+ const schemaEntry = import_core.getRouteSchemaEntry(headTags.routerSchema, routeId);
255
272
  if (!definition) {
256
273
  throw new Error(`Unknown server head route "${routeId}".`);
257
274
  }
@@ -372,7 +389,7 @@ async function handleDocumentHeadRequest(request, options, href) {
372
389
  async function handleHeadRequest(request, options) {
373
390
  const url = new URL(request.url);
374
391
  const basePath = normalizeBasePath(options.basePath);
375
- const headBasePath = options.headBasePath ?? prependBasePathToPathname("/head-api", basePath);
392
+ const headBasePath = prependBasePathToPathname(import_core.getRouterSchemaHostedRouting(options.headTags.routerSchema).headBasePath, basePath);
376
393
  if (url.pathname !== headBasePath) {
377
394
  return {
378
395
  matched: false,
@@ -445,8 +462,7 @@ async function handleRequest(request, options) {
445
462
  const basePath = normalizeBasePath(options.basePath);
446
463
  const handledHeadTagRequest = await handleHeadTagRequest(request, {
447
464
  headTags: options.headTags,
448
- basePath,
449
- headBasePath: options.headBasePath
465
+ basePath
450
466
  });
451
467
  if (handledHeadTagRequest.matched) {
452
468
  return handledHeadTagRequest;
@@ -29,6 +29,9 @@ function createTestArtifacts(options) {
29
29
  "/about": {
30
30
  serverHead: true
31
31
  }
32
+ }, {
33
+ passthrough: ["/api/$"],
34
+ headBasePath: options?.headBasePath
32
35
  });
33
36
  const headTags = import__.defineHeadTags(rootRoute, routerSchema, {
34
37
  "/about": {
@@ -49,6 +52,10 @@ function createTestArtifacts(options) {
49
52
  }
50
53
  }
51
54
  });
55
+ rootRoute._setHostedRouting({
56
+ headBasePath: options?.headBasePath ?? "/head-api",
57
+ passthrough: [options?.headBasePath ?? "/head-api", "/api/$"]
58
+ });
52
59
  return {
53
60
  routeManifest: rootRoute,
54
61
  headTags,
@@ -63,10 +70,86 @@ function createTestArtifacts(options) {
63
70
  { id: "/posts/", to: "/posts", parentId: "/posts", isRoot: false },
64
71
  { id: "/posts/$postId", to: "/posts/$postId", parentId: "/posts", isRoot: false }
65
72
  ],
66
- spaRoutes: ["/", "/about", "/dashboard", "/posts", "/posts/$postId"]
73
+ spaRoutes: ["/", "/about", "/dashboard", "/posts", "/posts/$postId"],
74
+ hostedRouting: {
75
+ headBasePath: options?.headBasePath ?? "/head-api",
76
+ passthrough: [options?.headBasePath ?? "/head-api", "/api/$"]
77
+ }
67
78
  }
68
79
  };
69
80
  }
81
+ function createCompetingHeadArtifacts() {
82
+ const rootRoute = import_core.createRouteNode("__root__", {}, { isRoot: true });
83
+ const usernameRoute = import_core.createRouteNode("/$username", {});
84
+ const usernameIndexRoute = import_core.createRouteNode("/$username/", {});
85
+ const usernameSlugRoute = import_core.createRouteNode("/$username/$slug", {});
86
+ const loginRoute = import_core.createRouteNode("/login", {});
87
+ const registerRoute = import_core.createRouteNode("/register", {});
88
+ const tagsTagRoute = import_core.createRouteNode("/tags/$tag", {});
89
+ usernameRoute._setServerHead(true);
90
+ usernameIndexRoute._setServerHead(true);
91
+ usernameSlugRoute._setServerHead(true);
92
+ loginRoute._setServerHead(true);
93
+ registerRoute._setServerHead(true);
94
+ tagsTagRoute._setServerHead(true);
95
+ usernameRoute._addFileChildren({
96
+ index: usernameIndexRoute,
97
+ slug: usernameSlugRoute
98
+ });
99
+ rootRoute._addFileChildren({
100
+ username: usernameRoute,
101
+ login: loginRoute,
102
+ register: registerRoute,
103
+ tags: tagsTagRoute
104
+ });
105
+ const routerSchema = import_core.defineRouterSchema({
106
+ "/$username/": {
107
+ serverHead: true
108
+ },
109
+ "/$username/$slug": {
110
+ serverHead: true
111
+ },
112
+ "/login": {
113
+ serverHead: true
114
+ },
115
+ "/register": {
116
+ serverHead: true
117
+ },
118
+ "/tags/$tag": {
119
+ serverHead: true
120
+ }
121
+ });
122
+ const headTags = import__.defineHeadTags(rootRoute, routerSchema, {
123
+ "/$username/": {
124
+ head: ({ params }) => [
125
+ { tag: "title", children: `User ${params.username}` }
126
+ ]
127
+ },
128
+ "/$username/$slug": {
129
+ head: ({ params }) => [
130
+ { tag: "title", children: `Post ${params.username}/${params.slug}` }
131
+ ]
132
+ },
133
+ "/login": {
134
+ head: () => [
135
+ { tag: "title", children: "Login" }
136
+ ]
137
+ },
138
+ "/register": {
139
+ head: () => [
140
+ { tag: "title", children: "Register" }
141
+ ]
142
+ },
143
+ "/tags/$tag": {
144
+ head: ({ params }) => [
145
+ { tag: "title", children: `Tag ${params.tag}` }
146
+ ]
147
+ }
148
+ });
149
+ return {
150
+ headTags
151
+ };
152
+ }
70
153
  import_bun_test.describe("handleSpaRequest", () => {
71
154
  import_bun_test.test('treats "/" as the root basePath and trims trailing slashes', () => {
72
155
  const { spaRoutesManifest } = createTestArtifacts();
@@ -94,6 +177,21 @@ import_bun_test.describe("handleSpaRequest", () => {
94
177
  basePath: "/project"
95
178
  })).toBe(false);
96
179
  });
180
+ import_bun_test.test("exposes passthrough matching for host-side routing decisions", () => {
181
+ const { spaRoutesManifest, routeManifest } = createTestArtifacts();
182
+ import_bun_test.expect(import__.matchesPassthroughPath("/project/head-api", {
183
+ spaRoutesManifest,
184
+ basePath: "/project"
185
+ })).toBe(true);
186
+ import_bun_test.expect(import__.matchesPassthroughPath("/project/api/health", {
187
+ routeManifest,
188
+ basePath: "/project"
189
+ })).toBe(true);
190
+ import_bun_test.expect(import__.matchesPassthroughPath("/project/about", {
191
+ spaRoutesManifest,
192
+ basePath: "/project"
193
+ })).toBe(false);
194
+ });
97
195
  import_bun_test.test("matches document requests under the basePath with a routeManifest", async () => {
98
196
  const { routeManifest } = createTestArtifacts();
99
197
  const result = await import__.handleSpaRequest(new Request("https://example.com/project/about"), {
@@ -242,6 +340,22 @@ import_bun_test.describe("handleRequest basePath", () => {
242
340
  ]
243
341
  });
244
342
  });
343
+ import_bun_test.test("reads a custom headBasePath from the router schema", async () => {
344
+ const { headTags } = createTestArtifacts({
345
+ headBasePath: "/meta"
346
+ });
347
+ const result = await import__.handleHeadTagRequest(new Request("https://example.com/project/meta?routeId=%2Fabout&params=%7B%7D&search=%7B%7D"), {
348
+ headTags,
349
+ basePath: "/project"
350
+ });
351
+ import_bun_test.expect(result.matched).toBe(true);
352
+ import_bun_test.expect(result.response.status).toBe(200);
353
+ import_bun_test.expect(await result.response.json()).toEqual({
354
+ head: [
355
+ { tag: "title", children: "About" }
356
+ ]
357
+ });
358
+ });
245
359
  import_bun_test.test("resolves merged document head payloads for host-rendered HTML shells", async () => {
246
360
  const { headTags } = createTestArtifacts();
247
361
  const result = await import__.handleHeadRequest(new Request("https://example.com/project/head-api?href=%2Fproject%2Fabout"), {
@@ -267,6 +381,39 @@ import_bun_test.describe("handleRequest basePath", () => {
267
381
  import_bun_test.expect(payload.richieRouterHead).toContain("window.__RICHIE_ROUTER_HEAD__");
268
382
  import_bun_test.expect(result.response.headers.get("cache-control")).toBe("private, no-store");
269
383
  });
384
+ import_bun_test.test("prefers static routes over dynamic siblings when resolving document head payloads", async () => {
385
+ const { headTags } = createCompetingHeadArtifacts();
386
+ const tagResult = await import__.handleHeadRequest(new Request("https://example.com/head-api?href=%2Ftags%2Ftesting"), {
387
+ headTags
388
+ });
389
+ import_bun_test.expect(tagResult.matched).toBe(true);
390
+ import_bun_test.expect(await tagResult.response.json()).toMatchObject({
391
+ href: "/tags/testing",
392
+ routeHeads: [
393
+ {
394
+ routeId: "/tags/$tag",
395
+ head: [
396
+ { tag: "title", children: "Tag testing" }
397
+ ]
398
+ }
399
+ ]
400
+ });
401
+ const loginResult = await import__.handleHeadRequest(new Request("https://example.com/head-api?href=%2Flogin"), {
402
+ headTags
403
+ });
404
+ import_bun_test.expect(loginResult.matched).toBe(true);
405
+ import_bun_test.expect(await loginResult.response.json()).toMatchObject({
406
+ href: "/login",
407
+ routeHeads: [
408
+ {
409
+ routeId: "/login",
410
+ head: [
411
+ { tag: "title", children: "Login" }
412
+ ]
413
+ }
414
+ ]
415
+ });
416
+ });
270
417
  import_bun_test.test("returns redirect responses for document head payload requests", async () => {
271
418
  const { headTags } = createTestArtifacts({
272
419
  redirectAbout: true
@@ -4,11 +4,14 @@ import {
4
4
  createParsedLocation,
5
5
  defaultParseSearch,
6
6
  defaultStringifySearch,
7
+ getRouteSchemaEntry,
8
+ getRouterSchemaHostedRouting,
7
9
  isNotFound,
8
10
  isRedirect,
9
11
  matchPathname,
10
12
  matchRouteTree,
11
13
  resolveHeadConfig,
14
+ resolveHostedRoutingConfig,
12
15
  serializeHeadConfig
13
16
  } from "@richie-router/core";
14
17
  function defineHeadTags(routeManifest, routerSchema, definitions) {
@@ -199,6 +202,15 @@ function resolveSpaRoutes(spaRoutesManifest) {
199
202
  }
200
203
  return spaRoutes;
201
204
  }
205
+ function resolveHostedRouting(options) {
206
+ if ("routeManifest" in options) {
207
+ return resolveHostedRoutingConfig(options.routeManifest.hostedRouting);
208
+ }
209
+ return resolveHostedRoutingConfig(options.spaRoutesManifest.hostedRouting);
210
+ }
211
+ function matchesPassthroughLocation(options, location) {
212
+ return resolveHostedRouting(options).passthrough.some((route) => matchPathname(route, location.pathname) !== null);
213
+ }
202
214
  function matchesSpaLocation(options, location) {
203
215
  if ("routeManifest" in options) {
204
216
  return buildMatches(options.routeManifest, location).length > 0;
@@ -212,9 +224,16 @@ function matchesSpaPath(path, options) {
212
224
  }
213
225
  return matchesSpaLocation(options, documentRequest.location);
214
226
  }
227
+ function matchesPassthroughPath(path, options) {
228
+ const documentRequest = resolveDocumentPath(path, options.basePath);
229
+ if (documentRequest === null) {
230
+ return false;
231
+ }
232
+ return matchesPassthroughLocation(options, documentRequest.location);
233
+ }
215
234
  async function executeHeadTag(request, headTags, routeId, params, rawSearch) {
216
235
  const definition = headTags.definitions[routeId];
217
- const schemaEntry = headTags.routerSchema[routeId];
236
+ const schemaEntry = getRouteSchemaEntry(headTags.routerSchema, routeId);
218
237
  if (!definition) {
219
238
  throw new Error(`Unknown server head route "${routeId}".`);
220
239
  }
@@ -335,7 +354,7 @@ async function handleDocumentHeadRequest(request, options, href) {
335
354
  async function handleHeadRequest(request, options) {
336
355
  const url = new URL(request.url);
337
356
  const basePath = normalizeBasePath(options.basePath);
338
- const headBasePath = options.headBasePath ?? prependBasePathToPathname("/head-api", basePath);
357
+ const headBasePath = prependBasePathToPathname(getRouterSchemaHostedRouting(options.headTags.routerSchema).headBasePath, basePath);
339
358
  if (url.pathname !== headBasePath) {
340
359
  return {
341
360
  matched: false,
@@ -408,8 +427,7 @@ async function handleRequest(request, options) {
408
427
  const basePath = normalizeBasePath(options.basePath);
409
428
  const handledHeadTagRequest = await handleHeadTagRequest(request, {
410
429
  headTags: options.headTags,
411
- basePath,
412
- headBasePath: options.headBasePath
430
+ basePath
413
431
  });
414
432
  if (handledHeadTagRequest.matched) {
415
433
  return handledHeadTagRequest;
@@ -461,6 +479,7 @@ async function handleRequest(request, options) {
461
479
  }
462
480
  export {
463
481
  matchesSpaPath,
482
+ matchesPassthroughPath,
464
483
  handleSpaRequest,
465
484
  handleRequest,
466
485
  handleHeadTagRequest,
@@ -1,7 +1,7 @@
1
1
  // packages/server/src/index.test.ts
2
2
  import { describe, expect, test } from "bun:test";
3
3
  import { defineRouterSchema, redirect, createRouteNode } from "@richie-router/core";
4
- import { defineHeadTags, handleHeadRequest, handleHeadTagRequest, handleRequest, handleSpaRequest, matchesSpaPath } from "./index.mjs";
4
+ import { defineHeadTags, handleHeadRequest, handleHeadTagRequest, handleRequest, handleSpaRequest, matchesPassthroughPath, matchesSpaPath } from "./index.mjs";
5
5
  function createTestArtifacts(options) {
6
6
  const rootRoute = createRouteNode("__root__", {}, { isRoot: true });
7
7
  const indexRoute = createRouteNode("/", {});
@@ -29,6 +29,9 @@ function createTestArtifacts(options) {
29
29
  "/about": {
30
30
  serverHead: true
31
31
  }
32
+ }, {
33
+ passthrough: ["/api/$"],
34
+ headBasePath: options?.headBasePath
32
35
  });
33
36
  const headTags = defineHeadTags(rootRoute, routerSchema, {
34
37
  "/about": {
@@ -49,6 +52,10 @@ function createTestArtifacts(options) {
49
52
  }
50
53
  }
51
54
  });
55
+ rootRoute._setHostedRouting({
56
+ headBasePath: options?.headBasePath ?? "/head-api",
57
+ passthrough: [options?.headBasePath ?? "/head-api", "/api/$"]
58
+ });
52
59
  return {
53
60
  routeManifest: rootRoute,
54
61
  headTags,
@@ -63,10 +70,86 @@ function createTestArtifacts(options) {
63
70
  { id: "/posts/", to: "/posts", parentId: "/posts", isRoot: false },
64
71
  { id: "/posts/$postId", to: "/posts/$postId", parentId: "/posts", isRoot: false }
65
72
  ],
66
- spaRoutes: ["/", "/about", "/dashboard", "/posts", "/posts/$postId"]
73
+ spaRoutes: ["/", "/about", "/dashboard", "/posts", "/posts/$postId"],
74
+ hostedRouting: {
75
+ headBasePath: options?.headBasePath ?? "/head-api",
76
+ passthrough: [options?.headBasePath ?? "/head-api", "/api/$"]
77
+ }
67
78
  }
68
79
  };
69
80
  }
81
+ function createCompetingHeadArtifacts() {
82
+ const rootRoute = createRouteNode("__root__", {}, { isRoot: true });
83
+ const usernameRoute = createRouteNode("/$username", {});
84
+ const usernameIndexRoute = createRouteNode("/$username/", {});
85
+ const usernameSlugRoute = createRouteNode("/$username/$slug", {});
86
+ const loginRoute = createRouteNode("/login", {});
87
+ const registerRoute = createRouteNode("/register", {});
88
+ const tagsTagRoute = createRouteNode("/tags/$tag", {});
89
+ usernameRoute._setServerHead(true);
90
+ usernameIndexRoute._setServerHead(true);
91
+ usernameSlugRoute._setServerHead(true);
92
+ loginRoute._setServerHead(true);
93
+ registerRoute._setServerHead(true);
94
+ tagsTagRoute._setServerHead(true);
95
+ usernameRoute._addFileChildren({
96
+ index: usernameIndexRoute,
97
+ slug: usernameSlugRoute
98
+ });
99
+ rootRoute._addFileChildren({
100
+ username: usernameRoute,
101
+ login: loginRoute,
102
+ register: registerRoute,
103
+ tags: tagsTagRoute
104
+ });
105
+ const routerSchema = defineRouterSchema({
106
+ "/$username/": {
107
+ serverHead: true
108
+ },
109
+ "/$username/$slug": {
110
+ serverHead: true
111
+ },
112
+ "/login": {
113
+ serverHead: true
114
+ },
115
+ "/register": {
116
+ serverHead: true
117
+ },
118
+ "/tags/$tag": {
119
+ serverHead: true
120
+ }
121
+ });
122
+ const headTags = defineHeadTags(rootRoute, routerSchema, {
123
+ "/$username/": {
124
+ head: ({ params }) => [
125
+ { tag: "title", children: `User ${params.username}` }
126
+ ]
127
+ },
128
+ "/$username/$slug": {
129
+ head: ({ params }) => [
130
+ { tag: "title", children: `Post ${params.username}/${params.slug}` }
131
+ ]
132
+ },
133
+ "/login": {
134
+ head: () => [
135
+ { tag: "title", children: "Login" }
136
+ ]
137
+ },
138
+ "/register": {
139
+ head: () => [
140
+ { tag: "title", children: "Register" }
141
+ ]
142
+ },
143
+ "/tags/$tag": {
144
+ head: ({ params }) => [
145
+ { tag: "title", children: `Tag ${params.tag}` }
146
+ ]
147
+ }
148
+ });
149
+ return {
150
+ headTags
151
+ };
152
+ }
70
153
  describe("handleSpaRequest", () => {
71
154
  test('treats "/" as the root basePath and trims trailing slashes', () => {
72
155
  const { spaRoutesManifest } = createTestArtifacts();
@@ -94,6 +177,21 @@ describe("handleSpaRequest", () => {
94
177
  basePath: "/project"
95
178
  })).toBe(false);
96
179
  });
180
+ test("exposes passthrough matching for host-side routing decisions", () => {
181
+ const { spaRoutesManifest, routeManifest } = createTestArtifacts();
182
+ expect(matchesPassthroughPath("/project/head-api", {
183
+ spaRoutesManifest,
184
+ basePath: "/project"
185
+ })).toBe(true);
186
+ expect(matchesPassthroughPath("/project/api/health", {
187
+ routeManifest,
188
+ basePath: "/project"
189
+ })).toBe(true);
190
+ expect(matchesPassthroughPath("/project/about", {
191
+ spaRoutesManifest,
192
+ basePath: "/project"
193
+ })).toBe(false);
194
+ });
97
195
  test("matches document requests under the basePath with a routeManifest", async () => {
98
196
  const { routeManifest } = createTestArtifacts();
99
197
  const result = await handleSpaRequest(new Request("https://example.com/project/about"), {
@@ -242,6 +340,22 @@ describe("handleRequest basePath", () => {
242
340
  ]
243
341
  });
244
342
  });
343
+ test("reads a custom headBasePath from the router schema", async () => {
344
+ const { headTags } = createTestArtifacts({
345
+ headBasePath: "/meta"
346
+ });
347
+ const result = await handleHeadTagRequest(new Request("https://example.com/project/meta?routeId=%2Fabout&params=%7B%7D&search=%7B%7D"), {
348
+ headTags,
349
+ basePath: "/project"
350
+ });
351
+ expect(result.matched).toBe(true);
352
+ expect(result.response.status).toBe(200);
353
+ expect(await result.response.json()).toEqual({
354
+ head: [
355
+ { tag: "title", children: "About" }
356
+ ]
357
+ });
358
+ });
245
359
  test("resolves merged document head payloads for host-rendered HTML shells", async () => {
246
360
  const { headTags } = createTestArtifacts();
247
361
  const result = await handleHeadRequest(new Request("https://example.com/project/head-api?href=%2Fproject%2Fabout"), {
@@ -267,6 +381,39 @@ describe("handleRequest basePath", () => {
267
381
  expect(payload.richieRouterHead).toContain("window.__RICHIE_ROUTER_HEAD__");
268
382
  expect(result.response.headers.get("cache-control")).toBe("private, no-store");
269
383
  });
384
+ test("prefers static routes over dynamic siblings when resolving document head payloads", async () => {
385
+ const { headTags } = createCompetingHeadArtifacts();
386
+ const tagResult = await handleHeadRequest(new Request("https://example.com/head-api?href=%2Ftags%2Ftesting"), {
387
+ headTags
388
+ });
389
+ expect(tagResult.matched).toBe(true);
390
+ expect(await tagResult.response.json()).toMatchObject({
391
+ href: "/tags/testing",
392
+ routeHeads: [
393
+ {
394
+ routeId: "/tags/$tag",
395
+ head: [
396
+ { tag: "title", children: "Tag testing" }
397
+ ]
398
+ }
399
+ ]
400
+ });
401
+ const loginResult = await handleHeadRequest(new Request("https://example.com/head-api?href=%2Flogin"), {
402
+ headTags
403
+ });
404
+ expect(loginResult.matched).toBe(true);
405
+ expect(await loginResult.response.json()).toMatchObject({
406
+ href: "/login",
407
+ routeHeads: [
408
+ {
409
+ routeId: "/login",
410
+ head: [
411
+ { tag: "title", children: "Login" }
412
+ ]
413
+ }
414
+ ]
415
+ });
416
+ });
270
417
  test("returns redirect responses for document head payload requests", async () => {
271
418
  const { headTags } = createTestArtifacts({
272
419
  redirectAbout: true
@@ -1,4 +1,4 @@
1
- import { type ResolveAllParamsForRouteId, type RouteIdsWithServerHead, type RouterSchemaShape, type InferRouterSearchSchema, type AnyRoute, type HeadConfig, type RouteHeadEntry } from '@richie-router/core';
1
+ import { type ResolveAllParamsForRouteId, type RouteIdsWithServerHead, type AnyRouterSchema, type InferRouterSearchSchema, type AnyRoute, type HeadConfig, type HostedRoutingConfig, type RouteHeadEntry } from '@richie-router/core';
2
2
  export interface HeadTagContext<TParams extends Record<string, string>, TSearch> {
3
3
  request: Request;
4
4
  params: TParams;
@@ -8,15 +8,15 @@ export interface HeadTagDefinition<TParams extends Record<string, string>, TSear
8
8
  staleTime?: number;
9
9
  head: (ctx: HeadTagContext<TParams, TSearch>) => Promise<HeadConfig> | HeadConfig;
10
10
  }
11
- export type HeadTagDefinitions<TRouterSchema extends RouterSchemaShape> = {
11
+ export type HeadTagDefinitions<TRouterSchema extends AnyRouterSchema> = {
12
12
  [TRouteId in RouteIdsWithServerHead<TRouterSchema>]: HeadTagDefinition<ResolveAllParamsForRouteId<TRouteId>, InferRouterSearchSchema<TRouterSchema, TRouteId>>;
13
13
  };
14
- export interface DefinedHeadTags<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape> {
14
+ export interface DefinedHeadTags<TRouteManifest extends AnyRoute, TRouterSchema extends AnyRouterSchema> {
15
15
  routeManifest: TRouteManifest;
16
16
  routerSchema: TRouterSchema;
17
17
  definitions: HeadTagDefinitions<TRouterSchema>;
18
18
  }
19
- export declare function defineHeadTags<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape>(routeManifest: TRouteManifest, routerSchema: TRouterSchema, definitions: HeadTagDefinitions<TRouterSchema>): DefinedHeadTags<TRouteManifest, TRouterSchema>;
19
+ export declare function defineHeadTags<TRouteManifest extends AnyRoute, TRouterSchema extends AnyRouterSchema>(routeManifest: TRouteManifest, routerSchema: TRouterSchema, definitions: HeadTagDefinitions<TRouterSchema>): DefinedHeadTags<TRouteManifest, TRouterSchema>;
20
20
  export interface HtmlOptions {
21
21
  template: string | ((ctx: {
22
22
  request: Request;
@@ -33,6 +33,7 @@ export interface SpaRoutesManifestRoute {
33
33
  export interface SpaRoutesManifest {
34
34
  routes?: SpaRoutesManifestRoute[];
35
35
  spaRoutes: string[];
36
+ hostedRouting?: HostedRoutingConfig;
36
37
  }
37
38
  interface BaseMatchSpaPathOptions {
38
39
  basePath?: string;
@@ -47,18 +48,16 @@ interface DocumentResponseOptions {
47
48
  headers?: HeadersInit;
48
49
  }
49
50
  export type HandleSpaRequestOptions = MatchSpaPathOptions & DocumentResponseOptions;
50
- export interface HandleRequestOptions<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape> {
51
+ export interface HandleRequestOptions<TRouteManifest extends AnyRoute, TRouterSchema extends AnyRouterSchema> {
51
52
  routeManifest: TRouteManifest;
52
53
  headTags: DefinedHeadTags<TRouteManifest, TRouterSchema>;
53
54
  html: HtmlOptions;
54
55
  basePath?: string;
55
56
  headers?: HeadersInit;
56
- headBasePath?: string;
57
57
  }
58
- export interface HandleHeadTagRequestOptions<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape> {
58
+ export interface HandleHeadTagRequestOptions<TRouteManifest extends AnyRoute, TRouterSchema extends AnyRouterSchema> {
59
59
  headTags: DefinedHeadTags<TRouteManifest, TRouterSchema>;
60
60
  basePath?: string;
61
- headBasePath?: string;
62
61
  }
63
62
  export interface HandleRequestResult {
64
63
  matched: boolean;
@@ -74,8 +73,9 @@ export interface DocumentHeadResponsePayload extends RouteHeadResponsePayload {
74
73
  routeHeads: RouteHeadEntry[];
75
74
  }
76
75
  export declare function matchesSpaPath(path: string, options: MatchSpaPathOptions): boolean;
77
- export declare function handleHeadRequest<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape>(request: Request, options: HandleHeadTagRequestOptions<TRouteManifest, TRouterSchema>): Promise<HandleRequestResult>;
78
- export declare function handleHeadTagRequest<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape>(request: Request, options: HandleHeadTagRequestOptions<TRouteManifest, TRouterSchema>): Promise<HandleRequestResult>;
76
+ export declare function matchesPassthroughPath(path: string, options: MatchSpaPathOptions): boolean;
77
+ export declare function handleHeadRequest<TRouteManifest extends AnyRoute, TRouterSchema extends AnyRouterSchema>(request: Request, options: HandleHeadTagRequestOptions<TRouteManifest, TRouterSchema>): Promise<HandleRequestResult>;
78
+ export declare function handleHeadTagRequest<TRouteManifest extends AnyRoute, TRouterSchema extends AnyRouterSchema>(request: Request, options: HandleHeadTagRequestOptions<TRouteManifest, TRouterSchema>): Promise<HandleRequestResult>;
79
79
  export declare function handleSpaRequest(request: Request, options: HandleSpaRequestOptions): Promise<HandleRequestResult>;
80
- export declare function handleRequest<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape>(request: Request, options: HandleRequestOptions<TRouteManifest, TRouterSchema>): Promise<HandleRequestResult>;
80
+ export declare function handleRequest<TRouteManifest extends AnyRoute, TRouterSchema extends AnyRouterSchema>(request: Request, options: HandleRequestOptions<TRouteManifest, TRouterSchema>): Promise<HandleRequestResult>;
81
81
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@richie-router/server",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Server helpers for Richie Router head tags and document handling",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -13,7 +13,7 @@
13
13
  }
14
14
  },
15
15
  "dependencies": {
16
- "@richie-router/core": "^0.1.3"
16
+ "@richie-router/core": "^0.1.5"
17
17
  },
18
18
  "author": "Richie <oss@ricsam.dev>",
19
19
  "homepage": "https://docs.ricsam.dev/richie-router",