@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.
- package/README.md +48 -11
- package/dist/api/api.d.ts +9 -9
- package/dist/api/api.d.ts.map +1 -1
- package/dist/api/api.js +18 -17
- package/dist/api/api.js.map +1 -1
- package/dist/api/api.middleware.d.ts +2 -2
- package/dist/api/api.middleware.d.ts.map +1 -1
- package/dist/api/api.middleware.js +22 -9
- package/dist/api/api.middleware.js.map +1 -1
- package/dist/api/api.type.d.ts +8 -8
- package/dist/api/api.type.d.ts.map +1 -1
- package/dist/api/api.util.d.ts +7 -8
- package/dist/api/api.util.d.ts.map +1 -1
- package/dist/api/api.util.js +10 -14
- package/dist/api/api.util.js.map +1 -1
- package/dist/generator/mongo/mongo.api.generator.d.ts +1 -85
- package/dist/generator/mongo/mongo.api.generator.d.ts.map +1 -1
- package/dist/generator/mongo/mongo.api.generator.js +3 -122
- package/dist/generator/mongo/mongo.api.generator.js.map +1 -1
- package/dist/generator/mongo/mongo.endpoint.d.ts +14 -0
- package/dist/generator/mongo/mongo.endpoint.d.ts.map +1 -0
- package/dist/generator/mongo/mongo.endpoint.js +34 -0
- package/dist/generator/mongo/mongo.endpoint.js.map +1 -0
- package/dist/generator/mongo/mongo.generator.d.ts +21 -16
- package/dist/generator/mongo/mongo.generator.d.ts.map +1 -1
- package/dist/generator/mongo/mongo.generator.js +134 -100
- package/dist/generator/mongo/mongo.generator.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
- package/dist/generator/mongo/mongo.util.d.ts +0 -4
- package/dist/generator/mongo/mongo.util.d.ts.map +0 -1
- package/dist/generator/mongo/mongo.util.js +0 -6
- 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
|
|
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
|
-
##
|
|
11
|
+
## Generated Mongo read endpoint
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
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 {
|
|
2
|
-
import { ServerAPISpecification } from
|
|
3
|
-
import type { APIHandler, ExpressMiddleware } from
|
|
4
|
-
export declare
|
|
5
|
-
export declare
|
|
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
|
-
|
|
9
|
+
middlewares?: ExpressMiddleware[];
|
|
10
|
+
apiEndpoint?: TSpec['APIEndpoint'];
|
|
11
|
+
method?: TSpec['Method'];
|
|
12
|
+
}): void;
|
|
13
13
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/api/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
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
|
|
2
|
-
export
|
|
3
|
-
return (
|
|
4
|
-
return Promise.resolve(
|
|
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
|
|
8
|
-
const { router, middlewares = [], apiSpec,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
24
|
+
registerRoute(router, method, apiEndpoint, [...middlewares, apiMiddleware]);
|
|
25
|
+
}
|
|
25
26
|
//# sourceMappingURL=api.js.map
|
package/dist/api/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api/api.ts"],"names":[],"mappings":"
|
|
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
|
|
2
|
-
type ExpressExceptionMiddleware = (
|
|
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":"
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
20
|
+
response.status(500).json({
|
|
10
21
|
success: false,
|
|
11
|
-
|
|
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":"
|
|
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"}
|
package/dist/api/api.type.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type { Request as ExpressRequest, Response as ExpressResponse
|
|
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.
|
|
5
|
-
export type ExtractBodyParams<TSpec extends ServerAPISpecification> = TSpec['Request']['body'] extends z.ZodTypeAny ? z.
|
|
6
|
-
export type ExtractResponseType<TSpec extends ServerAPISpecification> = TSpec['Response']['body'] extends z.ZodTypeAny ? z.
|
|
7
|
-
export type APIHandler<TSpec extends ServerAPISpecification> = (
|
|
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
|
|
14
|
+
next: NextFunction;
|
|
15
15
|
}) => ExtractResponseType<TSpec> | Promise<ExtractResponseType<TSpec>>;
|
|
16
|
-
export type ExpressMiddleware<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,
|
|
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"}
|
package/dist/api/api.util.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type { Request as ExpressRequest, Router } from
|
|
2
|
-
import {
|
|
3
|
-
import { ExpressMiddleware } from
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
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,
|
|
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"}
|
package/dist/api/api.util.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
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
|
package/dist/api/api.util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.util.js","sourceRoot":"","sources":["../../src/api/api.util.ts"],"names":[],"mappings":"AAMA,MAAM,
|
|
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
|
-
|
|
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":"
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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":"AAAA,
|
|
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 {
|
|
1
|
+
import { ObjectId } from 'mongodb';
|
|
2
|
+
import type { ClientSession, Filter, FindOneAndUpdateOptions, MongoClient, UpdateFilter } from 'mongodb';
|
|
2
3
|
import { z } from 'zod';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
type CreateDocument<
|
|
6
|
-
[K in keyof ReturnType<typeof extractCreateFieldWithSystem<
|
|
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(
|
|
15
|
+
getItems(input?: {
|
|
15
16
|
page?: number;
|
|
16
17
|
limit?: number;
|
|
17
|
-
|
|
18
|
+
filter?: SearchField<TDefinition>;
|
|
19
|
+
sort?: SortField<TDefinition>;
|
|
20
|
+
search?: SearchField<TDefinition>;
|
|
18
21
|
}): Promise<import("mongodb").WithId<DefinitionDocument<TDefinition>>[]>;
|
|
19
|
-
putItem(
|
|
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(
|
|
25
|
-
_id: ObjectId;
|
|
26
|
-
data:
|
|
27
|
-
},
|
|
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(
|
|
33
|
+
createItems(input: {
|
|
31
34
|
items: CreateDocument<TDefinition>[];
|
|
32
|
-
},
|
|
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(
|
|
43
|
+
getItems(input?: {
|
|
41
44
|
page?: number;
|
|
42
45
|
limit?: number;
|
|
43
|
-
|
|
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,
|
|
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
|
|
1
|
+
import { ObjectId } from 'mongodb';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { findRepositoryContext } from
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
return new Set([
|
|
6
|
+
...Object.keys(extractSearchOption({ definition })),
|
|
7
|
+
...Object.keys(extractSearchArrayOption({ definition })),
|
|
8
|
+
]);
|
|
10
9
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
16
|
-
|
|
19
|
+
}
|
|
20
|
+
const entries = Object.entries(filter)
|
|
21
|
+
.filter(([, value]) => value !== undefined)
|
|
17
22
|
.map(([key, value]) => {
|
|
18
|
-
if (!searchableFields.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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
|
|
43
|
-
|
|
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
|
|
46
|
-
const
|
|
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
|
-
.
|
|
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(
|
|
108
|
+
async putItem(input) {
|
|
54
109
|
const collection = await getCollection();
|
|
55
|
-
const
|
|
56
|
-
if (!
|
|
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
|
|
114
|
+
return document;
|
|
60
115
|
},
|
|
61
|
-
async updateItemById(
|
|
116
|
+
async updateItemById(input, options) {
|
|
62
117
|
const collection = await getCollection();
|
|
63
|
-
return collection.updateOne({ _id: { $eq:
|
|
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(
|
|
120
|
+
async createItems(input, options) {
|
|
66
121
|
const collection = await getCollection();
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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,
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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('
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
alias: `${
|
|
162
|
+
relation,
|
|
163
|
+
context,
|
|
164
|
+
alias: `${context.collectionName}_${relation.relationKey}_info`,
|
|
131
165
|
};
|
|
132
166
|
});
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
const
|
|
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:
|
|
143
|
-
localField:
|
|
144
|
-
foreignField:
|
|
178
|
+
from: context.collectionName,
|
|
179
|
+
localField: relation.baseKey,
|
|
180
|
+
foreignField: relation.relationKey,
|
|
145
181
|
as: alias,
|
|
146
182
|
},
|
|
147
183
|
}));
|
|
148
|
-
|
|
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
|
-
|
|
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":"AAAA,OAAO,
|
|
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
|
|
2
|
-
import { genRepository, genViewRepository } from
|
|
3
|
-
export { setAPIEndpoint, setMiddleware } from
|
|
4
|
-
export { ExceptionMiddleware } from
|
|
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;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
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
|
|
2
|
-
import { genRepository, genViewRepository } from
|
|
3
|
-
export { setAPIEndpoint, setMiddleware } from
|
|
4
|
-
export { ExceptionMiddleware } from
|
|
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,
|
|
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
|
|
4
|
-
"description": "
|
|
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": "
|
|
24
|
+
"license": "MIT",
|
|
19
25
|
"dependencies": {
|
|
20
|
-
"@eecho/definition": "^0.0
|
|
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 +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 +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"}
|