express-version-api 1.0.1 β 2.0.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/CHANGELOG.md +40 -0
- package/LICENSE +23 -21
- package/README.md +224 -146
- package/dist/index.cjs +708 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +444 -2
- package/dist/index.js +688 -7
- package/dist/index.js.map +1 -0
- package/package.json +83 -25
- package/dist/lib.d.ts +0 -15
- package/dist/lib.js +0 -147
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [2.0.0] - 2026-02-27
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
|
|
14
|
+
- Removed deprecated `createVersionMiddleware` API.
|
|
15
|
+
- Removed CommonJS default export path; CJS now uses named exports only.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- `test:types` now validates `test-types/**/*.test-d.ts` and runs in `validate`/CI.
|
|
20
|
+
- CI now targets `develop` and `main`, and PR checks use the actual base branch.
|
|
21
|
+
- `npm test` no longer writes coverage artifacts by default.
|
|
22
|
+
- Pre-commit hook now runs `lint-staged`.
|
|
23
|
+
- TypeScript incremental metadata moved outside publish output.
|
|
24
|
+
- Removed unused dev dependencies: `@types/semver`, `ts-node`.
|
|
25
|
+
- Updated README and package docs to match runtime behavior.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- `fallbackStrategy` is now validated at config resolution.
|
|
30
|
+
- Async `defaultHandler` errors are forwarded to Express `next(error)`.
|
|
31
|
+
- Caret matching for `0.x` follows semver-compatible constraints.
|
|
32
|
+
- `missingVersionMessage` from config is now applied in responses.
|
|
33
|
+
- Path extraction is stable with global/sticky regex (`lastIndex` handling).
|
|
34
|
+
- `req.versionInfo.source` now preserves the original extraction source in fallback paths.
|
|
35
|
+
|
|
36
|
+
## [1.0.6] - 2025-02-01
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Stable baseline release published to npm.
|
package/LICENSE
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c)
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Braian Quintian
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
For more information, see <https://github.com/Braian-Quintian/express-version-api>
|
package/README.md
CHANGED
|
@@ -1,146 +1,224 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/express-version-api)
|
|
4
|
+
[](https://www.npmjs.com/package/express-version-api)
|
|
5
|
+
[](https://github.com/Braian-Quintian/express-version-api/actions)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
Version-aware middleware for Express.js with semantic version matching.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install express-version-api
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requirements:
|
|
17
|
+
|
|
18
|
+
- Node.js >= 18
|
|
19
|
+
- Express >= 4
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import express from 'express';
|
|
25
|
+
import { versioningMiddleware } from 'express-version-api';
|
|
26
|
+
|
|
27
|
+
const app = express();
|
|
28
|
+
|
|
29
|
+
app.use(
|
|
30
|
+
'/api',
|
|
31
|
+
versioningMiddleware({
|
|
32
|
+
'^1': (_req, res) => {
|
|
33
|
+
res.json({ version: '1.x' });
|
|
34
|
+
},
|
|
35
|
+
'^2': (_req, res) => {
|
|
36
|
+
res.json({ version: '2.x' });
|
|
37
|
+
},
|
|
38
|
+
'3.0.0': (_req, res) => {
|
|
39
|
+
res.json({ version: '3.0.0' });
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Request examples:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
curl -H "Accept-Version: 1.2.0" http://localhost:3000/api
|
|
49
|
+
curl -H "Accept-Version: 2.5.1" http://localhost:3000/api
|
|
50
|
+
curl -H "Accept-Version: 3.0.0" http://localhost:3000/api
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Import Modes
|
|
54
|
+
|
|
55
|
+
ESM:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import versioningMiddleware, { parseVersion } from 'express-version-api';
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
CommonJS:
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
const { versioningMiddleware, parseVersion } = require('express-version-api');
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Matching Rules
|
|
68
|
+
|
|
69
|
+
Supported handler keys:
|
|
70
|
+
|
|
71
|
+
- Exact: `1.2.3`
|
|
72
|
+
- Caret: `^1.2.3`
|
|
73
|
+
- Tilde: `~1.2.3`
|
|
74
|
+
|
|
75
|
+
Priority when multiple handlers match:
|
|
76
|
+
|
|
77
|
+
1. Exact
|
|
78
|
+
2. Tilde
|
|
79
|
+
3. Caret
|
|
80
|
+
|
|
81
|
+
Notes:
|
|
82
|
+
|
|
83
|
+
- Caret behavior for `0.x` follows semver-compatible constraints.
|
|
84
|
+
- Versions like `1`, `1.2`, and `1.2.3` are accepted.
|
|
85
|
+
|
|
86
|
+
## Version Extraction
|
|
87
|
+
|
|
88
|
+
Default extraction order:
|
|
89
|
+
|
|
90
|
+
1. Header: `accept-version`
|
|
91
|
+
2. Query: `v`
|
|
92
|
+
|
|
93
|
+
You can configure `header`, `query`, `path`, or `custom` sources.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
versioningMiddleware(
|
|
97
|
+
{
|
|
98
|
+
'^1': v1Handler,
|
|
99
|
+
'^2': v2Handler,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
extraction: {
|
|
103
|
+
sources: ['header', 'query', 'path', 'custom'],
|
|
104
|
+
header: { name: 'x-api-version' },
|
|
105
|
+
query: { name: 'version' },
|
|
106
|
+
path: { pattern: /\/api\/v(\d+(?:\.\d+)?(?:\.\d+)?)\// },
|
|
107
|
+
custom: (req) => (req.hostname.startsWith('v2.') ? '2.0.0' : undefined),
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Configuration
|
|
114
|
+
|
|
115
|
+
Defaults:
|
|
116
|
+
|
|
117
|
+
- `requireVersion: true`
|
|
118
|
+
- `fallbackStrategy: 'default'`
|
|
119
|
+
- `attachVersionInfo: true`
|
|
120
|
+
- `validateHandlers: true`
|
|
121
|
+
- `errorResponse.missingVersionStatus: 422`
|
|
122
|
+
- `errorResponse.versionNotFoundStatus: 422`
|
|
123
|
+
- `errorResponse.missingVersionMessage: 'API version is required'`
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
interface VersioningOptions {
|
|
127
|
+
extraction?: {
|
|
128
|
+
sources?: Array<'header' | 'query' | 'path' | 'custom'>;
|
|
129
|
+
header?: { name?: string };
|
|
130
|
+
query?: { name?: string };
|
|
131
|
+
path?: { pattern?: RegExp };
|
|
132
|
+
custom?: (req: Request) => string | undefined;
|
|
133
|
+
};
|
|
134
|
+
requireVersion?: boolean;
|
|
135
|
+
fallbackStrategy?: 'latest' | 'none' | 'default';
|
|
136
|
+
defaultHandler?: RequestHandler;
|
|
137
|
+
validateHandlers?: boolean;
|
|
138
|
+
attachVersionInfo?: boolean;
|
|
139
|
+
errorResponse?: {
|
|
140
|
+
missingVersionStatus?: number;
|
|
141
|
+
versionNotFoundStatus?: number;
|
|
142
|
+
missingVersionMessage?: string;
|
|
143
|
+
versionNotFoundMessage?: string | ((version: string) => string);
|
|
144
|
+
includeRequestedVersion?: boolean;
|
|
145
|
+
onError?: (
|
|
146
|
+
error: VersioningError,
|
|
147
|
+
req: Request,
|
|
148
|
+
res: Response,
|
|
149
|
+
next: NextFunction
|
|
150
|
+
) => boolean | undefined;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Fallback Strategies
|
|
156
|
+
|
|
157
|
+
- `none`: return `VERSION_NOT_FOUND` error.
|
|
158
|
+
- `latest`: execute the highest available version handler.
|
|
159
|
+
- `default`: execute `defaultHandler` when provided; otherwise falls back to `latest`.
|
|
160
|
+
|
|
161
|
+
## Error Handling
|
|
162
|
+
|
|
163
|
+
Error codes:
|
|
164
|
+
|
|
165
|
+
- `MISSING_VERSION`
|
|
166
|
+
- `INVALID_VERSION_FORMAT`
|
|
167
|
+
- `VERSION_NOT_FOUND`
|
|
168
|
+
- `INVALID_CONFIGURATION`
|
|
169
|
+
- `INVALID_HANDLER`
|
|
170
|
+
|
|
171
|
+
Default error response shape:
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"error": "VERSION_NOT_FOUND",
|
|
176
|
+
"message": "No handler found for the requested API version",
|
|
177
|
+
"requestedVersion": "99.0.0",
|
|
178
|
+
"availableVersions": ["^1", "^2"]
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Version Info Metadata
|
|
183
|
+
|
|
184
|
+
When `attachVersionInfo` is enabled, the middleware sets `req.versionInfo`:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
{
|
|
188
|
+
requested: string;
|
|
189
|
+
matched: string;
|
|
190
|
+
source: 'header' | 'query' | 'path' | 'custom';
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## API
|
|
195
|
+
|
|
196
|
+
Main exports:
|
|
197
|
+
|
|
198
|
+
- `versioningMiddleware`
|
|
199
|
+
- `parseVersion`
|
|
200
|
+
- `parseVersionRange`
|
|
201
|
+
- `versionSatisfies`
|
|
202
|
+
- `compareVersions`
|
|
203
|
+
- `findLatestVersion`
|
|
204
|
+
- `isValidVersion`
|
|
205
|
+
- `isValidVersionRange`
|
|
206
|
+
- `normalizeVersion`
|
|
207
|
+
- `VersioningError`
|
|
208
|
+
- `DEFAULT_CONFIG`
|
|
209
|
+
|
|
210
|
+
## Breaking Changes (v2.0.0)
|
|
211
|
+
|
|
212
|
+
- Removed legacy `createVersionMiddleware` API.
|
|
213
|
+
- CommonJS consumers must use named exports (no default export in CJS).
|
|
214
|
+
|
|
215
|
+
## Development
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npm install
|
|
219
|
+
npm run validate
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
MIT
|