@richie-router/server 0.1.1 → 0.1.3

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,14 +40,15 @@ var __export = (target, all) => {
40
40
  var exports_src = {};
41
41
  __export(exports_src, {
42
42
  handleRequest: () => handleRequest,
43
+ handleHeadTagRequest: () => handleHeadTagRequest,
43
44
  defineHeadTags: () => defineHeadTags
44
45
  });
45
46
  module.exports = __toCommonJS(exports_src);
46
47
  var import_core = require("@richie-router/core");
47
- function defineHeadTags(routeManifest, headTagSchema, definitions) {
48
+ function defineHeadTags(routeManifest, routerSchema, definitions) {
48
49
  return {
49
50
  routeManifest,
50
- headTagSchema,
51
+ routerSchema,
51
52
  definitions
52
53
  };
53
54
  }
@@ -111,11 +112,11 @@ function buildMatches(routeManifest, location) {
111
112
  };
112
113
  });
113
114
  }
114
- async function executeHeadTag(request, headTags, headTagName, params, rawSearch) {
115
- const definition = headTags.definitions[headTagName];
116
- const schemaEntry = headTags.headTagSchema[headTagName];
115
+ async function executeHeadTag(request, headTags, routeId, params, rawSearch) {
116
+ const definition = headTags.definitions[routeId];
117
+ const schemaEntry = headTags.routerSchema[routeId];
117
118
  if (!definition) {
118
- throw new Error(`Unknown head tag "${headTagName}".`);
119
+ throw new Error(`Unknown server head route "${routeId}".`);
119
120
  }
120
121
  const search = schemaEntry?.searchSchema ? schemaEntry.searchSchema.parse(rawSearch) : rawSearch;
121
122
  const head = await definition.head({
@@ -131,44 +132,63 @@ async function executeHeadTag(request, headTags, headTagName, params, rawSearch)
131
132
  async function resolveMatchedHead(request, headTags, matches) {
132
133
  const resolvedHeadByRoute = new Map;
133
134
  for (const match of matches) {
134
- const headOption = match.route.options.head;
135
- if (typeof headOption !== "string") {
135
+ if (!match.route.serverHead) {
136
136
  continue;
137
137
  }
138
- const result = await executeHeadTag(request, headTags, headOption, match.params, match.search);
138
+ const result = await executeHeadTag(request, headTags, match.route.fullPath, match.params, match.search);
139
139
  resolvedHeadByRoute.set(match.route.fullPath, result.head);
140
140
  }
141
141
  return import_core.resolveHeadConfig(matches, resolvedHeadByRoute);
142
142
  }
143
- async function handleRequest(request, options) {
143
+ async function handleHeadTagRequest(request, options) {
144
144
  const url = new URL(request.url);
145
145
  const headBasePath = options.headBasePath ?? "/head-api";
146
- const routeBasePath = options.routeBasePath ?? "/";
147
- if (url.pathname.startsWith(`${headBasePath}/`)) {
148
- const headTagName = decodeURIComponent(url.pathname.slice(headBasePath.length + 1));
149
- const params = JSON.parse(url.searchParams.get("params") ?? "{}");
150
- const search = JSON.parse(url.searchParams.get("search") ?? "{}");
151
- try {
152
- const result = await executeHeadTag(request, options.headTags, headTagName, params, search);
146
+ if (url.pathname !== headBasePath) {
147
+ return {
148
+ matched: false,
149
+ response: new Response("Not Found", { status: 404 })
150
+ };
151
+ }
152
+ const routeId = url.searchParams.get("routeId");
153
+ if (!routeId) {
154
+ return {
155
+ matched: true,
156
+ response: jsonResponse({ message: "Missing routeId" }, { status: 400 })
157
+ };
158
+ }
159
+ const params = JSON.parse(url.searchParams.get("params") ?? "{}");
160
+ const search = JSON.parse(url.searchParams.get("search") ?? "{}");
161
+ try {
162
+ const result = await executeHeadTag(request, options.headTags, routeId, params, search);
163
+ return {
164
+ matched: true,
165
+ response: jsonResponse(result)
166
+ };
167
+ } catch (error) {
168
+ if (error instanceof Response) {
169
+ return {
170
+ matched: true,
171
+ response: error
172
+ };
173
+ }
174
+ if (import_core.isNotFound(error)) {
153
175
  return {
154
176
  matched: true,
155
- response: jsonResponse(result)
177
+ response: jsonResponse({ message: "Not Found" }, { status: 404 })
156
178
  };
157
- } catch (error) {
158
- if (error instanceof Response) {
159
- return {
160
- matched: true,
161
- response: error
162
- };
163
- }
164
- if (import_core.isNotFound(error)) {
165
- return {
166
- matched: true,
167
- response: jsonResponse({ message: "Not Found" }, { status: 404 })
168
- };
169
- }
170
- throw error;
171
179
  }
180
+ throw error;
181
+ }
182
+ }
183
+ async function handleRequest(request, options) {
184
+ const url = new URL(request.url);
185
+ const routeBasePath = options.routeBasePath ?? "/";
186
+ const handledHeadTagRequest = await handleHeadTagRequest(request, {
187
+ headTags: options.headTags,
188
+ headBasePath: options.headBasePath
189
+ });
190
+ if (handledHeadTagRequest.matched) {
191
+ return handledHeadTagRequest;
172
192
  }
173
193
  if (!url.pathname.startsWith(routeBasePath)) {
174
194
  return {
@@ -10,10 +10,10 @@ import {
10
10
  resolveHeadConfig,
11
11
  serializeHeadConfig
12
12
  } from "@richie-router/core";
13
- function defineHeadTags(routeManifest, headTagSchema, definitions) {
13
+ function defineHeadTags(routeManifest, routerSchema, definitions) {
14
14
  return {
15
15
  routeManifest,
16
- headTagSchema,
16
+ routerSchema,
17
17
  definitions
18
18
  };
19
19
  }
@@ -77,11 +77,11 @@ function buildMatches(routeManifest, location) {
77
77
  };
78
78
  });
79
79
  }
80
- async function executeHeadTag(request, headTags, headTagName, params, rawSearch) {
81
- const definition = headTags.definitions[headTagName];
82
- const schemaEntry = headTags.headTagSchema[headTagName];
80
+ async function executeHeadTag(request, headTags, routeId, params, rawSearch) {
81
+ const definition = headTags.definitions[routeId];
82
+ const schemaEntry = headTags.routerSchema[routeId];
83
83
  if (!definition) {
84
- throw new Error(`Unknown head tag "${headTagName}".`);
84
+ throw new Error(`Unknown server head route "${routeId}".`);
85
85
  }
86
86
  const search = schemaEntry?.searchSchema ? schemaEntry.searchSchema.parse(rawSearch) : rawSearch;
87
87
  const head = await definition.head({
@@ -97,44 +97,63 @@ async function executeHeadTag(request, headTags, headTagName, params, rawSearch)
97
97
  async function resolveMatchedHead(request, headTags, matches) {
98
98
  const resolvedHeadByRoute = new Map;
99
99
  for (const match of matches) {
100
- const headOption = match.route.options.head;
101
- if (typeof headOption !== "string") {
100
+ if (!match.route.serverHead) {
102
101
  continue;
103
102
  }
104
- const result = await executeHeadTag(request, headTags, headOption, match.params, match.search);
103
+ const result = await executeHeadTag(request, headTags, match.route.fullPath, match.params, match.search);
105
104
  resolvedHeadByRoute.set(match.route.fullPath, result.head);
106
105
  }
107
106
  return resolveHeadConfig(matches, resolvedHeadByRoute);
108
107
  }
109
- async function handleRequest(request, options) {
108
+ async function handleHeadTagRequest(request, options) {
110
109
  const url = new URL(request.url);
111
110
  const headBasePath = options.headBasePath ?? "/head-api";
112
- const routeBasePath = options.routeBasePath ?? "/";
113
- if (url.pathname.startsWith(`${headBasePath}/`)) {
114
- const headTagName = decodeURIComponent(url.pathname.slice(headBasePath.length + 1));
115
- const params = JSON.parse(url.searchParams.get("params") ?? "{}");
116
- const search = JSON.parse(url.searchParams.get("search") ?? "{}");
117
- try {
118
- const result = await executeHeadTag(request, options.headTags, headTagName, params, search);
111
+ if (url.pathname !== headBasePath) {
112
+ return {
113
+ matched: false,
114
+ response: new Response("Not Found", { status: 404 })
115
+ };
116
+ }
117
+ const routeId = url.searchParams.get("routeId");
118
+ if (!routeId) {
119
+ return {
120
+ matched: true,
121
+ response: jsonResponse({ message: "Missing routeId" }, { status: 400 })
122
+ };
123
+ }
124
+ const params = JSON.parse(url.searchParams.get("params") ?? "{}");
125
+ const search = JSON.parse(url.searchParams.get("search") ?? "{}");
126
+ try {
127
+ const result = await executeHeadTag(request, options.headTags, routeId, params, search);
128
+ return {
129
+ matched: true,
130
+ response: jsonResponse(result)
131
+ };
132
+ } catch (error) {
133
+ if (error instanceof Response) {
134
+ return {
135
+ matched: true,
136
+ response: error
137
+ };
138
+ }
139
+ if (isNotFound(error)) {
119
140
  return {
120
141
  matched: true,
121
- response: jsonResponse(result)
142
+ response: jsonResponse({ message: "Not Found" }, { status: 404 })
122
143
  };
123
- } catch (error) {
124
- if (error instanceof Response) {
125
- return {
126
- matched: true,
127
- response: error
128
- };
129
- }
130
- if (isNotFound(error)) {
131
- return {
132
- matched: true,
133
- response: jsonResponse({ message: "Not Found" }, { status: 404 })
134
- };
135
- }
136
- throw error;
137
144
  }
145
+ throw error;
146
+ }
147
+ }
148
+ async function handleRequest(request, options) {
149
+ const url = new URL(request.url);
150
+ const routeBasePath = options.routeBasePath ?? "/";
151
+ const handledHeadTagRequest = await handleHeadTagRequest(request, {
152
+ headTags: options.headTags,
153
+ headBasePath: options.headBasePath
154
+ });
155
+ if (handledHeadTagRequest.matched) {
156
+ return handledHeadTagRequest;
138
157
  }
139
158
  if (!url.pathname.startsWith(routeBasePath)) {
140
159
  return {
@@ -203,5 +222,6 @@ async function handleRequest(request, options) {
203
222
  }
204
223
  export {
205
224
  handleRequest,
225
+ handleHeadTagRequest,
206
226
  defineHeadTags
207
227
  };
@@ -1,23 +1,22 @@
1
- import { type AnyRoute, type HeadConfig, type HeadTagSchemaShape, type InferHeadTagSearchSchema } from '@richie-router/core';
2
- export interface HeadTagContext<TSearch> {
1
+ import { type ResolveAllParamsForRouteId, type RouteIdsWithServerHead, type RouterSchemaShape, type InferRouterSearchSchema, type AnyRoute, type HeadConfig } from '@richie-router/core';
2
+ export interface HeadTagContext<TParams extends Record<string, string>, TSearch> {
3
3
  request: Request;
4
- params: Record<string, string>;
4
+ params: TParams;
5
5
  search: TSearch;
6
6
  }
7
- export interface HeadTagDefinition<TSearch> {
7
+ export interface HeadTagDefinition<TParams extends Record<string, string>, TSearch> {
8
8
  staleTime?: number;
9
- head: (ctx: HeadTagContext<TSearch>) => Promise<HeadConfig> | HeadConfig;
9
+ head: (ctx: HeadTagContext<TParams, TSearch>) => Promise<HeadConfig> | HeadConfig;
10
10
  }
11
- export interface DefinedHeadTags<TRouteManifest extends AnyRoute, THeadTagSchema extends HeadTagSchemaShape, TDefinitions extends Partial<{
12
- [THeadTagName in keyof THeadTagSchema]: HeadTagDefinition<InferHeadTagSearchSchema<THeadTagSchema, THeadTagName>>;
13
- }>> {
11
+ export type HeadTagDefinitions<TRouterSchema extends RouterSchemaShape> = {
12
+ [TRouteId in RouteIdsWithServerHead<TRouterSchema>]: HeadTagDefinition<ResolveAllParamsForRouteId<TRouteId>, InferRouterSearchSchema<TRouterSchema, TRouteId>>;
13
+ };
14
+ export interface DefinedHeadTags<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape> {
14
15
  routeManifest: TRouteManifest;
15
- headTagSchema: THeadTagSchema;
16
- definitions: TDefinitions;
16
+ routerSchema: TRouterSchema;
17
+ definitions: HeadTagDefinitions<TRouterSchema>;
17
18
  }
18
- export declare function defineHeadTags<TRouteManifest extends AnyRoute, THeadTagSchema extends HeadTagSchemaShape, TDefinitions extends Partial<{
19
- [THeadTagName in keyof THeadTagSchema]: HeadTagDefinition<InferHeadTagSearchSchema<THeadTagSchema, THeadTagName>>;
20
- }>>(routeManifest: TRouteManifest, headTagSchema: THeadTagSchema, definitions: TDefinitions): DefinedHeadTags<TRouteManifest, THeadTagSchema, TDefinitions>;
19
+ export declare function defineHeadTags<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape>(routeManifest: TRouteManifest, routerSchema: TRouterSchema, definitions: HeadTagDefinitions<TRouterSchema>): DefinedHeadTags<TRouteManifest, TRouterSchema>;
21
20
  export interface HtmlOptions {
22
21
  template: string | ((ctx: {
23
22
  request: Request;
@@ -25,15 +24,20 @@ export interface HtmlOptions {
25
24
  head: HeadConfig;
26
25
  }) => string | Promise<string>);
27
26
  }
28
- export interface HandleRequestOptions<TRouteManifest extends AnyRoute, THeadTagSchema extends HeadTagSchemaShape, TDefinitions extends Partial<Record<keyof THeadTagSchema, HeadTagDefinition<any>>>> {
27
+ export interface HandleRequestOptions<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape> {
29
28
  routeManifest: TRouteManifest;
30
- headTags: DefinedHeadTags<TRouteManifest, THeadTagSchema, TDefinitions>;
29
+ headTags: DefinedHeadTags<TRouteManifest, TRouterSchema>;
31
30
  html: HtmlOptions;
32
31
  headBasePath?: string;
33
32
  routeBasePath?: string;
34
33
  }
34
+ export interface HandleHeadTagRequestOptions<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape> {
35
+ headTags: DefinedHeadTags<TRouteManifest, TRouterSchema>;
36
+ headBasePath?: string;
37
+ }
35
38
  export interface HandleRequestResult {
36
39
  matched: boolean;
37
40
  response: Response;
38
41
  }
39
- export declare function handleRequest<TRouteManifest extends AnyRoute, THeadTagSchema extends HeadTagSchemaShape, TDefinitions extends Partial<Record<keyof THeadTagSchema, HeadTagDefinition<any>>>>(request: Request, options: HandleRequestOptions<TRouteManifest, THeadTagSchema, TDefinitions>): Promise<HandleRequestResult>;
42
+ export declare function handleHeadTagRequest<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape>(request: Request, options: HandleHeadTagRequestOptions<TRouteManifest, TRouterSchema>): Promise<HandleRequestResult>;
43
+ export declare function handleRequest<TRouteManifest extends AnyRoute, TRouterSchema extends RouterSchemaShape>(request: Request, options: HandleRequestOptions<TRouteManifest, TRouterSchema>): Promise<HandleRequestResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@richie-router/server",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
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.1"
16
+ "@richie-router/core": "^0.1.2"
17
17
  },
18
18
  "author": "Richie <oss@ricsam.dev>",
19
19
  "homepage": "https://docs.ricsam.dev/richie-router",