@rudderjs/router 1.2.0 → 1.2.1

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.
@@ -0,0 +1,104 @@
1
+ /** @internal — verb table for `resource()` / `apiResource()`. */
2
+ export const RESOURCE_VERBS = [
3
+ { verb: 'index', method: 'GET', path: (n) => `/${n}`, nameSuffix: 'index' },
4
+ { verb: 'create', method: 'GET', path: (n) => `/${n}/create`, nameSuffix: 'create' },
5
+ { verb: 'store', method: 'POST', path: (n) => `/${n}`, nameSuffix: 'store' },
6
+ { verb: 'show', method: 'GET', path: (n, p) => `/${n}/:${p}`, nameSuffix: 'show' },
7
+ { verb: 'edit', method: 'GET', path: (n, p) => `/${n}/:${p}/edit`, nameSuffix: 'edit' },
8
+ { verb: 'update', method: 'PUT', path: (n, p) => `/${n}/:${p}`, nameSuffix: 'update' },
9
+ { verb: 'destroy', method: 'DELETE', path: (n, p) => `/${n}/:${p}`, nameSuffix: 'destroy' },
10
+ ];
11
+ /** @internal — verb table for `singleton()`. */
12
+ export const SINGLETON_VERBS = [
13
+ { verb: 'show', method: 'GET', path: (n) => `/${n}`, nameSuffix: 'show' },
14
+ { verb: 'edit', method: 'GET', path: (n) => `/${n}/edit`, nameSuffix: 'edit' },
15
+ { verb: 'update', method: 'PUT', path: (n) => `/${n}`, nameSuffix: 'update' },
16
+ ];
17
+ /** @internal — `.creatable()` opt-in for singletons. */
18
+ export const SINGLETON_CREATE_VERBS = [
19
+ { verb: 'create', method: 'GET', path: (n) => `/${n}/create`, nameSuffix: 'create' },
20
+ { verb: 'store', method: 'POST', path: (n) => `/${n}`, nameSuffix: 'store' },
21
+ ];
22
+ /** @internal — `.destroyable()` opt-in for singletons. */
23
+ export const SINGLETON_DESTROY_VERBS = [
24
+ { verb: 'destroy', method: 'DELETE', path: (n) => `/${n}`, nameSuffix: 'destroy' },
25
+ ];
26
+ /** @internal — apply `only` / `except` to a verb table. */
27
+ export function filterVerbs(table, opts) {
28
+ let verbs = table;
29
+ if (opts.only) {
30
+ const allow = new Set(opts.only);
31
+ verbs = verbs.filter(v => allow.has(v.verb));
32
+ }
33
+ if (opts.except) {
34
+ const deny = new Set(opts.except);
35
+ verbs = verbs.filter(v => !deny.has(v.verb));
36
+ }
37
+ return verbs;
38
+ }
39
+ /**
40
+ * @internal — naive English singularizer for the default resource param name.
41
+ * Handles the three patterns Laravel users hit constantly (`posts → post`,
42
+ * `categories → category`, `boxes → box`). Anything irregular — `people`,
43
+ * `data`, etc. — should be overridden via the `parameters` option, exactly
44
+ * as in Laravel.
45
+ */
46
+ export function singularize(name) {
47
+ if (/[^aeiou]ies$/i.test(name))
48
+ return name.slice(0, -3) + 'y'; // categories → category
49
+ if (/(s|x|z|ch|sh)es$/i.test(name))
50
+ return name.slice(0, -2); // boxes → box
51
+ if (/s$/i.test(name) && !/ss$/i.test(name))
52
+ return name.slice(0, -1); // posts → post
53
+ return name;
54
+ }
55
+ /**
56
+ * Returned by `router.resource()`/`apiResource()`. The `builders` array holds
57
+ * one `RouteBuilder` per registered route in declaration order — apply
58
+ * `where*()`, additional middleware, or rename individual routes by indexing
59
+ * directly. The `update` PATCH alias is included as a separate builder
60
+ * immediately after its PUT counterpart.
61
+ */
62
+ export class ResourceRegistration {
63
+ builders;
64
+ constructor(builders) {
65
+ this.builders = builders;
66
+ }
67
+ }
68
+ /**
69
+ * Returned by `router.singleton()`. Adds two opt-in helpers on top of
70
+ * `ResourceRegistration` for resources that also expose a creation flow
71
+ * (`.creatable()`) or deletion flow (`.destroyable()`).
72
+ */
73
+ export class SingletonRegistration extends ResourceRegistration {
74
+ _router;
75
+ _name;
76
+ _Ctrl;
77
+ _opts;
78
+ constructor(builders, _router, _name, _Ctrl, _opts) {
79
+ super(builders);
80
+ this._router = _router;
81
+ this._name = _name;
82
+ this._Ctrl = _Ctrl;
83
+ this._opts = _opts;
84
+ }
85
+ /**
86
+ * Add `GET /<name>/create` and `POST /<name>` — the create/store half of a
87
+ * full resource. Skipped for any verb the controller doesn't implement.
88
+ */
89
+ creatable() {
90
+ const reg = this._router._registerResource(this._name, this._Ctrl, SINGLETON_CREATE_VERBS, this._opts);
91
+ this.builders.push(...reg.builders);
92
+ return this;
93
+ }
94
+ /**
95
+ * Add `DELETE /<name>` — the destroy half of a full resource. Skipped if
96
+ * the controller doesn't implement `destroy()`.
97
+ */
98
+ destroyable() {
99
+ const reg = this._router._registerResource(this._name, this._Ctrl, SINGLETON_DESTROY_VERBS, this._opts);
100
+ this.builders.push(...reg.builders);
101
+ return this;
102
+ }
103
+ }
104
+ //# sourceMappingURL=resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { AppRequest, MiddlewareHandler } from '@rudderjs/contracts';
2
+ export declare class Url {
3
+ /**
4
+ * Override the HMAC signing key used for signed URLs.
5
+ * Falls back to `process.env.APP_KEY`.
6
+ */
7
+ static setKey(key: string): void;
8
+ /** The full URL of the current request. */
9
+ static current(req: AppRequest): string;
10
+ /** The previous URL from the `Referer` header, or `fallback`. */
11
+ static previous(req: AppRequest, fallback?: string): string;
12
+ /**
13
+ * Generate a signed URL for a named route.
14
+ *
15
+ * @example
16
+ * Url.signedRoute('invoice.download', { id: 42 })
17
+ * // → '/invoice/42?signature=abc123'
18
+ */
19
+ static signedRoute(name: string, params?: Record<string, string | number>, expiresAt?: Date): string;
20
+ /**
21
+ * Generate a signed URL that expires after `seconds` seconds.
22
+ *
23
+ * @example
24
+ * Url.temporarySignedRoute('invoice.download', 3600, { id: 42 })
25
+ * // → '/invoice/42?expires=1234567890&signature=abc123'
26
+ */
27
+ static temporarySignedRoute(name: string, seconds: number, params?: Record<string, string | number>): string;
28
+ /**
29
+ * Sign an arbitrary path string.
30
+ * Appends `?signature=...` (and `?expires=...` if `expiresAt` given).
31
+ */
32
+ static sign(path: string, expiresAt?: Date): string;
33
+ /**
34
+ * Return `true` if the request has a valid (and non-expired) signature.
35
+ */
36
+ static isValidSignature(req: AppRequest): boolean;
37
+ }
38
+ /**
39
+ * Middleware that verifies a signed URL signature.
40
+ * Responds with 403 if the signature is missing, invalid, or expired.
41
+ *
42
+ * @example
43
+ * router.get('/invoice/:id/download', handler, [ValidateSignature()])
44
+ */
45
+ export declare function ValidateSignature(): MiddlewareHandler;
46
+ //# sourceMappingURL=url-signing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-signing.d.ts","sourceRoot":"","sources":["../src/url-signing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AA6CxE,qBAAa,GAAG;IACd;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIhC,2CAA2C;IAC3C,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM;IAIvC,iEAAiE;IACjE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,SAAM,GAAG,MAAM;IAIxD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAChB,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAM,EAC5C,SAAS,CAAC,EAAE,IAAI,GACf,MAAM;IAIT;;;;;;OAMG;IACH,MAAM,CAAC,oBAAoB,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAM,GAC3C,MAAM;IAIT;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM;IAcnD;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;CA2BlD;AAID;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,CAOrD"}
@@ -0,0 +1,133 @@
1
+ import { route } from './index.js';
2
+ // ─── node:crypto lazy load ─────────────────────────────────
3
+ //
4
+ // Lazy-load node:crypto to avoid bundling it into the client. Only used by
5
+ // Url (signed URLs) and ValidateSignature — server-only features. The
6
+ // fire-and-forget import preloads on server and is a no-op in the browser
7
+ // where `globalThis.process` is undefined.
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ let _crypto;
10
+ if (typeof globalThis.process !== 'undefined') {
11
+ import(/* @vite-ignore */ 'node:crypto').then(m => { _crypto = m; }).catch(() => { });
12
+ }
13
+ // ─── Signing key + helpers ─────────────────────────────────
14
+ let _urlKey = '';
15
+ function _getSigningKey() {
16
+ const key = _urlKey || process.env['APP_KEY'] || '';
17
+ if (!key)
18
+ throw new Error('[RudderJS] No signing key configured. Set APP_KEY in your .env or call Url.setKey().');
19
+ return key;
20
+ }
21
+ function _splitPath(path) {
22
+ const idx = path.indexOf('?');
23
+ return idx === -1 ? [path, ''] : [path.slice(0, idx), path.slice(idx + 1)];
24
+ }
25
+ function _computeSignature(pathname, params) {
26
+ // Sort params for deterministic signing (exclude 'signature' itself)
27
+ const sorted = new URLSearchParams([...params.entries()]
28
+ .filter(([k]) => k !== 'signature')
29
+ .sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
30
+ const toSign = sorted.size > 0 ? `${pathname}?${sorted.toString()}` : pathname;
31
+ if (!_crypto)
32
+ throw new Error('[RudderJS Router] node:crypto not available — Url signing requires a server environment.');
33
+ return _crypto.createHmac('sha256', _getSigningKey()).update(toSign).digest('hex');
34
+ }
35
+ // ─── Url ───────────────────────────────────────────────────
36
+ export class Url {
37
+ /**
38
+ * Override the HMAC signing key used for signed URLs.
39
+ * Falls back to `process.env.APP_KEY`.
40
+ */
41
+ static setKey(key) {
42
+ _urlKey = key;
43
+ }
44
+ /** The full URL of the current request. */
45
+ static current(req) {
46
+ return req.url;
47
+ }
48
+ /** The previous URL from the `Referer` header, or `fallback`. */
49
+ static previous(req, fallback = '/') {
50
+ return req.headers['referer'] ?? fallback;
51
+ }
52
+ /**
53
+ * Generate a signed URL for a named route.
54
+ *
55
+ * @example
56
+ * Url.signedRoute('invoice.download', { id: 42 })
57
+ * // → '/invoice/42?signature=abc123'
58
+ */
59
+ static signedRoute(name, params = {}, expiresAt) {
60
+ return Url.sign(route(name, params), expiresAt);
61
+ }
62
+ /**
63
+ * Generate a signed URL that expires after `seconds` seconds.
64
+ *
65
+ * @example
66
+ * Url.temporarySignedRoute('invoice.download', 3600, { id: 42 })
67
+ * // → '/invoice/42?expires=1234567890&signature=abc123'
68
+ */
69
+ static temporarySignedRoute(name, seconds, params = {}) {
70
+ return Url.signedRoute(name, params, new Date(Date.now() + seconds * 1000));
71
+ }
72
+ /**
73
+ * Sign an arbitrary path string.
74
+ * Appends `?signature=...` (and `?expires=...` if `expiresAt` given).
75
+ */
76
+ static sign(path, expiresAt) {
77
+ const [pathname, search] = _splitPath(path);
78
+ const params = new URLSearchParams(search);
79
+ if (expiresAt) {
80
+ params.set('expires', String(Math.floor(expiresAt.getTime() / 1000)));
81
+ }
82
+ const sig = _computeSignature(pathname, params);
83
+ params.set('signature', sig);
84
+ return `${pathname}?${params.toString()}`;
85
+ }
86
+ /**
87
+ * Return `true` if the request has a valid (and non-expired) signature.
88
+ */
89
+ static isValidSignature(req) {
90
+ // `req.url` may be a full URL (Hono adapter populates protocol+host+path+query)
91
+ // or a bare path. `Url.sign(path)` only ever signs the pathname, so verification
92
+ // must hash the same shape. Use the URL parser so both forms collapse to a
93
+ // pathname + searchParams pair.
94
+ const u = new URL(req.url, 'http://placeholder.local');
95
+ const pathname = u.pathname;
96
+ const params = u.searchParams;
97
+ const signature = params.get('signature');
98
+ if (!signature)
99
+ return false;
100
+ // Check expiry before touching the signature
101
+ const expires = params.get('expires');
102
+ if (expires !== null) {
103
+ const expiry = parseInt(expires, 10);
104
+ if (isNaN(expiry) || Date.now() / 1000 > expiry)
105
+ return false;
106
+ }
107
+ const expected = _computeSignature(pathname, params);
108
+ if (!_crypto)
109
+ return signature === expected;
110
+ const sigBuf = Buffer.from(signature);
111
+ const expBuf = Buffer.from(expected);
112
+ if (sigBuf.length !== expBuf.length)
113
+ return false;
114
+ return _crypto.timingSafeEqual(sigBuf, expBuf);
115
+ }
116
+ }
117
+ // ─── ValidateSignature middleware ───────────────────────────
118
+ /**
119
+ * Middleware that verifies a signed URL signature.
120
+ * Responds with 403 if the signature is missing, invalid, or expired.
121
+ *
122
+ * @example
123
+ * router.get('/invoice/:id/download', handler, [ValidateSignature()])
124
+ */
125
+ export function ValidateSignature() {
126
+ return async (req, res, next) => {
127
+ if (!Url.isValidSignature(req)) {
128
+ return res.status(403).json({ message: 'Invalid or expired URL signature.' });
129
+ }
130
+ await next();
131
+ };
132
+ }
133
+ //# sourceMappingURL=url-signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-signing.js","sourceRoot":"","sources":["../src/url-signing.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rudderjs/router",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,6 +8,9 @@
8
8
  "directory": "packages/router"
9
9
  },
10
10
  "type": "module",
11
+ "engines": {
12
+ "node": "^20.19.0 || >=22.12.0"
13
+ },
11
14
  "files": [
12
15
  "dist",
13
16
  "boost"
@@ -27,7 +30,7 @@
27
30
  },
28
31
  "dependencies": {
29
32
  "reflect-metadata": "^0.2.2",
30
- "@rudderjs/contracts": "^1.4.0"
33
+ "@rudderjs/contracts": "^1.6.1"
31
34
  },
32
35
  "devDependencies": {
33
36
  "@types/node": "^20.0.0",