oc-fastify-server-adapter 0.1.3 → 0.1.4

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/dist/index.d.ts CHANGED
@@ -100,6 +100,20 @@ export interface FastifyServerAdapterOptions {
100
100
  host?: string;
101
101
  port?: number | string;
102
102
  trustProxy?: boolean | string | string[] | number;
103
+ /**
104
+ * When enabled, Fastify treats `/foo` and `/foo/` as the same route, matching
105
+ * Express' default (non-strict) trailing-slash behavior. This is convenient
106
+ * for incoming requests that include a trailing slash, but it is slightly less
107
+ * performant than Fastify's native routing and requires OC to deduplicate
108
+ * routes that only differ by a trailing slash.
109
+ *
110
+ * Defaults to `false` to keep Fastify's faster native routing. OC's own routes
111
+ * never rely on trailing slashes, so the default is safe for the built-in
112
+ * registry endpoints.
113
+ *
114
+ * @default false
115
+ */
116
+ ignoreTrailingSlash?: boolean;
103
117
  }
104
118
  export type HttpServerAdapterFactory<TOptions = unknown, TNative = unknown> = {
105
119
  (options?: unknown): HttpServerAdapter<TNative>;
package/dist/index.js CHANGED
@@ -28,15 +28,19 @@ class FastifyHttpServerAdapter {
28
28
  bodyInflationRegistered = false;
29
29
  bodyLimit = defaultBodyLimit;
30
30
  host;
31
+ ignoreTrailingSlash;
32
+ registeredRoutes = new Set();
31
33
  routes = [];
32
34
  optionsRoutesRegistered = false;
33
35
  constructor(options = {}) {
34
36
  this.host = options.host;
37
+ this.ignoreTrailingSlash = options.ignoreTrailingSlash ?? false;
35
38
  this.app = (0, fastify_1.default)({
36
39
  bodyLimit: this.bodyLimit,
37
40
  exposeHeadRoutes: true,
38
41
  logger: false,
39
42
  routerOptions: {
43
+ ignoreTrailingSlash: this.ignoreTrailingSlash,
40
44
  querystringParser: (str) => (0, node_querystring_1.parse)(str)
41
45
  },
42
46
  trustProxy: options.trustProxy
@@ -156,6 +160,18 @@ class FastifyHttpServerAdapter {
156
160
  }
157
161
  route(method, routePath, id, handlers) {
158
162
  const url = toFastifyRoutePath(routePath);
163
+ // With `ignoreTrailingSlash` enabled Fastify treats `/foo` and `/foo/` as
164
+ // the same route and throws on duplicate registrations. Deduplicate so a
165
+ // consumer registering both variants does not crash the server. When the
166
+ // option is disabled the two paths are distinct routes, so we let Fastify
167
+ // register both.
168
+ if (this.ignoreTrailingSlash) {
169
+ const routeKey = `${method}:${stripTrailingSlash(url)}`;
170
+ if (this.registeredRoutes.has(routeKey)) {
171
+ return;
172
+ }
173
+ this.registeredRoutes.add(routeKey);
174
+ }
159
175
  this.routes.push({ method, path: url });
160
176
  this.app.route({
161
177
  bodyLimit: this.bodyLimit,
@@ -506,10 +522,13 @@ function isFastifyAdapterOptions(options) {
506
522
  const port = candidate.port;
507
523
  const host = candidate.host;
508
524
  const trustProxy = candidate.trustProxy;
525
+ const ignoreTrailingSlash = candidate.ignoreTrailingSlash;
509
526
  return ((typeof port === 'undefined' ||
510
527
  typeof port === 'number' ||
511
528
  typeof port === 'string') &&
512
529
  (typeof host === 'undefined' || typeof host === 'string') &&
530
+ (typeof ignoreTrailingSlash === 'undefined' ||
531
+ typeof ignoreTrailingSlash === 'boolean') &&
513
532
  (typeof trustProxy === 'undefined' ||
514
533
  typeof trustProxy === 'boolean' ||
515
534
  typeof trustProxy === 'string' ||
@@ -520,6 +539,9 @@ function isFastifyAdapterOptions(options) {
520
539
  function toFastifyRoutePath(routePath) {
521
540
  return routePath.replace(/\*[A-Za-z0-9_]+/g, '*');
522
541
  }
542
+ function stripTrailingSlash(value) {
543
+ return value !== '/' && value.endsWith('/') ? value.slice(0, -1) : value;
544
+ }
523
545
  function routePathMatches(routePath, pathname) {
524
546
  if (routePath === pathname) {
525
547
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oc-fastify-server-adapter",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Fastify HTTP server adapter for OC",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",