moonflower 0.9.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/.eslintrc.js +26 -0
- package/.prettierrc.js +7 -0
- package/README.md +383 -0
- package/cli/cli.ts +59 -0
- package/cli/entry.cjs +3 -0
- package/cli/prettyprint.ts +16 -0
- package/dist/cli/cli.d.ts +2 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +79 -0
- package/dist/cli/prettyprint.d.ts +4 -0
- package/dist/cli/prettyprint.d.ts.map +1 -0
- package/dist/cli/prettyprint.js +18 -0
- package/dist/src/errors/BaseHttpError.d.ts +13 -0
- package/dist/src/errors/BaseHttpError.d.ts.map +1 -0
- package/dist/src/errors/BaseHttpError.js +13 -0
- package/dist/src/errors/HttpErrorHandler.d.ts +3 -0
- package/dist/src/errors/HttpErrorHandler.d.ts.map +1 -0
- package/dist/src/errors/HttpErrorHandler.js +23 -0
- package/dist/src/errors/UserFacingErrors.d.ts +11 -0
- package/dist/src/errors/UserFacingErrors.d.ts.map +1 -0
- package/dist/src/errors/UserFacingErrors.js +23 -0
- package/dist/src/hooks/authentication/useAuth.d.ts +3 -0
- package/dist/src/hooks/authentication/useAuth.d.ts.map +1 -0
- package/dist/src/hooks/authentication/useAuth.js +7 -0
- package/dist/src/hooks/authentication/useOptionalAuth.d.ts +3 -0
- package/dist/src/hooks/authentication/useOptionalAuth.d.ts.map +1 -0
- package/dist/src/hooks/authentication/useOptionalAuth.js +16 -0
- package/dist/src/hooks/useApiEndpoint.d.ts +8 -0
- package/dist/src/hooks/useApiEndpoint.d.ts.map +1 -0
- package/dist/src/hooks/useApiEndpoint.js +7 -0
- package/dist/src/hooks/useApiHeader/index.d.ts +2 -0
- package/dist/src/hooks/useApiHeader/index.d.ts.map +1 -0
- package/dist/src/hooks/useApiHeader/index.js +17 -0
- package/dist/src/hooks/useApiHeader/useApiHeader.d.ts +3 -0
- package/dist/src/hooks/useApiHeader/useApiHeader.d.ts.map +1 -0
- package/dist/src/hooks/useApiHeader/useApiHeader.js +6 -0
- package/dist/src/hooks/useApiHeader/useApiHeader.spec.data.d.ts +2 -0
- package/dist/src/hooks/useApiHeader/useApiHeader.spec.data.d.ts.map +1 -0
- package/dist/src/hooks/useApiHeader/useApiHeader.spec.data.js +22 -0
- package/dist/src/hooks/useCookieParams.d.ts +9 -0
- package/dist/src/hooks/useCookieParams.d.ts.map +1 -0
- package/dist/src/hooks/useCookieParams.js +50 -0
- package/dist/src/hooks/useExposeApiModel/index.d.ts +2 -0
- package/dist/src/hooks/useExposeApiModel/index.d.ts.map +1 -0
- package/dist/src/hooks/useExposeApiModel/index.js +17 -0
- package/dist/src/hooks/useExposeApiModel/useExposeApiModel.d.ts +3 -0
- package/dist/src/hooks/useExposeApiModel/useExposeApiModel.d.ts.map +1 -0
- package/dist/src/hooks/useExposeApiModel/useExposeApiModel.js +9 -0
- package/dist/src/hooks/useExposeApiModel/useExposeApiModel.spec.data.d.ts +2 -0
- package/dist/src/hooks/useExposeApiModel/useExposeApiModel.spec.data.d.ts.map +1 -0
- package/dist/src/hooks/useExposeApiModel/useExposeApiModel.spec.data.js +16 -0
- package/dist/src/hooks/useHeaderParams.d.ts +12 -0
- package/dist/src/hooks/useHeaderParams.d.ts.map +1 -0
- package/dist/src/hooks/useHeaderParams.js +52 -0
- package/dist/src/hooks/usePathParams.d.ts +22 -0
- package/dist/src/hooks/usePathParams.d.ts.map +1 -0
- package/dist/src/hooks/usePathParams.js +46 -0
- package/dist/src/hooks/useQueryParams.d.ts +9 -0
- package/dist/src/hooks/useQueryParams.d.ts.map +1 -0
- package/dist/src/hooks/useQueryParams.js +50 -0
- package/dist/src/hooks/useRequestBody.d.ts +9 -0
- package/dist/src/hooks/useRequestBody.d.ts.map +1 -0
- package/dist/src/hooks/useRequestBody.js +59 -0
- package/dist/src/hooks/useRequestRawBody.d.ts +7 -0
- package/dist/src/hooks/useRequestRawBody.d.ts.map +1 -0
- package/dist/src/hooks/useRequestRawBody.js +34 -0
- package/dist/src/index.d.ts +18 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +33 -0
- package/dist/src/openapi/analyzerModule/analyzerModule.d.ts +18 -0
- package/dist/src/openapi/analyzerModule/analyzerModule.d.ts.map +1 -0
- package/dist/src/openapi/analyzerModule/analyzerModule.js +192 -0
- package/dist/src/openapi/analyzerModule/nodeParsers.d.ts +19 -0
- package/dist/src/openapi/analyzerModule/nodeParsers.d.ts.map +1 -0
- package/dist/src/openapi/analyzerModule/nodeParsers.js +521 -0
- package/dist/src/openapi/analyzerModule/parseEndpoint.d.ts +4 -0
- package/dist/src/openapi/analyzerModule/parseEndpoint.d.ts.map +1 -0
- package/dist/src/openapi/analyzerModule/parseEndpoint.js +246 -0
- package/dist/src/openapi/analyzerModule/parseExposedModels.d.ts +5 -0
- package/dist/src/openapi/analyzerModule/parseExposedModels.d.ts.map +1 -0
- package/dist/src/openapi/analyzerModule/parseExposedModels.js +32 -0
- package/dist/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.d.ts +2 -0
- package/dist/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.d.ts.map +1 -0
- package/dist/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.js +400 -0
- package/dist/src/openapi/analyzerModule/types.d.ts +53 -0
- package/dist/src/openapi/analyzerModule/types.d.ts.map +1 -0
- package/dist/src/openapi/analyzerModule/types.js +2 -0
- package/dist/src/openapi/discoveryModule/discoverImports/discoverImports.d.ts +8 -0
- package/dist/src/openapi/discoveryModule/discoverImports/discoverImports.d.ts.map +1 -0
- package/dist/src/openapi/discoveryModule/discoverImports/discoverImports.js +33 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterA.spec.data.d.ts +4 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterA.spec.data.d.ts.map +1 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterA.spec.data.js +8 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterB.spec.data.d.ts +4 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterB.spec.data.d.ts.map +1 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterB.spec.data.js +8 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.d.ts +17 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.d.ts.map +1 -0
- package/dist/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.js +80 -0
- package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.d.ts +6 -0
- package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.d.ts.map +1 -0
- package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.js +31 -0
- package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.data.d.ts +5 -0
- package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.data.d.ts.map +1 -0
- package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.data.js +38 -0
- package/dist/src/openapi/discoveryModule/index.d.ts +3 -0
- package/dist/src/openapi/discoveryModule/index.d.ts.map +1 -0
- package/dist/src/openapi/discoveryModule/index.js +18 -0
- package/dist/src/openapi/generatorModule/generateComponentSchemas.d.ts +4 -0
- package/dist/src/openapi/generatorModule/generateComponentSchemas.d.ts.map +1 -0
- package/dist/src/openapi/generatorModule/generateComponentSchemas.js +12 -0
- package/dist/src/openapi/generatorModule/generatePaths.d.ts +10 -0
- package/dist/src/openapi/generatorModule/generatePaths.d.ts.map +1 -0
- package/dist/src/openapi/generatorModule/generatePaths.js +116 -0
- package/dist/src/openapi/generatorModule/generatorModule.d.ts +16 -0
- package/dist/src/openapi/generatorModule/generatorModule.d.ts.map +1 -0
- package/dist/src/openapi/generatorModule/generatorModule.js +18 -0
- package/dist/src/openapi/generatorModule/getSchema.d.ts +36 -0
- package/dist/src/openapi/generatorModule/getSchema.d.ts.map +1 -0
- package/dist/src/openapi/generatorModule/getSchema.js +133 -0
- package/dist/src/openapi/generatorModule/index.d.ts +5 -0
- package/dist/src/openapi/generatorModule/index.d.ts.map +1 -0
- package/dist/src/openapi/generatorModule/index.js +20 -0
- package/dist/src/openapi/generatorModule/test/openApiGenerator.spec.data.d.ts +515 -0
- package/dist/src/openapi/generatorModule/test/openApiGenerator.spec.data.d.ts.map +1 -0
- package/dist/src/openapi/generatorModule/test/openApiGenerator.spec.data.js +1119 -0
- package/dist/src/openapi/initOpenApiEngine.d.ts +4 -0
- package/dist/src/openapi/initOpenApiEngine.d.ts.map +1 -0
- package/dist/src/openapi/initOpenApiEngine.js +14 -0
- package/dist/src/openapi/manager/OpenApiManager.d.ts +67 -0
- package/dist/src/openapi/manager/OpenApiManager.d.ts.map +1 -0
- package/dist/src/openapi/manager/OpenApiManager.js +86 -0
- package/dist/src/openapi/router/OpenApiRouter.d.ts +4 -0
- package/dist/src/openapi/router/OpenApiRouter.d.ts.map +1 -0
- package/dist/src/openapi/router/OpenApiRouter.js +11 -0
- package/dist/src/openapi/types.d.ts +81 -0
- package/dist/src/openapi/types.d.ts.map +1 -0
- package/dist/src/openapi/types.js +2 -0
- package/dist/src/router/Router.d.ts +23 -0
- package/dist/src/router/Router.d.ts.map +1 -0
- package/dist/src/router/Router.js +81 -0
- package/dist/src/router/responseValueToJson.d.ts +2 -0
- package/dist/src/router/responseValueToJson.d.ts.map +1 -0
- package/dist/src/router/responseValueToJson.js +10 -0
- package/dist/src/setupTests.d.ts +1 -0
- package/dist/src/setupTests.d.ts.map +1 -0
- package/dist/src/setupTests.js +3 -0
- package/dist/src/test/TestAppRouter.d.ts +8 -0
- package/dist/src/test/TestAppRouter.d.ts.map +1 -0
- package/dist/src/test/TestAppRouter.js +58 -0
- package/dist/src/test/app.d.ts +3 -0
- package/dist/src/test/app.d.ts.map +1 -0
- package/dist/src/test/app.js +41 -0
- package/dist/src/utils/TypeUtils.d.ts +22 -0
- package/dist/src/utils/TypeUtils.d.ts.map +1 -0
- package/dist/src/utils/TypeUtils.js +2 -0
- package/dist/src/utils/fromZodSchema.d.ts +2 -0
- package/dist/src/utils/fromZodSchema.d.ts.map +1 -0
- package/dist/src/utils/fromZodSchema.js +6 -0
- package/dist/src/utils/loadTestData.d.ts +2 -0
- package/dist/src/utils/loadTestData.d.ts.map +1 -0
- package/dist/src/utils/loadTestData.js +39 -0
- package/dist/src/utils/mockContext.d.ts +20 -0
- package/dist/src/utils/mockContext.d.ts.map +1 -0
- package/dist/src/utils/mockContext.js +85 -0
- package/dist/src/utils/nameOf.d.ts +5 -0
- package/dist/src/utils/nameOf.d.ts.map +1 -0
- package/dist/src/utils/nameOf.js +7 -0
- package/dist/src/utils/object.d.ts +7 -0
- package/dist/src/utils/object.d.ts.map +1 -0
- package/dist/src/utils/object.js +21 -0
- package/dist/src/utils/printers.d.ts +6 -0
- package/dist/src/utils/printers.d.ts.map +1 -0
- package/dist/src/utils/printers.js +76 -0
- package/dist/src/utils/validationMessages.d.ts +18 -0
- package/dist/src/utils/validationMessages.d.ts.map +1 -0
- package/dist/src/utils/validationMessages.js +43 -0
- package/dist/src/validators/BuiltInValidators.d.ts +61 -0
- package/dist/src/validators/BuiltInValidators.d.ts.map +1 -0
- package/dist/src/validators/BuiltInValidators.js +66 -0
- package/dist/src/validators/InternalParamWrappers.d.ts +5 -0
- package/dist/src/validators/InternalParamWrappers.d.ts.map +1 -0
- package/dist/src/validators/InternalParamWrappers.js +5 -0
- package/dist/src/validators/ParamWrappers.d.ts +11 -0
- package/dist/src/validators/ParamWrappers.d.ts.map +1 -0
- package/dist/src/validators/ParamWrappers.js +9 -0
- package/dist/src/validators/types.d.ts +18 -0
- package/dist/src/validators/types.d.ts.map +1 -0
- package/dist/src/validators/types.js +2 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +59 -0
- package/src/errors/BaseHttpError.ts +16 -0
- package/src/errors/HttpErrorHandler.ts +20 -0
- package/src/errors/UserFacingErrors.ts +39 -0
- package/src/hooks/authentication/useAuth.ts +8 -0
- package/src/hooks/authentication/useOptionalAuth.ts +17 -0
- package/src/hooks/useApiEndpoint.spec.ts +11 -0
- package/src/hooks/useApiEndpoint.ts +10 -0
- package/src/hooks/useApiHeader/index.ts +1 -0
- package/src/hooks/useApiHeader/useApiHeader.spec.data.ts +22 -0
- package/src/hooks/useApiHeader/useApiHeader.spec.ts +34 -0
- package/src/hooks/useApiHeader/useApiHeader.ts +6 -0
- package/src/hooks/useCookieParams.spec.ts +174 -0
- package/src/hooks/useCookieParams.ts +73 -0
- package/src/hooks/useExposeApiModel/index.ts +1 -0
- package/src/hooks/useExposeApiModel/useExposeApiModel.spec.data.ts +48 -0
- package/src/hooks/useExposeApiModel/useExposeApiModel.spec.ts +388 -0
- package/src/hooks/useExposeApiModel/useExposeApiModel.ts +9 -0
- package/src/hooks/useHeaderParams.spec.ts +186 -0
- package/src/hooks/useHeaderParams.ts +83 -0
- package/src/hooks/usePathParams.spec.ts +161 -0
- package/src/hooks/usePathParams.ts +89 -0
- package/src/hooks/useQueryParams.spec.ts +224 -0
- package/src/hooks/useQueryParams.ts +73 -0
- package/src/hooks/useRequestBody.spec.ts +215 -0
- package/src/hooks/useRequestBody.ts +94 -0
- package/src/hooks/useRequestRawBody.spec.ts +154 -0
- package/src/hooks/useRequestRawBody.ts +56 -0
- package/src/index.ts +17 -0
- package/src/openapi/analyzerModule/analyzerModule.ts +228 -0
- package/src/openapi/analyzerModule/nodeParsers.ts +648 -0
- package/src/openapi/analyzerModule/parseEndpoint.ts +305 -0
- package/src/openapi/analyzerModule/parseExposedModels.ts +34 -0
- package/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.ts +521 -0
- package/src/openapi/analyzerModule/test/openApiAnalyzer.spec.ts +1043 -0
- package/src/openapi/analyzerModule/types.ts +72 -0
- package/src/openapi/discoveryModule/discoverImports/discoverImports.ts +43 -0
- package/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterA.spec.data.ts +7 -0
- package/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterB.spec.data.ts +7 -0
- package/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.spec.ts +36 -0
- package/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.ts +80 -0
- package/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.data.ts +42 -0
- package/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.ts +18 -0
- package/src/openapi/discoveryModule/discoverRouters/discoverRouters.ts +39 -0
- package/src/openapi/discoveryModule/index.ts +2 -0
- package/src/openapi/generatorModule/generateComponentSchemas.ts +12 -0
- package/src/openapi/generatorModule/generatePaths.ts +138 -0
- package/src/openapi/generatorModule/generatorModule.ts +17 -0
- package/src/openapi/generatorModule/getSchema.ts +169 -0
- package/src/openapi/generatorModule/index.ts +4 -0
- package/src/openapi/generatorModule/test/openApiGenerator.spec.data.ts +1119 -0
- package/src/openapi/generatorModule/test/openApiGenerator.spec.ts +783 -0
- package/src/openapi/initOpenApiEngine.ts +20 -0
- package/src/openapi/manager/OpenApiManager.ts +153 -0
- package/src/openapi/router/OpenApiRouter.ts +11 -0
- package/src/openapi/types.ts +86 -0
- package/src/router/Router.ts +123 -0
- package/src/router/responseValueToJson.ts +6 -0
- package/src/setupTests.ts +3 -0
- package/src/test/TestAppRouter.ts +76 -0
- package/src/test/app.spec.ts +130 -0
- package/src/test/app.ts +43 -0
- package/src/utils/TypeUtils.ts +51 -0
- package/src/utils/loadTestData.ts +15 -0
- package/src/utils/mockContext.ts +86 -0
- package/src/utils/nameOf.ts +7 -0
- package/src/utils/object.spec.ts +27 -0
- package/src/utils/object.ts +17 -0
- package/src/utils/printers.spec.ts +103 -0
- package/src/utils/printers.ts +49 -0
- package/src/utils/validationMessages.ts +65 -0
- package/src/validators/BuiltInValidators.ts +64 -0
- package/src/validators/InternalParamWrappers.ts +14 -0
- package/src/validators/ParamWrappers.ts +22 -0
- package/src/validators/types.ts +35 -0
- package/tsconfig.build.json +15 -0
- package/tsconfig.json +29 -0
- package/vite.config.ts +16 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
parser: '@typescript-eslint/parser',
|
|
4
|
+
parserOptions: {
|
|
5
|
+
project: 'tsconfig.json',
|
|
6
|
+
tsconfigRootDir: __dirname,
|
|
7
|
+
sourceType: 'module',
|
|
8
|
+
},
|
|
9
|
+
plugins: ['simple-import-sort', 'unused-imports', '@typescript-eslint/eslint-plugin'],
|
|
10
|
+
extends: ['plugin:@typescript-eslint/recommended', 'prettier', 'plugin:prettier/recommended'],
|
|
11
|
+
root: true,
|
|
12
|
+
env: {
|
|
13
|
+
node: true,
|
|
14
|
+
jest: true,
|
|
15
|
+
},
|
|
16
|
+
ignorePatterns: ['**/dist/**', '*.md'],
|
|
17
|
+
rules: {
|
|
18
|
+
'@typescript-eslint/interface-name-prefix': 'off',
|
|
19
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
20
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
21
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
22
|
+
'@typescript-eslint/no-namespace': 'off',
|
|
23
|
+
'simple-import-sort/imports': 'error',
|
|
24
|
+
'simple-import-sort/exports': 'error',
|
|
25
|
+
},
|
|
26
|
+
}
|
package/.prettierrc.js
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
# Moonflower
|
|
2
|
+
|
|
3
|
+
> This section is work-in-progress.
|
|
4
|
+
|
|
5
|
+
Moonflower is a TypeScript-first [Koa Router](https://www.npmjs.com/package/koa-router) extension that allows for automatic [OpenAPI](https://www.openapis.org/what-is-openapi) spec generation directly from backend code, without any extra work. Combined with an ORM like [Prisma.js](https://www.npmjs.com/package/prisma) and an API client generator on frontend, it allows for creation of end-to-end type safe REST API.
|
|
6
|
+
|
|
7
|
+
Moonflower provides type safe 'hooks' that handle runtime validation and return clean types with minimal boilerplate.
|
|
8
|
+
|
|
9
|
+
## Feature Overview
|
|
10
|
+
|
|
11
|
+
- React hooks inspired Node.js backend REST API
|
|
12
|
+
- Fully type safe definitions for path, query and header params, request body and response
|
|
13
|
+
- Minimal boilerplate code
|
|
14
|
+
- Out-of-the-box OpenAPI 3.1.0 spec generation
|
|
15
|
+
|
|
16
|
+
## Usage example
|
|
17
|
+
|
|
18
|
+
Every variable and parameter in this example is fully typed.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
const router = new Router()
|
|
22
|
+
|
|
23
|
+
router.post('/auth', (ctx) => {
|
|
24
|
+
useApiEndpoint({
|
|
25
|
+
name: 'createAccount',
|
|
26
|
+
summary: 'Registration endpoint',
|
|
27
|
+
description: 'Creates a new user account with provided credentials',
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const body = useRequestBody(ctx, {
|
|
31
|
+
email: EmailValidator,
|
|
32
|
+
username: NonEmptyStringValidator,
|
|
33
|
+
password: NonEmptyStringValidator,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const user = UserService.register(body.email, body.username, body.password)
|
|
37
|
+
const token = TokenService.generateJwtToken(user)
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
accessToken: token,
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Outputs the following spec (parts omitted for brevity):
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
"/auth": {
|
|
49
|
+
"post": {
|
|
50
|
+
"operationId": "createAccount",
|
|
51
|
+
"summary": "Registration endpoint",
|
|
52
|
+
"description": "Creates a new user account with provided credentials",
|
|
53
|
+
"parameters": [],
|
|
54
|
+
"requestBody": {
|
|
55
|
+
"content": {
|
|
56
|
+
"application/json": {
|
|
57
|
+
"schema": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"properties": {
|
|
60
|
+
"email": {
|
|
61
|
+
"type": "string"
|
|
62
|
+
},
|
|
63
|
+
"username": {
|
|
64
|
+
"type": "string"
|
|
65
|
+
},
|
|
66
|
+
"password": {
|
|
67
|
+
"type": "string"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"required": [
|
|
71
|
+
"email",
|
|
72
|
+
"username",
|
|
73
|
+
"password"
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"responses": {
|
|
80
|
+
"200": {
|
|
81
|
+
"content": {
|
|
82
|
+
"application/json": {
|
|
83
|
+
"schema": {
|
|
84
|
+
"oneOf": [{
|
|
85
|
+
"type": "object",
|
|
86
|
+
"properties": {
|
|
87
|
+
"accessToken": {
|
|
88
|
+
"type": "string"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"required": [
|
|
92
|
+
"accessToken"
|
|
93
|
+
]
|
|
94
|
+
}]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Getting Started
|
|
105
|
+
|
|
106
|
+
> This package requires a TypeScript based project. OpenAPI spec is created through parsing the TypeScript AST and can't be done in plain JS projects.
|
|
107
|
+
|
|
108
|
+
Install dependencies:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
yarn add moonflower koa @koa/router koa-bodyparser
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Create a Koa instance with required middleware
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import Koa from 'koa'
|
|
118
|
+
import bodyParser from 'koa-bodyparser'
|
|
119
|
+
import { HttpErrorHandler, initOpenApiEngine, Router } from 'moonflower'
|
|
120
|
+
|
|
121
|
+
const app = new Koa()
|
|
122
|
+
const myRouter = new Router()
|
|
123
|
+
|
|
124
|
+
myRouter.get('/api/hello', (ctx) => {
|
|
125
|
+
/* Unlike in Koa, all endpoints must do a plain return.
|
|
126
|
+
* However, Koa context is still available for edge cases.
|
|
127
|
+
*/
|
|
128
|
+
return {
|
|
129
|
+
greeting: 'hello world',
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
app
|
|
134
|
+
// Returns standard HTTP errors for common requests
|
|
135
|
+
.use(HttpErrorHandler)
|
|
136
|
+
.use(
|
|
137
|
+
// Required for requests with body
|
|
138
|
+
bodyParser({
|
|
139
|
+
enableTypes: ['text', 'json', 'form'],
|
|
140
|
+
})
|
|
141
|
+
)
|
|
142
|
+
// Register the router in Koa
|
|
143
|
+
.use(myRouter.routes())
|
|
144
|
+
.use(myRouter.allowedMethods())
|
|
145
|
+
.use(
|
|
146
|
+
// Enables collection of OpenAPI spec from code
|
|
147
|
+
initOpenApiEngine({
|
|
148
|
+
tsconfigPath: './tsconfig.json',
|
|
149
|
+
})
|
|
150
|
+
)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Planned features
|
|
154
|
+
|
|
155
|
+
- Support for list query params
|
|
156
|
+
- Support for thrown errors in OpenApi engine
|
|
157
|
+
- Support for binary data responses
|
|
158
|
+
- Support for multipart form data
|
|
159
|
+
|
|
160
|
+
### Known issues
|
|
161
|
+
|
|
162
|
+
- Exported models are referenced by name only, leading to potential name collisions
|
|
163
|
+
|
|
164
|
+
# Hooks
|
|
165
|
+
> This section is work-in-progress.
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
// Dangling hooks
|
|
169
|
+
useApiHeader({...})
|
|
170
|
+
|
|
171
|
+
// Endpoint hooks
|
|
172
|
+
const params = usePathParams(ctx, {...})
|
|
173
|
+
const query = useQueryParams(ctx, {...})
|
|
174
|
+
const body = useRequestBody(ctx, {...})
|
|
175
|
+
const rawBody = useRequestRawBody(ctx, {...})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
# Validators
|
|
179
|
+
|
|
180
|
+
Validators are run for every parameter received from the client. Failed validation or an error thrown during validation will return 400 Bad Request to the user.
|
|
181
|
+
|
|
182
|
+
**Example:**
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
const query = useQueryParams(ctx, {
|
|
186
|
+
name: RequiredParam(StringValidator),
|
|
187
|
+
fooBar: OptionalParam<{ foo: string; bar: string }>({
|
|
188
|
+
parse: (v) => JSON.parse(v),
|
|
189
|
+
validate: (v) => !!v.foo && !!v.bar
|
|
190
|
+
}),
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
query.name // type is 'string'
|
|
194
|
+
query.fooBar // type is '{ foo: string; bar: string } | undefined'
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Built-in validators
|
|
198
|
+
|
|
199
|
+
The most common validators are available out-of-the-box.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
const query = useQueryParams(ctx, {
|
|
203
|
+
myNumber: NumberValidator,
|
|
204
|
+
myString: StringValidator,
|
|
205
|
+
myBoolean: BooleanValidator,
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
query.myNumber // type is 'number'
|
|
209
|
+
query.myString // type is 'string'
|
|
210
|
+
query.myBoolean // type is 'boolean'
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Required and optional parameters
|
|
214
|
+
```ts
|
|
215
|
+
const query = useQueryParams(ctx, {
|
|
216
|
+
predefinedBool: BooleanValidator,
|
|
217
|
+
optionalBool: OptionalParam(BooleanValidator),
|
|
218
|
+
customBool: RequiredParam({
|
|
219
|
+
parse: (v) => v === '1',
|
|
220
|
+
}),
|
|
221
|
+
customOptionalBool: OptionalParam({
|
|
222
|
+
parse: (v) => v === '1',
|
|
223
|
+
}),
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
query.predefinedBool // type is 'boolean'
|
|
227
|
+
query.optionalBool // type is 'boolean | undefined'
|
|
228
|
+
query.customBool // type is 'boolean'
|
|
229
|
+
query.customOptionalBool // type is 'boolean | undefined'
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Custom validators
|
|
233
|
+
|
|
234
|
+
Custom validators are simple objects that can be defined either inline, or elsewhere for reusability.
|
|
235
|
+
|
|
236
|
+
### Inline
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
const query = useQueryParams(ctx, {
|
|
240
|
+
numberInRange: RequiredParam({
|
|
241
|
+
parse: (v) => Number(v),
|
|
242
|
+
validate: (v) => !isNaN(v) && v >= 0 && v <= 100,
|
|
243
|
+
}),
|
|
244
|
+
optionalBoolean: OptionalParam({
|
|
245
|
+
parse: (v) => v === '1',
|
|
246
|
+
}),
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
query.numberInRange // type is 'number'
|
|
250
|
+
query.optionalBoolean // type is 'boolean | undefined'
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Using Zod
|
|
254
|
+
|
|
255
|
+
Zod schemas are compatible with validators, allowing you to directly use them to define runtime validation.
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
const body = useRequestBody(ctx, {
|
|
259
|
+
email: RequiredParam(z.string().email()),
|
|
260
|
+
password: RequiredParam(z.string()),
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
const { email, password } = body
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Anatomy of a validator
|
|
267
|
+
|
|
268
|
+
A validator contains a number of functions that are useful to check and transform incoming data.
|
|
269
|
+
|
|
270
|
+
### Parse
|
|
271
|
+
|
|
272
|
+
> `parse: (v: string) => T extends any`
|
|
273
|
+
|
|
274
|
+
The only required function of a validator. It takes the raw input param and transforms it into correct data type. The return type of `parse` will match the one specified in the `RequiredParam` or `OptionalParam` generics, or will be used to infer the type.
|
|
275
|
+
|
|
276
|
+
Make sure that it returns a correctly typed object.
|
|
277
|
+
|
|
278
|
+
### Validate
|
|
279
|
+
|
|
280
|
+
> `validate: (v: T) => boolean`
|
|
281
|
+
|
|
282
|
+
This function is called on incoming data after it is parsed.
|
|
283
|
+
|
|
284
|
+
Returning `false` or any falsy value will cause the validation to fail, and `400 Bad Request` to be sent back to the client.
|
|
285
|
+
|
|
286
|
+
### Prevalidate
|
|
287
|
+
|
|
288
|
+
> `prevalidate: (v: string) => boolean`
|
|
289
|
+
|
|
290
|
+
This function is called on incoming data before it is parsed. Useful in cases where rehydration function is slow (i.e. includes a DB read), and some premature validation is desired. In most cases, however, `validate` is preferred.
|
|
291
|
+
|
|
292
|
+
The behaviour is identical to `validate`, aside from the call order.
|
|
293
|
+
|
|
294
|
+
### Type inference
|
|
295
|
+
|
|
296
|
+
In many cases, type of the parameter can be inferred from the return value of `parse` function. For more complex objects, it is possible to specify the type with `as ...` clause:
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
useQueryParams(ctx, {
|
|
301
|
+
fooBar: RequiredParam({
|
|
302
|
+
prevalidate: (v) => v.length > 5,
|
|
303
|
+
parse: (v) => JSON.parse(v) as { foo: string; bar: string },
|
|
304
|
+
validate: (v) => !!v.foo && !!v.bar
|
|
305
|
+
}),
|
|
306
|
+
})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Alternatively, the expected type can be mentioned in `RequiredParam`, `OptionalParam` or `PathParam` generics:
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
useQueryParams(ctx, {
|
|
313
|
+
fooBar: RequiredParam<{ foo: string; bar: string }>({
|
|
314
|
+
prevalidate: (v) => v.length > 5,
|
|
315
|
+
parse: (v) => JSON.parse(v),
|
|
316
|
+
validate: (v) => !!v.foo && !!v.bar
|
|
317
|
+
}),
|
|
318
|
+
})
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Avoid
|
|
322
|
+
|
|
323
|
+
While the following is valid code, the type of the parameter can't be inferred as TS will not parse this as Validator type. The type of `validate` will be `(v: any) => boolean`, which is unsafe.
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
useQueryParams(ctx, {
|
|
327
|
+
myParam: {
|
|
328
|
+
parse: (v) => Number(v),
|
|
329
|
+
validate: (v) => v > 0,
|
|
330
|
+
optional: false,
|
|
331
|
+
},
|
|
332
|
+
})
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
# Path params
|
|
336
|
+
|
|
337
|
+
Path params have extra binding to the endpoint path. Only the properties mentioned in the path can be used.
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
router.get('/user/:userId', (ctx) => {
|
|
341
|
+
const params = usePathParams(ctx, {
|
|
342
|
+
userId: StringValidator, // valid
|
|
343
|
+
username: StringValidator, // 'username' is not a path param
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
params.userId // type is 'string'
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Optional path params
|
|
351
|
+
|
|
352
|
+
Following standard Koa way of defining an optional param, a param marked by a question mark is considered optional.
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
router.get('/user/:userId?', (ctx) => {
|
|
356
|
+
const params = usePathParams(ctx, {
|
|
357
|
+
userId: StringValidator,
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
params.userId // type is 'string | undefined'
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Custom path parameters
|
|
365
|
+
|
|
366
|
+
As parameter optionaliy is defined in a path, `RequiredParam` and `OptionalParam` will be ignored. To reduce confusion, `PathParam` is available.
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
router.get('/user/:numberId', (ctx) => {
|
|
370
|
+
usePathParams(ctx, {
|
|
371
|
+
numberId: PathParam({
|
|
372
|
+
parse: (v) => Number(v),
|
|
373
|
+
validate: (v) => !isNaN(v) && v >= 0 && v <= 100,
|
|
374
|
+
})
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Escape hatch
|
|
380
|
+
|
|
381
|
+
All Koa and Koa Router APIs are still available in case some functionality is unavailable through Moonflower. Endpoints provide a `ctx` prop, and the router expose `koaRouter` which is raw underlying router implementation.
|
|
382
|
+
|
|
383
|
+
However, avoiding Moonflower's API will degrade the quality of the generated spec.
|
package/cli/cli.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as fs from 'fs'
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
import yargs, { ArgumentsCamelCase } from 'yargs'
|
|
4
|
+
import { hideBin } from 'yargs/helpers'
|
|
5
|
+
|
|
6
|
+
import { prepareOpenApiSpec } from '../src/openapi/analyzerModule/analyzerModule'
|
|
7
|
+
import { generateOpenApiSpec } from '../src/openapi/generatorModule'
|
|
8
|
+
import { OpenApiManager } from '../src/openapi/manager/OpenApiManager'
|
|
9
|
+
import { printAnalysisStats } from './prettyprint'
|
|
10
|
+
|
|
11
|
+
const originalConsole = console.info
|
|
12
|
+
console.info = (message, ...args) => {
|
|
13
|
+
originalConsole(`${message}`, ...args)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
yargs(hideBin(process.argv))
|
|
17
|
+
.showHelpOnFail(true)
|
|
18
|
+
.command({
|
|
19
|
+
command: 'openapi <targetPath>',
|
|
20
|
+
describe: 'Generates the current openapi spec into a specified file path',
|
|
21
|
+
builder: {
|
|
22
|
+
targetPath: {
|
|
23
|
+
describe: 'Target path',
|
|
24
|
+
demandOption: true,
|
|
25
|
+
type: 'string',
|
|
26
|
+
coerce: (f) => path.resolve(f),
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
tsConfigPath: {
|
|
30
|
+
describe: 'tsconfig',
|
|
31
|
+
type: 'string',
|
|
32
|
+
coerce: (f) => path.resolve(f),
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
handler(argv: ArgumentsCamelCase<{ targetPath: string; tsConfigPath?: string }>) {
|
|
37
|
+
if (fs.existsSync(argv.targetPath)) {
|
|
38
|
+
console.error(`[Error] File already exists at ${argv.targetPath}`)
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (argv.tsConfigPath && !fs.existsSync(argv.tsConfigPath)) {
|
|
43
|
+
console.error(`[Error] Unable to find a tsconfig file at ${argv.tsConfigPath}`)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
prepareOpenApiSpec({
|
|
48
|
+
tsconfigPath: argv.tsConfigPath ?? 'tsconfig.json',
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const manager = OpenApiManager.getInstance()
|
|
52
|
+
printAnalysisStats(manager.getStats())
|
|
53
|
+
|
|
54
|
+
const spec = generateOpenApiSpec(manager)
|
|
55
|
+
fs.writeFileSync(argv.targetPath, JSON.stringify(spec))
|
|
56
|
+
},
|
|
57
|
+
})
|
|
58
|
+
.demandCommand()
|
|
59
|
+
.parse()
|
package/cli/entry.cjs
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ApiAnalysisStats } from '../src/openapi/manager/OpenApiManager'
|
|
2
|
+
|
|
3
|
+
export const printAnalysisStats = (stats: ApiAnalysisStats) => {
|
|
4
|
+
stats.explicitRouterFiles.forEach((file) => printRouterFile(file))
|
|
5
|
+
stats.discoveredRouterFiles.forEach((file) => printRouterFile(file))
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const printRouterFile = (file: ApiAnalysisStats['discoveredRouterFiles'][number]) => {
|
|
9
|
+
console.info(`${file.path}`)
|
|
10
|
+
file.routers.forEach((r) => {
|
|
11
|
+
console.info(`└ ${r.name}`)
|
|
12
|
+
r.endpoints.forEach((e) => {
|
|
13
|
+
console.info(` └ ${e}`)
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../cli/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli/cli.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const fs = __importStar(require("fs"));
|
|
30
|
+
const path = __importStar(require("path"));
|
|
31
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
32
|
+
const helpers_1 = require("yargs/helpers");
|
|
33
|
+
const analyzerModule_1 = require("../src/openapi/analyzerModule/analyzerModule");
|
|
34
|
+
const generatorModule_1 = require("../src/openapi/generatorModule");
|
|
35
|
+
const OpenApiManager_1 = require("../src/openapi/manager/OpenApiManager");
|
|
36
|
+
const prettyprint_1 = require("./prettyprint");
|
|
37
|
+
const originalConsole = console.info;
|
|
38
|
+
console.info = (message, ...args) => {
|
|
39
|
+
originalConsole(`${message}`, ...args);
|
|
40
|
+
};
|
|
41
|
+
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
42
|
+
.showHelpOnFail(true)
|
|
43
|
+
.command({
|
|
44
|
+
command: 'openapi <targetPath>',
|
|
45
|
+
describe: 'Generates the current openapi spec into a specified file path',
|
|
46
|
+
builder: {
|
|
47
|
+
targetPath: {
|
|
48
|
+
describe: 'Target path',
|
|
49
|
+
demandOption: true,
|
|
50
|
+
type: 'string',
|
|
51
|
+
coerce: (f) => path.resolve(f),
|
|
52
|
+
},
|
|
53
|
+
tsConfigPath: {
|
|
54
|
+
describe: 'tsconfig',
|
|
55
|
+
type: 'string',
|
|
56
|
+
coerce: (f) => path.resolve(f),
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
handler(argv) {
|
|
60
|
+
var _a;
|
|
61
|
+
if (fs.existsSync(argv.targetPath)) {
|
|
62
|
+
console.error(`[Error] File already exists at ${argv.targetPath}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (argv.tsConfigPath && !fs.existsSync(argv.tsConfigPath)) {
|
|
66
|
+
console.error(`[Error] Unable to find a tsconfig file at ${argv.tsConfigPath}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
(0, analyzerModule_1.prepareOpenApiSpec)({
|
|
70
|
+
tsconfigPath: (_a = argv.tsConfigPath) !== null && _a !== void 0 ? _a : 'tsconfig.json',
|
|
71
|
+
});
|
|
72
|
+
const manager = OpenApiManager_1.OpenApiManager.getInstance();
|
|
73
|
+
(0, prettyprint_1.printAnalysisStats)(manager.getStats());
|
|
74
|
+
const spec = (0, generatorModule_1.generateOpenApiSpec)(manager);
|
|
75
|
+
fs.writeFileSync(argv.targetPath, JSON.stringify(spec));
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
.demandCommand()
|
|
79
|
+
.parse();
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ApiAnalysisStats } from '../src/openapi/manager/OpenApiManager';
|
|
2
|
+
export declare const printAnalysisStats: (stats: ApiAnalysisStats) => void;
|
|
3
|
+
export declare const printRouterFile: (file: ApiAnalysisStats['discoveredRouterFiles'][number]) => void;
|
|
4
|
+
//# sourceMappingURL=prettyprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prettyprint.d.ts","sourceRoot":"","sources":["../../cli/prettyprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AAExE,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,SAGzD,CAAA;AAED,eAAO,MAAM,eAAe,SAAU,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,SAQtF,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.printRouterFile = exports.printAnalysisStats = void 0;
|
|
4
|
+
const printAnalysisStats = (stats) => {
|
|
5
|
+
stats.explicitRouterFiles.forEach((file) => (0, exports.printRouterFile)(file));
|
|
6
|
+
stats.discoveredRouterFiles.forEach((file) => (0, exports.printRouterFile)(file));
|
|
7
|
+
};
|
|
8
|
+
exports.printAnalysisStats = printAnalysisStats;
|
|
9
|
+
const printRouterFile = (file) => {
|
|
10
|
+
console.info(`${file.path}`);
|
|
11
|
+
file.routers.forEach((r) => {
|
|
12
|
+
console.info(`└ ${r.name}`);
|
|
13
|
+
r.endpoints.forEach((e) => {
|
|
14
|
+
console.info(` └ ${e}`);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
exports.printRouterFile = printRouterFile;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { StatusCodes } from 'http-status-codes';
|
|
2
|
+
export interface HttpError {
|
|
3
|
+
status: StatusCodes;
|
|
4
|
+
reason: string;
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class BaseHttpError extends Error implements HttpError {
|
|
8
|
+
status: StatusCodes;
|
|
9
|
+
message: string;
|
|
10
|
+
reason: string;
|
|
11
|
+
constructor(status: StatusCodes, message: string);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=BaseHttpError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseHttpError.d.ts","sourceRoot":"","sources":["../../../src/errors/BaseHttpError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEhE,MAAM,WAAW,SAAS;IACzB,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CACf;AAED,qBAAa,aAAc,SAAQ,KAAM,YAAW,SAAS;IAGzC,MAAM,EAAE,WAAW;IAAS,OAAO,EAAE,MAAM;IAFvD,MAAM,EAAE,MAAM,CAAA;gBAEF,MAAM,EAAE,WAAW,EAAS,OAAO,EAAE,MAAM;CAI9D"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseHttpError = void 0;
|
|
4
|
+
const http_status_codes_1 = require("http-status-codes");
|
|
5
|
+
class BaseHttpError extends Error {
|
|
6
|
+
constructor(status, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.message = message;
|
|
10
|
+
this.reason = (0, http_status_codes_1.getReasonPhrase)(status);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.BaseHttpError = BaseHttpError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpErrorHandler.d.ts","sourceRoot":"","sources":["../../../src/errors/HttpErrorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AAIrB,eAAO,MAAM,gBAAgB,QAAe,IAAI,oBAAoB,QAAQ,IAAI,IAAI,kBAenF,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpErrorHandler = void 0;
|
|
4
|
+
const BaseHttpError_1 = require("./BaseHttpError");
|
|
5
|
+
const HttpErrorHandler = async (ctx, next) => {
|
|
6
|
+
try {
|
|
7
|
+
await next();
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
if (err instanceof BaseHttpError_1.BaseHttpError) {
|
|
11
|
+
ctx.status = err.status;
|
|
12
|
+
ctx.body = {
|
|
13
|
+
status: err.status,
|
|
14
|
+
reason: err.reason,
|
|
15
|
+
message: err.message,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
throw err;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
exports.HttpErrorHandler = HttpErrorHandler;
|