@extk/expressive 0.5.4 → 0.6.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.
- package/README.md +28 -14
- package/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +14 -6
- package/dist/index.mjs +14 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
- **Auto-generated OpenAPI 3.1 docs** from your route definitions
|
|
24
24
|
- **Structured error handling** with typed error classes and consistent JSON responses
|
|
25
|
-
- **
|
|
25
|
+
- **Bring-your-own logger** — any object with `info/warn/error/debug` works
|
|
26
26
|
- **Security defaults** via Helmet, safe query parsing, and morgan request logging
|
|
27
27
|
- **Standardized responses** (`ApiResponse` / `ApiErrorResponse`) across your entire API
|
|
28
28
|
|
|
@@ -58,13 +58,9 @@ const {
|
|
|
58
58
|
const swaggerDoc = swaggerBuilder()
|
|
59
59
|
.withInfo({ title: 'My API', version: '1.0.0' })
|
|
60
60
|
.withServers([{ url: 'http://localhost:3000' }])
|
|
61
|
-
.
|
|
61
|
+
.build();
|
|
62
62
|
|
|
63
|
-
// 3.
|
|
64
|
-
const app = expressiveServer()
|
|
65
|
-
.withDefaults({ path: '/api-docs', doc: swaggerDoc });
|
|
66
|
-
|
|
67
|
-
// 4. Define routes — they auto-register in the OpenAPI spec
|
|
63
|
+
// 3. Define routes — they auto-register in the OpenAPI spec
|
|
68
64
|
const { router, addRoute } = expressiveRouter({
|
|
69
65
|
oapi: { tags: ['Users'] },
|
|
70
66
|
});
|
|
@@ -85,10 +81,24 @@ addRoute(
|
|
|
85
81
|
},
|
|
86
82
|
);
|
|
87
83
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> [!IMPORTANT]
|
|
87
|
+
> Method call order on `ServerBuilder` matters — middleware is registered in the order you chain it.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
// 4. Build the Express app
|
|
91
|
+
const app = expressiveServer()
|
|
92
|
+
.withHelmet()
|
|
93
|
+
.withQs()
|
|
94
|
+
.withMorgan()
|
|
95
|
+
.withRoutes(router)
|
|
96
|
+
.withSwagger({ path: '/api-docs', config: swaggerDoc })
|
|
97
|
+
.with((app) => {
|
|
98
|
+
app.use(getErrorHandlerMiddleware());
|
|
99
|
+
app.use(notFoundMiddleware);
|
|
100
|
+
})
|
|
101
|
+
.build();
|
|
92
102
|
|
|
93
103
|
app.listen(3000);
|
|
94
104
|
```
|
|
@@ -203,15 +213,19 @@ export const loginSchema = z.object({
|
|
|
203
213
|
import z from 'zod';
|
|
204
214
|
|
|
205
215
|
const app = expressiveServer()
|
|
206
|
-
.
|
|
207
|
-
|
|
216
|
+
.withHelmet()
|
|
217
|
+
.withQs()
|
|
218
|
+
.withMorgan()
|
|
219
|
+
.withSwagger({
|
|
220
|
+
config: swaggerBuilder()
|
|
208
221
|
.withInfo({ title: 'My API' })
|
|
209
222
|
.withServers([{ url: 'http://localhost:3000/api' }])
|
|
210
223
|
.withSchemas(z.toJSONSchema(z.globalRegistry).schemas) // all Zod schemas -> OpenAPI
|
|
211
224
|
.withSecuritySchemes({ auth: SWG.securitySchemes.BearerAuth() })
|
|
212
225
|
.withDefaultSecurity([SWG.security('auth')])
|
|
213
226
|
.get(),
|
|
214
|
-
})
|
|
227
|
+
})
|
|
228
|
+
.build();
|
|
215
229
|
```
|
|
216
230
|
|
|
217
231
|
**3. Reference them in routes with `SWG.jsonSchemaRef`:**
|
package/dist/index.d.mts
CHANGED
|
@@ -163,19 +163,23 @@ type SwaggerConfig = {
|
|
|
163
163
|
|
|
164
164
|
type SwaggerOptions = {
|
|
165
165
|
path?: ExpressRoute;
|
|
166
|
-
|
|
166
|
+
config: SwaggerConfig;
|
|
167
167
|
};
|
|
168
168
|
declare class ServerBuilder {
|
|
169
169
|
private app;
|
|
170
170
|
private container;
|
|
171
171
|
constructor(app: express__default.Express, container: Container);
|
|
172
|
-
|
|
172
|
+
build(): express__default.Express;
|
|
173
173
|
withHelmet(options?: Readonly<HelmetOptions>): this;
|
|
174
174
|
withQs(): this;
|
|
175
175
|
withMorgan(format?: string, // TODO: FormatFn
|
|
176
176
|
options?: Parameters<typeof morgan>[1]): this;
|
|
177
|
+
withRoutes(routes: ExpressRoute): this;
|
|
178
|
+
/**
|
|
179
|
+
* Helper function for fluent design
|
|
180
|
+
*/
|
|
181
|
+
with(fn: (app: express__default.Express, container: Container) => void): this;
|
|
177
182
|
withSwagger(swagger: SwaggerOptions, ...handlers: ExpressHandler[]): this;
|
|
178
|
-
withDefaults(swagger: SwaggerOptions): express__default.Express;
|
|
179
183
|
}
|
|
180
184
|
|
|
181
185
|
declare class ApiError extends Error {
|
package/dist/index.d.ts
CHANGED
|
@@ -163,19 +163,23 @@ type SwaggerConfig = {
|
|
|
163
163
|
|
|
164
164
|
type SwaggerOptions = {
|
|
165
165
|
path?: ExpressRoute;
|
|
166
|
-
|
|
166
|
+
config: SwaggerConfig;
|
|
167
167
|
};
|
|
168
168
|
declare class ServerBuilder {
|
|
169
169
|
private app;
|
|
170
170
|
private container;
|
|
171
171
|
constructor(app: express__default.Express, container: Container);
|
|
172
|
-
|
|
172
|
+
build(): express__default.Express;
|
|
173
173
|
withHelmet(options?: Readonly<HelmetOptions>): this;
|
|
174
174
|
withQs(): this;
|
|
175
175
|
withMorgan(format?: string, // TODO: FormatFn
|
|
176
176
|
options?: Parameters<typeof morgan>[1]): this;
|
|
177
|
+
withRoutes(routes: ExpressRoute): this;
|
|
178
|
+
/**
|
|
179
|
+
* Helper function for fluent design
|
|
180
|
+
*/
|
|
181
|
+
with(fn: (app: express__default.Express, container: Container) => void): this;
|
|
177
182
|
withSwagger(swagger: SwaggerOptions, ...handlers: ExpressHandler[]): this;
|
|
178
|
-
withDefaults(swagger: SwaggerOptions): express__default.Express;
|
|
179
183
|
}
|
|
180
184
|
|
|
181
185
|
declare class ApiError extends Error {
|
package/dist/index.js
CHANGED
|
@@ -198,7 +198,7 @@ var ServerBuilder = class {
|
|
|
198
198
|
this.app = app;
|
|
199
199
|
this.container = container;
|
|
200
200
|
}
|
|
201
|
-
|
|
201
|
+
build() {
|
|
202
202
|
return this.app;
|
|
203
203
|
}
|
|
204
204
|
withHelmet(options) {
|
|
@@ -222,15 +222,23 @@ var ServerBuilder = class {
|
|
|
222
222
|
));
|
|
223
223
|
return this;
|
|
224
224
|
}
|
|
225
|
+
withRoutes(routes) {
|
|
226
|
+
this.app.use(routes);
|
|
227
|
+
return this;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Helper function for fluent design
|
|
231
|
+
*/
|
|
232
|
+
with(fn) {
|
|
233
|
+
fn(this.app, this.container);
|
|
234
|
+
return this;
|
|
235
|
+
}
|
|
225
236
|
withSwagger(swagger, ...handlers) {
|
|
226
|
-
this.app.use(swagger.path ?? "/api-docs", ...handlers, import_swagger_ui_express.default.serve, import_swagger_ui_express.default.setup(swagger.
|
|
227
|
-
customSiteTitle: swagger.
|
|
237
|
+
this.app.use(swagger.path ?? "/api-docs", ...handlers, import_swagger_ui_express.default.serve, import_swagger_ui_express.default.setup(swagger.config, {
|
|
238
|
+
customSiteTitle: swagger.config.info?.title
|
|
228
239
|
}));
|
|
229
240
|
return this;
|
|
230
241
|
}
|
|
231
|
-
withDefaults(swagger) {
|
|
232
|
-
return this.withHelmet().withQs().withMorgan().withSwagger(swagger).get();
|
|
233
|
-
}
|
|
234
242
|
};
|
|
235
243
|
function buildExpressive(container, swaggerDoc) {
|
|
236
244
|
return {
|
package/dist/index.mjs
CHANGED
|
@@ -137,7 +137,7 @@ var ServerBuilder = class {
|
|
|
137
137
|
this.app = app;
|
|
138
138
|
this.container = container;
|
|
139
139
|
}
|
|
140
|
-
|
|
140
|
+
build() {
|
|
141
141
|
return this.app;
|
|
142
142
|
}
|
|
143
143
|
withHelmet(options) {
|
|
@@ -161,15 +161,23 @@ var ServerBuilder = class {
|
|
|
161
161
|
));
|
|
162
162
|
return this;
|
|
163
163
|
}
|
|
164
|
+
withRoutes(routes) {
|
|
165
|
+
this.app.use(routes);
|
|
166
|
+
return this;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Helper function for fluent design
|
|
170
|
+
*/
|
|
171
|
+
with(fn) {
|
|
172
|
+
fn(this.app, this.container);
|
|
173
|
+
return this;
|
|
174
|
+
}
|
|
164
175
|
withSwagger(swagger, ...handlers) {
|
|
165
|
-
this.app.use(swagger.path ?? "/api-docs", ...handlers, swaggerUi.serve, swaggerUi.setup(swagger.
|
|
166
|
-
customSiteTitle: swagger.
|
|
176
|
+
this.app.use(swagger.path ?? "/api-docs", ...handlers, swaggerUi.serve, swaggerUi.setup(swagger.config, {
|
|
177
|
+
customSiteTitle: swagger.config.info?.title
|
|
167
178
|
}));
|
|
168
179
|
return this;
|
|
169
180
|
}
|
|
170
|
-
withDefaults(swagger) {
|
|
171
|
-
return this.withHelmet().withQs().withMorgan().withSwagger(swagger).get();
|
|
172
|
-
}
|
|
173
181
|
};
|
|
174
182
|
function buildExpressive(container, swaggerDoc) {
|
|
175
183
|
return {
|