@eecho/express 0.0.3 → 0.1.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.
Files changed (36) hide show
  1. package/README.md +48 -11
  2. package/dist/api/api.d.ts +9 -9
  3. package/dist/api/api.d.ts.map +1 -1
  4. package/dist/api/api.js +18 -17
  5. package/dist/api/api.js.map +1 -1
  6. package/dist/api/api.middleware.d.ts +2 -2
  7. package/dist/api/api.middleware.d.ts.map +1 -1
  8. package/dist/api/api.middleware.js +22 -9
  9. package/dist/api/api.middleware.js.map +1 -1
  10. package/dist/api/api.type.d.ts +8 -8
  11. package/dist/api/api.type.d.ts.map +1 -1
  12. package/dist/api/api.util.d.ts +7 -8
  13. package/dist/api/api.util.d.ts.map +1 -1
  14. package/dist/api/api.util.js +10 -14
  15. package/dist/api/api.util.js.map +1 -1
  16. package/dist/generator/mongo/mongo.api.generator.d.ts +1 -85
  17. package/dist/generator/mongo/mongo.api.generator.d.ts.map +1 -1
  18. package/dist/generator/mongo/mongo.api.generator.js +3 -122
  19. package/dist/generator/mongo/mongo.api.generator.js.map +1 -1
  20. package/dist/generator/mongo/mongo.endpoint.d.ts +14 -0
  21. package/dist/generator/mongo/mongo.endpoint.d.ts.map +1 -0
  22. package/dist/generator/mongo/mongo.endpoint.js +34 -0
  23. package/dist/generator/mongo/mongo.endpoint.js.map +1 -0
  24. package/dist/generator/mongo/mongo.generator.d.ts +21 -16
  25. package/dist/generator/mongo/mongo.generator.d.ts.map +1 -1
  26. package/dist/generator/mongo/mongo.generator.js +134 -100
  27. package/dist/generator/mongo/mongo.generator.js.map +1 -1
  28. package/dist/index.d.ts +5 -4
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +6 -5
  31. package/dist/index.js.map +1 -1
  32. package/package.json +10 -4
  33. package/dist/generator/mongo/mongo.util.d.ts +0 -4
  34. package/dist/generator/mongo/mongo.util.d.ts.map +0 -1
  35. package/dist/generator/mongo/mongo.util.js +0 -6
  36. package/dist/generator/mongo/mongo.util.js.map +0 -1
package/README.md CHANGED
@@ -1,21 +1,58 @@
1
1
  # @eecho/express
2
2
 
3
- Express server framework library for the EEcho framework with MongoDB integration.
3
+ Express and MongoDB adapters for contracts created by `@eecho/definition`.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @eecho/express @eecho/definition express mongodb
8
+ npm install @eecho/express @eecho/definition express mongodb zod
9
9
  ```
10
10
 
11
- ## Features
11
+ ## Generated Mongo read endpoint
12
12
 
13
- - Express-based server framework
14
- - MongoDB integration with automatic repository generation
15
- - Auto-generated API endpoints from definitions
16
- - Type-safe middleware support
17
- - Repository pattern implementation
18
- - Built-in CRUD operations
19
- - Custom field validation and transformation
13
+ ```ts
14
+ import { Router } from 'express';
15
+ import { MongoGenerator, registerMongoReadEndpoint } from '@eecho/express';
16
+ import { PetAPI, PetDefinition } from './pet-api.js';
20
17
 
