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
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type ShapeOfType =
|
|
2
|
+
| ShapeOfProperty
|
|
3
|
+
| ShapeOfStringLiteral
|
|
4
|
+
| ShapeOfNumberLiteral
|
|
5
|
+
| ShapeOfUnion
|
|
6
|
+
| ShapeOfUnionEntry
|
|
7
|
+
| ShapeOfRecord
|
|
8
|
+
| ShapeOfArray
|
|
9
|
+
| ShapeOfRef
|
|
10
|
+
| ShapeOfTuple
|
|
11
|
+
| ShapeOfTupleEntry
|
|
12
|
+
|
|
13
|
+
export type ShapeOfProperty = {
|
|
14
|
+
role: 'property'
|
|
15
|
+
identifier: string
|
|
16
|
+
shape: string | ShapeOfType[]
|
|
17
|
+
optional: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ShapeOfStringLiteral = {
|
|
21
|
+
role: 'literal_string'
|
|
22
|
+
shape: string
|
|
23
|
+
optional: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type ShapeOfNumberLiteral = {
|
|
27
|
+
role: 'literal_number'
|
|
28
|
+
shape: string
|
|
29
|
+
optional: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type ShapeOfUnion = {
|
|
33
|
+
role: 'union'
|
|
34
|
+
shape: ShapeOfUnionEntry[]
|
|
35
|
+
optional: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type ShapeOfUnionEntry = {
|
|
39
|
+
role: 'union_entry'
|
|
40
|
+
shape: string | ShapeOfType[]
|
|
41
|
+
optional: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type ShapeOfRecord = {
|
|
45
|
+
role: 'record'
|
|
46
|
+
shape: string | ShapeOfType[]
|
|
47
|
+
optional: boolean
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type ShapeOfArray = {
|
|
51
|
+
role: 'array'
|
|
52
|
+
shape: string | ShapeOfType[]
|
|
53
|
+
optional: boolean
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type ShapeOfRef = {
|
|
57
|
+
role: 'ref'
|
|
58
|
+
shape: string
|
|
59
|
+
optional: boolean
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type ShapeOfTuple = {
|
|
63
|
+
role: 'tuple'
|
|
64
|
+
shape: ShapeOfTupleEntry[]
|
|
65
|
+
optional: boolean
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type ShapeOfTupleEntry = {
|
|
69
|
+
role: 'tuple_entry'
|
|
70
|
+
shape: string | ShapeOfType[]
|
|
71
|
+
optional: boolean
|
|
72
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SourceFile, SyntaxKind } from 'ts-morph'
|
|
2
|
+
|
|
3
|
+
type Props = {
|
|
4
|
+
sourceFile: SourceFile
|
|
5
|
+
originalName: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const discoverImportedName = ({ sourceFile, originalName }: Props): string | null => {
|
|
9
|
+
const importDeclarations = sourceFile.getDescendantsOfKind(SyntaxKind.ImportDeclaration)
|
|
10
|
+
const discoveredName = importDeclarations
|
|
11
|
+
.filter((declaration) => {
|
|
12
|
+
// declaration
|
|
13
|
+
const importPathNode = declaration.getLastChildByKind(SyntaxKind.StringLiteral)
|
|
14
|
+
if (!importPathNode) {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const importPath = importPathNode.getText()
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
/moonflower/.test(importPath) ||
|
|
22
|
+
process.env.NODE_ENV === 'test' ||
|
|
23
|
+
process.env.NODE_ENV === 'development'
|
|
24
|
+
)
|
|
25
|
+
})
|
|
26
|
+
.map((declaration) => {
|
|
27
|
+
const routerImport = declaration
|
|
28
|
+
.getDescendantsOfKind(SyntaxKind.ImportSpecifier)
|
|
29
|
+
.filter((i) => i.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === originalName)[0]
|
|
30
|
+
|
|
31
|
+
if (!routerImport) {
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return routerImport.getLastChildByKindOrThrow(SyntaxKind.Identifier).getText()
|
|
36
|
+
})
|
|
37
|
+
.filter((declaration): declaration is NonNullable<typeof declaration> => declaration !== null)[0]
|
|
38
|
+
|
|
39
|
+
if (!discoveredName) {
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
return discoveredName
|
|
43
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { resolve } from 'path'
|
|
2
|
+
|
|
3
|
+
import { discoverRouterFiles } from './discoverRouterFiles'
|
|
4
|
+
|
|
5
|
+
describe('discoverRouterFiles', () => {
|
|
6
|
+
it('discovers routers from folder correctly', () => {
|
|
7
|
+
const { discoveredRouterFiles } = discoverRouterFiles({
|
|
8
|
+
targetPath: resolve(__dirname, '.'),
|
|
9
|
+
tsConfigPath: resolve('./tsconfig.json'),
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
expect(discoveredRouterFiles.length).toEqual(2)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('respects ignoring files by string', () => {
|
|
16
|
+
const { discoveredRouterFiles } = discoverRouterFiles({
|
|
17
|
+
targetPath: resolve(__dirname, '.'),
|
|
18
|
+
tsConfigPath: resolve('./tsconfig.json'),
|
|
19
|
+
excludedFiles: ['testRouterA'],
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
expect(discoveredRouterFiles.length).toEqual(1)
|
|
23
|
+
expect(discoveredRouterFiles[0].fileName.endsWith('testRouterB.spec.data.ts')).toBeTruthy()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('respects ignoring files by regex', () => {
|
|
27
|
+
const { discoveredRouterFiles } = discoverRouterFiles({
|
|
28
|
+
targetPath: resolve(__dirname, '.'),
|
|
29
|
+
tsConfigPath: resolve('./tsconfig.json'),
|
|
30
|
+
excludedFiles: [/B/g],
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
expect(discoveredRouterFiles.length).toEqual(1)
|
|
34
|
+
expect(discoveredRouterFiles[0].fileName.endsWith('testRouterA.spec.data.ts')).toBeTruthy()
|
|
35
|
+
})
|
|
36
|
+
})
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as fs from 'fs'
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
import { Project } from 'ts-morph'
|
|
4
|
+
|
|
5
|
+
import { discoverRouters } from '../discoverRouters/discoverRouters'
|
|
6
|
+
|
|
7
|
+
export type DiscoveredSourceFile = ReturnType<typeof discoverRouterFiles>['discoveredRouterFiles'][number]
|
|
8
|
+
|
|
9
|
+
export const discoverRouterFiles = ({
|
|
10
|
+
targetPath,
|
|
11
|
+
tsConfigPath,
|
|
12
|
+
excludedFiles,
|
|
13
|
+
}: {
|
|
14
|
+
targetPath: string
|
|
15
|
+
tsConfigPath: string
|
|
16
|
+
excludedFiles?: (string | RegExp)[]
|
|
17
|
+
}) => {
|
|
18
|
+
if (!fs.existsSync(targetPath)) {
|
|
19
|
+
return { discoveredRouterFiles: [], discoveredSourceFiles: [] }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const usersExcludedFiles = (excludedFiles ?? []).map((value) =>
|
|
23
|
+
typeof value === 'string' ? new RegExp(`${value}`) : value
|
|
24
|
+
)
|
|
25
|
+
const excludedPrefixes = [/^node_modules/, /^\./, /^dist/].concat(usersExcludedFiles ?? [])
|
|
26
|
+
|
|
27
|
+
const files = fs.readdirSync(targetPath, { recursive: true }).filter((filePath): filePath is string => {
|
|
28
|
+
if (typeof filePath !== 'string') {
|
|
29
|
+
return false
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (excludedPrefixes.some((p) => p.test(filePath))) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!filePath.endsWith('.ts')) {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
return true
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const project = new Project({
|
|
43
|
+
tsConfigFilePath: tsConfigPath,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const allSourceFiles = files
|
|
47
|
+
.map((fileName) => {
|
|
48
|
+
const filePath = path.resolve(targetPath, fileName)
|
|
49
|
+
return {
|
|
50
|
+
fileName,
|
|
51
|
+
sourceFile: project.getSourceFile(filePath),
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
.filter(
|
|
55
|
+
(
|
|
56
|
+
file
|
|
57
|
+
): file is Omit<typeof file, 'sourceFile'> & { sourceFile: NonNullable<typeof file['sourceFile']> } =>
|
|
58
|
+
!!file.sourceFile
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const routersInFiles = allSourceFiles
|
|
62
|
+
.map((file) => {
|
|
63
|
+
const { fileName, sourceFile } = file
|
|
64
|
+
const routers = discoverRouters(sourceFile)
|
|
65
|
+
if (routers.named.length === 0 && routers.anonymous.length === 0) {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
fileName,
|
|
70
|
+
sourceFile,
|
|
71
|
+
routers,
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
.filter((file): file is NonNullable<typeof file> => file !== null)
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
discoveredRouterFiles: routersInFiles,
|
|
78
|
+
discoveredSourceFiles: allSourceFiles.map((file) => file.sourceFile),
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Router as RenamedRouter } from '../../../router/Router'
|
|
2
|
+
|
|
3
|
+
const namedRouterVariable = new RenamedRouter()
|
|
4
|
+
|
|
5
|
+
namedRouterVariable.get('/api', () => {
|
|
6
|
+
return 'test-data'
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
const anotherRouterVariable = new RenamedRouter()
|
|
10
|
+
.use((_, next) => next())
|
|
11
|
+
.with(() => {
|
|
12
|
+
const user = { id: '123' }
|
|
13
|
+
return {
|
|
14
|
+
user,
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
anotherRouterVariable.get('/api', () => {
|
|
19
|
+
return 'more-test-data'
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
export default new RenamedRouter()
|
|
23
|
+
.get('/anonapi', () => {
|
|
24
|
+
return 'otherdata'
|
|
25
|
+
})
|
|
26
|
+
.get('/anonapitwo', () => {
|
|
27
|
+
return 'otherdata'
|
|
28
|
+
})
|
|
29
|
+
.get('/anonapithree', () => {
|
|
30
|
+
return 'otherdata'
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// Exists to make sure that discovery module ignores unrelated objects
|
|
34
|
+
class Router {
|
|
35
|
+
value = 'foo'
|
|
36
|
+
|
|
37
|
+
setValue(val: string) {
|
|
38
|
+
this.value = val
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const unrelatedObject = new Router()
|
|
42
|
+
unrelatedObject.setValue('bar')
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SyntaxKind } from 'ts-morph'
|
|
2
|
+
|
|
3
|
+
import { loadTestData } from '../../../utils/loadTestData'
|
|
4
|
+
import { discoverRouters } from './discoverRouters'
|
|
5
|
+
|
|
6
|
+
describe('discoverRouters', () => {
|
|
7
|
+
const dataFile = loadTestData('discoverRouters.spec.data.ts')
|
|
8
|
+
|
|
9
|
+
it('discovers routers from single file correctly', () => {
|
|
10
|
+
const routers = discoverRouters(dataFile)
|
|
11
|
+
|
|
12
|
+
expect(routers.named.length).toEqual(2)
|
|
13
|
+
expect(routers.named[0]).toEqual('namedRouterVariable')
|
|
14
|
+
expect(routers.named[1]).toEqual('anotherRouterVariable')
|
|
15
|
+
expect(routers.anonymous.length).toEqual(1)
|
|
16
|
+
expect(routers.anonymous[0].getKind()).toEqual(SyntaxKind.CallExpression)
|
|
17
|
+
})
|
|
18
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SourceFile, SyntaxKind } from 'ts-morph'
|
|
2
|
+
|
|
3
|
+
import { Router } from '../../../router/Router'
|
|
4
|
+
import { nameOf } from '../../../utils/nameOf'
|
|
5
|
+
import { discoverImportedName } from '../discoverImports/discoverImports'
|
|
6
|
+
|
|
7
|
+
export const discoverRouters = (sourceFile: SourceFile) => {
|
|
8
|
+
const routerClassName = discoverImportedName({
|
|
9
|
+
sourceFile,
|
|
10
|
+
originalName: nameOf(Router),
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
if (!routerClassName) {
|
|
14
|
+
return { named: [], anonymous: [] }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const routers = sourceFile
|
|
18
|
+
.getDescendantsOfKind(SyntaxKind.NewExpression)
|
|
19
|
+
.filter((exp) => exp.getFirstChildByKindOrThrow(SyntaxKind.Identifier).getText() === routerClassName)
|
|
20
|
+
|
|
21
|
+
const namedRouters = routers.filter((node) => !!node.getFirstAncestorByKind(SyntaxKind.VariableDeclaration))
|
|
22
|
+
const anonymousRouters = routers.filter(
|
|
23
|
+
(node) => !!node.getFirstAncestorByKind(SyntaxKind.ExportAssignment)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
named: namedRouters.map((node) =>
|
|
28
|
+
node
|
|
29
|
+
.getFirstAncestorByKindOrThrow(SyntaxKind.VariableDeclaration)
|
|
30
|
+
.getFirstChildByKindOrThrow(SyntaxKind.Identifier)
|
|
31
|
+
.getText()
|
|
32
|
+
),
|
|
33
|
+
anonymous: anonymousRouters.map((node) =>
|
|
34
|
+
node
|
|
35
|
+
.getFirstAncestorByKindOrThrow(SyntaxKind.ExportAssignment)
|
|
36
|
+
.getFirstChildByKindOrThrow(SyntaxKind.CallExpression)
|
|
37
|
+
),
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
2
|
+
import { ExposedModelData } from '../types'
|
|
3
|
+
import { getSchema, SchemaType } from './getSchema'
|
|
4
|
+
|
|
5
|
+
export const generateComponentSchemas = (models: ExposedModelData[]) => {
|
|
6
|
+
const schemas: Record<string, SchemaType> = {}
|
|
7
|
+
|
|
8
|
+
models.forEach((model) => {
|
|
9
|
+
schemas[model.name] = getSchema(model.shape)
|
|
10
|
+
})
|
|
11
|
+
return schemas
|
|
12
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
2
|
+
import { ApiDocsPreferences } from '../manager/OpenApiManager'
|
|
3
|
+
import { EndpointData, PathDefinition } from '../types'
|
|
4
|
+
import { getSchema } from './getSchema'
|
|
5
|
+
|
|
6
|
+
export const generatePaths = (endpoints: EndpointData[], preferences: ApiDocsPreferences) => {
|
|
7
|
+
const paths: Record<
|
|
8
|
+
string,
|
|
9
|
+
{
|
|
10
|
+
get?: PathDefinition
|
|
11
|
+
post?: PathDefinition
|
|
12
|
+
put?: PathDefinition
|
|
13
|
+
patch?: PathDefinition
|
|
14
|
+
delete?: PathDefinition
|
|
15
|
+
}
|
|
16
|
+
> = {}
|
|
17
|
+
|
|
18
|
+
const { allowOptionalPathParams } = preferences
|
|
19
|
+
|
|
20
|
+
endpoints.forEach((endpoint) => {
|
|
21
|
+
const path = endpoint.path
|
|
22
|
+
.split('/')
|
|
23
|
+
.map((param) => {
|
|
24
|
+
if (param.startsWith(':')) {
|
|
25
|
+
return `{${param.substring(1).replace('?', '')}}`
|
|
26
|
+
}
|
|
27
|
+
return param
|
|
28
|
+
})
|
|
29
|
+
.join('/')
|
|
30
|
+
|
|
31
|
+
const pathParams = endpoint.requestPathParams.map((param) => ({
|
|
32
|
+
name: param.identifier,
|
|
33
|
+
in: 'path' as const,
|
|
34
|
+
description:
|
|
35
|
+
param.optional && !allowOptionalPathParams
|
|
36
|
+
? `(Optional parameter) ${param.description}`
|
|
37
|
+
: param.description ?? '',
|
|
38
|
+
required: !allowOptionalPathParams || !param.optional,
|
|
39
|
+
schema: getSchema(param.signature),
|
|
40
|
+
}))
|
|
41
|
+
|
|
42
|
+
const queryParams = endpoint.requestQuery.map((param) => ({
|
|
43
|
+
name: param.identifier,
|
|
44
|
+
in: 'query' as const,
|
|
45
|
+
description: param.description ?? '',
|
|
46
|
+
required: !param.optional,
|
|
47
|
+
schema: getSchema(param.signature),
|
|
48
|
+
}))
|
|
49
|
+
|
|
50
|
+
const headerParams = endpoint.requestHeaders.map((param) => ({
|
|
51
|
+
name: param.identifier,
|
|
52
|
+
in: 'header' as const,
|
|
53
|
+
description: param.description ?? '',
|
|
54
|
+
required: !param.optional,
|
|
55
|
+
schema: getSchema(param.signature),
|
|
56
|
+
}))
|
|
57
|
+
|
|
58
|
+
const acceptedBodyTypes: Partial<
|
|
59
|
+
Record<'text/plain' | 'application/json' | 'application/x-www-form-urlencoded', unknown>
|
|
60
|
+
> = {}
|
|
61
|
+
|
|
62
|
+
if (endpoint.rawBody) {
|
|
63
|
+
acceptedBodyTypes['text/plain'] = {
|
|
64
|
+
schema: getSchema(endpoint.rawBody.signature),
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (endpoint.objectBody.length > 0) {
|
|
69
|
+
const properties: Record<string, unknown> = {}
|
|
70
|
+
endpoint.objectBody.forEach((prop) => {
|
|
71
|
+
properties[prop.identifier] = getSchema(prop.signature)
|
|
72
|
+
})
|
|
73
|
+
const required = endpoint.objectBody.filter((prop) => !prop.optional).map((prop) => prop.identifier)
|
|
74
|
+
const content = {
|
|
75
|
+
schema: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties,
|
|
78
|
+
required: required.length > 0 ? required : undefined,
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
acceptedBodyTypes['application/json'] = content
|
|
82
|
+
acceptedBodyTypes['application/x-www-form-urlencoded'] = content
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const requestsWithBody = ['POST', 'PATCH', 'PUT']
|
|
86
|
+
const requestBody =
|
|
87
|
+
requestsWithBody.includes(endpoint.method) && Object.keys(acceptedBodyTypes).length > 0
|
|
88
|
+
? { content: acceptedBodyTypes }
|
|
89
|
+
: undefined
|
|
90
|
+
|
|
91
|
+
const responses: PathDefinition['responses'] = {}
|
|
92
|
+
endpoint.responses.forEach((response) => {
|
|
93
|
+
const status = String(response.status)
|
|
94
|
+
|
|
95
|
+
const existingSchemas = responses[status]?.['content']?.['application/json']['schema']['oneOf'] ?? []
|
|
96
|
+
|
|
97
|
+
const responseSchema = getSchema(response.signature)
|
|
98
|
+
const content = (() => {
|
|
99
|
+
if ('type' in responseSchema && (responseSchema.type === 'void' || responseSchema.type === 'null')) {
|
|
100
|
+
return undefined
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
'application/json': {
|
|
105
|
+
schema: {
|
|
106
|
+
oneOf: [...existingSchemas, getSchema(response.signature)],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
})()
|
|
111
|
+
|
|
112
|
+
responses[status] = {
|
|
113
|
+
description: response.description || '',
|
|
114
|
+
content,
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
const definition: PathDefinition = {
|
|
119
|
+
operationId: endpoint.name,
|
|
120
|
+
summary: endpoint.summary,
|
|
121
|
+
description: endpoint.description ?? '',
|
|
122
|
+
parameters: ([] as PathDefinition['parameters'])
|
|
123
|
+
.concat(pathParams)
|
|
124
|
+
.concat(queryParams)
|
|
125
|
+
.concat(headerParams),
|
|
126
|
+
requestBody: requestBody,
|
|
127
|
+
responses: responses,
|
|
128
|
+
tags: endpoint.tags,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
paths[path] = {
|
|
132
|
+
...paths[path],
|
|
133
|
+
[endpoint.method.toLowerCase()]: definition,
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
return paths
|
|
138
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OpenApiManager } from '../manager/OpenApiManager'
|
|
2
|
+
import { generateComponentSchemas } from './generateComponentSchemas'
|
|
3
|
+
import { generatePaths } from './generatePaths'
|
|
4
|
+
|
|
5
|
+
export const generateOpenApiSpec = (manager: OpenApiManager) => {
|
|
6
|
+
const header = manager.getHeader()
|
|
7
|
+
const endpoints = manager.getEndpoints()
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
openapi: '3.1.0' as const,
|
|
11
|
+
info: header,
|
|
12
|
+
paths: generatePaths(endpoints, manager.getPreferences()),
|
|
13
|
+
components: {
|
|
14
|
+
schemas: generateComponentSchemas(manager.getExposedModels()),
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ShapeOfNumberLiteral,
|
|
3
|
+
ShapeOfProperty,
|
|
4
|
+
ShapeOfRecord,
|
|
5
|
+
ShapeOfRef,
|
|
6
|
+
ShapeOfStringLiteral,
|
|
7
|
+
ShapeOfTuple,
|
|
8
|
+
ShapeOfType,
|
|
9
|
+
ShapeOfUnion,
|
|
10
|
+
} from '../../openapi/analyzerModule/types'
|
|
11
|
+
|
|
12
|
+
export type SchemaType =
|
|
13
|
+
| { type: string }
|
|
14
|
+
| { type: string; properties: Record<string, SchemaType>; required: string[] }
|
|
15
|
+
| { oneOf: SchemaType[] }
|
|
16
|
+
| { allOf: SchemaType[] }
|
|
17
|
+
| { type: 'array'; items: SchemaType }
|
|
18
|
+
| { type: 'array'; items: SchemaType; minItems: number; maxItems: number }
|
|
19
|
+
| { type: 'object'; additionalProperties: SchemaType }
|
|
20
|
+
| { type: 'string'; enum: string[] }
|
|
21
|
+
| { type: 'string'; format: string }
|
|
22
|
+
| { type: 'number'; enum: string[] }
|
|
23
|
+
| { $ref: string }
|
|
24
|
+
|
|
25
|
+
export const getSchema = (shape: string | ShapeOfType[]): SchemaType => {
|
|
26
|
+
if (typeof shape === 'string' && shape === 'any') {
|
|
27
|
+
return generateAny()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (typeof shape === 'string' && shape === 'circular') {
|
|
31
|
+
return generateAny()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (typeof shape === 'string' && shape === 'null') {
|
|
35
|
+
return {
|
|
36
|
+
type: 'null',
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (typeof shape === 'string' && shape === 'Date') {
|
|
41
|
+
return {
|
|
42
|
+
type: 'string',
|
|
43
|
+
format: 'date-time',
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (typeof shape === 'string' && shape === 'bigint') {
|
|
48
|
+
return {
|
|
49
|
+
type: 'string',
|
|
50
|
+
format: 'bigint',
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (typeof shape === 'string') {
|
|
55
|
+
return {
|
|
56
|
+
type: shape,
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (shape.length === 0) {
|
|
61
|
+
return {
|
|
62
|
+
type: 'unknown_20',
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const isStringLiteral = shape[0].role === 'literal_string'
|
|
67
|
+
if (isStringLiteral) {
|
|
68
|
+
const typedShape = shape[0] as ShapeOfStringLiteral
|
|
69
|
+
return {
|
|
70
|
+
type: 'string',
|
|
71
|
+
enum: [typedShape.shape],
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const isNumberLiteral = shape[0].role === 'literal_number'
|
|
76
|
+
if (isNumberLiteral) {
|
|
77
|
+
const typedShape = shape[0] as ShapeOfNumberLiteral
|
|
78
|
+
return {
|
|
79
|
+
type: 'number',
|
|
80
|
+
enum: [typedShape.shape],
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const isObject = shape[0].role === 'property'
|
|
85
|
+
if (isObject) {
|
|
86
|
+
const typedShapes = shape as ShapeOfProperty[]
|
|
87
|
+
const properties: Record<string, SchemaType> = {}
|
|
88
|
+
typedShapes.forEach((prop) => {
|
|
89
|
+
properties[prop.identifier] = getSchema(prop.shape)
|
|
90
|
+
})
|
|
91
|
+
const required = typedShapes.filter((prop) => !prop.optional).map((prop) => prop.identifier)
|
|
92
|
+
return {
|
|
93
|
+
type: 'object',
|
|
94
|
+
properties,
|
|
95
|
+
required: required.length > 0 ? required : undefined,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const isUnion = shape[0].role === 'union'
|
|
100
|
+
if (isUnion) {
|
|
101
|
+
const typedShape = shape[0] as ShapeOfUnion
|
|
102
|
+
return {
|
|
103
|
+
oneOf: typedShape.shape.map((unionEntry) => getSchema(unionEntry.shape)),
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const isRecord = shape[0].role === 'record'
|
|
108
|
+
if (isRecord) {
|
|
109
|
+
const recordShape = shape[0] as ShapeOfRecord
|
|
110
|
+
return {
|
|
111
|
+
type: 'object',
|
|
112
|
+
additionalProperties: getSchema(recordShape.shape),
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const isArray = shape[0].role === 'array'
|
|
117
|
+
if (isArray) {
|
|
118
|
+
return {
|
|
119
|
+
type: 'array',
|
|
120
|
+
items: getSchema(shape[0].shape),
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const isRef = shape[0].role === 'ref'
|
|
125
|
+
if (isRef) {
|
|
126
|
+
const refShape = shape[0] as ShapeOfRef
|
|
127
|
+
return {
|
|
128
|
+
$ref: `#/components/schemas/${refShape.shape}`,
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const isTuple = shape[0].role === 'tuple'
|
|
133
|
+
if (isTuple) {
|
|
134
|
+
const tupleShape = shape[0] as ShapeOfTuple
|
|
135
|
+
const tupleEntries = tupleShape.shape
|
|
136
|
+
return {
|
|
137
|
+
type: 'array',
|
|
138
|
+
items: {
|
|
139
|
+
oneOf: tupleEntries.map((entry) => getSchema(entry.shape)),
|
|
140
|
+
},
|
|
141
|
+
minItems: tupleEntries.length,
|
|
142
|
+
maxItems: tupleEntries.length,
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
type: 'unknown_21',
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const generateAny = () => ({
|
|
152
|
+
oneOf: [
|
|
153
|
+
{
|
|
154
|
+
type: 'string',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
type: 'boolean',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
type: 'number',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'object',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
type: 'array',
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
})
|