@veloxts/router 0.6.57 → 0.6.59
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/CHANGELOG.md +18 -0
- package/GUIDE.md +237 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +11 -0
- package/dist/openapi/generator.d.ts +52 -0
- package/dist/openapi/generator.js +442 -0
- package/dist/openapi/index.d.ts +37 -0
- package/dist/openapi/index.js +51 -0
- package/dist/openapi/path-extractor.d.ts +212 -0
- package/dist/openapi/path-extractor.js +256 -0
- package/dist/openapi/plugin.d.ts +101 -0
- package/dist/openapi/plugin.js +228 -0
- package/dist/openapi/schema-converter.d.ts +119 -0
- package/dist/openapi/schema-converter.js +246 -0
- package/dist/openapi/security-mapper.d.ts +131 -0
- package/dist/openapi/security-mapper.js +226 -0
- package/dist/openapi/types.d.ts +437 -0
- package/dist/openapi/types.js +8 -0
- package/package.json +8 -3
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Mapper
|
|
3
|
+
*
|
|
4
|
+
* Maps VeloxTS guards to OpenAPI security schemes.
|
|
5
|
+
*
|
|
6
|
+
* @module @veloxts/router/openapi/security-mapper
|
|
7
|
+
*/
|
|
8
|
+
import type { GuardLike } from '../types.js';
|
|
9
|
+
import type { OpenAPISecurityRequirement, OpenAPISecurityScheme } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Default mapping from guard names to security scheme names
|
|
12
|
+
*
|
|
13
|
+
* Maps common @veloxts/auth guard names to their corresponding
|
|
14
|
+
* OpenAPI security scheme identifiers.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEFAULT_GUARD_MAPPINGS: Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Default security schemes for VeloxTS auth patterns
|
|
19
|
+
*
|
|
20
|
+
* These are commonly used security schemes that can be merged
|
|
21
|
+
* with user-provided schemes.
|
|
22
|
+
*/
|
|
23
|
+
export declare const DEFAULT_SECURITY_SCHEMES: Record<string, OpenAPISecurityScheme>;
|
|
24
|
+
/**
|
|
25
|
+
* Options for mapping guards to security
|
|
26
|
+
*/
|
|
27
|
+
export interface GuardMappingOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Custom guard name to security scheme mapping
|
|
30
|
+
* Merged with default mappings (custom takes precedence)
|
|
31
|
+
*/
|
|
32
|
+
customMappings?: Record<string, string>;
|
|
33
|
+
/**
|
|
34
|
+
* Extract scopes from guard names
|
|
35
|
+
* e.g., 'hasRole:admin' -> scopes: ['admin']
|
|
36
|
+
* @default true
|
|
37
|
+
*/
|
|
38
|
+
extractScopes?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Scope separator in guard names
|
|
41
|
+
* @default ':'
|
|
42
|
+
*/
|
|
43
|
+
scopeSeparator?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Maps a single guard to an OpenAPI security requirement
|
|
47
|
+
*
|
|
48
|
+
* @param guard - Guard to map
|
|
49
|
+
* @param options - Mapping options
|
|
50
|
+
* @returns Security requirement or undefined if no mapping
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* mapGuardToSecurity({ name: 'authenticated', check: () => true })
|
|
55
|
+
* // { bearerAuth: [] }
|
|
56
|
+
*
|
|
57
|
+
* mapGuardToSecurity({ name: 'hasRole:admin', check: () => true })
|
|
58
|
+
* // { bearerAuth: ['admin'] }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function mapGuardToSecurity(guard: GuardLike<unknown>, options?: GuardMappingOptions): OpenAPISecurityRequirement | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Maps multiple guards to OpenAPI security requirements
|
|
64
|
+
*
|
|
65
|
+
* Multiple guards result in multiple security requirements,
|
|
66
|
+
* meaning ALL must be satisfied (AND logic in OpenAPI).
|
|
67
|
+
*
|
|
68
|
+
* @param guards - Guards to map
|
|
69
|
+
* @param options - Mapping options
|
|
70
|
+
* @returns Array of security requirements
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* guardsToSecurity([
|
|
75
|
+
* { name: 'authenticated', check: () => true },
|
|
76
|
+
* { name: 'hasRole:admin', check: () => true }
|
|
77
|
+
* ])
|
|
78
|
+
* // [{ bearerAuth: [] }, { bearerAuth: ['admin'] }]
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare function guardsToSecurity(guards: ReadonlyArray<GuardLike<unknown>>, options?: GuardMappingOptions): OpenAPISecurityRequirement[];
|
|
82
|
+
/**
|
|
83
|
+
* Merges security schemes, with custom schemes taking precedence
|
|
84
|
+
*
|
|
85
|
+
* @param customSchemes - Custom security schemes
|
|
86
|
+
* @param includeDefaults - Whether to include default schemes
|
|
87
|
+
* @returns Merged security schemes
|
|
88
|
+
*/
|
|
89
|
+
export declare function mergeSecuritySchemes(customSchemes?: Record<string, OpenAPISecurityScheme>, includeDefaults?: boolean): Record<string, OpenAPISecurityScheme>;
|
|
90
|
+
/**
|
|
91
|
+
* Extracts unique security scheme names from guards
|
|
92
|
+
*
|
|
93
|
+
* Useful for determining which schemes to include in the spec.
|
|
94
|
+
*
|
|
95
|
+
* @param guards - Guards to analyze
|
|
96
|
+
* @param options - Mapping options
|
|
97
|
+
* @returns Set of security scheme names used
|
|
98
|
+
*/
|
|
99
|
+
export declare function extractUsedSecuritySchemes(guards: ReadonlyArray<GuardLike<unknown>>, options?: GuardMappingOptions): Set<string>;
|
|
100
|
+
/**
|
|
101
|
+
* Filters security schemes to only include those that are used
|
|
102
|
+
*
|
|
103
|
+
* @param allSchemes - All available security schemes
|
|
104
|
+
* @param usedNames - Names of schemes that are actually used
|
|
105
|
+
* @returns Filtered security schemes
|
|
106
|
+
*/
|
|
107
|
+
export declare function filterUsedSecuritySchemes(allSchemes: Record<string, OpenAPISecurityScheme>, usedNames: Set<string>): Record<string, OpenAPISecurityScheme>;
|
|
108
|
+
/**
|
|
109
|
+
* Checks if guards require authentication
|
|
110
|
+
*
|
|
111
|
+
* @param guards - Guards to check
|
|
112
|
+
* @param options - Mapping options
|
|
113
|
+
* @returns True if any guard maps to a security scheme
|
|
114
|
+
*/
|
|
115
|
+
export declare function guardsRequireAuth(guards: ReadonlyArray<GuardLike<unknown>>, options?: GuardMappingOptions): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Extracts all scopes from guards
|
|
118
|
+
*
|
|
119
|
+
* @param guards - Guards to analyze
|
|
120
|
+
* @param options - Mapping options
|
|
121
|
+
* @returns Array of unique scopes
|
|
122
|
+
*/
|
|
123
|
+
export declare function extractGuardScopes(guards: ReadonlyArray<GuardLike<unknown>>, options?: GuardMappingOptions): string[];
|
|
124
|
+
/**
|
|
125
|
+
* Creates a security requirement from scheme name and optional scopes
|
|
126
|
+
*
|
|
127
|
+
* @param schemeName - Name of the security scheme
|
|
128
|
+
* @param scopes - Optional scopes
|
|
129
|
+
* @returns Security requirement object
|
|
130
|
+
*/
|
|
131
|
+
export declare function createSecurityRequirement(schemeName: string, scopes?: string[]): OpenAPISecurityRequirement;
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Mapper
|
|
3
|
+
*
|
|
4
|
+
* Maps VeloxTS guards to OpenAPI security schemes.
|
|
5
|
+
*
|
|
6
|
+
* @module @veloxts/router/openapi/security-mapper
|
|
7
|
+
*/
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Default Mappings
|
|
10
|
+
// ============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Default mapping from guard names to security scheme names
|
|
13
|
+
*
|
|
14
|
+
* Maps common @veloxts/auth guard names to their corresponding
|
|
15
|
+
* OpenAPI security scheme identifiers.
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_GUARD_MAPPINGS = {
|
|
18
|
+
// Authentication guards
|
|
19
|
+
authenticated: 'bearerAuth',
|
|
20
|
+
requireAuth: 'bearerAuth',
|
|
21
|
+
// Role-based guards (all map to bearer since they require auth)
|
|
22
|
+
hasRole: 'bearerAuth',
|
|
23
|
+
hasAnyRole: 'bearerAuth',
|
|
24
|
+
hasAllRoles: 'bearerAuth',
|
|
25
|
+
// Permission-based guards
|
|
26
|
+
hasPermission: 'bearerAuth',
|
|
27
|
+
hasAnyPermission: 'bearerAuth',
|
|
28
|
+
hasAllPermissions: 'bearerAuth',
|
|
29
|
+
// API key auth
|
|
30
|
+
apiKey: 'apiKeyAuth',
|
|
31
|
+
apiKeyAuth: 'apiKeyAuth',
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Default security schemes for VeloxTS auth patterns
|
|
35
|
+
*
|
|
36
|
+
* These are commonly used security schemes that can be merged
|
|
37
|
+
* with user-provided schemes.
|
|
38
|
+
*/
|
|
39
|
+
export const DEFAULT_SECURITY_SCHEMES = {
|
|
40
|
+
bearerAuth: {
|
|
41
|
+
type: 'http',
|
|
42
|
+
scheme: 'bearer',
|
|
43
|
+
bearerFormat: 'JWT',
|
|
44
|
+
description: 'JWT authentication token. Obtain via /auth/login endpoint.',
|
|
45
|
+
},
|
|
46
|
+
apiKeyAuth: {
|
|
47
|
+
type: 'apiKey',
|
|
48
|
+
in: 'header',
|
|
49
|
+
name: 'X-API-Key',
|
|
50
|
+
description: 'API key for programmatic access.',
|
|
51
|
+
},
|
|
52
|
+
cookieAuth: {
|
|
53
|
+
type: 'apiKey',
|
|
54
|
+
in: 'cookie',
|
|
55
|
+
name: 'session',
|
|
56
|
+
description: 'Session cookie for browser-based authentication.',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Maps a single guard to an OpenAPI security requirement
|
|
61
|
+
*
|
|
62
|
+
* @param guard - Guard to map
|
|
63
|
+
* @param options - Mapping options
|
|
64
|
+
* @returns Security requirement or undefined if no mapping
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* mapGuardToSecurity({ name: 'authenticated', check: () => true })
|
|
69
|
+
* // { bearerAuth: [] }
|
|
70
|
+
*
|
|
71
|
+
* mapGuardToSecurity({ name: 'hasRole:admin', check: () => true })
|
|
72
|
+
* // { bearerAuth: ['admin'] }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export function mapGuardToSecurity(guard, options = {}) {
|
|
76
|
+
const { customMappings = {}, extractScopes = true, scopeSeparator = ':' } = options;
|
|
77
|
+
// Merge mappings (custom takes precedence)
|
|
78
|
+
const mappings = { ...DEFAULT_GUARD_MAPPINGS, ...customMappings };
|
|
79
|
+
// Parse guard name and optional scopes
|
|
80
|
+
const parts = guard.name.split(scopeSeparator);
|
|
81
|
+
const baseName = parts[0];
|
|
82
|
+
const scopes = extractScopes && parts.length > 1 ? parts.slice(1) : [];
|
|
83
|
+
// Find matching security scheme
|
|
84
|
+
const schemeName = mappings[guard.name] ?? mappings[baseName];
|
|
85
|
+
if (!schemeName) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
return { [schemeName]: scopes };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Maps multiple guards to OpenAPI security requirements
|
|
92
|
+
*
|
|
93
|
+
* Multiple guards result in multiple security requirements,
|
|
94
|
+
* meaning ALL must be satisfied (AND logic in OpenAPI).
|
|
95
|
+
*
|
|
96
|
+
* @param guards - Guards to map
|
|
97
|
+
* @param options - Mapping options
|
|
98
|
+
* @returns Array of security requirements
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* guardsToSecurity([
|
|
103
|
+
* { name: 'authenticated', check: () => true },
|
|
104
|
+
* { name: 'hasRole:admin', check: () => true }
|
|
105
|
+
* ])
|
|
106
|
+
* // [{ bearerAuth: [] }, { bearerAuth: ['admin'] }]
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export function guardsToSecurity(guards, options = {}) {
|
|
110
|
+
if (guards.length === 0) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
const requirements = [];
|
|
114
|
+
const seen = new Set(); // Deduplicate identical requirements
|
|
115
|
+
for (const guard of guards) {
|
|
116
|
+
const requirement = mapGuardToSecurity(guard, options);
|
|
117
|
+
if (requirement) {
|
|
118
|
+
const key = JSON.stringify(requirement);
|
|
119
|
+
if (!seen.has(key)) {
|
|
120
|
+
seen.add(key);
|
|
121
|
+
requirements.push(requirement);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return requirements;
|
|
126
|
+
}
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// Security Scheme Utilities
|
|
129
|
+
// ============================================================================
|
|
130
|
+
/**
|
|
131
|
+
* Merges security schemes, with custom schemes taking precedence
|
|
132
|
+
*
|
|
133
|
+
* @param customSchemes - Custom security schemes
|
|
134
|
+
* @param includeDefaults - Whether to include default schemes
|
|
135
|
+
* @returns Merged security schemes
|
|
136
|
+
*/
|
|
137
|
+
export function mergeSecuritySchemes(customSchemes, includeDefaults = true) {
|
|
138
|
+
if (!includeDefaults) {
|
|
139
|
+
return customSchemes ?? {};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
...DEFAULT_SECURITY_SCHEMES,
|
|
143
|
+
...customSchemes,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Extracts unique security scheme names from guards
|
|
148
|
+
*
|
|
149
|
+
* Useful for determining which schemes to include in the spec.
|
|
150
|
+
*
|
|
151
|
+
* @param guards - Guards to analyze
|
|
152
|
+
* @param options - Mapping options
|
|
153
|
+
* @returns Set of security scheme names used
|
|
154
|
+
*/
|
|
155
|
+
export function extractUsedSecuritySchemes(guards, options = {}) {
|
|
156
|
+
const schemeNames = new Set();
|
|
157
|
+
for (const guard of guards) {
|
|
158
|
+
const requirement = mapGuardToSecurity(guard, options);
|
|
159
|
+
if (requirement) {
|
|
160
|
+
for (const schemeName of Object.keys(requirement)) {
|
|
161
|
+
schemeNames.add(schemeName);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return schemeNames;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Filters security schemes to only include those that are used
|
|
169
|
+
*
|
|
170
|
+
* @param allSchemes - All available security schemes
|
|
171
|
+
* @param usedNames - Names of schemes that are actually used
|
|
172
|
+
* @returns Filtered security schemes
|
|
173
|
+
*/
|
|
174
|
+
export function filterUsedSecuritySchemes(allSchemes, usedNames) {
|
|
175
|
+
const filtered = {};
|
|
176
|
+
for (const name of usedNames) {
|
|
177
|
+
if (allSchemes[name]) {
|
|
178
|
+
filtered[name] = allSchemes[name];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return filtered;
|
|
182
|
+
}
|
|
183
|
+
// ============================================================================
|
|
184
|
+
// Guard Analysis
|
|
185
|
+
// ============================================================================
|
|
186
|
+
/**
|
|
187
|
+
* Checks if guards require authentication
|
|
188
|
+
*
|
|
189
|
+
* @param guards - Guards to check
|
|
190
|
+
* @param options - Mapping options
|
|
191
|
+
* @returns True if any guard maps to a security scheme
|
|
192
|
+
*/
|
|
193
|
+
export function guardsRequireAuth(guards, options = {}) {
|
|
194
|
+
return guardsToSecurity(guards, options).length > 0;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Extracts all scopes from guards
|
|
198
|
+
*
|
|
199
|
+
* @param guards - Guards to analyze
|
|
200
|
+
* @param options - Mapping options
|
|
201
|
+
* @returns Array of unique scopes
|
|
202
|
+
*/
|
|
203
|
+
export function extractGuardScopes(guards, options = {}) {
|
|
204
|
+
const scopes = new Set();
|
|
205
|
+
for (const guard of guards) {
|
|
206
|
+
const requirement = mapGuardToSecurity(guard, options);
|
|
207
|
+
if (requirement) {
|
|
208
|
+
for (const scopeList of Object.values(requirement)) {
|
|
209
|
+
for (const scope of scopeList) {
|
|
210
|
+
scopes.add(scope);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return [...scopes];
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Creates a security requirement from scheme name and optional scopes
|
|
219
|
+
*
|
|
220
|
+
* @param schemeName - Name of the security scheme
|
|
221
|
+
* @param scopes - Optional scopes
|
|
222
|
+
* @returns Security requirement object
|
|
223
|
+
*/
|
|
224
|
+
export function createSecurityRequirement(schemeName, scopes = []) {
|
|
225
|
+
return { [schemeName]: scopes };
|
|
226
|
+
}
|