express-version-api 1.0.6 → 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/README.md +171 -109
- package/dist/index.cjs +708 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +444 -0
- package/dist/index.js +689 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -31
- package/dist/cjs/index.js +0 -11
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/lib.js +0 -209
- package/dist/cjs/lib.js.map +0 -1
- package/dist/esm/index.js +0 -4
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/lib.js +0 -201
- package/dist/esm/lib.js.map +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/lib.d.ts +0 -137
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/README.md
CHANGED
|
@@ -1,162 +1,224 @@
|
|
|
1
|
-
#
|
|
1
|
+
# express-version-api
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/express-version-api)
|
|
4
|
-
[](https://nodejs.org)
|
|
4
|
+
[](https://www.npmjs.com/package/express-version-api)
|
|
5
|
+
[](https://github.com/Braian-Quintian/express-version-api/actions)
|
|
6
|
+
[](./LICENSE)
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
Version-aware middleware for Express.js with semantic version matching.
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
**⚠️ NOTE:** This package is intended for personal use and experimentation. It is **not recommended** for production use.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 🚧 Project Status
|
|
18
|
-
|
|
19
|
-
This library is under **active development**. Features and improvements are being added frequently. Use at your own discretion in unstable environments.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## ✨ Features
|
|
24
|
-
|
|
25
|
-
- ✅ Version-based routing (`^`, `~`, exact versions)
|
|
26
|
-
- ✅ Automatic fallback to default or latest version
|
|
27
|
-
- ✅ Fully compatible with Express middleware
|
|
28
|
-
- ✅ Well-tested with Jest and Supertest
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## 📦 Installation
|
|
10
|
+
## Installation
|
|
33
11
|
|
|
34
12
|
```bash
|
|
35
13
|
npm install express-version-api
|
|
36
14
|
```
|
|
37
15
|
|
|
38
|
-
|
|
16
|
+
Requirements:
|
|
39
17
|
|
|
40
|
-
|
|
18
|
+
- Node.js >= 18
|
|
19
|
+
- Express >= 4
|
|
41
20
|
|
|
42
|
-
|
|
43
|
-
const express = require("express");
|
|
44
|
-
const versionApi = require("express-version-api");
|
|
45
|
-
const app = express();
|
|
21
|
+
## Quick Start
|
|
46
22
|
|
|
47
|
-
|
|
48
|
-
|
|
23
|
+
```ts
|
|
24
|
+
import express from 'express';
|
|
25
|
+
import { versioningMiddleware } from 'express-version-api';
|
|
49
26
|
|
|
50
|
-
app
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
+
},
|
|
55
41
|
})
|
|
56
42
|
);
|
|
43
|
+
```
|
|
57
44
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
|
61
51
|
```
|
|
62
52
|
|
|
63
|
-
|
|
53
|
+
## Import Modes
|
|
64
54
|
|
|
65
|
-
|
|
55
|
+
ESM:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import versioningMiddleware, { parseVersion } from 'express-version-api';
|
|
59
|
+
```
|
|
66
60
|
|
|
67
|
-
|
|
68
|
-
| ------ | -------------------------- | ------------------ |
|
|
69
|
-
| `^` | Major-compatible (`1.x.x`) | `^1.0.0` → `1.2.3` |
|
|
70
|
-
| `~` | Minor-compatible (`2.1.x`) | `~2.1.0` → `2.1.4` |
|
|
71
|
-
| Exact | Exact version only | `3.0.0` → `3.0.0` |
|
|
61
|
+
CommonJS:
|
|
72
62
|
|
|
73
63
|
```js
|
|
74
|
-
|
|
75
|
-
"/api",
|
|
76
|
-
versionApi({
|
|
77
|
-
"^1.0.0": handlerV1,
|
|
78
|
-
"~2.1.0": handlerV2,
|
|
79
|
-
"3.0.0": handlerV3,
|
|
80
|
-
})
|
|
81
|
-
);
|
|
64
|
+
const { versioningMiddleware, parseVersion } = require('express-version-api');
|
|
82
65
|
```
|
|
83
66
|
|
|
84
|
-
|
|
67
|
+
## Matching Rules
|
|
85
68
|
|
|
86
|
-
|
|
69
|
+
Supported handler keys:
|
|
87
70
|
|
|
88
|
-
|
|
71
|
+
- Exact: `1.2.3`
|
|
72
|
+
- Caret: `^1.2.3`
|
|
73
|
+
- Tilde: `~1.2.3`
|
|
89
74
|
|
|
90
|
-
|
|
91
|
-
curl -H "Accept-Version: 1.0.0" http://localhost:3000/api
|
|
92
|
-
```
|
|
75
|
+
Priority when multiple handlers match:
|
|
93
76
|
|
|
94
|
-
|
|
77
|
+
1. Exact
|
|
78
|
+
2. Tilde
|
|
79
|
+
3. Caret
|
|
95
80
|
|
|
96
|
-
|
|
81
|
+
Notes:
|
|
97
82
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Tests are powered by [Jest](https://jestjs.io/) and [Supertest](https://github.com/visionmedia/supertest). Full coverage is included.
|
|
83
|
+
- Caret behavior for `0.x` follows semver-compatible constraints.
|
|
84
|
+
- Versions like `1`, `1.2`, and `1.2.3` are accepted.
|
|
103
85
|
|
|
104
|
-
|
|
86
|
+
## Version Extraction
|
|
105
87
|
|
|
106
|
-
|
|
88
|
+
Default extraction order:
|
|
107
89
|
|
|
108
|
-
|
|
90
|
+
1. Header: `accept-version`
|
|
91
|
+
2. Query: `v`
|
|
109
92
|
|
|
110
|
-
|
|
111
|
-
- `defaultHandler`: Optional fallback if no version matches.
|
|
93
|
+
You can configure `header`, `query`, `path`, or `custom` sources.
|
|
112
94
|
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
+
}
|
|
121
110
|
);
|
|
122
111
|
```
|
|
123
112
|
|
|
124
|
-
|
|
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
|
+
```
|
|
125
154
|
|
|
126
|
-
##
|
|
155
|
+
## Fallback Strategies
|
|
127
156
|
|
|
128
|
-
|
|
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`.
|
|
129
160
|
|
|
130
|
-
|
|
131
|
-
2. Otherwise, fallback to the latest available handler
|
|
132
|
-
3. If no handler matches, return `422 Unprocessable Entity`
|
|
161
|
+
## Error Handling
|
|
133
162
|
|
|
134
|
-
|
|
163
|
+
Error codes:
|
|
135
164
|
|
|
136
|
-
|
|
165
|
+
- `MISSING_VERSION`
|
|
166
|
+
- `INVALID_VERSION_FORMAT`
|
|
167
|
+
- `VERSION_NOT_FOUND`
|
|
168
|
+
- `INVALID_CONFIGURATION`
|
|
169
|
+
- `INVALID_HANDLER`
|
|
137
170
|
|
|
138
|
-
|
|
171
|
+
Default error response shape:
|
|
139
172
|
|
|
140
|
-
|
|
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
|
|
141
195
|
|
|
142
|
-
|
|
196
|
+
Main exports:
|
|
143
197
|
|
|
144
|
-
-
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
-
|
|
198
|
+
- `versioningMiddleware`
|
|
199
|
+
- `parseVersion`
|
|
200
|
+
- `parseVersionRange`
|
|
201
|
+
- `versionSatisfies`
|
|
202
|
+
- `compareVersions`
|
|
203
|
+
- `findLatestVersion`
|
|
204
|
+
- `isValidVersion`
|
|
205
|
+
- `isValidVersionRange`
|
|
206
|
+
- `normalizeVersion`
|
|
207
|
+
- `VersioningError`
|
|
208
|
+
- `DEFAULT_CONFIG`
|
|
150
209
|
|
|
151
|
-
|
|
210
|
+
## Breaking Changes (v2.0.0)
|
|
152
211
|
|
|
153
|
-
|
|
212
|
+
- Removed legacy `createVersionMiddleware` API.
|
|
213
|
+
- CommonJS consumers must use named exports (no default export in CJS).
|
|
154
214
|
|
|
155
|
-
|
|
156
|
-
Contact: [bquintian.developer@gmail.com](mailto:bquintian.developer@gmail.com)
|
|
215
|
+
## Development
|
|
157
216
|
|
|
158
|
-
|
|
217
|
+
```bash
|
|
218
|
+
npm install
|
|
219
|
+
npm run validate
|
|
220
|
+
```
|
|
159
221
|
|
|
160
|
-
##
|
|
222
|
+
## License
|
|
161
223
|
|
|
162
|
-
|
|
224
|
+
MIT
|