standard-api-core 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Standard API Core
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.
package/README.md ADDED
@@ -0,0 +1,522 @@
1
+ # @standard-api/core
2
+
3
+ A production-ready NPM package that standardizes API responses and automatically generates best-practice Swagger (OpenAPI) documentation for Express.js applications.
4
+
5
+ ## Features
6
+
7
+ - **Standardized Response Format** - Consistent success/error responses across your entire API
8
+ - **Auto-Generated Swagger UI** - Beautiful, interactive API documentation
9
+ - **Configuration-Based** - Flexible configuration file support
10
+ - **Downloadable Specs** - Download full or per-endpoint OpenAPI specs in JSON/YAML
11
+ - **Headers & Security** - Built-in support for authentication headers
12
+ - **Type-Safe** - Full TypeScript support with Zod schemas
13
+ - **Zero Boilerplate** - Minimal setup, maximum productivity
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @standard-api/core express zod
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### 1. Create Configuration File
24
+
25
+ Create `standard-api.config.ts` in your project root:
26
+
27
+ ```typescript
28
+ import { StandardApiConfig } from "@standard-api/core";
29
+
30
+ const config: StandardApiConfig = {
31
+ api: {
32
+ title: "User Service API",
33
+ description: "API documentation for User Service",
34
+ version: "1.0.0",
35
+ baseUrl: "/api/v1",
36
+ },
37
+ headers: {
38
+ Authorization: {
39
+ description: "JWT Bearer token",
40
+ required: true,
41
+ },
42
+ },
43
+ swagger: {
44
+ path: "/docs",
45
+ enableDownload: true,
46
+ },
47
+ };
48
+
49
+ export default config;
50
+ ```
51
+
52
+ ### 2. Setup Express App
53
+
54
+ ```typescript
55
+ import express from "express";
56
+ import {
57
+ setupSwagger,
58
+ responseMiddleware,
59
+ apiDoc,
60
+ loadConfig,
61
+ } from "@standard-api/core";
62
+ import { z } from "zod";
63
+
64
+ const app = express();
65
+ app.use(express.json());
66
+
67
+ // Load configuration
68
+ const config = loadConfig("./standard-api.config.ts");
69
+
70
+ // Setup response handlers (adds sendSuccess/sendError methods)
71
+ app.use(responseMiddleware);
72
+
73
+ // Setup Swagger documentation
74
+ setupSwagger(app, config);
75
+
76
+ // Define schemas
77
+ const UserSchema = z.object({
78
+ success: z.literal(true),
79
+ message: z.string(),
80
+ data: z.object({
81
+ id: z.string(),
82
+ name: z.string(),
83
+ email: z.string().email(),
84
+ role: z.enum(["ADMIN", "USER"]),
85
+ }),
86
+ meta: z.object({
87
+ timestamp: z.string(),
88
+ requestId: z.string(),
89
+ }),
90
+ });
91
+
92
+ // Create documented endpoints
93
+ app.get(
94
+ "/api/v1/users/:id",
95
+ apiDoc({
96
+ method: "get",
97
+ path: "/api/v1/users/{id}",
98
+ summary: "Get user by ID",
99
+ description: "Returns a single user",
100
+ tags: ["Users"],
101
+ request: {
102
+ params: z.object({
103
+ id: z.string().describe("User ID"),
104
+ }),
105
+ },
106
+ response: UserSchema,
107
+ }),
108
+ (req, res) => {
109
+ const user = {
110
+ id: req.params.id,
111
+ name: "John Doe",
112
+ email: "john@example.com",
113
+ role: "USER",
114
+ };
115
+
116
+ res.sendSuccess({
117
+ message: "User fetched successfully",
118
+ data: user,
119
+ });
120
+ }
121
+ );
122
+
123
+ app.listen(3000, () => {
124
+ console.log("Server running on http://localhost:3000");
125
+ console.log("Swagger docs available at http://localhost:3000/docs");
126
+ });
127
+ ```
128
+
129
+ ## API Reference
130
+
131
+ ### Response Handlers
132
+
133
+ #### `res.sendSuccess(options)`
134
+
135
+ Send a standardized success response.
136
+
137
+ ```typescript
138
+ res.sendSuccess({
139
+ message: "Operation successful",
140
+ data: { id: 1, name: "John" },
141
+ meta: { customField: "value" }, // optional
142
+ });
143
+ ```
144
+
145
+ **Response Format:**
146
+
147
+ ```json
148
+ {
149
+ "success": true,
150
+ "message": "Operation successful",
151
+ "data": { "id": 1, "name": "John" },
152
+ "meta": {
153
+ "timestamp": "2026-01-01T00:00:00.000Z",
154
+ "requestId": "uuid-here",
155
+ "customField": "value"
156
+ }
157
+ }
158
+ ```
159
+
160
+ #### `res.sendError(options)`
161
+
162
+ Send a standardized error response.
163
+
164
+ ```typescript
165
+ res.sendError({
166
+ message: "Validation failed",
167
+ code: "VALIDATION_ERROR",
168
+ error: { field: "email", issue: "invalid format" },
169
+ status: 400,
170
+ });
171
+ ```
172
+
173
+ **Response Format:**
174
+
175
+ ```json
176
+ {
177
+ "success": false,
178
+ "message": "Validation failed",
179
+ "error": {
180
+ "code": "VALIDATION_ERROR",
181
+ "details": { "field": "email", "issue": "invalid format" }
182
+ },
183
+ "meta": {
184
+ "timestamp": "2026-01-01T00:00:00.000Z",
185
+ "requestId": "uuid-here"
186
+ }
187
+ }
188
+ ```
189
+
190
+ ### Middleware
191
+
192
+ #### `responseMiddleware`
193
+
194
+ Middleware that adds `sendSuccess` and `sendError` methods to Express response object.
195
+
196
+ ```typescript
197
+ app.use(responseMiddleware);
198
+ ```
199
+
200
+ #### `apiDoc(config)`
201
+
202
+ Middleware that registers route documentation with Swagger.
203
+
204
+ ```typescript
205
+ app.get(
206
+ "/users",
207
+ apiDoc({
208
+ method: "get",
209
+ path: "/users",
210
+ summary: "Get all users",
211
+ description: "Returns a list of users",
212
+ tags: ["Users"],
213
+ request: {
214
+ query: z.object({
215
+ page: z.string().optional(),
216
+ limit: z.string().optional(),
217
+ }),
218
+ },
219
+ response: UserListSchema,
220
+ }),
221
+ handler
222
+ );
223
+ ```
224
+
225
+ **Configuration Parameters:**
226
+
227
+ - `method` - HTTP method (get, post, put, delete, patch)
228
+ - `path` - Route path matching Express route
229
+ - `summary` - Short description of the endpoint
230
+ - `description` - Detailed description (optional)
231
+ - `tags` - Array of tags for grouping endpoints
232
+ - `request` - Request schema (query, params, body)
233
+ - `response` - Response schema (Zod schema)
234
+
235
+ ### Setup Functions
236
+
237
+ #### `setupSwagger(app, config)`
238
+
239
+ Initializes Swagger UI and documentation endpoints.
240
+
241
+ ```typescript
242
+ setupSwagger(app, config);
243
+ **Auto-discovery:** If no path is provided, the loader searches in the following order:
244
+ 1. `standard-api.config.ts` (root)
245
+ 2. `standard-api.config.js` (root)
246
+ 3. `config/standard-api.config.ts`
247
+ 4. `config/standard-api.config.js`
248
+
249
+ ##
250
+
251
+ #### `loadConfig(path?)`
252
+
253
+ Loads configuration from file. Auto-discovers if path not provided.
254
+
255
+ ```typescript
256
+ const config = loadConfig("./standard-api.config.ts");
257
+ ```
258
+
259
+ ## 🔧 Configuration Options
260
+
261
+ ```typescript
262
+ interface StandardApiConfig {
263
+ api: {
264
+ title: string; // API title
265
+ description: string; // API description
266
+ version: string; // API version
267
+ seUrl: string; // Base URL for all endpoints
268
+ };
269
+ headers?: {
270
+ [headerName: string]: {
271
+ description: string;
272
+ required: boolean;
273
+ example?: string;
274
+ };
275
+ };
276
+ swagger: {
277
+ path: string; // Swagger UI path (e.g., '/docs')
278
+ enableDownload: boolean; // Enable spec downloads
279
+ };
280
+ }
281
+ ```
282
+
283
+ ## 📥 Download Endpoints
284
+
285
+ WheenableDownload: true`, the following endpoints are available:
286
+
287
+ - `GET /docs/openapi.json` - Download full OpenAPI spec (JSON)
288
+ - `GET /docs/openapi.yaml` - Download full OpenAPI spec (YAML)
289
+ - `GET /docs/endpoint/:method/:path?format=json` - Download single endpoint spec
290
+
291
+ Example:
292
+
293
+ ```bash
294
+ # Download full spec
295
+ curl http://localhost:3000/docs/openapi.json > openapi.json
296
+
297
+ # Download single endpoint
298
+ curl http://localhost:3000/docs/endpoint/get/users?format=yaml
299
+ ```
300
+
301
+ ## 🎨 Schema Definition
302
+
303
+ Use Zod for type-safe schema definitions:
304
+
305
+ ```typescript
306
+ const CreateUserSchema = z.object({
307
+ success: z.literal(true),
308
+ message: z.string(),
309
+ data: z.object({
310
+ name: z.string().min(3),
311
+ email: z.string().email(),
312
+ role: z.enum(["ADMIN", "USER", "MODERATOR"]),
313
+ age: z.number().min(18).optional(),
314
+ }),
315
+ meta: z.object({
316
+ mestamp: z.string(),
317
+ requestId: z.string(),
318
+ }),
319
+ });
320
+ ```
321
+
322
+ ## 🔐 Authentication Headers
323
+
324
+ Configure global authentication headers:
325
+
326
+ ```typescript
327
+ {
328
+ headers: {
329
+ Authorization: {
330
+ description: "Bearer JWT token",
331
+ required: true
332
+ },
333
+ "X-API-Key": {
334
+ description: "API Key for service authentication",
335
+ required: false,
336
+ example: "your-api-key-here"
337
+ }
338
+ }
339
+ }
340
+ ```
341
+
342
+ ## 📝 Advanced Example
343
+
344
+ ```typescript
345
+ import express from "express";
346
+ import { z } from "zod";
347
+ import {
348
+ setupSwagger,
349
+ responseMiddleware,
350
+ apiDoc,
351
+ loadConfig,
352
+ } from "@standard-api/core";
353
+
354
+ const app = express();
355
+ app.use(express.json());
356
+
357
+ const config = loadConfig();
358
+ app.use(responseMiddleware);
359
+ setupSwagger(app, config);
360
+
361
+ // Response schema
362
+ const UserListSchema = z.object({
363
+ success: z.literal(true),
364
+ message: z.string(),
365
+ data: z.array(
366
+ z.object({
367
+ id: z.string(),
368
+ name: z.string(),
369
+ email: z.string().email(),
370
+ role: z.enum(["ADMIN", "USER"]),
371
+ })
372
+ ),
373
+ meta: z.object({
374
+ timestamp: z.string(),
375
+ requestId: z.string(),
376
+ pagination: z.object({
377
+ page: z.number(),
378
+ limit: z.number(),
379
+ total: z.number(),
380
+ }),
381
+ }),
382
+ });
383
+
384
+ // GET endpoint with query params
385
+ app.get(
386
+ "/api/v1/users",
387
+ apiDoc({
388
+ method: "get",
389
+ path: "/api/v1/users",
390
+ summary: "List all users",
391
+ description: "Get paginated list of users",
392
+ tags: ["Users"],
393
+ request: {
394
+ query: z.object({
395
+ page: z.string().optional().describe("Page number"),
396
+ limit: z.string().optional().describe("Items per page"),
397
+ }),
398
+ },
399
+ response: UserListSchema,
400
+ }),
401
+ (req, res) => {
402
+ const page = parseInt(req.query.page as string) || 1;
403
+ const limit = parseInt(req.query.limit as string) || 10;
404
+
405
+ res.sendSuccess({
406
+ message: "Users fetched successfully",
407
+ data: users,
408
+ meta: {
409
+ pagination: { page, limit, total: 100 },
410
+ },
411
+ });
412
+ }
413
+ );
414
+
415
+ // POST endpoint with body
416
+ const CreateUserRequestSchema = z.object({
417
+ name: z.string().min(3),
418
+ email: z.string().email(),
419
+ role: z.enum(["ADMIN", "USER"]),
420
+ });
421
+
422
+ app.post(
423
+ "/api/v1/users",
424
+ apiDoc({
425
+ method: "post",
426
+ path: "/api/v1/users",
427
+ summary: "Create new user",
428
+ tags: ["Users"],
429
+ request: {
430
+ body: CreateUserRequestSchema,
431
+ },
432
+ response: UserSchema,
433
+ }),
434
+ (req, res) => {
435
+ // Validation happens automatically via Zod
436
+ const newUser = {
437
+ id: "123",
438
+ ...req.body,
439
+ };
440
+
441
+ res.sendSuccess({
442
+ message: "User created successfully",
443
+ data: newUser,
444
+ });
445
+ }
446
+ );
447
+
448
+ // Error handling
449
+ app.use((err, req, res, next) => {
450
+ res.sendError({
451
+ message: err.message || "Internal server error",
452
+ code: err.code || "INTERNAL_ERROR",
453
+ error: process.env.NODE_ENV === "development" ? err.stack : {},
454
+ status: err.status || 500,
455
+ });
456
+ });
457
+
458
+ app.listen(3000);
459
+ ```
460
+
461
+ ## TypeScript Configuration
462
+
463
+ Ensure your `tsconfig.json` includes:
464
+
465
+ ```json
466
+ {
467
+ "compilerOptions": {
468
+ "target": "ES2020",
469
+ "module": "commonjs",
470
+ "lib": ["ES2020"],
471
+ "strict": true,
472
+ Error Handling
473
+
474
+ The package provides standardized error responses. Implement a global error handler:
475
+
476
+ ```typescript
477
+ app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
478
+ res.sendError({
479
+ message: err.message || "Internal server error",
480
+ code: err.code || "INTERNAL_ERROR",
481
+ error: process.env.NODE_ENV === "development" ? err.stack : undefined,
482
+ status: err.status || 500,
483
+ });
484
+ });
485
+ ```
486
+
487
+ ## Requirements
488
+
489
+ - Node.js >= 16.0.0
490
+ - Express.js >= 4.18.0
491
+ - Zod >= 3.22.0
492
+ - TypeScript >= 5.0.0 (for TypeScript projects)
493
+
494
+ ## License
495
+
496
+ MIT
497
+
498
+ ## Contributing
499
+
500
+ Contributions are welcome! Please feel free to submit a Pull Request.
501
+
502
+ ## Support
503
+
504
+ For issues and questions, please open an issue on the GitHub repository.
505
+ }
506
+ ```
507
+
508
+ ## 📄 License
509
+
510
+ MIT
511
+
512
+ ## 🤝 Contributing
513
+
514
+ Contributions are welcome! Please feel free to submit a Pull Request.
515
+
516
+ ## 📧 Support
517
+
518
+ For issues and questions, please open an issue on the GitHub repository.
519
+
520
+ ---
521
+
522
+ Made with ❤️ for the Express.js community
@@ -0,0 +1,3 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ export declare const responseMiddleware: (req: Request, res: Response, next: NextFunction) => void;
3
+ //# sourceMappingURL=response-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../src/core/response-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,eAAO,MAAM,kBAAkB,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,SAuBjF,CAAC"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.responseMiddleware = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const responseMiddleware = (req, res, next) => {
6
+ const requestId = (0, uuid_1.v4)();
7
+ const timestamp = new Date().toISOString();
8
+ res.sendSuccess = ({ message, data = {}, meta = {} }) => {
9
+ res.status(200).json({
10
+ success: true,
11
+ message,
12
+ data,
13
+ meta: { ...meta, timestamp, requestId }
14
+ });
15
+ };
16
+ res.sendError = ({ message, error = {}, code = 'INTERNAL_ERROR', status = 500 }) => {
17
+ res.status(status).json({
18
+ success: false,
19
+ message,
20
+ error: { code, details: error },
21
+ meta: { timestamp, requestId }
22
+ });
23
+ };
24
+ next();
25
+ };
26
+ exports.responseMiddleware = responseMiddleware;
27
+ //# sourceMappingURL=response-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-handler.js","sourceRoot":"","sources":["../../src/core/response-handler.ts"],"names":[],"mappings":";;;AACA,+BAAoC;AAE7B,MAAM,kBAAkB,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACpF,MAAM,SAAS,GAAG,IAAA,SAAM,GAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE3C,GAAG,CAAC,WAAW,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE,EAAE;QACtD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,IAAI;YACb,OAAO;YACP,IAAI;YACJ,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE;SACxC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,GAAG,EAAE,EAAE,IAAI,GAAG,gBAAgB,EAAE,MAAM,GAAG,GAAG,EAAE,EAAE,EAAE;QACjF,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YACtB,OAAO,EAAE,KAAK;YACd,OAAO;YACP,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE;YAC/B,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,IAAI,EAAE,CAAC;AACT,CAAC,CAAC;AAvBW,QAAA,kBAAkB,sBAuB7B"}
@@ -0,0 +1,9 @@
1
+ export * from "./types";
2
+ export * from "./core/response-handler";
3
+ export * from "./swagger/builder";
4
+ export * from "./swagger/registry";
5
+ export * from "./middleware/api-documenter";
6
+ export * from "./utils/config-loader";
7
+ export { responseMiddleware as setupResponseHandlers } from "./core/response-handler";
8
+ export { apiDoc as apiResponse } from "./middleware/api-documenter";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AAGtC,OAAO,EAAE,kBAAkB,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,6BAA6B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.apiResponse = exports.setupResponseHandlers = void 0;
18
+ __exportStar(require("./types"), exports);
19
+ __exportStar(require("./core/response-handler"), exports);
20
+ __exportStar(require("./swagger/builder"), exports);
21
+ __exportStar(require("./swagger/registry"), exports);
22
+ __exportStar(require("./middleware/api-documenter"), exports);
23
+ __exportStar(require("./utils/config-loader"), exports);
24
+ // Re-export commonly used items for convenience
25
+ var response_handler_1 = require("./core/response-handler");
26
+ Object.defineProperty(exports, "setupResponseHandlers", { enumerable: true, get: function () { return response_handler_1.responseMiddleware; } });
27
+ var api_documenter_1 = require("./middleware/api-documenter");
28
+ Object.defineProperty(exports, "apiResponse", { enumerable: true, get: function () { return api_documenter_1.apiDoc; } });
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,0DAAwC;AACxC,oDAAkC;AAClC,qDAAmC;AACnC,8DAA4C;AAC5C,wDAAsC;AAEtC,gDAAgD;AAChD,4DAAsF;AAA7E,yHAAA,kBAAkB,OAAyB;AACpD,8DAAoE;AAA3D,6GAAA,MAAM,OAAe"}
@@ -0,0 +1,4 @@
1
+ import { RouteDoc } from "../types";
2
+ import { Request, Response, NextFunction } from "express";
3
+ export declare const apiDoc: (doc: RouteDoc) => (req: Request, res: Response, next: NextFunction) => void;
4
+ //# sourceMappingURL=api-documenter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-documenter.d.ts","sourceRoot":"","sources":["../../src/middleware/api-documenter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D,eAAO,MAAM,MAAM,GAAI,KAAK,QAAQ,MAwB1B,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,SACxD,CAAC"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.apiDoc = void 0;
4
+ const registry_1 = require("../swagger/registry");
5
+ const apiDoc = (doc) => {
6
+ registry_1.registry.registerPath({
7
+ method: doc.method,
8
+ path: doc.path,
9
+ summary: doc.summary,
10
+ description: doc.description,
11
+ tags: doc.tags,
12
+ request: {
13
+ params: doc.request?.params,
14
+ query: doc.request?.query,
15
+ body: doc.request?.body
16
+ ? {
17
+ content: { "application/json": { schema: doc.request.body } },
18
+ }
19
+ : undefined,
20
+ },
21
+ responses: {
22
+ 200: {
23
+ description: "Successful Response",
24
+ content: { "application/json": { schema: doc.response } },
25
+ },
26
+ },
27
+ });
28
+ return (req, res, next) => next();
29
+ };
30
+ exports.apiDoc = apiDoc;
31
+ //# sourceMappingURL=api-documenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-documenter.js","sourceRoot":"","sources":["../../src/middleware/api-documenter.ts"],"names":[],"mappings":";;;AAAA,kDAA+C;AAIxC,MAAM,MAAM,GAAG,CAAC,GAAa,EAAE,EAAE;IACtC,mBAAQ,CAAC,YAAY,CAAC;QACpB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO,EAAE;YACP,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,MAAa;YAClC,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,KAAY;YAChC,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI;gBACrB,CAAC,CAAC;oBACE,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE;iBAC9D;gBACH,CAAC,CAAC,SAAS;SACd;QACD,SAAS,EAAE;YACT,GAAG,EAAE;gBACH,WAAW,EAAE,qBAAqB;gBAClC,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE;aAC1D;SACF;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AACrE,CAAC,CAAC;AAzBW,QAAA,MAAM,UAyBjB"}
@@ -0,0 +1,4 @@
1
+ import { StandardApiConfig } from "../types";
2
+ import { Express } from "express";
3
+ export declare const setupSwagger: (app: Express, config: StandardApiConfig) => void;
4
+ //# sourceMappingURL=builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/swagger/builder.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,eAAO,MAAM,YAAY,GAAI,KAAK,OAAO,EAAE,QAAQ,iBAAiB,SAqHnE,CAAC"}
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setupSwagger = void 0;
7
+ const zod_to_openapi_1 = require("@asteasolutions/zod-to-openapi");
8
+ const registry_1 = require("./registry");
9
+ const swagger_ui_express_1 = __importDefault(require("swagger-ui-express"));
10
+ const js_yaml_1 = __importDefault(require("js-yaml"));
11
+ const setupSwagger = (app, config) => {
12
+ const generator = new zod_to_openapi_1.OpenApiGeneratorV3(registry_1.registry.definitions);
13
+ // Build security schemes from headers
14
+ const components = {};
15
+ const security = [];
16
+ if (config.headers) {
17
+ components.securitySchemes = {};
18
+ Object.entries(config.headers).forEach(([name, headerConfig]) => {
19
+ const schemeName = name.toLowerCase();
20
+ if (name.toLowerCase() === "authorization") {
21
+ components.securitySchemes[schemeName] = {
22
+ type: "http",
23
+ scheme: "bearer",
24
+ bearerFormat: "JWT",
25
+ description: headerConfig.description,
26
+ };
27
+ }
28
+ else {
29
+ components.securitySchemes[schemeName] = {
30
+ type: "apiKey",
31
+ in: "header",
32
+ name: name,
33
+ description: headerConfig.description,
34
+ };
35
+ }
36
+ if (headerConfig.required) {
37
+ security.push({ [schemeName]: [] });
38
+ }
39
+ });
40
+ }
41
+ const docConfig = {
42
+ openapi: "3.0.0",
43
+ info: {
44
+ title: config.api.title,
45
+ version: config.api.version,
46
+ description: config.api.description,
47
+ },
48
+ servers: [{ url: config.api.baseUrl }],
49
+ };
50
+ if (Object.keys(components).length > 0) {
51
+ docConfig.components = components;
52
+ }
53
+ if (security.length > 0) {
54
+ docConfig.security = security;
55
+ }
56
+ const spec = generator.generateDocument(docConfig);
57
+ // Serve Swagger UI
58
+ app.use(config.swagger.path, swagger_ui_express_1.default.serve, swagger_ui_express_1.default.setup(spec, {
59
+ customSiteTitle: config.api.title,
60
+ customCss: ".swagger-ui .topbar { display: none }",
61
+ }));
62
+ // Download endpoints
63
+ if (config.swagger.enableDownload) {
64
+ // Full API spec - JSON
65
+ app.get(`${config.swagger.path}/openapi.json`, (req, res) => {
66
+ res.setHeader("Content-Type", "application/json");
67
+ res.setHeader("Content-Disposition", 'attachment; filename="openapi.json"');
68
+ res.json(spec);
69
+ });
70
+ // Full API spec - YAML
71
+ app.get(`${config.swagger.path}/openapi.yaml`, (req, res) => {
72
+ res.setHeader("Content-Type", "application/x-yaml");
73
+ res.setHeader("Content-Disposition", 'attachment; filename="openapi.yaml"');
74
+ res.send(js_yaml_1.default.dump(spec));
75
+ });
76
+ // Single endpoint spec
77
+ app.get(`${config.swagger.path}/endpoint/:method/:path(*)?`, (req, res) => {
78
+ const { method, path } = req.params;
79
+ const format = req.query.format || "json";
80
+ const fullPath = path ? `/${path}` : "/";
81
+ const pathSpec = spec.paths?.[fullPath];
82
+ const methodLower = method.toLowerCase();
83
+ if (!pathSpec || !pathSpec[methodLower]) {
84
+ return res.status(404).json({ error: "Endpoint not found" });
85
+ }
86
+ const endpointSpec = {
87
+ openapi: spec.openapi,
88
+ info: spec.info,
89
+ servers: spec.servers,
90
+ components: spec.components,
91
+ paths: {
92
+ [fullPath]: {
93
+ [methodLower]: pathSpec[methodLower],
94
+ },
95
+ },
96
+ };
97
+ if (format === "yaml") {
98
+ res.setHeader("Content-Type", "application/x-yaml");
99
+ res.send(js_yaml_1.default.dump(endpointSpec));
100
+ }
101
+ else {
102
+ res.json(endpointSpec);
103
+ }
104
+ });
105
+ }
106
+ };
107
+ exports.setupSwagger = setupSwagger;
108
+ //# sourceMappingURL=builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/swagger/builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
2
+ export declare const registry: OpenAPIRegistry;
3
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/swagger/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,eAAO,MAAM,QAAQ,iBAAwB,CAAC"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registry = void 0;
4
+ const zod_to_openapi_1 = require("@asteasolutions/zod-to-openapi");
5
+ exports.registry = new zod_to_openapi_1.OpenAPIRegistry();
6
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/swagger/registry.ts"],"names":[],"mappings":";;;AAAA,mEAAiE;AAEpD,QAAA,QAAQ,GAAG,IAAI,gCAAe,EAAE,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { ZodSchema } from "zod";
2
+ export interface HeaderConfig {
3
+ description: string;
4
+ required: boolean;
5
+ example?: string;
6
+ }
7
+ export interface StandardApiConfig {
8
+ api: {
9
+ title: string;
10
+ description: string;
11
+ version: string;
12
+ baseUrl: string;
13
+ };
14
+ headers?: Record<string, HeaderConfig>;
15
+ swagger: {
16
+ path: string;
17
+ enableDownload: boolean;
18
+ };
19
+ }
20
+ export interface RouteDoc {
21
+ method: "get" | "post" | "put" | "delete" | "patch";
22
+ path: string;
23
+ summary: string;
24
+ description?: string;
25
+ tags?: string[];
26
+ request?: {
27
+ body?: ZodSchema;
28
+ query?: ZodSchema;
29
+ params?: ZodSchema;
30
+ headers?: ZodSchema;
31
+ };
32
+ response: ZodSchema;
33
+ errors?: {
34
+ [statusCode: number]: {
35
+ description: string;
36
+ schema?: ZodSchema;
37
+ };
38
+ };
39
+ }
40
+ export interface SuccessOptions {
41
+ message: string;
42
+ data?: any;
43
+ meta?: any;
44
+ }
45
+ export interface ErrorOptions {
46
+ message: string;
47
+ error?: any;
48
+ code?: string;
49
+ status?: number;
50
+ }
51
+ declare global {
52
+ namespace Express {
53
+ interface Response {
54
+ sendSuccess: (options: SuccessOptions) => void;
55
+ sendError: (options: ErrorOptions) => void;
56
+ }
57
+ }
58
+ }
59
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAEhC,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACvC,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,SAAS,CAAC;QACjB,KAAK,CAAC,EAAE,SAAS,CAAC;QAClB,MAAM,CAAC,EAAE,SAAS,CAAC;QACnB,OAAO,CAAC,EAAE,SAAS,CAAC;KACrB,CAAC;IACF,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE;QACP,CAAC,UAAU,EAAE,MAAM,GAAG;YACpB,WAAW,EAAE,MAAM,CAAC;YACpB,MAAM,CAAC,EAAE,SAAS,CAAC;SACpB,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,QAAQ;YAChB,WAAW,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;YAC/C,SAAS,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;SAC5C;KACF;CACF"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import { StandardApiConfig } from "../types";
2
+ export declare const loadConfig: (configPath?: string) => StandardApiConfig;
3
+ //# sourceMappingURL=config-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAI7C,eAAO,MAAM,UAAU,GAAI,aAAa,MAAM,KAAG,iBAsChD,CAAC"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadConfig = void 0;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs"));
39
+ const loadConfig = (configPath) => {
40
+ if (!configPath) {
41
+ // Try to find config file in common locations
42
+ const possiblePaths = [
43
+ "standard-api.config.ts",
44
+ "standard-api.config.js",
45
+ "./config/standard-api.config.ts",
46
+ "./config/standard-api.config.js",
47
+ ];
48
+ for (const p of possiblePaths) {
49
+ const fullPath = path.resolve(process.cwd(), p);
50
+ if (fs.existsSync(fullPath)) {
51
+ configPath = fullPath;
52
+ break;
53
+ }
54
+ }
55
+ }
56
+ if (!configPath) {
57
+ throw new Error("Config file not found. Please provide a configPath or create standard-api.config.ts/js");
58
+ }
59
+ const fullPath = path.resolve(process.cwd(), configPath);
60
+ if (!fs.existsSync(fullPath)) {
61
+ throw new Error(`Config file not found at: ${fullPath}`);
62
+ }
63
+ try {
64
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
65
+ const config = require(fullPath);
66
+ return config.default || config;
67
+ }
68
+ catch (error) {
69
+ throw new Error(`Failed to load config from ${fullPath}: ${error}`);
70
+ }
71
+ };
72
+ exports.loadConfig = loadConfig;
73
+ //# sourceMappingURL=config-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/utils/config-loader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,2CAA6B;AAC7B,uCAAyB;AAElB,MAAM,UAAU,GAAG,CAAC,UAAmB,EAAqB,EAAE;IACnE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,8CAA8C;QAC9C,MAAM,aAAa,GAAG;YACpB,wBAAwB;YACxB,wBAAwB;YACxB,iCAAiC;YACjC,iCAAiC;SAClC,CAAC;QAEF,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YAChD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,UAAU,GAAG,QAAQ,CAAC;gBACtB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,wFAAwF,CACzF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;IAEzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,CAAC;QACH,8DAA8D;QAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC,CAAC;AAtCW,QAAA,UAAU,cAsCrB"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "standard-api-core",
3
+ "version": "1.0.0",
4
+ "description": "Production-ready NPM package for standardized API responses and automatic Swagger documentation generation for Express.js",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md",
10
+ "LICENSE"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsc -w",
15
+ "test": "jest",
16
+ "test:coverage": "jest --coverage",
17
+ "test:watch": "jest --watch",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "dependencies": {
21
+ "@asteasolutions/zod-to-openapi": "^8.2.0",
22
+ "express": "^4.22.1",
23
+ "js-yaml": "^4.1.0",
24
+ "swagger-ui-express": "^5.0.0",
25
+ "uuid": "^9.0.1",
26
+ "zod": "^4.3.4"
27
+ },
28
+ "devDependencies": {
29
+ "@types/express": "^5.0.6",
30
+ "@types/jest": "^30.0.0",
31
+ "@types/js-yaml": "^4.0.9",
32
+ "@types/node": "^25.0.3",
33
+ "@types/supertest": "^6.0.2",
34
+ "@types/swagger-ui-express": "^4.1.6",
35
+ "@types/uuid": "^9.0.8",
36
+ "jest": "^30.2.0",
37
+ "supertest": "^7.1.4",
38
+ "ts-jest": "^29.1.1",
39
+ "typescript": "^5.3.3"
40
+ },
41
+ "peerDependencies": {
42
+ "express": "^4.22.0",
43
+ "zod": "^4.3.0"
44
+ },
45
+ "keywords": [
46
+ "api",
47
+ "rest",
48
+ "swagger",
49
+ "openapi",
50
+ "express",
51
+ "middleware",
52
+ "response",
53
+ "standardization",
54
+ "documentation",
55
+ "zod",
56
+ "typescript"
57
+ ],
58
+ "author": "",
59
+ "license": "MIT",
60
+ "repository": {
61
+ "type": "git",
62
+ "url": "https://github.com/inaumanmajeed/standard-api-core"
63
+ },
64
+ "bugs": {
65
+ "url": "https://github.com/inaumanmajeed/standard-api-core/issues"
66
+ },
67
+ "homepage": "https://github.com/inaumanmajeed/standard-api-core#readme",
68
+ "engines": {
69
+ "node": ">=18.0.0"
70
+ },
71
+ "type": "commonjs"
72
+ }