21
- ## Usage
18
+ const repository = MongoGenerator.genRepository({
19
+ definition: PetDefinition,
20
+ collectionName: 'Pet',
21
+ dbClient,
22
+ });
23
+
24
+ const router = Router();
25
+ registerMongoReadEndpoint({
26
+ router,
27
+ apiSpec: PetAPI.ReadAPISpecification,
28
+ repository,
29
+ });
30
+ ```
31
+
32
+ The generated read path supports positive-integer pagination, declared search
33
+ fields, declared sort fields, MongoDB ObjectIds, response serialization, and
34
+ response-schema validation.
35
+
36
+ ## Custom endpoint
37
+
38
+ Use `setAPIEndpoint` when application policy is part of the operation:
39
+
40
+ ```ts
41
+ setAPIEndpoint({
42
+ router,
43
+ apiSpec: PetAPI.UpdateAPISpecification,
44
+ handler: async ({ res, params }) => {
45
+ await updatePet(params.body);
46
+ const response = { success: true } as const;
47
+ res.json(response);
48
+ return response;
49
+ },
50
+ });
51
+ ```
52
+
53
+ Mount `ExceptionMiddleware` after the routers. Zod request failures become a
54
+ structured HTTP 400 response; unexpected errors become HTTP 500 without leaking
55
+ internal details.
56
+
57
+ `MongoGenerator.genAPISpec` is a compatibility alias. The server should normally
58
+ import the contract instance already shared with the client.
package/dist/api/api.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- import { Router, Request as ExpressRequest, Response as ExpressResponse, NextFunction } from "express";
2
- import { ServerAPISpecification } from "@eecho/definition";
3
- import type { APIHandler, ExpressMiddleware } from "./api.type";
4
- export declare const setMiddleware: <TResult>(fn: ExpressMiddleware<TResult>) => (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => Promise<void | Awaited<TResult>>;
5
- export declare const setAPIEndpoint: <TSpec extends ServerAPISpecification>(input: {
1
+ import type { NextFunction, Request as ExpressRequest, Response as ExpressResponse, Router } from 'express';
2
+ import type { ServerAPISpecification } from '@eecho/definition';
3
+ import type { APIHandler, ExpressMiddleware } from './api.type.js';
4
+ export declare function setMiddleware<TResult>(middleware: ExpressMiddleware<TResult>): (request: ExpressRequest, response: ExpressResponse, next: NextFunction) => Promise<void | Awaited<TResult>>;
5
+ export declare function setAPIEndpoint<TSpec extends ServerAPISpecification>(input: {
6
6
  router: Router;
7
- apiEndpoint: TSpec["APIEndpoint"];
8
- method: TSpec["Method"];
9
- middlewares?: ExpressMiddleware[];
10
7
  apiSpec: TSpec;
11
8
  handler: APIHandler<TSpec>;
12
- }) => void;
9
+ middlewares?: ExpressMiddleware[];
10
+ apiEndpoint?: TSpec['APIEndpoint'];
11
+ method?: TSpec['Method'];
12
+ }): void;
13
13
  //# sourceMappingURL=api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,cAAc,EAAE,QAAQ,IAAI,eAAe,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvG,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAyC,MAAM,YAAY,CAAC;AAGvG,eAAO,MAAM,aAAa,GAAI,OAAO,EAAE,IAAI,iBAAiB,CAAC,OAAO,CAAC,MAC3D,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,qCAGtE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,KAAK,SAAS,sBAAsB,EACjE,OAAO;IACL,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAClC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxB,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;CAC5B,SAqBF,CAAC"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,IAAI,cAAc,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE5G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGnE,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,iBAAiB,CAAC,OAAO,CAAC,IACnE,SAAS,cAAc,EAAE,UAAU,eAAe,EAAE,MAAM,YAAY,sCAG/E;AAED,wBAAgB,cAAc,CAAC,KAAK,SAAS,sBAAsB,EAAE,KAAK,EAAE;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;CAC1B,QA6BA"}
package/dist/api/api.js CHANGED
@@ -1,25 +1,26 @@
1
- import { parseRequestParams, registerRoute } from "./api.util";
2
- export const setMiddleware = (fn) => {
3
- return (req, res, next) => {
4
- return Promise.resolve(fn(req, res, next)).catch(next);
1
+ import { parseRequestParams, registerRoute } from './api.util.js';
2
+ export function setMiddleware(middleware) {
3
+ return (request, response, next) => {
4
+ return Promise.resolve(middleware(request, response, next)).catch(next);
5
5
  };
6
- };
7
- export const setAPIEndpoint = (input) => {
8
- const { router, middlewares = [], apiSpec, handler } = input;
9
- const { APIEndpoint, Method, Request } = apiSpec;
10
- const apiMiddleware = setMiddleware((req, res, next) => {
11
- const { queryParams, bodyParams } = parseRequestParams(req, Request);
6
+ }
7
+ export function setAPIEndpoint(input) {
8
+ const { router, apiSpec, handler, middlewares = [], apiEndpoint = apiSpec.APIEndpoint, method = apiSpec.Method, } = input;
9
+ if (apiEndpoint !== apiSpec.APIEndpoint || method !== apiSpec.Method) {
10
+ throw new Error('Route endpoint and method must match the API specification.');
11
+ }
12
+ const apiMiddleware = setMiddleware((request, response, next) => {
13
+ const { queryParams, bodyParams } = parseRequestParams(request, apiSpec.Request);
12
14
  return handler({
13
- req,
14
- res,
15
+ req: request,
16
+ res: response,
15
17
  next,
16
18
  params: {
17
19
  query: queryParams,
18
- body: bodyParams
19
- }
20
+ body: bodyParams,
21
+ },
20
22
  });
21
23
  });
22
- const allMiddlewares = [...middlewares, apiMiddleware];
23
- registerRoute(router, Method, APIEndpoint, allMiddlewares);
24
- };
24
+ registerRoute(router, method, apiEndpoint, [...middlewares, apiMiddleware]);
25
+ }
25
26
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,MAAM,CAAC,MAAM,aAAa,GAAG,CAAU,EAA8B,EAAE,EAAE;IACvE,OAAO,CAAC,GAAmB,EAAE,GAAoB,EAAE,IAAkB,EAAE,EAAE;QACvE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,KAOC,EACD,EAAE;IACF,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC7D,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAEjD,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACrD,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAErE,OAAO,OAAO,CAAC;YACb,GAAG;YACH,GAAG;YACH,IAAI;YACJ,MAAM,EAAE;gBACN,KAAK,EAAE,WAAwC;gBAC/C,IAAI,EAAE,UAAsC;aAC7C;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,CAAC,GAAG,WAAW,EAAE,aAAa,CAAC,CAAC;IACvD,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;AAC7D,CAAC,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,UAAU,aAAa,CAAU,UAAsC;IAC3E,OAAO,CAAC,OAAuB,EAAE,QAAyB,EAAE,IAAkB,EAAE,EAAE;QAChF,OAAO,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAuC,KAOpE;IACC,MAAM,EACJ,MAAM,EACN,OAAO,EACP,OAAO,EACP,WAAW,GAAG,EAAE,EAChB,WAAW,GAAG,OAAO,CAAC,WAAW,EACjC,MAAM,GAAG,OAAO,CAAC,MAAM,GACxB,GAAG,KAAK,CAAC;IAEV,IAAI,WAAW,KAAK,OAAO,CAAC,WAAW,IAAI,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QAC9D,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,kBAAkB,CAAQ,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAExF,OAAO,OAAO,CAAC;YACb,GAAG,EAAE,OAAO;YACZ,GAAG,EAAE,QAAQ;YACb,IAAI;YACJ,MAAM,EAAE;gBACN,KAAK,EAAE,WAAW;gBAClB,IAAI,EAAE,UAAU;aACjB;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,GAAG,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;AAC9E,CAAC"}
@@ -1,5 +1,5 @@
1
- import { NextFunction, Request as ExpressRequest, Response as ExpressResponse } from "express";
2
- type ExpressExceptionMiddleware = (err: Error, req: ExpressRequest, res: ExpressResponse, next: NextFunction) => void;
1
+ import type { NextFunction, Request, Response } from 'express';
2
+ type ExpressExceptionMiddleware = (error: Error, request: Request, response: Response, next: NextFunction) => void;
3
3
  export declare const ExceptionMiddleware: ExpressExceptionMiddleware;
4
4
  export {};
5
5
  //# sourceMappingURL=api.middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.middleware.d.ts","sourceRoot":"","sources":["../../src/api/api.middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,OAAO,IAAI,cAAc,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/F,KAAK,0BAA0B,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;AAEtH,eAAO,MAAM,mBAAmB,EAAE,0BAajC,CAAC"}
1
+ {"version":3,"file":"api.middleware.d.ts","sourceRoot":"","sources":["../../src/api/api.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG/D,KAAK,0BAA0B,GAAG,CAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,YAAY,KACf,IAAI,CAAC;AAEV,eAAO,MAAM,mBAAmB,EAAE,0BA0BjC,CAAC"}
@@ -1,14 +1,27 @@
1
- export const ExceptionMiddleware = (err, req, res, next) => {
2
- console.error('API Exception occurred', {
3
- method: req.method,
4
- url: req.originalUrl,
5
- userAgent: req.get('User-Agent'),
6
- ip: req.ip,
7
- error: err
1
+ import { ZodError } from 'zod';
2
+ export const ExceptionMiddleware = (error, request, response, _next) => {
3
+ if (error instanceof ZodError) {
4
+ response.status(400).json({
5
+ success: false,
6
+ error: {
7
+ code: 'INVALID_REQUEST',
8
+ issues: error.issues.map(({ code, message, path }) => ({ code, message, path })),
9
+ },
10
+ });
11
+ return;
12
+ }
13
+ console.error('API exception occurred', {
14
+ method: request.method,
15
+ url: request.originalUrl,
16
+ userAgent: request.get('User-Agent'),
17
+ ip: request.ip,
18
+ error,
8
19
  });
9
- return res.status(500).json({
20
+ response.status(500).json({
10
21
  success: false,
11
- message: "EXCEPTION_MIDDLEWARE_UNKNOWN_ERROR"
22
+ error: {
23
+ code: 'INTERNAL_SERVER_ERROR',
24
+ },
12
25
  });
13
26
  };
14
27
  //# sourceMappingURL=api.middleware.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.middleware.js","sourceRoot":"","sources":["../../src/api/api.middleware.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,mBAAmB,GAA+B,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACrF,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE;QACtC,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,GAAG,CAAC,WAAW;QACpB,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;QAChC,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,KAAK,EAAE,GAAG;KACX,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1B,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,oCAAoC;KAC9C,CAAC,CAAC;AACL,CAAC,CAAC"}
1
+ {"version":3,"file":"api.middleware.js","sourceRoot":"","sources":["../../src/api/api.middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAS/B,MAAM,CAAC,MAAM,mBAAmB,GAA+B,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;IACjG,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACxB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE;gBACL,IAAI,EAAE,iBAAiB;gBACvB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;aACjF;SACF,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE;QACtC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,GAAG,EAAE,OAAO,CAAC,WAAW;QACxB,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QACpC,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,KAAK;KACN,CAAC,CAAC;IAEH,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACxB,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACL,IAAI,EAAE,uBAAuB;SAC9B;KACF,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -1,17 +1,17 @@
1
- import type { Request as ExpressRequest, Response as ExpressResponse, NextFunction } from 'express';
1
+ import type { NextFunction, Request as ExpressRequest, Response as ExpressResponse } from 'express';
2
2
  import { z } from 'zod';
3
- import { ServerAPISpecification } from '@eecho/definition';
4
- export type ExtractQueryParams<TSpec extends ServerAPISpecification> = TSpec['Request']['queryParams'] extends z.ZodTypeAny ? z.infer<TSpec['Request']['queryParams']> : {};
5
- export type ExtractBodyParams<TSpec extends ServerAPISpecification> = TSpec['Request']['body'] extends z.ZodTypeAny ? z.infer<TSpec['Request']['body']> : {};
6
- export type ExtractResponseType<TSpec extends ServerAPISpecification> = TSpec['Response']['body'] extends z.ZodTypeAny ? z.infer<TSpec['Response']['body']> : any;
7
- export type APIHandler<TSpec extends ServerAPISpecification> = (opts: {
3
+ import type { ServerAPISpecification } from '@eecho/definition';
4
+ export type ExtractQueryParams<TSpec extends ServerAPISpecification> = TSpec['Request']['queryParams'] extends z.ZodTypeAny ? z.output<TSpec['Request']['queryParams']> : Record<string, never>;
5
+ export type ExtractBodyParams<TSpec extends ServerAPISpecification> = TSpec['Request']['body'] extends z.ZodTypeAny ? z.output<TSpec['Request']['body']> : Record<string, never>;
6
+ export type ExtractResponseType<TSpec extends ServerAPISpecification> = TSpec['Response']['body'] extends z.ZodTypeAny ? z.output<TSpec['Response']['body']> : unknown;
7
+ export type APIHandler<TSpec extends ServerAPISpecification> = (options: {
8
8
  req: ExpressRequest;
9
9
  res: ExpressResponse;
10
10
  params: {
11
11
  query: ExtractQueryParams<TSpec>;
12
12
  body: ExtractBodyParams<TSpec>;
13
13
  };
14
- next?: NextFunction;
14
+ next: NextFunction;
15
15
  }) => ExtractResponseType<TSpec> | Promise<ExtractResponseType<TSpec>>;
16
- export type ExpressMiddleware<TReturn = any> = (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => TReturn | Promise<TReturn>;
16
+ export type ExpressMiddleware<TReturn = unknown> = (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => TReturn | Promise<TReturn>;
17
17
  //# sourceMappingURL=api.type.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.type.d.ts","sourceRoot":"","sources":["../../src/api/api.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,cAAc,EAAE,QAAQ,IAAI,eAAe,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,MAAM,kBAAkB,CAAC,KAAK,SAAS,sBAAsB,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,UAAU,GACvH,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC,GACxC,EAAE,CAAC;AAEP,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,sBAAsB,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,GAC/G,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GACjC,EAAE,CAAC;AAEP,MAAM,MAAM,mBAAmB,CAAC,KAAK,SAAS,sBAAsB,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,GAClH,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GAClC,GAAG,CAAC;AAER,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,sBAAsB,IAAI,CAAC,IAAI,EAAE;IACpE,GAAG,EAAE,cAAc,CAAC;IACpB,GAAG,EAAE,eAAe,CAAC;IACrB,MAAM,EAAE;QACN,KAAK,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC;KAChC,CAAC;IACF,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,KAAK,mBAAmB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;AAEvE,MAAM,MAAM,iBAAiB,CAAC,OAAO,GAAG,GAAG,IAAI,CAC7C,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,KACf,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"api.type.d.ts","sourceRoot":"","sources":["../../src/api/api.type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,IAAI,cAAc,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,MAAM,MAAM,kBAAkB,CAAC,KAAK,SAAS,sBAAsB,IACjE,KAAK,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,UAAU,GAChD,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC,GACzC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE5B,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,sBAAsB,IAChE,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,GACzC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE5B,MAAM,MAAM,mBAAmB,CAAC,KAAK,SAAS,sBAAsB,IAClE,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,GAC1C,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GACnC,OAAO,CAAC;AAEd,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,sBAAsB,IAAI,CAAC,OAAO,EAAE;IACvE,GAAG,EAAE,cAAc,CAAC;IACpB,GAAG,EAAE,eAAe,CAAC;IACrB,MAAM,EAAE;QACN,KAAK,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC;KAChC,CAAC;IACF,IAAI,EAAE,YAAY,CAAC;CACpB,KAAK,mBAAmB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;AAEvE,MAAM,MAAM,iBAAiB,CAAC,OAAO,GAAG,OAAO,IAAI,CACjD,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,YAAY,KACf,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC"}
@@ -1,10 +1,9 @@
1
- import type { Request as ExpressRequest, Router } from "express";
2
- import { z } from "zod";
3
- import { ExpressMiddleware } from "./api.type";
4
- import { ServerAPISpecification } from "@eecho/definition";
5
- export declare const parseRequestParams: <TSpec extends ServerAPISpecification>(req: ExpressRequest, requestSpec: TSpec["Request"]) => {
6
- queryParams: TSpec["Request"]["queryParams"] extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.output<TSpec["Request"]["queryParams"]> : Record<string, any>;
7
- bodyParams: TSpec["Request"]["body"] extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.output<TSpec["Request"]["body"]> : Record<string, any>;
1
+ import type { Request as ExpressRequest, Router } from 'express';
2
+ import type { ServerAPISpecification } from '@eecho/definition';
3
+ import type { ExpressMiddleware, ExtractBodyParams, ExtractQueryParams } from './api.type.js';
4
+ export declare function parseRequestParams<TSpec extends ServerAPISpecification>(request: ExpressRequest, requestSpec: TSpec['Request']): {
5
+ queryParams: ExtractQueryParams<TSpec>;
6
+ bodyParams: ExtractBodyParams<TSpec>;
8
7
  };
9
- export declare const registerRoute: (router: Router, method: ServerAPISpecification["Method"], endpoint: string, middlewares: ExpressMiddleware[]) => void;
8
+ export declare function registerRoute(router: Router, method: ServerAPISpecification['Method'], endpoint: string, middlewares: readonly ExpressMiddleware[]): void;
10
9
  //# sourceMappingURL=api.util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.util.d.ts","sourceRoot":"","sources":["../../src/api/api.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,cAAc,EAA6C,MAAM,EAAE,MAAM,SAAS,CAAC;AAC5G,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,eAAO,MAAM,kBAAkB,GAAI,KAAK,SAAS,sBAAsB,EACrE,KAAK,cAAc,EACnB,aAAa,KAAK,CAAC,SAAS,CAAC;;;CAsB9B,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,QAAQ,MAAM,EACd,QAAQ,sBAAsB,CAAC,QAAQ,CAAC,EACxC,UAAU,MAAM,EAChB,aAAa,iBAAiB,EAAE,SAqBjC,CAAC"}
1
+ {"version":3,"file":"api.util.d.ts","sourceRoot":"","sources":["../../src/api/api.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAE9F,wBAAgB,kBAAkB,CAAC,KAAK,SAAS,sBAAsB,EACrE,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC;;;EAU9B;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,EACxC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,SAAS,iBAAiB,EAAE,QAmB1C"}
@@ -1,15 +1,13 @@
1
- export const parseRequestParams = (req, requestSpec) => {
2
- let queryParams = {};
3
- let bodyParams = {};
4
- if (requestSpec.queryParams) {
5
- queryParams = requestSpec.queryParams.parse(req.query);
6
- }
7
- if (requestSpec.body) {
8
- bodyParams = requestSpec.body.parse(req.body);
9
- }
1
+ export function parseRequestParams(request, requestSpec) {
2
+ const queryParams = requestSpec.queryParams
3
+ ? requestSpec.queryParams.parse(request.query)
4
+ : {};
5
+ const bodyParams = requestSpec.body
6
+ ? requestSpec.body.parse(request.body)
7
+ : {};
10
8
  return { queryParams, bodyParams };
11
- };
12
- export const registerRoute = (router, method, endpoint, middlewares) => {
9
+ }
10
+ export function registerRoute(router, method, endpoint, middlewares) {
13
11
  switch (method) {
14
12
  case 'GET':
15
13
  router.get(endpoint, ...middlewares);
@@ -26,8 +24,6 @@ export const registerRoute = (router, method, endpoint, middlewares) => {
26
24
  case 'DELETE':
27
25
  router.delete(endpoint, ...middlewares);
28
26
  break;
29
- default:
30
- throw new Error(`Unsupported HTTP method: ${method}`);
31
27
  }
32
- };
28
+ }
33
29
  //# sourceMappingURL=api.util.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.util.js","sourceRoot":"","sources":["../../src/api/api.util.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,GAAmB,EACnB,WAA6B,EAC7B,EAAE;IASF,IAAI,WAAW,GAAoB,EAAqB,CAAC;IACzD,IAAI,UAAU,GAAmB,EAAoB,CAAC;IAEtD,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;QAC5B,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAoB,CAAC;IAC5E,CAAC;IAED,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;QACrB,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAmB,CAAC;IAClE,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACrC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAc,EACd,MAAwC,EACxC,QAAgB,EAChB,WAAgC,EAChC,EAAE;IACF,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK;YACR,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACrC,MAAM;QACR,KAAK,MAAM;YACT,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACtC,MAAM;QACR,KAAK,KAAK;YACR,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACrC,MAAM;QACR,KAAK,OAAO;YACV,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACvC,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACxC,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC,CAAC"}
1
+ {"version":3,"file":"api.util.js","sourceRoot":"","sources":["../../src/api/api.util.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,kBAAkB,CAChC,OAAuB,EACvB,WAA6B;IAE7B,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW;QACzC,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAA8B;QAC3E,CAAC,CAAC,EAA+B,CAAC;IACpC,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI;QACjC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAA6B;QAClE,CAAC,CAAC,EAA8B,CAAC;IAEnC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,MAAwC,EACxC,QAAgB,EAChB,WAAyC;IAEzC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK;YACR,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACrC,MAAM;QACR,KAAK,MAAM;YACT,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACtC,MAAM;QACR,KAAK,KAAK;YACR,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACrC,MAAM;QACR,KAAK,OAAO;YACV,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACvC,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;YACxC,MAAM;IACV,CAAC;AACH,CAAC"}
@@ -1,86 +1,2 @@
1
- import { ObjectId } from 'bson';
2
- import { z } from 'zod';
3
- import { Definition } from '@eecho/definition';
4
- export declare function genAPISpec<TDefinition extends Definition, const TPrefix extends string>(params: {
5
- definition: TDefinition;
6
- endpointPrefix: TPrefix;
7
- }): {
8
- CreateAPISpecification: {
9
- readonly APIEndpoint: `${TPrefix}/createItems`;
10
- readonly Method: "POST";
11
- readonly Request: {
12
- readonly body: z.ZodObject<{
13
- data: z.ZodObject<({ [K_1 in keyof TDefinition]: TDefinition[K_1] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<any, any, infer TApi extends import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TApi["create"] extends readonly unknown[] ? Extract<"Optional", TApi["create"][number]> | Extract<"System", TApi["create"][number]> extends never ? K_1 : never : K_1 : never; }[keyof TDefinition] extends infer T_1 extends keyof TDefinition ? { [K in T_1 as TDefinition[K] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? K : never]: TDefinition[K] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<infer TSchema extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TSchema : never; } : never) extends infer T ? { -readonly [P in keyof T]: T[P]; } : never, z.core.$strip>;
14
- }, z.core.$strip>;
15
- };
16
- readonly Response: {
17
- readonly body: z.ZodObject<{
18
- success: z.ZodLiteral<true>;
19
- data: z.ZodObject<{
20
- id: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<ObjectId, ObjectId>]>;
21
- }, z.core.$strip>;
22
- }, z.core.$strip>;
23
- };
24
- };
25
- ReadAPISpecification: {
26
- readonly APIEndpoint: `${TPrefix}/getItems`;
27
- readonly Method: "GET";
28
- readonly Request: {
29
- readonly queryParams: z.ZodObject<{
30
- page: z.ZodOptional<z.ZodDefault<z.ZodCoercedNumber<unknown>>>;
31
- limit: z.ZodOptional<z.ZodDefault<z.ZodCoercedNumber<unknown>>>;
32
- filter: z.ZodUnion<readonly [z.ZodOptional<z.ZodObject<(({ [K_4 in keyof TDefinition]: TDefinition[K_4] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<any, any, infer TApi extends import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TApi["read"] extends readonly unknown[] ? "Searchable" extends infer T_5 ? T_5 extends "Searchable" ? T_5 extends TApi["read"][number] ? K_4 : never : never : never : never : never; }[keyof TDefinition] extends infer T_4 extends keyof TDefinition ? { [K_3 in T_4 as TDefinition[K_3] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? K_3 : never]: TDefinition[K_3] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<infer TSchema extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TSchema : never; } : never) extends infer T_3 extends Record<string, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>> ? { [K_2 in keyof T_3]: z.ZodOptional<T_3[K_2]>; } : never) extends infer T_2 ? { -readonly [P_1 in keyof T_2]: T_2[P_1]; } : never, z.core.$strip>>, z.ZodOptional<z.ZodObject<(({ [K_7 in keyof TDefinition]: TDefinition[K_7] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<any, any, infer TApi extends import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TApi["read"] extends readonly unknown[] ? "SearchableArray" extends infer T_8 ? T_8 extends "SearchableArray" ? T_8 extends TApi["read"][number] ? K_7 : never : never : never : never : never; }[keyof TDefinition] extends infer T_7 extends keyof TDefinition ? { [K_6 in T_7 as TDefinition[K_6] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? K_6 : never]: TDefinition[K_6] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<infer TSchema extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TSchema : never; } : never) extends infer T_6 extends Record<string, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>> ? { [K_5 in keyof T_6]: z.ZodOptional<z.ZodArray<z.ZodOptional<T_6[K_5]>>>; } : never) extends infer T_5 ? { -readonly [P_2 in keyof T_5]: T_5[P_2]; } : never, z.core.$strip>>]>;
33
- sort: z.ZodOptional<z.ZodObject<(({ [K_10 in keyof TDefinition]: TDefinition[K_10] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<any, any, infer TApi extends import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TApi["read"] extends readonly unknown[] ? "Sortable" extends infer T_11 ? T_11 extends "Sortable" ? T_11 extends TApi["read"][number] ? K_10 : never : never : never : never : never; }[keyof TDefinition] extends infer T_10 extends keyof TDefinition ? { [K_9 in T_10 as TDefinition[K_9] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? K_9 : never]: TDefinition[K_9] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<infer TSchema extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TSchema : never; } : never) extends infer T_9 extends Record<string, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>> ? { [K_8 in keyof T_9]: z.ZodOptional<T_9[K_8]>; } : never) extends infer T_8 ? { -readonly [P_3 in keyof T_8]: T_8[P_3]; } : never, z.core.$strip>>;
34
- }, z.core.$strip>;
35
- };
36
- readonly Response: {
37
- readonly body: z.ZodObject<{
38
- success: z.ZodLiteral<true>;
39
- data: z.ZodArray<z.ZodObject<({ [K_12 in keyof TDefinition]: TDefinition[K_12] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<any, any, infer TApi extends import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TApi["read"] extends readonly unknown[] ? Extract<"Hidden", TApi["read"][number]> | Extract<"Detail", TApi["read"][number]> extends never ? K_12 : never : K_12 : never; }[keyof TDefinition] extends infer T_12 extends keyof TDefinition ? { [K_11 in T_12 as TDefinition[K_11] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? K_11 : never]: TDefinition[K_11] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<infer TSchema extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TSchema : never; } : never) extends infer T_11 ? { -readonly [P_4 in keyof T_11]: T_11[P_4]; } : never, z.core.$strip>>;
40
- }, z.core.$strip>;
41
- };
42
- };
43
- UpdateAPISpecification: {
44
- readonly APIEndpoint: `${TPrefix}/updateItem`;
45
- readonly Method: "POST";
46
- readonly Request: {
47
- readonly body: z.ZodObject<{
48
- id: z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<ObjectId, ObjectId>]>, z.ZodTransform<ObjectId, string | ObjectId>>;
49
- data: z.ZodObject<(({ [K_15 in keyof TDefinition]: TDefinition[K_15] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<any, any, infer TApi extends import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TApi["update"] extends readonly unknown[] ? "Updatable" extends infer T_16 ? T_16 extends "Updatable" ? T_16 extends TApi["update"][number] ? K_15 : never : never : never : never : never; }[keyof TDefinition] extends infer T_15 extends keyof TDefinition ? { [K_14 in T_15 as TDefinition[K_14] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? K_14 : never]: TDefinition[K_14] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<infer TSchema extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TSchema : never; } : never) extends infer T_14 extends Record<string, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>> ? { [K_13 in keyof T_14]: z.ZodOptional<T_14[K_13]>; } : never) extends infer T_13 ? { -readonly [P_5 in keyof T_13]: T_13[P_5]; } : never, z.core.$strip>;
50
- }, z.core.$strip>;
51
- };
52
- readonly Response: {
53
- readonly body: z.ZodObject<{}, z.core.$strip>;
54
- };
55
- };
56
- DeleteAPISpecification: {
57
- readonly APIEndpoint: `${TPrefix}/deleteItems`;
58
- readonly Method: "POST";
59
- readonly Request: {
60
- readonly body: z.ZodObject<{
61
- ids: z.ZodArray<z.ZodObject<{}, z.core.$strip>>;
62
- }, z.core.$strip>;
63
- };
64
- readonly Response: {
65
- readonly body: z.ZodObject<{}, z.core.$strip>;
66
- };
67
- };
68
- PutAPISpecification: {
69
- readonly APIEndpoint: `${TPrefix}/putItem`;
70
- readonly Method: "PUT";
71
- readonly Request: {
72
- readonly body: z.ZodObject<{
73
- data: z.ZodObject<({ [K_1 in keyof TDefinition]: TDefinition[K_1] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<any, any, infer TApi extends import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TApi["create"] extends readonly unknown[] ? Extract<"Optional", TApi["create"][number]> | Extract<"System", TApi["create"][number]> extends never ? K_1 : never : K_1 : never; }[keyof TDefinition] extends infer T_17 extends keyof TDefinition ? { [K in T_17 as TDefinition[K] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? K : never]: TDefinition[K] extends import("@eecho/definition/dist/model/model.define.type").PrimitiveDefinition<infer TSchema extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, readonly import("@eecho/definition/dist/model/model.define.type").PrimitiveIndex[], import("@eecho/definition/dist/model/model.define.type").APIIndex, string> ? TSchema : never; } : never) extends infer T_16 ? { -readonly [P in keyof T_16]: T_16[P]; } : never, z.core.$strip>;
74
- }, z.core.$strip>;
75
- };
76
- readonly Response: {
77
- readonly body: z.ZodObject<{
78
- success: z.ZodLiteral<true>;
79
- data: z.ZodObject<{
80
- id: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<ObjectId, ObjectId>]>;
81
- }, z.core.$strip>;
82
- }, z.core.$strip>;
83
- };
84
- };
85
- };
1
+ export { genAPIDefinition as genAPISpec } from '@eecho/definition';
86
2
  //# sourceMappingURL=mongo.api.generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mongo.api.generator.d.ts","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.api.generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EASL,UAAU,EACV,MAAM,mBAAmB,CAAC;AAuC5B,wBAAgB,UAAU,CAAC,WAAW,SAAS,UAAU,EAAE,KAAK,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,EAAE;IAC/F,UAAU,EAAE,WAAW,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;CACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyGA"}
1
+ {"version":3,"file":"mongo.api.generator.d.ts","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.api.generator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,123 +1,4 @@
1
- import { ObjectId } from 'bson';
2
- import { z } from 'zod';
3
- import { extractCreateRequiredField, extractReadbleField, extractSearchArrayOption, extractSearchOption, extractSortableOption, extractUpdateOption, extractObjectIdFields } from '@eecho/definition';
4
- import { ObjectIdCompatible } from './mongo.util';
5
- const convertToObjectId = (value) => {
6
- if (value === undefined || value === null) {
7
- return value;
8
- }
9
- if (value instanceof ObjectId) {
10
- return value;
11
- }
12
- if (Array.isArray(value)) {
13
- return value.map((item) => convertToObjectId(item));
14
- }
15
- return new ObjectId(value);
16
- };
17
- const applyObjectIdTransforms = (shape, objectIdFields) => {
18
- if (objectIdFields.size === 0) {
19
- return shape;
20
- }
21
- return Object.fromEntries(Object.entries(shape).map(([key, schema]) => {
22
- if (!objectIdFields.has(key)) {
23
- return [key, schema];
24
- }
25
- return [key, schema.transform((val) => convertToObjectId(val))];
26
- }));
27
- };
28
- export function genAPISpec(params) {
29
- const { definition, endpointPrefix } = params;
30
- const createRequiredField = extractCreateRequiredField({ definition });
31
- const readableField = extractReadbleField({ definition });
32
- const searchableOption = extractSearchOption({ definition });
33
- const searchableArrayOption = extractSearchArrayOption({ definition });
34
- const sortableOption = extractSortableOption({ definition });
35
- const updatableOption = extractUpdateOption({ definition });
36
- const objectIdFields = new Set(extractObjectIdFields({ definition }).map((key) => String(key)));
37
- const createBodyShape = applyObjectIdTransforms(createRequiredField, objectIdFields);
38
- const updateBodyShape = applyObjectIdTransforms(updatableOption, objectIdFields);
39
- const searchableShape = applyObjectIdTransforms(searchableOption, objectIdFields);
40
- const searchableArrayShape = applyObjectIdTransforms(searchableArrayOption, objectIdFields);
41
- const sortableShape = applyObjectIdTransforms(sortableOption, objectIdFields);
42
- const CreateAPISpecification = {
43
- APIEndpoint: `${endpointPrefix}/createItems`,
44
- Method: 'POST',
45
- Request: {
46
- body: z.object({ data: z.object(createBodyShape) }),
47
- },
48
- Response: {
49
- body: z.object({
50
- success: z.literal(true),
51
- data: z.object({
52
- id: ObjectIdCompatible,
53
- }),
54
- }),
55
- },
56
- };
57
- const ReadAPISpecification = {
58
- APIEndpoint: `${endpointPrefix}/getItems`,
59
- Method: 'GET',
60
- Request: {
61
- queryParams: z.object({
62
- page: z.coerce.number().default(1).optional(),
63
- limit: z.coerce.number().default(15).optional(),
64
- filter: z.union([z.object(searchableShape).optional(), z.object(searchableArrayShape).optional()]),
65
- sort: z.object(sortableShape).optional(),
66
- }),
67
- },
68
- Response: {
69
- body: z.object({
70
- success: z.literal(true),
71
- data: z.array(z.object(readableField)),
72
- }),
73
- },
74
- };
75
- const UpdateAPISpecification = {
76
- APIEndpoint: `${endpointPrefix}/updateItem`,
77
- Method: 'POST',
78
- Request: {
79
- body: z.object({
80
- id: ObjectIdCompatible.transform((val) => new ObjectId(val ?? 'Undefined ObjectId')),
81
- data: z.object(updateBodyShape),
82
- })
83
- },
84
- Response: {
85
- body: z.object({})
86
- },
87
- };
88
- const DeleteAPISpecification = {
89
- APIEndpoint: `${endpointPrefix}/deleteItems`,
90
- Method: 'POST',
91
- Request: {
92
- body: z.object({
93
- ids: z.array(z.object({})),
94
- }),
95
- },
96
- Response: {
97
- body: z.object({})
98
- },
99
- };
100
- const PutAPISpecification = {
101
- APIEndpoint: `${endpointPrefix}/putItem`,
102
- Method: 'PUT',
103
- Request: {
104
- body: z.object({ data: z.object(createBodyShape) }),
105
- },
106
- Response: {
107
- body: z.object({
108
- success: z.literal(true),
109
- data: z.object({
110
- id: ObjectIdCompatible,
111
- }),
112
- }),
113
- },
114
- };
115
- return {
116
- CreateAPISpecification,
117
- ReadAPISpecification,
118
- UpdateAPISpecification,
119
- DeleteAPISpecification,
120
- PutAPISpecification
121
- };
122
- }
1
+ // Compatibility alias. The shared transport contract is database-agnostic and
2
+ // is now owned by @eecho/definition.
3
+ export { genAPIDefinition as genAPISpec } from '@eecho/definition';
123
4
  //# sourceMappingURL=mongo.api.generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mongo.api.generator.js","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.api.generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mongo.api.generator.js","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.api.generator.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,qCAAqC;AACrC,OAAO,EAAE,gBAAgB,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Router } from 'express';
2
+ import type { ServerAPISpecification } from '@eecho/definition';
3
+ import type { ExtractQueryParams } from '../../api/api.type.js';
4
+ interface MongoReadRepository<TQuery> {
5
+ getItems(input: TQuery): Promise<unknown[]>;
6
+ }
7
+ /** Registers the conventional generated read endpoint for a Mongo repository. */
8
+ export declare function registerMongoReadEndpoint<TSpec extends ServerAPISpecification>(input: {
9
+ router: Router;
10
+ apiSpec: TSpec;
11
+ repository: MongoReadRepository<ExtractQueryParams<TSpec>>;
12
+ }): void;
13
+ export {};
14
+ //# sourceMappingURL=mongo.endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongo.endpoint.d.ts","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGtC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAGhE,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,uBAAuB,CAAC;AAErF,UAAU,mBAAmB,CAAC,MAAM;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CAC7C;AAwBD,iFAAiF;AACjF,wBAAgB,yBAAyB,CAAC,KAAK,SAAS,sBAAsB,EAAE,KAAK,EAAE;IACrF,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,KAAK,CAAC;IACf,UAAU,EAAE,mBAAmB,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;CAC5D,QAeA"}
@@ -0,0 +1,34 @@
1
+ import { ObjectId } from 'mongodb';
2
+ import { setAPIEndpoint } from '../../api/api.js';
3
+ function toTransportValue(value) {
4
+ if (value instanceof ObjectId) {
5
+ return value.toHexString();
6
+ }
7
+ if (Array.isArray(value)) {
8
+ return value.map(toTransportValue);
9
+ }
10
+ if (value instanceof Date) {
11
+ return value;
12
+ }
13
+ if (typeof value === 'object' && value !== null) {
14
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, toTransportValue(entry)]));
15
+ }
16
+ return value;
17
+ }
18
+ /** Registers the conventional generated read endpoint for a Mongo repository. */
19
+ export function registerMongoReadEndpoint(input) {
20
+ setAPIEndpoint({
21
+ router: input.router,
22
+ apiSpec: input.apiSpec,
23
+ handler: async ({ res, params }) => {
24
+ const documents = await input.repository.getItems(params.query);
25
+ const response = input.apiSpec.Response.body.parse({
26
+ success: true,
27
+ data: toTransportValue(documents),
28
+ });
29
+ res.json(response);
30
+ return response;
31
+ },
32
+ });
33
+ }
34
+ //# sourceMappingURL=mongo.endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongo.endpoint.js","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.endpoint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAInC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOlD,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAC5E,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,yBAAyB,CAAuC,KAI/E;IACC,cAAc,CAAC;QACb,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;YACjC,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;gBACjD,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC;aAClC,CAA+B,CAAC;YAEjC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnB,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -1,9 +1,10 @@
1
- import { ClientSession, Filter, FindOneAndUpdateOptions, MongoClient, ObjectId, UpdateFilter } from "mongodb";
1
+ import { ObjectId } from 'mongodb';
2
+ import type { ClientSession, Filter, FindOneAndUpdateOptions, MongoClient, UpdateFilter } from 'mongodb';
2
3
  import { z } from 'zod';
3
- import { DefinitionDocument, ViewDefinition, Definition } from "@eecho/definition";
4
- import { extractCreateFieldWithSystem } from "@eecho/definition";
5
- type CreateDocument<T extends Definition> = {
6
- [K in keyof ReturnType<typeof extractCreateFieldWithSystem<T>>]: z.infer<ReturnType<typeof extractCreateFieldWithSystem<T>>[K]>;
4
+ import { extractCreateFieldWithSystem } from '@eecho/definition';
5
+ import type { Definition, DefinitionDocument, SearchField, SortField, UpdateField, ViewDefinition } from '@eecho/definition';
6
+ type CreateDocument<TDefinition extends Definition> = {
7
+ [K in keyof ReturnType<typeof extractCreateFieldWithSystem<TDefinition>>]: z.input<ReturnType<typeof extractCreateFieldWithSystem<TDefinition>>[K]>;
7
8
  };
8
9
  export declare function genRepository<TDefinition extends Definition>(params: {
9
10
  definition: TDefinition;
@@ -11,25 +12,27 @@ export declare function genRepository<TDefinition extends Definition>(params: {
11
12
  dbName?: string;
12
13
  collectionName: string;
13
14
  }): {
14
- getItems(params: {
15
+ getItems(input?: {
15
16
  page?: number;
16
17
  limit?: number;
17
- search?: any;
18
+ filter?: SearchField<TDefinition>;
19
+ sort?: SortField<TDefinition>;
20
+ search?: SearchField<TDefinition>;
18
21
  }): Promise<import("mongodb").WithId<DefinitionDocument<TDefinition>>[]>;
19
- putItem(params: {
22
+ putItem(input: {
20
23
  idFilter: Filter<DefinitionDocument<TDefinition>>;
21
24
  updateFilter: UpdateFilter<DefinitionDocument<TDefinition>>;
22
25
  putOption?: FindOneAndUpdateOptions;
23
26
  }): Promise<import("mongodb").WithId<DefinitionDocument<TDefinition>>>;
24
- updateItemById(params: {
25
- _id: ObjectId;
26
- data: any;
27
- }, option?: {
27
+ updateItemById(input: {
28
+ _id: ObjectId | string;
29
+ data: UpdateField<TDefinition>;
30
+ }, options?: {
28
31
  session?: ClientSession;
29
32
  }): Promise<import("mongodb").UpdateResult<DefinitionDocument<TDefinition>>>;
30
- createItems(params: {
33
+ createItems(input: {
31
34
  items: CreateDocument<TDefinition>[];
32
- }, option?: {
35
+ }, options?: {
33
36
  session?: ClientSession;
34
37
  }): Promise<import("mongodb").InsertManyResult<DefinitionDocument<TDefinition>>>;
35
38
  };
@@ -37,10 +40,12 @@ export declare function genViewRepository<TDefinition extends ViewDefinition>(pa
37
40
  definition: TDefinition;
38
41
  dbClient: Promise<MongoClient>;
39
42
  }): {
40
- getItems(params: {
43
+ getItems(input?: {
41
44
  page?: number;
42
45
  limit?: number;
43
- search?: any;
46
+ filter?: SearchField<TDefinition["viewDefinition"]>;
47
+ sort?: SortField<TDefinition["viewDefinition"]>;
48
+ search?: SearchField<TDefinition["viewDefinition"]>;
44
49
  }): Promise<DefinitionDocument<TDefinition["viewDefinition"]>[]>;
45
50
  };
46
51
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"mongo.generator.d.ts","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,uBAAuB,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC9G,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,UAAU,EAAyB,MAAM,mBAAmB,CAAC;AAC1G,OAAO,EAAsE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAGrI,KAAK,cAAc,CAAC,CAAC,SAAS,UAAU,IAAI;KACzC,CAAC,IAAI,MAAM,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAChI,CAAC;AAkCF,wBAAgB,aAAa,CAAC,WAAW,SAAS,UAAU,EAAE,MAAM,EAAE;IACpE,UAAU,EAAE,WAAW,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;qBAa0B;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,GAAG,CAAC;KACd;oBAYqB;QACpB,QAAQ,EAAE,MAAM,iCAAQ,CAAC;QACzB,YAAY,EAAE,YAAY,iCAAQ,CAAC;QACnC,SAAS,CAAC,EAAE,uBAAuB,CAAC;KACrC;2BAeS;QACN,GAAG,EAAE,QAAQ,CAAC;QACd,IAAI,EAAE,GAAG,CAAC;KACX,WACQ;QACP,OAAO,CAAC,EAAE,aAAa,CAAC;KACzB;wBAWO;QACN,KAAK,EAAE,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;KACtC,WACQ;QACP,OAAO,CAAC,EAAE,aAAa,CAAC;KACzB;EAoBN;AAyCD,wBAAgB,iBAAiB,CAAC,WAAW,SAAS,cAAc,EAAE,MAAM,EAAE;IAC5E,UAAU,EAAE,WAAW,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAChC;qBAqC0B;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,GAAG,CAAC;KACd;EAoCJ"}
1
+ {"version":3,"file":"mongo.generator.d.ts","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,EACV,aAAa,EAEb,MAAM,EACN,uBAAuB,EACvB,WAAW,EAGX,YAAY,EACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,4BAA4B,EAM7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAElB,WAAW,EACX,SAAS,EACT,WAAW,EACX,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,KAAK,cAAc,CAAC,WAAW,SAAS,UAAU,IAAI;KACnD,CAAC,IAAI,MAAM,UAAU,CAAC,OAAO,4BAA4B,CAAC,WAAW,CAAC,CAAC,GACtE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,4BAA4B,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3E,CAAC;AA+HF,wBAAgB,aAAa,CAAC,WAAW,SAAS,UAAU,EAAE,MAAM,EAAE;IACpE,UAAU,EAAE,WAAW,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;qBAayB;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;QAClC,IAAI,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;QAE9B,MAAM,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;KACnC;mBAuBoB;QACnB,QAAQ,EAAE,MAAM,iCAAQ,CAAC;QACzB,YAAY,EAAE,YAAY,iCAAQ,CAAC;QACnC,SAAS,CAAC,EAAE,uBAAuB,CAAC;KACrC;0BAgBQ;QACL,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC;QACvB,IAAI,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;KAChC,YACS;QAAE,OAAO,CAAC,EAAE,aAAa,CAAA;KAAE;uBAY9B;QAAE,KAAK,EAAE,cAAc,CAAC,WAAW,CAAC,EAAE,CAAA;KAAE,YACrC;QAAE,OAAO,CAAC,EAAE,aAAa,CAAA;KAAE;EAc1C;AA+BD,wBAAgB,iBAAiB,CAAC,WAAW,SAAS,cAAc,EAAE,MAAM,EAAE;IAC5E,UAAU,EAAE,WAAW,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAChC;qBAkCyB;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAEhD,MAAM,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC;KACrD;EAiCJ"}
@@ -1,165 +1,199 @@
1
- import { ObjectId } from "mongodb";
1
+ import { ObjectId } from 'mongodb';
2
2
  import { z } from 'zod';
3
- import { findRepositoryContext } from "@eecho/definition";
4
- import { extractSearchOption, extractSearchArrayOption, extractCreateFieldWithSystem } from "@eecho/definition";
5
- // 검색 가능한 필드들을 추출하는 헬퍼 함수 (기존 helper 활용)
3
+ import { extractCreateFieldWithSystem, extractObjectIdFields, extractSearchArrayOption, extractSearchOption, extractSortableOption, findRepositoryContext, } from '@eecho/definition';
6
4
  function getSearchableFields(definition) {
7
- const searchableFields = Object.keys(extractSearchOption({ definition }));
8
- const searchableArrayFields = Object.keys(extractSearchArrayOption({ definition }));
9
- return [...searchableFields, ...searchableArrayFields];
5
+ return new Set([
6
+ ...Object.keys(extractSearchOption({ definition })),
7
+ ...Object.keys(extractSearchArrayOption({ definition })),
8
+ ]);
10
9
  }
11
- // 검색 쿼리를 빌드하는 헬퍼 함수
12
- function buildSearchQuery(search, searchableFields) {
13
- if (!search)
10
+ function getSortableFields(definition) {
11
+ return new Set(Object.keys(extractSortableOption({ definition })));
12
+ }
13
+ function escapeRegularExpression(value) {
14
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
15
+ }
16
+ function buildSearchQuery(filter, searchableFields, objectIdFields) {
17
+ if (!filter) {
14
18
  return {};
15
- return Object.fromEntries(Object.entries(search)
16
- .filter(([_, value]) => value)
19
+ }
20
+ const entries = Object.entries(filter)
21
+ .filter(([, value]) => value !== undefined)
17
22
  .map(([key, value]) => {
18
- if (!searchableFields.includes(key)) {
23
+ if (!searchableFields.has(key)) {
19
24
  throw new Error(`Invalid search field: ${key}`);
20
25
  }
26
+ if (objectIdFields.has(key)) {
27
+ const objectIdValue = (item) => (item === null || item instanceof ObjectId
28
+ ? item
29
+ : new ObjectId(String(item)));
30
+ return Array.isArray(value)
31
+ ? [key, { $in: value.map(objectIdValue) }]
32
+ : [key, objectIdValue(value)];
33
+ }
21
34
  if (Array.isArray(value)) {
22
35
  return [key, { $in: value }];
23
36
  }
24
- else if (typeof value === 'string') {
25
- return [key, { $regex: value, $options: 'i' }];
37
+ if (typeof value === 'string') {
38
+ return [key, { $regex: escapeRegularExpression(value), $options: 'i' }];
39
+ }
40
+ if (value === null
41
+ || typeof value === 'number'
42
+ || typeof value === 'boolean'
43
+ || value instanceof Date
44
+ || value instanceof ObjectId) {
45
+ return [key, value];
46
+ }
47
+ throw new Error(`Unsupported search value for field: ${key}`);
48
+ });
49
+ return Object.fromEntries(entries);
50
+ }
51
+ function buildSort(sort, sortableFields) {
52
+ if (!sort) {
53
+ return undefined;
54
+ }
55
+ const entries = Object.entries(sort).map(([key, direction]) => {
56
+ if (!sortableFields.has(key)) {
57
+ throw new Error(`Invalid sort field: ${key}`);
58
+ }
59
+ if (direction !== 'asc' && direction !== 'desc') {
60
+ throw new Error(`Invalid sort direction for field: ${key}`);
26
61
  }
27
- else if (value instanceof ObjectId) {
62
+ return [key, direction === 'asc' ? 1 : -1];
63
+ });
64
+ return Object.fromEntries(entries);
65
+ }
66
+ function convertObjectIdFields(document, objectIdFields) {
67
+ return Object.fromEntries(Object.entries(document).map(([key, value]) => {
68
+ if (!objectIdFields.has(key) || value === null || value === undefined) {
28
69
  return [key, value];
29
70
  }
30
- else {
31
- throw new Error(`Unsupported search field type for key: ${key}`);
71
+ if (Array.isArray(value)) {
72
+ return [key, value.map((item) => item instanceof ObjectId ? item : new ObjectId(String(item)))];
32
73
  }
74
+ return [key, value instanceof ObjectId ? value : new ObjectId(String(value))];
33
75
  }));
34
76
  }
77
+ function validatePagination(page, limit) {
78
+ if (!Number.isInteger(page) || page < 1) {
79
+ throw new RangeError('page must be a positive integer.');
80
+ }
81
+ if (!Number.isInteger(limit) || limit < 1) {
82
+ throw new RangeError('limit must be a positive integer.');
83
+ }
84
+ }
35
85
  export function genRepository(params) {
36
86
  const { definition, dbClient, dbName, collectionName } = params;
37
- // 컬렉션 가져오기
38
- const getCollection = async () => {
39
- return (await dbClient).db(dbName).collection(collectionName);
40
- };
41
87
  const searchableFields = getSearchableFields(definition);
42
- const repository = {
43
- async getItems(params) {
88
+ const sortableFields = getSortableFields(definition);
89
+ const objectIdFields = new Set(extractObjectIdFields({ definition }).map(String));
90
+ const createSchema = z.object(extractCreateFieldWithSystem({ definition }));
91
+ const getCollection = async () => ((await dbClient).db(dbName).collection(collectionName));
92
+ return {
93
+ async getItems(input = {}) {
94
+ const { page = 1, limit = 15, filter, search, sort } = input;
95
+ validatePagination(page, limit);
44
96
  const collection = await getCollection();
45
- const { page = 1, limit = 15, search } = params;
46
- const query = buildSearchQuery(search, searchableFields);
47
- return collection
97
+ const query = buildSearchQuery(filter ?? search, searchableFields, objectIdFields);
98
+ const cursor = collection
48
99
  .find(query)
49
- .limit(limit)
50
100
  .skip((page - 1) * limit)
51
- .toArray();
101
+ .limit(limit);
102
+ const mongoSort = buildSort(sort, sortableFields);
103
+ if (mongoSort) {
104
+ cursor.sort(mongoSort);
105
+ }
106
+ return cursor.toArray();
52
107
  },
53
- async putItem(params) {
108
+ async putItem(input) {
54
109
  const collection = await getCollection();
55
- const doc = await collection.findOneAndUpdate(params.idFilter, params.updateFilter, params.putOption ?? {});
56
- if (!doc) {
110
+ const document = await collection.findOneAndUpdate(input.idFilter, input.updateFilter, input.putOption ?? {});
111
+ if (!document) {
57
112
  throw new Error('Failed to upsert document.');
58
113
  }
59
- return doc;
114
+ return document;
60
115
  },
61
- async updateItemById(params, option) {
116
+ async updateItemById(input, options) {
62
117
  const collection = await getCollection();
63
- return collection.updateOne({ _id: { $eq: params._id } }, { $set: params.data }, { session: option?.session });
118
+ return collection.updateOne({ _id: { $eq: input._id instanceof ObjectId ? input._id : new ObjectId(input._id) } }, { $set: input.data }, { session: options?.session });
64
119
  },
65
- async createItems(params, option) {
120
+ async createItems(input, options) {
66
121
  const collection = await getCollection();
67
- // extractCreateFieldWithSystem을 사용하여 스키마 생성 (Optional만 제외)
68
- const createFields = extractCreateFieldWithSystem({ definition });
69
- const createSchema = z.object(createFields);
70
- // 각 아이템에 대해 스키마 검증
71
- const validatedItems = params.items.map(item => createSchema.parse(item));
72
- return collection.insertMany(validatedItems, { session: option?.session });
122
+ const validatedItems = input.items.map((item) => (convertObjectIdFields(createSchema.parse(item), objectIdFields)));
123
+ // Zod validates the generated shape, but MongoDB cannot derive its generic from that runtime schema.
124
+ return collection.insertMany(validatedItems, { session: options?.session });
73
125
  },
74
126
  };
75
- return repository;
76
127
  }
77
- // Projection을 빌드하는 헬퍼 함수
78
128
  function buildProjection(viewDefinition, baseModelKeys, relationInfos) {
79
129
  const projectionEntries = [['_id', 1]];
80
- for (const [key, fieldDef] of Object.entries(viewDefinition)) {
130
+ for (const [key, fieldDefinition] of Object.entries(viewDefinition)) {
81
131
  if (baseModelKeys.has(key)) {
82
132
  projectionEntries.push([key, 1]);
83
133
  continue;
84
134
  }
85
- let mapped = false;
86
- for (const { rel, alias } of relationInfos) {
87
- const relationField = Object.values(rel.relationModel).find((relationDef) => relationDef.key === fieldDef.key);
88
- if (relationField) {
89
- projectionEntries.push([
90
- key,
91
- { $first: `$${alias}.${relationField.key}` }
92
- ]);
93
- mapped = true;
94
- break;
95
- }
96
- }
97
- if (!mapped) {
98
- projectionEntries.push([key, 1]);
99
- }
135
+ const relationInfo = relationInfos.find(({ relation }) => (Object.values(relation.relationModel)
136
+ .some((relationField) => relationField.key === fieldDefinition.key)));
137
+ projectionEntries.push([
138
+ key,
139
+ relationInfo
140
+ ? { $first: `$${relationInfo.alias}.${fieldDefinition.key}` }
141
+ : 1,
142
+ ]);
100
143
  }
101
144
  return { $project: Object.fromEntries(projectionEntries) };
102
145
  }
103
- // View Repository 생성 함수 (인터셉터 미지원)
104
146
  export function genViewRepository(params) {
105
147
  const { definition, dbClient } = params;
106
- // Base Model 컨텍스트 찾기
107
148
  const baseModelContext = findRepositoryContext(definition.baseModel);
108
149
  if (!baseModelContext) {
109
- throw new Error('BaseModel Not Registered');
150
+ throw new Error('Base model is not registered.');
110
151
  }
111
- // 컬렉션 가져오기
112
- const getCollection = async () => {
113
- const client = await dbClient;
114
- return client
115
- .db(baseModelContext.dbName)
116
- .collection(baseModelContext.collectionName);
117
- };
118
- // 검색 가능한 필드들 추출 (기존 helper 활용)
119
152
  const searchableFields = getSearchableFields(definition.viewDefinition);
153
+ const sortableFields = getSortableFields(definition.viewDefinition);
154
+ const objectIdFields = new Set(extractObjectIdFields({ definition: definition.viewDefinition }).map(String));
120
155
  const baseModelKeys = new Set(Object.keys(definition.baseModel));
121
- // Relation 정보들을 미리 계산
122
- const relationInfos = definition.relations.map((rel) => {
123
- const relModelContext = findRepositoryContext(rel.relationModel);
124
- if (!relModelContext) {
125
- throw new Error('Relation Model Not Registered');
156
+ const relationInfos = definition.relations.map((relation) => {
157
+ const context = findRepositoryContext(relation.relationModel);
158
+ if (!context) {
159
+ throw new Error('Relation model is not registered.');
126
160
  }
127
161
  return {
128
- rel,
129
- relModelContext,
130
- alias: `${relModelContext.collectionName}_${rel.relationKey}_info`,
162
+ relation,
163
+ context,
164
+ alias: `${context.collectionName}_${relation.relationKey}_info`,
131
165
  };
132
166
  });
133
- const repository = {
134
- async getItems(params) {
135
- const collection = await getCollection();
136
- const { page = 1, limit = 15, search } = params;
137
- // 검색 조건 빌드
138
- const query = buildSearchQuery(search, searchableFields);
139
- // $lookup 단계 빌드
140
- const lookups = relationInfos.map(({ rel, relModelContext, alias }) => ({
167
+ const getCollection = async () => ((await dbClient)
168
+ .db(baseModelContext.dbName)
169
+ .collection(baseModelContext.collectionName));
170
+ return {
171
+ async getItems(input = {}) {
172
+ const { page = 1, limit = 15, filter, search, sort } = input;
173
+ validatePagination(page, limit);
174
+ const query = buildSearchQuery(filter ?? search, searchableFields, objectIdFields);
175
+ const mongoSort = buildSort(sort, sortableFields);
176
+ const lookups = relationInfos.map(({ relation, context, alias }) => ({
141
177
  $lookup: {
142
- from: relModelContext.collectionName,
143
- localField: rel.baseKey,
144
- foreignField: rel.relationKey,
178
+ from: context.collectionName,
179
+ localField: relation.baseKey,
180
+ foreignField: relation.relationKey,
145
181
  as: alias,
146
182
  },
147
183
  }));
148
- // Projection 단계 빌드
149
- const projection = buildProjection(definition.viewDefinition, baseModelKeys, relationInfos);
150
- // Aggregate 실행
151
- const docs = await collection
152
- .aggregate([
153
- { $match: query },
184
+ const pipeline = [
154
185
  ...lookups,
186
+ buildProjection(definition.viewDefinition, baseModelKeys, relationInfos),
187
+ { $match: query },
188
+ ...(mongoSort ? [{ $sort: mongoSort }] : []),
155
189
  { $skip: (page - 1) * limit },
156
190
  { $limit: limit },
157
- projection,
158
- ])
191
+ ];
192
+ const collection = await getCollection();
193
+ return collection
194
+ .aggregate(pipeline)
159
195
  .toArray();
160
- return docs;
161
196
  },
162
197
  };
163
- return repository;
164
198
  }
165
199
  //# sourceMappingURL=mongo.generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mongo.generator.js","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mongo.generator.js","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.generator.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { genAPISpec } from "./generator/mongo/mongo.api.generator";
2
- import { genRepository, genViewRepository } from "./generator/mongo/mongo.generator";
3
- export { setAPIEndpoint, setMiddleware } from "./api/api";
4
- export { ExceptionMiddleware } from "./api/api.middleware";
1
+ import { genAPISpec } from './generator/mongo/mongo.api.generator.js';
2
+ import { genRepository, genViewRepository } from './generator/mongo/mongo.generator.js';
3
+ export { setAPIEndpoint, setMiddleware } from './api/api.js';
4
+ export { ExceptionMiddleware } from './api/api.middleware.js';
5
+ export { registerMongoReadEndpoint } from './generator/mongo/mongo.endpoint.js';
5
6
  export declare const MongoGenerator: {
6
7
  genAPISpec: typeof genAPISpec;
7
8
  genRepository: typeof genRepository;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAErF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,eAAO,MAAM,cAAc;;;;CAI1B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAExF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAEhF,eAAO,MAAM,cAAc;;;;CAI1B,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
- import { genAPISpec } from "./generator/mongo/mongo.api.generator";
2
- import { genRepository, genViewRepository } from "./generator/mongo/mongo.generator";
3
- export { setAPIEndpoint, setMiddleware } from "./api/api";
4
- export { ExceptionMiddleware } from "./api/api.middleware";
1
+ import { genAPISpec } from './generator/mongo/mongo.api.generator.js';
2
+ import { genRepository, genViewRepository } from './generator/mongo/mongo.generator.js';
3
+ export { setAPIEndpoint, setMiddleware } from './api/api.js';
4
+ export { ExceptionMiddleware } from './api/api.middleware.js';
5
+ export { registerMongoReadEndpoint } from './generator/mongo/mongo.endpoint.js';
5
6
  export const MongoGenerator = {
6
7
  genAPISpec,
7
8
  genRepository,
8
- genViewRepository
9
+ genViewRepository,
9
10
  };
10
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAErF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU;IACV,aAAa;IACb,iBAAiB;CAClB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAExF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAEhF,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU;IACV,aAAa;IACb,iBAAiB;CAClB,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,15 @@
1
1
  {
2
2
  "name": "@eecho/express",
3
- "version": "0.0.3",
4
- "description": "EEcho express framework with Express and MongoDB support",
3
+ "version": "0.1.0",
4
+ "description": "Express and MongoDB adapters for shared EEcho API contracts",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
7
13
  "type": "module",
8
14
  "files": [
9
15
  "dist/**/*"
@@ -15,9 +21,9 @@
15
21
  "test": "echo \"Error: no test specified\" && exit 1"
16
22
  },
17
23
  "author": "",
18
- "license": "ISC",
24
+ "license": "MIT",
19
25
  "dependencies": {
20
- "@eecho/definition": "^0.0.2",
26
+ "@eecho/definition": "^0.1.0",
21
27
  "express": "^5.1.0",
22
28
  "mongodb": "^6.20.0",
23
29
  "zod": "^4.1.12"
@@ -1,4 +0,0 @@
1
- import { z } from 'zod';
2
- import type { ObjectId } from 'bson';
3
- export declare const ObjectIdCompatible: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<ObjectId, ObjectId>]>;
4
- //# sourceMappingURL=mongo.util.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mongo.util.d.ts","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAErC,eAAO,MAAM,kBAAkB,qEAG7B,CAAC"}
@@ -1,6 +0,0 @@
1
- import { z } from 'zod';
2
- export const ObjectIdCompatible = z.union([
3
- z.string().regex(/^[a-fA-F0-9]{24}$/),
4
- z.custom()
5
- ]);
6
- //# sourceMappingURL=mongo.util.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mongo.util.js","sourceRoot":"","sources":["../../../src/generator/mongo/mongo.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC;IACxC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC;IACrC,CAAC,CAAC,MAAM,EAAY;CACrB,CAAC,CAAC"}