@extk/expressive 0.5.5 → 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 +23 -17
- package/dist/index.d.mts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +14 -3
- package/dist/index.mjs +14 -3
- 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,17 +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
|
-
.withHelmet()
|
|
66
|
-
.withQs()
|
|
67
|
-
.withMorgan()
|
|
68
|
-
.withSwagger({ path: '/api-docs', doc: swaggerDoc })
|
|
69
|
-
.get();
|
|
70
|
-
|
|
71
|
-
// 4. Define routes — they auto-register in the OpenAPI spec
|
|
63
|
+
// 3. Define routes — they auto-register in the OpenAPI spec
|
|
72
64
|
const { router, addRoute } = expressiveRouter({
|
|
73
65
|
oapi: { tags: ['Users'] },
|
|
74
66
|
});
|
|
@@ -89,10 +81,24 @@ addRoute(
|
|
|
89
81
|
},
|
|
90
82
|
);
|
|
91
83
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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();
|
|
96
102
|
|
|
97
103
|
app.listen(3000);
|
|
98
104
|
```
|
|
@@ -211,7 +217,7 @@ const app = expressiveServer()
|
|
|
211
217
|
.withQs()
|
|
212
218
|
.withMorgan()
|
|
213
219
|
.withSwagger({
|
|
214
|
-
|
|
220
|
+
config: swaggerBuilder()
|
|
215
221
|
.withInfo({ title: 'My API' })
|
|
216
222
|
.withServers([{ url: 'http://localhost:3000/api' }])
|
|
217
223
|
.withSchemas(z.toJSONSchema(z.globalRegistry).schemas) // all Zod schemas -> OpenAPI
|
|
@@ -219,7 +225,7 @@ const app = expressiveServer()
|
|
|
219
225
|
.withDefaultSecurity([SWG.security('auth')])
|
|
220
226
|
.get(),
|
|
221
227
|
})
|
|
222
|
-
.
|
|
228
|
+
.build();
|
|
223
229
|
```
|
|
224
230
|
|
|
225
231
|
**3. Reference them in routes with `SWG.jsonSchemaRef`:**
|
package/dist/index.d.mts
CHANGED
|
@@ -163,17 +163,22 @@ 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
183
|
}
|
|
179
184
|
|
package/dist/index.d.ts
CHANGED
|
@@ -163,17 +163,22 @@ 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
183
|
}
|
|
179
184
|
|
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,9 +222,20 @@ 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
|
}
|
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,9 +161,20 @@ 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
|
}
|