route-scoped-cors 0.1.0
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/core/middleware.d.ts +30 -0
- package/dist/core/middleware.d.ts.map +1 -0
- package/dist/core/middleware.js +67 -0
- package/dist/core/middleware.js.map +1 -0
- package/dist/core/path-matcher.d.ts +7 -0
- package/dist/core/path-matcher.d.ts.map +1 -0
- package/dist/core/path-matcher.js +28 -0
- package/dist/core/path-matcher.js.map +1 -0
- package/dist/core/route-map.d.ts +9 -0
- package/dist/core/route-map.d.ts.map +1 -0
- package/dist/core/route-map.js +44 -0
- package/dist/core/route-map.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/nestjs/index.d.ts +5 -0
- package/dist/nestjs/index.d.ts.map +1 -0
- package/dist/nestjs/index.js +10 -0
- package/dist/nestjs/index.js.map +1 -0
- package/dist/nestjs/middleware.d.ts +9 -0
- package/dist/nestjs/middleware.d.ts.map +1 -0
- package/dist/nestjs/middleware.js +34 -0
- package/dist/nestjs/middleware.js.map +1 -0
- package/dist/nestjs/module.d.ts +23 -0
- package/dist/nestjs/module.d.ts.map +1 -0
- package/dist/nestjs/module.js +52 -0
- package/dist/nestjs/module.js.map +1 -0
- package/dist/nestjs/tokens.d.ts +2 -0
- package/dist/nestjs/tokens.d.ts.map +1 -0
- package/dist/nestjs/tokens.js +5 -0
- package/dist/nestjs/tokens.js.map +1 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RouteScopedCorsOptions, ExpressMiddlewareFn } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns an Express middleware function that overrides
|
|
4
|
+
* `Access-Control-Allow-Methods` with the exact set of HTTP methods
|
|
5
|
+
* registered for the matched route.
|
|
6
|
+
*
|
|
7
|
+
* The route map is built lazily on the first request so all routes are
|
|
8
|
+
* guaranteed to be registered in the Express router before inspection.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Express
|
|
12
|
+
* app.use(routeScopedCors());
|
|
13
|
+
*
|
|
14
|
+
* // Express with options
|
|
15
|
+
* app.use(routeScopedCors({ fallbackMethods: ['GET', 'POST', 'OPTIONS'] }));
|
|
16
|
+
*/
|
|
17
|
+
export declare function routeScopedCors(options?: RouteScopedCorsOptions): ExpressMiddlewareFn;
|
|
18
|
+
/**
|
|
19
|
+
* Installs `routeScopedCors` onto an Express (or Connect-compatible) app.
|
|
20
|
+
* Equivalent to calling `app.use(routeScopedCors(options))`.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* import express from 'express';
|
|
24
|
+
* import { install } from 'route-scoped-cors';
|
|
25
|
+
*
|
|
26
|
+
* const app = express();
|
|
27
|
+
* install(app);
|
|
28
|
+
*/
|
|
29
|
+
export declare function install(app: any, options?: RouteScopedCorsOptions): void;
|
|
30
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/core/middleware.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAM5E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,mBAAmB,CAmCzF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAOxE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.routeScopedCors = routeScopedCors;
|
|
4
|
+
exports.install = install;
|
|
5
|
+
const route_map_1 = require("./route-map");
|
|
6
|
+
const path_matcher_1 = require("./path-matcher");
|
|
7
|
+
const DEFAULT_FALLBACK_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];
|
|
8
|
+
/**
|
|
9
|
+
* Returns an Express middleware function that overrides
|
|
10
|
+
* `Access-Control-Allow-Methods` with the exact set of HTTP methods
|
|
11
|
+
* registered for the matched route.
|
|
12
|
+
*
|
|
13
|
+
* The route map is built lazily on the first request so all routes are
|
|
14
|
+
* guaranteed to be registered in the Express router before inspection.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Express
|
|
18
|
+
* app.use(routeScopedCors());
|
|
19
|
+
*
|
|
20
|
+
* // Express with options
|
|
21
|
+
* app.use(routeScopedCors({ fallbackMethods: ['GET', 'POST', 'OPTIONS'] }));
|
|
22
|
+
*/
|
|
23
|
+
function routeScopedCors(options = {}) {
|
|
24
|
+
var _a;
|
|
25
|
+
const fallbackMethods = (_a = options.fallbackMethods) !== null && _a !== void 0 ? _a : DEFAULT_FALLBACK_METHODS;
|
|
26
|
+
let routeMap = null;
|
|
27
|
+
return function routeScopedCorsMiddleware(req, res, next) {
|
|
28
|
+
if (!routeMap) {
|
|
29
|
+
routeMap = (0, route_map_1.buildRouteMap)(req.app);
|
|
30
|
+
}
|
|
31
|
+
const allowedMethods = (0, path_matcher_1.matchAllowedMethods)(routeMap, req.path, fallbackMethods);
|
|
32
|
+
res.setHeader('Access-Control-Allow-Methods', allowedMethods.join(', '));
|
|
33
|
+
if (req.method === 'OPTIONS') {
|
|
34
|
+
res.status(204).end();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!allowedMethods.includes(req.method.toUpperCase())) {
|
|
38
|
+
const actualMethods = allowedMethods.filter((m) => m !== 'OPTIONS');
|
|
39
|
+
res.setHeader('Allow', actualMethods.join(', '));
|
|
40
|
+
res.status(405).json({
|
|
41
|
+
statusCode: 405,
|
|
42
|
+
message: 'Method Not Allowed',
|
|
43
|
+
error: `${req.method} is not supported on this resource. Allowed: ${actualMethods.join(', ')}`,
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
next();
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Installs `routeScopedCors` onto an Express (or Connect-compatible) app.
|
|
52
|
+
* Equivalent to calling `app.use(routeScopedCors(options))`.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* import express from 'express';
|
|
56
|
+
* import { install } from 'route-scoped-cors';
|
|
57
|
+
*
|
|
58
|
+
* const app = express();
|
|
59
|
+
* install(app);
|
|
60
|
+
*/
|
|
61
|
+
function install(app, options) {
|
|
62
|
+
if (typeof (app === null || app === void 0 ? void 0 : app.use) !== 'function') {
|
|
63
|
+
throw new Error('[route-scoped-cors] install() requires an Express or Connect-compatible application instance.');
|
|
64
|
+
}
|
|
65
|
+
app.use(routeScopedCors(options));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/core/middleware.ts"],"names":[],"mappings":";;AAsBA,0CAmCC;AAaD,0BAOC;AA3ED,2CAA4C;AAC5C,iDAAqD;AAErD,MAAM,wBAAwB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;AAEtF;;;;;;;;;;;;;;GAcG;AACH,SAAgB,eAAe,CAAC,UAAkC,EAAE;;IAClE,MAAM,eAAe,GAAG,MAAA,OAAO,CAAC,eAAe,mCAAI,wBAAwB,CAAC;IAC5E,IAAI,QAAQ,GAAoC,IAAI,CAAC;IAErD,OAAO,SAAS,yBAAyB,CACvC,GAA4B,EAC5B,GAAa,EACb,IAAkB;QAElB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,IAAA,yBAAa,EAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,cAAc,GAAG,IAAA,kCAAmB,EAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAEhF,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAEzE,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YACvD,MAAM,aAAa,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;YACpE,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACjD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,UAAU,EAAE,GAAG;gBACf,OAAO,EAAE,oBAAoB;gBAC7B,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,gDAAgD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aAC/F,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,OAAO,CAAC,GAAQ,EAAE,OAAgC;IAChE,IAAI,OAAO,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,GAAG,CAAA,KAAK,UAAU,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,+FAA+F,CAChG,CAAC;IACJ,CAAC;IACD,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the allowed methods for `requestPath` by matching against the
|
|
3
|
+
* stored route map. Express path params (`:id`) are treated as wildcards.
|
|
4
|
+
* Returns `fallbackMethods` when no pattern matches.
|
|
5
|
+
*/
|
|
6
|
+
export declare function matchAllowedMethods(routeMap: Map<string, Set<string>>, requestPath: string, fallbackMethods: string[]): string[];
|
|
7
|
+
//# sourceMappingURL=path-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-matcher.d.ts","sourceRoot":"","sources":["../../src/core/path-matcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAClC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EAAE,GACxB,MAAM,EAAE,CAkBV"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.matchAllowedMethods = matchAllowedMethods;
|
|
4
|
+
/**
|
|
5
|
+
* Finds the allowed methods for `requestPath` by matching against the
|
|
6
|
+
* stored route map. Express path params (`:id`) are treated as wildcards.
|
|
7
|
+
* Returns `fallbackMethods` when no pattern matches.
|
|
8
|
+
*/
|
|
9
|
+
function matchAllowedMethods(routeMap, requestPath, fallbackMethods) {
|
|
10
|
+
for (const [pattern, methods] of routeMap.entries()) {
|
|
11
|
+
const regexStr = '^' +
|
|
12
|
+
pattern
|
|
13
|
+
.replace(/\//g, '\\/')
|
|
14
|
+
.replace(/:[^/]+/g, '[^/]+') // :param → any non-slash segment
|
|
15
|
+
.replace(/\*/g, '.*') + // wildcard support
|
|
16
|
+
'$';
|
|
17
|
+
try {
|
|
18
|
+
if (new RegExp(regexStr).test(requestPath)) {
|
|
19
|
+
return [...methods];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Malformed pattern — skip rather than crash
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return fallbackMethods;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=path-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-matcher.js","sourceRoot":"","sources":["../../src/core/path-matcher.ts"],"names":[],"mappings":";;AAKA,kDAsBC;AA3BD;;;;GAIG;AACH,SAAgB,mBAAmB,CACjC,QAAkC,EAClC,WAAmB,EACnB,eAAyB;IAEzB,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QACpD,MAAM,QAAQ,GACZ,GAAG;YACH,OAAO;iBACJ,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;iBACrB,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,iCAAiC;iBAC7D,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,GAAS,mBAAmB;YACnD,GAAG,CAAC;QACN,IAAI,CAAC;YACH,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks the Express _router.stack recursively to build a map of
|
|
3
|
+
* route path-pattern → Set of uppercase HTTP methods.
|
|
4
|
+
*
|
|
5
|
+
* Built lazily on the first request so that all routes are guaranteed
|
|
6
|
+
* to be registered before inspection.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildRouteMap(expressApp: any): Map<string, Set<string>>;
|
|
9
|
+
//# sourceMappingURL=route-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-map.d.ts","sourceRoot":"","sources":["../../src/core/route-map.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAmCvE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildRouteMap = buildRouteMap;
|
|
4
|
+
/**
|
|
5
|
+
* Walks the Express _router.stack recursively to build a map of
|
|
6
|
+
* route path-pattern → Set of uppercase HTTP methods.
|
|
7
|
+
*
|
|
8
|
+
* Built lazily on the first request so that all routes are guaranteed
|
|
9
|
+
* to be registered before inspection.
|
|
10
|
+
*/
|
|
11
|
+
function buildRouteMap(expressApp) {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const map = new Map();
|
|
14
|
+
const walkLayer = (layer, prefix = '') => {
|
|
15
|
+
var _a, _b, _c;
|
|
16
|
+
if (layer.route) {
|
|
17
|
+
const path = (prefix + layer.route.path).replace(/\/+/g, '/');
|
|
18
|
+
const methods = new Set(Object.keys(layer.route.methods)
|
|
19
|
+
.filter((m) => m !== '_all' && layer.route.methods[m])
|
|
20
|
+
.map((m) => m.toUpperCase()));
|
|
21
|
+
// OPTIONS is always required for CORS preflight
|
|
22
|
+
methods.add('OPTIONS');
|
|
23
|
+
const existing = map.get(path);
|
|
24
|
+
if (existing) {
|
|
25
|
+
methods.forEach((m) => existing.add(m));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
map.set(path, methods);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if ((_a = layer.handle) === null || _a === void 0 ? void 0 : _a.stack) {
|
|
32
|
+
// Nested router: extract the path segment from the compiled regexp.
|
|
33
|
+
// Express compiles router paths into regexps like: ^\/segment\/?(?=\/|$)
|
|
34
|
+
const src = (_c = (_b = layer.regexp) === null || _b === void 0 ? void 0 : _b.source) !== null && _c !== void 0 ? _c : '';
|
|
35
|
+
const match = src.match(/^\^\\\/([^\\?$/]*)/);
|
|
36
|
+
const segment = match ? `/${match[1].replace(/\\\//g, '/')}` : '';
|
|
37
|
+
layer.handle.stack.forEach((child) => walkLayer(child, prefix + segment));
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const stack = (_b = (_a = expressApp === null || expressApp === void 0 ? void 0 : expressApp._router) === null || _a === void 0 ? void 0 : _a.stack) !== null && _b !== void 0 ? _b : [];
|
|
41
|
+
stack.forEach((layer) => walkLayer(layer));
|
|
42
|
+
return map;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=route-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-map.js","sourceRoot":"","sources":["../../src/core/route-map.ts"],"names":[],"mappings":";;AAOA,sCAmCC;AA1CD;;;;;;GAMG;AACH,SAAgB,aAAa,CAAC,UAAe;;IAC3C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuB,CAAC;IAE3C,MAAM,SAAS,GAAG,CAAC,KAAU,EAAE,MAAM,GAAG,EAAE,EAAQ,EAAE;;QAClD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAI,KAAK,CAAC,KAAK,CAAC,IAAe,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC1E,MAAM,OAAO,GAAG,IAAI,GAAG,CACpB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAc;iBAC3C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;iBACrD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAC/B,CAAC;YACF,gDAAgD;YAChD,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAEvB,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;aAAM,IAAI,MAAA,KAAK,CAAC,MAAM,0CAAE,KAAK,EAAE,CAAC;YAC/B,oEAAoE;YACpE,yEAAyE;YACzE,MAAM,GAAG,GAAW,MAAA,MAAA,KAAK,CAAC,MAAM,0CAAE,MAAM,mCAAI,EAAE,CAAC;YAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;YAC9C,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,KAAK,CAAC,MAAM,CAAC,KAAe,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAC9C,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CACnC,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,KAAK,GAAU,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,OAAO,0CAAE,KAAK,mCAAI,EAAE,CAAC;IACtD,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC7D,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.install = exports.routeScopedCors = void 0;
|
|
4
|
+
var middleware_1 = require("./core/middleware");
|
|
5
|
+
Object.defineProperty(exports, "routeScopedCors", { enumerable: true, get: function () { return middleware_1.routeScopedCors; } });
|
|
6
|
+
Object.defineProperty(exports, "install", { enumerable: true, get: function () { return middleware_1.install; } });
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,gDAA6D;AAApD,6GAAA,eAAe,OAAA;AAAE,qGAAA,OAAO,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nestjs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrD,YAAY,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ROUTE_SCOPED_CORS_OPTIONS = exports.RouteScopedCorsMiddleware = exports.RouteScopedCorsModule = void 0;
|
|
4
|
+
var module_1 = require("./module");
|
|
5
|
+
Object.defineProperty(exports, "RouteScopedCorsModule", { enumerable: true, get: function () { return module_1.RouteScopedCorsModule; } });
|
|
6
|
+
var middleware_1 = require("./middleware");
|
|
7
|
+
Object.defineProperty(exports, "RouteScopedCorsMiddleware", { enumerable: true, get: function () { return middleware_1.RouteScopedCorsMiddleware; } });
|
|
8
|
+
var tokens_1 = require("./tokens");
|
|
9
|
+
Object.defineProperty(exports, "ROUTE_SCOPED_CORS_OPTIONS", { enumerable: true, get: function () { return tokens_1.ROUTE_SCOPED_CORS_OPTIONS; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nestjs/index.ts"],"names":[],"mappings":";;;AAAA,mCAAiD;AAAxC,+GAAA,qBAAqB,OAAA;AAC9B,2CAAyD;AAAhD,uHAAA,yBAAyB,OAAA;AAClC,mCAAqD;AAA5C,mHAAA,yBAAyB,OAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NestMiddleware } from '@nestjs/common';
|
|
2
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
3
|
+
import type { RouteScopedCorsOptions } from '../types';
|
|
4
|
+
export declare class RouteScopedCorsMiddleware implements NestMiddleware {
|
|
5
|
+
private readonly handler;
|
|
6
|
+
constructor(options?: RouteScopedCorsOptions);
|
|
7
|
+
use(req: Request, res: Response, next: NextFunction): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/nestjs/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,cAAc,EAAY,MAAM,gBAAgB,CAAC;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,KAAK,EAAuB,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAG5E,qBACa,yBAA0B,YAAW,cAAc;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;gBAGG,OAAO,CAAC,EAAE,sBAAsB;IAKjF,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI;CAG3D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.RouteScopedCorsMiddleware = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const middleware_1 = require("../core/middleware");
|
|
18
|
+
const tokens_1 = require("./tokens");
|
|
19
|
+
let RouteScopedCorsMiddleware = class RouteScopedCorsMiddleware {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.handler = (0, middleware_1.routeScopedCors)(options !== null && options !== void 0 ? options : {});
|
|
22
|
+
}
|
|
23
|
+
use(req, res, next) {
|
|
24
|
+
this.handler(req, res, next);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.RouteScopedCorsMiddleware = RouteScopedCorsMiddleware;
|
|
28
|
+
exports.RouteScopedCorsMiddleware = RouteScopedCorsMiddleware = __decorate([
|
|
29
|
+
(0, common_1.Injectable)(),
|
|
30
|
+
__param(0, (0, common_1.Optional)()),
|
|
31
|
+
__param(0, (0, common_1.Inject)(tokens_1.ROUTE_SCOPED_CORS_OPTIONS)),
|
|
32
|
+
__metadata("design:paramtypes", [Object])
|
|
33
|
+
], RouteScopedCorsMiddleware);
|
|
34
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/nestjs/middleware.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA8E;AAE9E,mDAAqD;AAErD,qCAAqD;AAG9C,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;IAGpC,YACiD,OAAgC;QAE/E,IAAI,CAAC,OAAO,GAAG,IAAA,4BAAe,EAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;QACjD,IAAI,CAAC,OAAO,CAAC,GAAU,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;CACF,CAAA;AAZY,8DAAyB;oCAAzB,yBAAyB;IADrC,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,iBAAQ,GAAE,CAAA;IAAE,WAAA,IAAA,eAAM,EAAC,kCAAyB,CAAC,CAAA;;GAJrC,yBAAyB,CAYrC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
|
|
2
|
+
import type { RouteScopedCorsOptions } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Drop-in NestJS module that automatically applies per-route CORS method
|
|
5
|
+
* scoping to every route in the application.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // app.module.ts
|
|
9
|
+
* import { RouteScopedCorsModule } from 'route-scoped-cors/nestjs';
|
|
10
|
+
*
|
|
11
|
+
* @Module({
|
|
12
|
+
* imports: [RouteScopedCorsModule.forRoot()],
|
|
13
|
+
* })
|
|
14
|
+
* export class AppModule {}
|
|
15
|
+
*
|
|
16
|
+
* // With options:
|
|
17
|
+
* RouteScopedCorsModule.forRoot({ fallbackMethods: ['GET', 'POST', 'OPTIONS'] })
|
|
18
|
+
*/
|
|
19
|
+
export declare class RouteScopedCorsModule implements NestModule {
|
|
20
|
+
static forRoot(options?: RouteScopedCorsOptions): DynamicModule;
|
|
21
|
+
configure(consumer: MiddlewareConsumer): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/nestjs/module.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,kBAAkB,EAElB,UAAU,EAEX,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAIvD;;;;;;;;;;;;;;;GAeG;AACH,qBACa,qBAAsB,YAAW,UAAU;IACtD,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,sBAA2B,GAAG,aAAa;IAYnE,SAAS,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;CAK9C"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var RouteScopedCorsModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.RouteScopedCorsModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const middleware_1 = require("./middleware");
|
|
13
|
+
const tokens_1 = require("./tokens");
|
|
14
|
+
/**
|
|
15
|
+
* Drop-in NestJS module that automatically applies per-route CORS method
|
|
16
|
+
* scoping to every route in the application.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // app.module.ts
|
|
20
|
+
* import { RouteScopedCorsModule } from 'route-scoped-cors/nestjs';
|
|
21
|
+
*
|
|
22
|
+
* @Module({
|
|
23
|
+
* imports: [RouteScopedCorsModule.forRoot()],
|
|
24
|
+
* })
|
|
25
|
+
* export class AppModule {}
|
|
26
|
+
*
|
|
27
|
+
* // With options:
|
|
28
|
+
* RouteScopedCorsModule.forRoot({ fallbackMethods: ['GET', 'POST', 'OPTIONS'] })
|
|
29
|
+
*/
|
|
30
|
+
let RouteScopedCorsModule = RouteScopedCorsModule_1 = class RouteScopedCorsModule {
|
|
31
|
+
static forRoot(options = {}) {
|
|
32
|
+
return {
|
|
33
|
+
module: RouteScopedCorsModule_1,
|
|
34
|
+
global: true,
|
|
35
|
+
providers: [
|
|
36
|
+
{ provide: tokens_1.ROUTE_SCOPED_CORS_OPTIONS, useValue: options },
|
|
37
|
+
middleware_1.RouteScopedCorsMiddleware,
|
|
38
|
+
],
|
|
39
|
+
exports: [middleware_1.RouteScopedCorsMiddleware],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
configure(consumer) {
|
|
43
|
+
consumer
|
|
44
|
+
.apply(middleware_1.RouteScopedCorsMiddleware)
|
|
45
|
+
.forRoutes({ path: '*', method: common_1.RequestMethod.ALL });
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
exports.RouteScopedCorsModule = RouteScopedCorsModule;
|
|
49
|
+
exports.RouteScopedCorsModule = RouteScopedCorsModule = RouteScopedCorsModule_1 = __decorate([
|
|
50
|
+
(0, common_1.Module)({})
|
|
51
|
+
], RouteScopedCorsModule);
|
|
52
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/nestjs/module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAMwB;AAExB,6CAAyD;AACzD,qCAAqD;AAErD;;;;;;;;;;;;;;;GAeG;AAEI,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IAChC,MAAM,CAAC,OAAO,CAAC,UAAkC,EAAE;QACjD,OAAO;YACL,MAAM,EAAE,uBAAqB;YAC7B,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE;gBACT,EAAE,OAAO,EAAE,kCAAyB,EAAE,QAAQ,EAAE,OAAO,EAAE;gBACzD,sCAAyB;aAC1B;YACD,OAAO,EAAE,CAAC,sCAAyB,CAAC;SACrC,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,QAA4B;QACpC,QAAQ;aACL,KAAK,CAAC,sCAAyB,CAAC;aAChC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,sBAAa,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;CACF,CAAA;AAlBY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,qBAAqB,CAkBjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/nestjs/tokens.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,8BAA8B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/nestjs/tokens.ts"],"names":[],"mappings":";;;AAAa,QAAA,yBAAyB,GAAG,2BAA2B,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
export interface RouteScopedCorsOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Methods returned for unmatched paths and preflight requests on unknown
|
|
5
|
+
* routes. Defaults to the standard set: GET POST PUT PATCH DELETE OPTIONS.
|
|
6
|
+
*/
|
|
7
|
+
fallbackMethods?: string[];
|
|
8
|
+
}
|
|
9
|
+
export type ExpressMiddlewareFn = (req: Request, res: Response, next: NextFunction) => void;
|
|
10
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,MAAM,mBAAmB,GAAG,CAChC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,KACf,IAAI,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "route-scoped-cors",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Per-route CORS method scoping middleware for Express and NestJS — prevents HTTP verb tampering by advertising only the methods each route actually handles.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./nestjs": {
|
|
16
|
+
"require": "./dist/nestjs/index.js",
|
|
17
|
+
"types": "./dist/nestjs/index.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"typesVersions": {
|
|
21
|
+
"*": {
|
|
22
|
+
"nestjs": [
|
|
23
|
+
"dist/nestjs/index.d.ts"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc -p tsconfig.build.json",
|
|
29
|
+
"prepublishOnly": "npm run build"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"cors",
|
|
33
|
+
"express",
|
|
34
|
+
"nestjs",
|
|
35
|
+
"middleware",
|
|
36
|
+
"route-scoped",
|
|
37
|
+
"http-methods",
|
|
38
|
+
"verb-tampering"
|
|
39
|
+
],
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@nestjs/common": ">=9.0.0",
|
|
43
|
+
"@nestjs/core": ">=9.0.0",
|
|
44
|
+
"express": ">=4.0.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"@nestjs/common": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"@nestjs/core": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@nestjs/common": "^10.0.0",
|
|
56
|
+
"@nestjs/core": "^10.0.0",
|
|
57
|
+
"@types/express": "^4.17.21",
|
|
58
|
+
"@types/node": "^20.0.0",
|
|
59
|
+
"reflect-metadata": "^0.1.13",
|
|
60
|
+
"typescript": "^5.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|