@visulima/api-platform 1.2.6 → 1.2.8
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/CHANGELOG.md +26 -0
- package/README.md +8 -11
- package/dist/{chunk-A2BQLJ5W.mjs → chunk-2BDDP26Z.mjs} +1 -1
- package/dist/{chunk-BIZOICFF.js.map → chunk-2BDDP26Z.mjs.map} +1 -1
- package/dist/{chunk-BIZOICFF.js → chunk-5B2CCUEK.js} +1 -1
- package/dist/{chunk-A2BQLJ5W.mjs.map → chunk-5B2CCUEK.js.map} +1 -1
- package/dist/{chunk-NH4B62H7.js → chunk-JC55W6OX.js} +1 -1
- package/dist/{chunk-NH4B62H7.js.map → chunk-JC55W6OX.js.map} +1 -1
- package/dist/{chunk-4GBB2H25.mjs → chunk-MAUWX6TE.mjs} +1 -1
- package/dist/{chunk-4GBB2H25.mjs.map → chunk-MAUWX6TE.mjs.map} +1 -1
- package/dist/{chunk-SNOJMSHW.js → chunk-RK2WQGNS.js} +5 -5
- package/dist/chunk-RK2WQGNS.js.map +1 -0
- package/dist/{chunk-S26T4TPK.mjs → chunk-S2NV4N4L.mjs} +4 -4
- package/dist/chunk-S2NV4N4L.mjs.map +1 -0
- package/dist/framework/cli/commander/index.js +2 -2
- package/dist/framework/cli/commander/index.mjs +1 -1
- package/dist/framework/cli/index.js +2 -2
- package/dist/framework/cli/index.mjs +1 -1
- package/dist/framework/next/index-browser.d.ts +5 -2
- package/dist/framework/next/index-browser.js +2 -2
- package/dist/framework/next/index-browser.mjs +1 -1
- package/dist/framework/next/index-server.d.ts +1 -1
- package/dist/framework/next/index-server.js +4 -4
- package/dist/framework/next/index-server.js.map +1 -1
- package/dist/framework/next/index-server.mjs +2 -2
- package/dist/framework/next/index-server.mjs.map +1 -1
- package/dist/framework/next/routes/pages/redoc/index.d.ts +1 -1
- package/dist/framework/next/routes/pages/swagger/index.d.ts +1 -1
- package/dist/index-browser.d.ts +1 -1
- package/dist/index-server.d.ts +1 -1
- package/dist/index-server.js +4 -4
- package/dist/index-server.js.map +1 -1
- package/dist/index-server.mjs +2 -2
- package/dist/index-server.mjs.map +1 -1
- package/package.json +7 -7
- package/dist/chunk-S26T4TPK.mjs.map +0 -1
- package/dist/chunk-SNOJMSHW.js.map +0 -1
- package/dist/get-static-properties-swagger-546ee3ba.d.ts +0 -5
- /package/dist/{index-bd61921e.d.ts → index-browser-bd61921e.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
## @visulima/api-platform [1.2.8](https://github.com/visulima/visulima/compare/@visulima/api-platform@1.2.7...@visulima/api-platform@1.2.8) (2023-05-30)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **nextra-theme-docs:** updates theme to be nextra compatible ([#87](https://github.com/visulima/visulima/issues/87)) ([b9fbeb2](https://github.com/visulima/visulima/commit/b9fbeb2e59d842a8755b0c8f19a67f93778ba979))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Dependencies
|
|
11
|
+
|
|
12
|
+
* **@visulima/connect:** upgraded to 1.3.5
|
|
13
|
+
|
|
14
|
+
## @visulima/api-platform [1.2.7](https://github.com/visulima/visulima/compare/@visulima/api-platform@1.2.6...@visulima/api-platform@1.2.7) (2023-05-29)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* fixed wrong path for windows ([53cb491](https://github.com/visulima/visulima/commit/53cb4916dc072af385255936da2e054509f9b712))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Dependencies
|
|
24
|
+
|
|
25
|
+
* **@visulima/jsdoc-open-api:** upgraded to 1.3.6
|
|
26
|
+
|
|
1
27
|
## @visulima/api-platform [1.2.6](https://github.com/visulima/visulima/compare/@visulima/api-platform@1.2.5...@visulima/api-platform@1.2.6) (2023-05-29)
|
|
2
28
|
|
|
3
29
|
|
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
<p>
|
|
4
4
|
Visulima api platform is built on top of
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
[OpenAPI (Swagger) specification](https://swagger.io/specification/),
|
|
7
|
+
[node-rate-limiter-flexible](https://github.com/animir/node-rate-limiter-flexible),
|
|
8
|
+
[@visulima/connect](https://github.com/visulima/visulima/tree/main/packages/connect)
|
|
9
9
|
|
|
10
10
|
With a more intuitive API for creating HTTP API endpoints.
|
|
11
11
|
|
|
@@ -37,6 +37,7 @@ With a more intuitive API for creating HTTP API endpoints.
|
|
|
37
37
|
## Installation
|
|
38
38
|
|
|
39
39
|
### Npm
|
|
40
|
+
|
|
40
41
|
```sh
|
|
41
42
|
npm install @visulima/api-platform zod
|
|
42
43
|
```
|
|
@@ -80,8 +81,9 @@ npm install swagger-ui-react
|
|
|
80
81
|
To have a styled version of the swagger-ui you need to add the following css to your project:
|
|
81
82
|
|
|
82
83
|
```ts
|
|
83
|
-
import "swagger-ui-react/swagger-ui.css"
|
|
84
|
+
import "swagger-ui-react/swagger-ui.css";
|
|
84
85
|
```
|
|
86
|
+
|
|
85
87
|
> Note: For `next.js` you can add it to your `_app.tsx` file
|
|
86
88
|
|
|
87
89
|
Or
|
|
@@ -90,14 +92,12 @@ Or
|
|
|
90
92
|
npm install redoc
|
|
91
93
|
```
|
|
92
94
|
|
|
93
|
-
|
|
94
95
|
## Usage
|
|
95
96
|
|
|
96
97
|
### CLI:
|
|
97
98
|
|
|
98
99
|
#### To use the CLI, you need to install this missing packages:
|
|
99
100
|
|
|
100
|
-
|
|
101
101
|
```sh
|
|
102
102
|
npm install cli-progress commander chalk
|
|
103
103
|
```
|
|
@@ -112,7 +112,6 @@ pnpm add cli-progress commander chalk
|
|
|
112
112
|
|
|
113
113
|
#### Then you can use the CLI like this:
|
|
114
114
|
|
|
115
|
-
|
|
116
115
|
```bash
|
|
117
116
|
// Shows the help with all available commands
|
|
118
117
|
|
|
@@ -134,10 +133,9 @@ import cors from "cors";
|
|
|
134
133
|
// You may want to pass in NextApiRequest and NextApiResponse
|
|
135
134
|
const router = createNodeRouter<NextApiRequest, NextApiResponse>();
|
|
136
135
|
|
|
137
|
-
router
|
|
138
|
-
.get((req, res) => {
|
|
136
|
+
router.get((req, res) => {
|
|
139
137
|
res.send("Hello world");
|
|
140
|
-
|
|
138
|
+
});
|
|
141
139
|
|
|
142
140
|
export default router.nodeHandler();
|
|
143
141
|
```
|
|
@@ -169,4 +167,3 @@ The visulima api-platform is open-sourced software licensed under the [MIT][lice
|
|
|
169
167
|
[license-url]: LICENSE.md "license"
|
|
170
168
|
[npm-image]: https://img.shields.io/npm/v/@visulima/api-platform/latest.svg?style=for-the-badge&logo=npm
|
|
171
169
|
[npm-url]: https://www.npmjs.com/package/@visulima/api-platform/v/latest "npm"
|
|
172
|
-
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/framework/next/routes/pages/get-static-properties-swagger.ts"],"names":["debug","swaggerDebug","getStaticProps","swaggerUrl","swaggerData","get_static_properties_swagger_default"],"mappings":"AACA,OAAOA,MAAW,QAKlB,IAAMC,EAAeD,EAAM,6DAA6D,EAGlFE,
|
|
1
|
+
{"version":3,"sources":["../src/framework/next/routes/pages/get-static-properties-swagger.ts"],"names":["debug","swaggerDebug","getStaticProps","swaggerUrl","swaggerData","get_static_properties_swagger_default"],"mappings":"AACA,OAAOA,MAAW,QAKlB,IAAMC,EAAeD,EAAM,6DAA6D,EAGlFE,EAA0DC,GAAe,SAKzE,CAGF,IAAMC,EAAc,MADH,MAAM,MAAMD,CAAU,GACJ,KAAK,EAExC,OAAAF,EAAaG,CAAW,EAEjB,CACH,MAAO,CACH,WAAAD,EACA,YAAa,KAAK,MAAM,KAAK,UAAUC,CAAW,CAAC,CACvD,CACJ,CACJ,EAEOC,EAAQH","sourcesContent":["// eslint-disable-next-line unicorn/prevent-abbreviations\nimport debug from \"debug\";\nimport type { GetStaticProps } from \"next\";\nimport type { OpenAPIV3 } from \"openapi-types\";\n\n// eslint-disable-next-line testing-library/no-debugging-utils\nconst swaggerDebug = debug(\"visulima:api-platform:swagger:get-static-properties-swagger\");\n\n// eslint-disable-next-line unicorn/consistent-function-scoping\nconst getStaticProps: (swaggerUrl: string) => GetStaticProps = (swaggerUrl) => async (): Promise<{\n props: {\n swaggerUrl: string;\n swaggerData: OpenAPIV3.Document;\n };\n}> => {\n // eslint-disable-next-line compat/compat\n const response = await fetch(swaggerUrl);\n const swaggerData = await response.json();\n\n swaggerDebug(swaggerData);\n\n return {\n props: {\n swaggerUrl,\n swaggerData: JSON.parse(JSON.stringify(swaggerData)),\n },\n };\n};\n\nexport default getStaticProps;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/framework/next/routes/pages/get-static-properties-swagger.ts"],"names":["debug","swaggerDebug","getStaticProps","swaggerUrl","swaggerData","get_static_properties_swagger_default"],"mappings":"AACA,OAAOA,MAAW,QAKlB,IAAMC,EAAeD,EAAM,6DAA6D,EAGlFE,
|
|
1
|
+
{"version":3,"sources":["../src/framework/next/routes/pages/get-static-properties-swagger.ts"],"names":["debug","swaggerDebug","getStaticProps","swaggerUrl","swaggerData","get_static_properties_swagger_default"],"mappings":"AACA,OAAOA,MAAW,QAKlB,IAAMC,EAAeD,EAAM,6DAA6D,EAGlFE,EAA0DC,GAAe,SAKzE,CAGF,IAAMC,EAAc,MADH,MAAM,MAAMD,CAAU,GACJ,KAAK,EAExC,OAAAF,EAAaG,CAAW,EAEjB,CACH,MAAO,CACH,WAAAD,EACA,YAAa,KAAK,MAAM,KAAK,UAAUC,CAAW,CAAC,CACvD,CACJ,CACJ,EAEOC,EAAQH","sourcesContent":["// eslint-disable-next-line unicorn/prevent-abbreviations\nimport debug from \"debug\";\nimport type { GetStaticProps } from \"next\";\nimport type { OpenAPIV3 } from \"openapi-types\";\n\n// eslint-disable-next-line testing-library/no-debugging-utils\nconst swaggerDebug = debug(\"visulima:api-platform:swagger:get-static-properties-swagger\");\n\n// eslint-disable-next-line unicorn/consistent-function-scoping\nconst getStaticProps: (swaggerUrl: string) => GetStaticProps = (swaggerUrl) => async (): Promise<{\n props: {\n swaggerUrl: string;\n swaggerData: OpenAPIV3.Document;\n };\n}> => {\n // eslint-disable-next-line compat/compat\n const response = await fetch(swaggerUrl);\n const swaggerData = await response.json();\n\n swaggerDebug(swaggerData);\n\n return {\n props: {\n swaggerUrl,\n swaggerData: JSON.parse(JSON.stringify(swaggerData)),\n },\n };\n};\n\nexport default getStaticProps;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/serializers/transformer/yaml.ts","../src/swagger/api/swagger-handler.ts","../src/swagger/extend-swagger-spec.ts","../src/utils.ts"],"names":["stringify","yamlTransformer","data","yaml_default","modelsToOpenApi","debug","merge","existsSync","readFileSync","path","xml","urlParse","toHeaderCase","string_","c","jsonMediaType","prepareStatusContent","methodSpec","status","mediaType","extendComponentSchemas","spec","schemaName","schema","extendResponseSchema","schemaIsArray","extendSwaggerWithMediaTypeSchema","responseSpec","allowedMediaTypes","pathKey","example","examples","mediaName","contentSpec","allowed","extendSwaggerWithMediaTypeExample","transformers","transformed","regex","transformer","extendComponentExamples","exampleName","prepareResponseExamples","transformedExamples","extendSwaggerWithMediaTypeExamples","examplesName","extendSwaggerSpec","value","pathSpec","swaggerCrudDebug","swaggerHandler","options","swaggerFilePath","crud","specs","request","response","swaggerPath","fileContents","crudSwagger","modelsOpenApi","error","swagger_handler_default"],"mappings":"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","sourcesContent":["import { stringify } from \"yaml\";\n\nimport type { Serializer } from \"../types\";\n\nconst yamlTransformer: Serializer = (data) => stringify(data, { indent: 2 });\n\nexport default yamlTransformer;\n","// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies\nimport type { ModelsToOpenApiParameters, SwaggerModelsConfig } from \"@visulima/crud\";\n// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies\nimport { modelsToOpenApi } from \"@visulima/crud\";\nimport debug from \"debug\";\nimport merge from \"lodash.merge\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport path from \"node:path\";\nimport type { OpenAPIV3 } from \"openapi-types\";\n\nimport yamlTransformer from \"../../serializers/transformer/yaml\";\nimport extendSwaggerSpec from \"../extend-swagger-spec\";\n\n// eslint-disable-next-line testing-library/no-debugging-utils\nconst swaggerCrudDebug = debug(\"visulima:api-platform:swagger:crud:get-static-properties-swagger\");\n\nconst swaggerHandler = <M extends string, PrismaClient>(\n options: Partial<SwaggerHandlerOptions<M, PrismaClient>> = {},\n): ((request: IncomingMessage, response: ServerResponse) => Promise<void>) => {\n const {\n allowedMediaTypes = {\n \"application/json\": true,\n },\n swaggerFilePath,\n crud,\n specs,\n } = options;\n\n return async <Request extends IncomingMessage, Response extends ServerResponse>(request: Request, response: Response) => {\n const swaggerPath = path.join(process.cwd(), swaggerFilePath ?? \"swagger/swagger.json\");\n\n if (!existsSync(swaggerPath)) {\n throw new Error(`Swagger file not found at \"${swaggerPath}\".`);\n }\n\n const fileContents = readFileSync(swaggerPath, \"utf8\");\n\n let spec = extendSwaggerSpec(JSON.parse(fileContents) as OpenAPIV3.Document, allowedMediaTypes) as OpenAPIV3.Document;\n let crudSwagger: Partial<OpenAPIV3.Document> = {};\n\n if (crud !== undefined) {\n try {\n const modelsOpenApi = await modelsToOpenApi(crud);\n\n crudSwagger = {\n components: { schemas: modelsOpenApi.schemas, examples: modelsOpenApi.examples },\n tags: modelsOpenApi.tags,\n paths: modelsOpenApi.paths,\n };\n\n crudSwagger = extendSwaggerSpec(crudSwagger, allowedMediaTypes);\n\n swaggerCrudDebug(JSON.stringify(crudSwagger, null, 2));\n\n spec = merge(spec, crudSwagger);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.log(error);\n\n throw new Error(\"Please install @visulima/crud to use the crud swagger generator.\");\n }\n }\n\n if (Array.isArray(specs)) {\n specs.forEach((value) => {\n spec = merge(spec, extendSwaggerSpec(value, allowedMediaTypes));\n });\n }\n\n let data: Buffer | Uint8Array | string;\n\n if (typeof request.headers.accept === \"string\" && /yaml|yml/.test(request.headers.accept)) {\n response.setHeader(\"Content-Type\", request.headers.accept);\n\n data = yamlTransformer(spec);\n } else {\n response.setHeader(\"Content-Type\", \"application/json\");\n\n data = JSON.stringify(spec, null, 2);\n }\n\n response.statusCode = 200;\n response.end(data);\n };\n};\n\nexport type SwaggerHandlerOptions<M extends string, PrismaClient> = {\n allowedMediaTypes: { [key: string]: boolean };\n swaggerFilePath: string;\n crud: Exclude<ModelsToOpenApiParameters<M, PrismaClient>, \"swagger\"> & {\n swagger?: {\n models?: SwaggerModelsConfig<M>;\n };\n };\n specs?: Partial<OpenAPIV3.Document>[];\n};\n\nexport default swaggerHandler;\n","import type { XmlElement } from \"jstoxml\";\nimport xml from \"jstoxml\";\nimport type { OpenAPIV3 } from \"openapi-types\";\nimport { stringify } from \"yaml\";\n\nimport { toHeaderCase } from \"../utils\";\n\ntype Transformers = { regex: RegExp; transformer: (data: any) => string }[];\n\nconst jsonMediaType = \"application/json\";\n\nconst prepareStatusContent = (methodSpec: OpenAPIV3.OperationObject, status: string, mediaType: string) => {\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content === undefined) {\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content = {};\n }\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType] === undefined) {\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] = {} as OpenAPIV3.MediaTypeObject;\n }\n};\n\nconst extendComponentSchemas = (spec: Partial<OpenAPIV3.Document>, schemaName: string, schema: OpenAPIV3.SchemaObject) => {\n if (typeof spec.components !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components = {};\n }\n\n if (typeof spec.components.schemas !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components.schemas = {};\n }\n\n if (spec.components.schemas[schemaName] === undefined) {\n // eslint-disable-next-line no-param-reassign\n spec.components.schemas[schemaName] = schema;\n }\n};\n\nconst extendResponseSchema = (methodSpec: OpenAPIV3.OperationObject, status: string, mediaType: string, schemaName: string, schemaIsArray: boolean) => {\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.schema === undefined) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).schema = {} as OpenAPIV3.SchemaObject;\n }\n\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).schema = schemaIsArray\n ? {\n type: \"array\",\n items: {\n $ref: `#/components/schemas/${schemaName}`,\n },\n }\n : {\n $ref: `#/components/schemas/${schemaName}`,\n };\n};\n\nconst extendSwaggerWithMediaTypeSchema = (\n methodSpec: OpenAPIV3.OperationObject,\n responseSpec: OpenAPIV3.ResponseObject,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n pathKey: string,\n spec: Partial<OpenAPIV3.Document>,\n status: string,\n): {\n example?: any;\n examples?: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n };\n} => {\n let example: any | undefined;\n let examples:\n | {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n }\n | undefined;\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n Object.entries(responseSpec.content as object).forEach(([mediaName, contentSpec]) => {\n if (typeof contentSpec.schema === \"object\") {\n const { schema } = contentSpec;\n\n if (mediaName === jsonMediaType && contentSpec.examples !== undefined) {\n examples = contentSpec.examples;\n } else if (mediaName === jsonMediaType && contentSpec.example !== undefined) {\n example = contentSpec.example;\n }\n\n const schemaIsArray = (schema as OpenAPIV3.SchemaObject).type === \"array\";\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n let schemaName: string;\n\n if (schema?.$ref === undefined) {\n // eslint-disable-next-line max-len\n schemaName = `${toHeaderCase(pathKey.trim().replace(\"/\", \"\"))}${mediaType === \"application/ld+json\" ? \".jsonld\" : \"\"}`;\n\n extendComponentSchemas(spec as OpenAPIV3.Document, schemaName, schema as OpenAPIV3.SchemaObject);\n } else {\n // eslint-disable-next-line max-len\n schemaName = (schema as OpenAPIV3.ReferenceObject).$ref.replace(\"#/components/schemas/\", \"\");\n }\n\n extendResponseSchema(methodSpec, status, mediaType, schemaName, schemaIsArray);\n });\n }\n });\n\n return { examples, example };\n};\n\nconst extendSwaggerWithMediaTypeExample = (\n methodSpec: OpenAPIV3.OperationObject,\n responseSpec: OpenAPIV3.ResponseObject,\n status: string,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n transformers: Transformers,\n example: any,\n) => {\n Object.keys(responseSpec.content as object).forEach((mediaName) => {\n if (mediaName === jsonMediaType) {\n return;\n }\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.example\n === undefined\n ) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = {};\n }\n\n let transformed: boolean = false;\n\n transformers.forEach(({ regex, transformer }) => {\n if (!transformed && regex.test(mediaType)) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = transformer(example);\n\n transformed = true;\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!transformed) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = example;\n }\n });\n });\n};\n\nconst extendComponentExamples = (\n spec: Partial<OpenAPIV3.Document>,\n exampleName: string,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n) => {\n if (typeof spec.components !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components = {};\n }\n\n if (typeof spec.components.examples !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components.examples = {};\n }\n\n if (spec.components.examples[exampleName] === undefined && examples[exampleName] !== undefined) {\n // eslint-disable-next-line no-param-reassign\n spec.components.examples[exampleName] = examples[exampleName] as OpenAPIV3.ExampleObject;\n }\n};\n\nconst prepareResponseExamples = (\n spec: Partial<OpenAPIV3.Document>,\n methodSpec: OpenAPIV3.OperationObject,\n status: string,\n mediaType: string,\n transformers: Transformers,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n // eslint-disable-next-line sonarjs/cognitive-complexity\n) => {\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.examples === undefined) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).examples = {};\n }\n\n const transformedExamples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n } = {};\n\n Object.entries(examples).forEach(([exampleName, example]) => {\n let transformed: boolean = false;\n\n transformers.forEach(({ regex, transformer }) => {\n if (!transformed && regex.test(mediaType)) {\n let data: any = \"\";\n\n if (spec.components?.examples?.[exampleName]) {\n data = (spec.components.examples[exampleName] as OpenAPIV3.ExampleObject).value;\n } else if ((example as OpenAPIV3.ReferenceObject).$ref) {\n data = (\n spec.components?.examples?.[\n (example as OpenAPIV3.ReferenceObject).$ref.replace(\"#/components/examples/\", \"\")\n ] as OpenAPIV3.ExampleObject\n ).value;\n } else if (typeof (example as OpenAPIV3.ExampleObject).value === \"string\") {\n data = (example as OpenAPIV3.ExampleObject).value;\n }\n\n transformedExamples[exampleName] = {\n value: transformer(data),\n };\n\n transformed = true;\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!transformed) {\n transformedExamples[exampleName] = spec.components?.examples?.[exampleName] === undefined\n ? example\n : {\n $ref: `#/components/examples/${exampleName}`,\n };\n }\n });\n\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).examples = transformedExamples;\n};\n\nconst extendSwaggerWithMediaTypeExamples = (\n spec: Partial<OpenAPIV3.Document>,\n methodSpec: OpenAPIV3.OperationObject,\n status: string,\n responseSpec: OpenAPIV3.ResponseObject,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n pathKey: string,\n transformers: Transformers,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n) => {\n const examplesName = `${toHeaderCase(pathKey.trim().replace(\"/\", \"\"))}`;\n\n Object.keys(responseSpec.content as object).forEach((mediaName) => {\n if (mediaName === jsonMediaType) {\n return;\n }\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n extendComponentExamples(spec, examplesName, examples);\n\n prepareResponseExamples(spec, methodSpec, status, mediaType, transformers, examples);\n });\n });\n};\n\n// eslint-disable-next-line sonarjs/cognitive-complexity\nexport default function extendSwaggerSpec(\n spec: Partial<OpenAPIV3.Document>,\n allowedMediaTypes?: { [key: string]: boolean },\n transformers: Transformers = [\n {\n regex: /xml/,\n transformer: (value: XmlElement | XmlElement[] | undefined) => xml.toXML(value, {\n header: true,\n indent: \" \",\n }),\n },\n {\n regex: /yaml|yml/,\n transformer: (value) => stringify(value, { indent: 2 }),\n },\n ],\n): Partial<OpenAPIV3.Document> {\n if (typeof spec === \"object\" && typeof spec.paths === \"object\") {\n Object.entries(spec.paths).forEach(([pathKey, pathSpec]) => {\n Object.values(pathSpec as OpenAPIV3.OperationObject & OpenAPIV3.PathsObject).forEach((methodSpec) => {\n if (typeof (methodSpec as OpenAPIV3.OperationObject).responses === \"object\") {\n Object.entries((methodSpec as OpenAPIV3.OperationObject).responses).forEach(([status, responseSpec]) => {\n if (typeof (responseSpec as OpenAPIV3.ResponseObject).content === \"object\") {\n const { examples, example } = extendSwaggerWithMediaTypeSchema(\n methodSpec as OpenAPIV3.OperationObject,\n responseSpec as OpenAPIV3.ResponseObject,\n allowedMediaTypes,\n pathKey,\n spec,\n status,\n );\n\n if (example !== undefined) {\n extendSwaggerWithMediaTypeExample(\n methodSpec as OpenAPIV3.OperationObject,\n responseSpec as OpenAPIV3.ResponseObject,\n status,\n allowedMediaTypes,\n transformers,\n example,\n );\n } else if (examples !== undefined) {\n extendSwaggerWithMediaTypeExamples(\n spec,\n methodSpec as OpenAPIV3.OperationObject,\n status,\n responseSpec as OpenAPIV3.ResponseObject,\n allowedMediaTypes,\n pathKey,\n transformers,\n examples,\n );\n }\n }\n });\n }\n });\n });\n }\n\n return spec;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { parse as urlParse } from \"node:url\";\n\ntype IncomingApiRequest<TApiRequest = IncomingMessage> = TApiRequest & {\n body?: any;\n query?: any;\n};\n\nexport const jsonResponse = (response: ServerResponse, status: number, data?: unknown): void => {\n response.statusCode = status;\n response.setHeader(\"Content-Type\", \"application/json\");\n response.end(data ? JSON.stringify(data) : \"\");\n};\n\nexport const parseBody = async (request: IncomingApiRequest): Promise<any> => {\n if (request.body) {\n return request.body;\n }\n\n const buffers = [];\n\n // eslint-disable-next-line no-restricted-syntax\n for await (const chunk of request) {\n buffers.push(chunk);\n }\n\n const data = Buffer.concat(buffers).toString();\n\n return data ? JSON.parse(data) : null;\n};\n\nexport const parseQuery = (request: IncomingApiRequest): unknown => {\n if (request.query) {\n return request.query;\n }\n\n return urlParse(request.url ?? \"\", true).query;\n};\n\nexport const toHeaderCase = (string_: string): string => string_\n .toLowerCase()\n .replaceAll(/[^\\s\\w]/g, \" \") // Remove all non-word characters\n .trimEnd() // Remove trailing spaces\n .replaceAll(/\\s+|_/g, \"-\") // Replace multiple spaces or underline with a single hyphen\n .replaceAll(/\\b\\w/g, (c) => c.toUpperCase());\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/serializers/transformer/yaml.ts","../src/swagger/api/swagger-handler.ts","../src/swagger/extend-swagger-spec.ts","../src/utils.ts"],"names":["stringify","yamlTransformer","data","yaml_default","modelsToOpenApi","debug","merge","existsSync","readFileSync","path","xml","urlParse","toHeaderCase","string_","c","jsonMediaType","prepareStatusContent","methodSpec","status","mediaType","extendComponentSchemas","spec","schemaName","schema","extendResponseSchema","schemaIsArray","extendSwaggerWithMediaTypeSchema","responseSpec","allowedMediaTypes","pathKey","example","examples","mediaName","contentSpec","allowed","extendSwaggerWithMediaTypeExample","transformers","transformed","regex","transformer","extendComponentExamples","exampleName","prepareResponseExamples","transformedExamples","extendSwaggerWithMediaTypeExamples","examplesName","extendSwaggerSpec","value","pathSpec","swaggerCrudDebug","swaggerHandler","options","swaggerFilePath","crud","specs","request","response","swaggerPath","fileContents","crudSwagger","modelsOpenApi","error","swagger_handler_default"],"mappings":"AAAA,OAAS,aAAAA,MAAiB,OAI1B,IAAMC,EAA+BC,GAASF,EAAUE,EAAM,CAAE,OAAQ,CAAE,CAAC,EAEpEC,EAAQF,ECHf,OAAS,mBAAAG,MAAuB,iBAChC,OAAOC,MAAW,QAClB,OAAOC,MAAW,eAClB,OAAS,cAAAC,EAAY,gBAAAC,MAAoB,KAEzC,OAAOC,MAAU,OCPjB,OAAOC,MAAS,UAEhB,OAAS,aAAAV,MAAiB,OCF1B,OAAS,SAASW,MAAgB,MAsC3B,IAAMC,EAAgBC,GAA4BA,EACpD,YAAY,EACZ,WAAW,WAAY,GAAG,EAC1B,QAAQ,EACR,WAAW,SAAU,GAAG,EACxB,WAAW,QAAUC,GAAMA,EAAE,YAAY,CAAC,EDnC/C,IAAMC,EAAgB,mBAEhBC,EAAuB,CAACC,EAAuCC,EAAgBC,IAAsB,CACjGF,EAAW,UAAmDC,CAAM,EAA+B,UAAY,SAE/GD,EAAW,UAAmDC,CAAM,EAA+B,QAAU,CAAC,GAG9GD,EAAW,UAAmDC,CAAM,EAA+B,UAAUC,CAAS,IAAM,SAGxHF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EAAI,CAAC,EAExB,EAEMC,EAAyB,CAACC,EAAmCC,EAAoBC,IAAmC,CAClH,OAAOF,EAAK,YAAe,WAE3BA,EAAK,WAAa,CAAC,GAGnB,OAAOA,EAAK,WAAW,SAAY,WAEnCA,EAAK,WAAW,QAAU,CAAC,GAG3BA,EAAK,WAAW,QAAQC,CAAU,IAAM,SAExCD,EAAK,WAAW,QAAQC,CAAU,EAAIC,EAE9C,EAEMC,EAAuB,CAACP,EAAuCC,EAAgBC,EAAmBG,EAAoBG,IAA2B,CACnJT,EAAqBC,EAAYC,EAAQC,CAAS,EAE5CF,EAAW,UAAmDC,CAAM,EAA+B,UAAUC,CAAS,GAAG,SAAW,SAI5HF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,OAAS,CAAC,GAMNF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,OAASM,EACL,CACE,KAAM,QACN,MAAO,CACH,KAAM,wBAAwBH,GAClC,CACJ,EACE,CACE,KAAM,wBAAwBA,GAClC,CACR,EAEMI,EAAmC,CACrCT,EACAU,EACAC,EACAC,EACAR,EACAH,IAMC,CACD,IAAIY,EACAC,EAOJ,cAAO,QAAQJ,EAAa,OAAiB,EAAE,QAAQ,CAAC,CAACK,EAAWC,CAAW,IAAM,CACjF,GAAI,OAAOA,EAAY,QAAW,SAAU,CACxC,GAAM,CAAE,OAAAV,CAAO,EAAIU,EAEfD,IAAcjB,GAAiBkB,EAAY,WAAa,OACxDF,EAAWE,EAAY,SAChBD,IAAcjB,GAAiBkB,EAAY,UAAY,SAC9DH,EAAUG,EAAY,SAG1B,IAAMR,EAAiBF,EAAkC,OAAS,QAElE,OAAO,QAAQK,GAAqB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAACT,EAAWe,CAAO,IAAM,CACtE,GAAI,CAACA,EACD,OAGJ,IAAIZ,EAEAC,GAAQ,OAAS,QAEjBD,EAAa,GAAGV,EAAaiB,EAAQ,KAAK,EAAE,QAAQ,IAAK,EAAE,CAAC,IAAIV,IAAc,sBAAwB,UAAY,KAElHC,EAAuBC,EAA4BC,EAAYC,CAAgC,GAG/FD,EAAcC,EAAqC,KAAK,QAAQ,wBAAyB,EAAE,EAG/FC,EAAqBP,EAAYC,EAAQC,EAAWG,EAAYG,CAAa,CACjF,CAAC,EAET,CAAC,EAEM,CAAE,SAAAM,EAAU,QAAAD,CAAQ,CAC/B,EAEMK,EAAoC,CACtClB,EACAU,EACAT,EACAU,EACAQ,EACAN,IACC,CACD,OAAO,KAAKH,EAAa,OAAiB,EAAE,QAASK,GAAc,CAC3DA,IAAcjB,GAIlB,OAAO,QAAQa,GAAqB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAACT,EAAWe,CAAO,IAAM,CACtE,GAAI,CAACA,EACD,OAGJlB,EAAqBC,EAAYC,EAAQC,CAAS,EAG5CF,EAAW,UAAmDC,CAAM,EAA+B,UAAUC,CAAS,GAAG,UAAY,SAK7HF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,QAAU,CAAC,GAGjB,IAAIkB,EAAuB,GAE3BD,EAAa,QAAQ,CAAC,CAAE,MAAAE,EAAO,YAAAC,CAAY,IAAM,CACzC,CAACF,GAAeC,EAAM,KAAKnB,CAAS,IAI1BF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,QAAUoB,EAAYT,CAAO,EAE/BO,EAAc,GAEtB,CAAC,EAGIA,IAISpB,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,QAAUW,EAEpB,CAAC,CACL,CAAC,CACL,EAEMU,EAA0B,CAC5BnB,EACAoB,EACAV,IAGC,CACG,OAAOV,EAAK,YAAe,WAE3BA,EAAK,WAAa,CAAC,GAGnB,OAAOA,EAAK,WAAW,UAAa,WAEpCA,EAAK,WAAW,SAAW,CAAC,GAG5BA,EAAK,WAAW,SAASoB,CAAW,IAAM,QAAaV,EAASU,CAAW,IAAM,SAEjFpB,EAAK,WAAW,SAASoB,CAAW,EAAIV,EAASU,CAAW,EAEpE,EAEMC,EAA0B,CAC5BrB,EACAJ,EACAC,EACAC,EACAiB,EACAL,IAIC,CACDf,EAAqBC,EAAYC,EAAQC,CAAS,EAE5CF,EAAW,UAAmDC,CAAM,EAA+B,UAAUC,CAAS,GAAG,WAAa,SAI9HF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,SAAW,CAAC,GAGlB,IAAMwB,EAEF,CAAC,EAEL,OAAO,QAAQZ,CAAQ,EAAE,QAAQ,CAAC,CAACU,EAAaX,CAAO,IAAM,CACzD,IAAIO,EAAuB,GAE3BD,EAAa,QAAQ,CAAC,CAAE,MAAAE,EAAO,YAAAC,CAAY,IAAM,CAC7C,GAAI,CAACF,GAAeC,EAAM,KAAKnB,CAAS,EAAG,CACvC,IAAIjB,EAAY,GAEZmB,EAAK,YAAY,WAAWoB,CAAW,EACvCvC,EAAQmB,EAAK,WAAW,SAASoB,CAAW,EAA8B,MAClEX,EAAsC,KAC9C5B,GACImB,EAAK,YAAY,WACZS,EAAsC,KAAK,QAAQ,yBAA0B,EAAE,CACpF,GACF,MACK,OAAQA,EAAoC,OAAU,WAC7D5B,EAAQ4B,EAAoC,OAGhDa,EAAoBF,CAAW,EAAI,CAC/B,MAAOF,EAAYrC,CAAI,CAC3B,EAEAmC,EAAc,GAEtB,CAAC,EAGIA,IACDM,EAAoBF,CAAW,EAAIpB,EAAK,YAAY,WAAWoB,CAAW,IAAM,OAC1EX,EACA,CACE,KAAM,yBAAyBW,GACnC,EAEZ,CAAC,EAKSxB,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,SAAWwB,CACjB,EAEMC,EAAqC,CACvCvB,EACAJ,EACAC,EACAS,EACAC,EACAC,EACAO,EACAL,IAGC,CACD,IAAMc,EAAe,GAAGjC,EAAaiB,EAAQ,KAAK,EAAE,QAAQ,IAAK,EAAE,CAAC,IAEpE,OAAO,KAAKF,EAAa,OAAiB,EAAE,QAASK,GAAc,CAC3DA,IAAcjB,GAIlB,OAAO,QAAQa,GAAqB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAACT,EAAWe,CAAO,IAAM,CACjEA,IAILM,EAAwBnB,EAAMwB,EAAcd,CAAQ,EAEpDW,EAAwBrB,EAAMJ,EAAYC,EAAQC,EAAWiB,EAAcL,CAAQ,EACvF,CAAC,CACL,CAAC,CACL,EAGe,SAARe,EACHzB,EACAO,EACAQ,EAA6B,CACzB,CACI,MAAO,MACP,YAAcW,GAAiDrC,EAAI,MAAMqC,EAAO,CAC5E,OAAQ,GACR,OAAQ,IACZ,CAAC,CACL,EACA,CACI,MAAO,WACP,YAAcA,GAAU/C,EAAU+C,EAAO,CAAE,OAAQ,CAAE,CAAC,CAC1D,CACJ,EAC2B,CAC3B,OAAI,OAAO1B,GAAS,UAAY,OAAOA,EAAK,OAAU,UAClD,OAAO,QAAQA,EAAK,KAAK,EAAE,QAAQ,CAAC,CAACQ,EAASmB,CAAQ,IAAM,CACxD,OAAO,OAAOA,CAA6D,EAAE,QAAS/B,GAAe,CAC7F,OAAQA,EAAyC,WAAc,UAC/D,OAAO,QAASA,EAAyC,SAAS,EAAE,QAAQ,CAAC,CAACC,EAAQS,CAAY,IAAM,CACpG,GAAI,OAAQA,EAA0C,SAAY,SAAU,CACxE,GAAM,CAAE,SAAAI,EAAU,QAAAD,CAAQ,EAAIJ,EAC1BT,EACAU,EACAC,EACAC,EACAR,EACAH,CACJ,EAEIY,IAAY,OACZK,EACIlB,EACAU,EACAT,EACAU,EACAQ,EACAN,CACJ,EACOC,IAAa,QACpBa,EACIvB,EACAJ,EACAC,EACAS,EACAC,EACAC,EACAO,EACAL,CACJ,EAGZ,CAAC,CAET,CAAC,CACL,CAAC,EAGEV,CACX,CDxXA,IAAM4B,EAAmB5C,EAAM,kEAAkE,EAE3F6C,EAAiB,CACnBC,EAA2D,CAAC,IACc,CAC1E,GAAM,CACF,kBAAAvB,EAAoB,CAChB,mBAAoB,EACxB,EACA,gBAAAwB,EACA,KAAAC,EACA,MAAAC,CACJ,EAAIH,EAEJ,MAAO,OAAyEI,EAAkBC,IAAuB,CACrH,IAAMC,EAAchD,EAAK,KAAK,QAAQ,IAAI,EAAG2C,GAAmB,sBAAsB,EAEtF,GAAI,CAAC7C,EAAWkD,CAAW,EACvB,MAAM,IAAI,MAAM,8BAA8BA,KAAe,EAGjE,IAAMC,EAAelD,EAAaiD,EAAa,MAAM,EAEjDpC,EAAOyB,EAAkB,KAAK,MAAMY,CAAY,EAAyB9B,CAAiB,EAC1F+B,EAA2C,CAAC,EAEhD,GAAIN,IAAS,OACT,GAAI,CACA,IAAMO,EAAgB,MAAMxD,EAAgBiD,CAAI,EAEhDM,EAAc,CACV,WAAY,CAAE,QAASC,EAAc,QAAS,SAAUA,EAAc,QAAS,EAC/E,KAAMA,EAAc,KACpB,MAAOA,EAAc,KACzB,EAEAD,EAAcb,EAAkBa,EAAa/B,CAAiB,EAE9DqB,EAAiB,KAAK,UAAUU,EAAa,KAAM,CAAC,CAAC,EAErDtC,EAAOf,EAAMe,EAAMsC,CAAW,CAClC,OAASE,EAAP,CAEE,cAAQ,IAAIA,CAAK,EAEX,IAAI,MAAM,kEAAkE,CACtF,CAGA,MAAM,QAAQP,CAAK,GACnBA,EAAM,QAASP,GAAU,CACrB1B,EAAOf,EAAMe,EAAMyB,EAAkBC,EAAOnB,CAAiB,CAAC,CAClE,CAAC,EAGL,IAAI1B,EAEA,OAAOqD,EAAQ,QAAQ,QAAW,UAAY,WAAW,KAAKA,EAAQ,QAAQ,MAAM,GACpFC,EAAS,UAAU,eAAgBD,EAAQ,QAAQ,MAAM,EAEzDrD,EAAOC,EAAgBkB,CAAI,IAE3BmC,EAAS,UAAU,eAAgB,kBAAkB,EAErDtD,EAAO,KAAK,UAAUmB,EAAM,KAAM,CAAC,GAGvCmC,EAAS,WAAa,IACtBA,EAAS,IAAItD,CAAI,CACrB,CACJ,EAaO4D,GAAQZ","sourcesContent":["import { stringify } from \"yaml\";\n\nimport type { Serializer } from \"../types\";\n\nconst yamlTransformer: Serializer = (data) => stringify(data, { indent: 2 });\n\nexport default yamlTransformer;\n","// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies\nimport type { ModelsToOpenApiParameters, SwaggerModelsConfig } from \"@visulima/crud\";\n// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies\nimport { modelsToOpenApi } from \"@visulima/crud\";\nimport debug from \"debug\";\nimport merge from \"lodash.merge\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport path from \"node:path\";\nimport type { OpenAPIV3 } from \"openapi-types\";\n\nimport yamlTransformer from \"../../serializers/transformer/yaml\";\nimport extendSwaggerSpec from \"../extend-swagger-spec\";\n\n// eslint-disable-next-line testing-library/no-debugging-utils\nconst swaggerCrudDebug = debug(\"visulima:api-platform:swagger:crud:get-static-properties-swagger\");\n\nconst swaggerHandler = <M extends string, PrismaClient>(\n options: Partial<SwaggerHandlerOptions<M, PrismaClient>> = {},\n): ((request: IncomingMessage, response: ServerResponse) => Promise<void>) => {\n const {\n allowedMediaTypes = {\n \"application/json\": true,\n },\n swaggerFilePath,\n crud,\n specs,\n } = options;\n\n return async <Request extends IncomingMessage, Response extends ServerResponse>(request: Request, response: Response) => {\n const swaggerPath = path.join(process.cwd(), swaggerFilePath ?? \"swagger/swagger.json\");\n\n if (!existsSync(swaggerPath)) {\n throw new Error(`Swagger file not found at \"${swaggerPath}\".`);\n }\n\n const fileContents = readFileSync(swaggerPath, \"utf8\");\n\n let spec = extendSwaggerSpec(JSON.parse(fileContents) as OpenAPIV3.Document, allowedMediaTypes) as OpenAPIV3.Document;\n let crudSwagger: Partial<OpenAPIV3.Document> = {};\n\n if (crud !== undefined) {\n try {\n const modelsOpenApi = await modelsToOpenApi(crud);\n\n crudSwagger = {\n components: { schemas: modelsOpenApi.schemas, examples: modelsOpenApi.examples },\n tags: modelsOpenApi.tags,\n paths: modelsOpenApi.paths,\n };\n\n crudSwagger = extendSwaggerSpec(crudSwagger, allowedMediaTypes);\n\n swaggerCrudDebug(JSON.stringify(crudSwagger, null, 2));\n\n spec = merge(spec, crudSwagger);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.log(error);\n\n throw new Error(\"Please install @visulima/crud to use the crud swagger generator.\");\n }\n }\n\n if (Array.isArray(specs)) {\n specs.forEach((value) => {\n spec = merge(spec, extendSwaggerSpec(value, allowedMediaTypes));\n });\n }\n\n let data: Buffer | Uint8Array | string;\n\n if (typeof request.headers.accept === \"string\" && /yaml|yml/.test(request.headers.accept)) {\n response.setHeader(\"Content-Type\", request.headers.accept);\n\n data = yamlTransformer(spec);\n } else {\n response.setHeader(\"Content-Type\", \"application/json\");\n\n data = JSON.stringify(spec, null, 2);\n }\n\n response.statusCode = 200;\n response.end(data);\n };\n};\n\nexport type SwaggerHandlerOptions<M extends string, PrismaClient> = {\n allowedMediaTypes: { [key: string]: boolean };\n swaggerFilePath: string;\n crud: Exclude<ModelsToOpenApiParameters<M, PrismaClient>, \"swagger\"> & {\n swagger?: {\n models?: SwaggerModelsConfig<M>;\n };\n };\n specs?: Partial<OpenAPIV3.Document>[];\n};\n\nexport default swaggerHandler;\n","import type { XmlElement } from \"jstoxml\";\nimport xml from \"jstoxml\";\nimport type { OpenAPIV3 } from \"openapi-types\";\nimport { stringify } from \"yaml\";\n\nimport { toHeaderCase } from \"../utils\";\n\ntype Transformers = { regex: RegExp; transformer: (data: any) => string }[];\n\nconst jsonMediaType = \"application/json\";\n\nconst prepareStatusContent = (methodSpec: OpenAPIV3.OperationObject, status: string, mediaType: string) => {\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content === undefined) {\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content = {};\n }\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType] === undefined) {\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] = {} as OpenAPIV3.MediaTypeObject;\n }\n};\n\nconst extendComponentSchemas = (spec: Partial<OpenAPIV3.Document>, schemaName: string, schema: OpenAPIV3.SchemaObject) => {\n if (typeof spec.components !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components = {};\n }\n\n if (typeof spec.components.schemas !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components.schemas = {};\n }\n\n if (spec.components.schemas[schemaName] === undefined) {\n // eslint-disable-next-line no-param-reassign\n spec.components.schemas[schemaName] = schema;\n }\n};\n\nconst extendResponseSchema = (methodSpec: OpenAPIV3.OperationObject, status: string, mediaType: string, schemaName: string, schemaIsArray: boolean) => {\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.schema === undefined) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).schema = {} as OpenAPIV3.SchemaObject;\n }\n\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).schema = schemaIsArray\n ? {\n type: \"array\",\n items: {\n $ref: `#/components/schemas/${schemaName}`,\n },\n }\n : {\n $ref: `#/components/schemas/${schemaName}`,\n };\n};\n\nconst extendSwaggerWithMediaTypeSchema = (\n methodSpec: OpenAPIV3.OperationObject,\n responseSpec: OpenAPIV3.ResponseObject,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n pathKey: string,\n spec: Partial<OpenAPIV3.Document>,\n status: string,\n): {\n example?: any;\n examples?: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n };\n} => {\n let example: any | undefined;\n let examples:\n | {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n }\n | undefined;\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n Object.entries(responseSpec.content as object).forEach(([mediaName, contentSpec]) => {\n if (typeof contentSpec.schema === \"object\") {\n const { schema } = contentSpec;\n\n if (mediaName === jsonMediaType && contentSpec.examples !== undefined) {\n examples = contentSpec.examples;\n } else if (mediaName === jsonMediaType && contentSpec.example !== undefined) {\n example = contentSpec.example;\n }\n\n const schemaIsArray = (schema as OpenAPIV3.SchemaObject).type === \"array\";\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n let schemaName: string;\n\n if (schema?.$ref === undefined) {\n // eslint-disable-next-line max-len\n schemaName = `${toHeaderCase(pathKey.trim().replace(\"/\", \"\"))}${mediaType === \"application/ld+json\" ? \".jsonld\" : \"\"}`;\n\n extendComponentSchemas(spec as OpenAPIV3.Document, schemaName, schema as OpenAPIV3.SchemaObject);\n } else {\n // eslint-disable-next-line max-len\n schemaName = (schema as OpenAPIV3.ReferenceObject).$ref.replace(\"#/components/schemas/\", \"\");\n }\n\n extendResponseSchema(methodSpec, status, mediaType, schemaName, schemaIsArray);\n });\n }\n });\n\n return { examples, example };\n};\n\nconst extendSwaggerWithMediaTypeExample = (\n methodSpec: OpenAPIV3.OperationObject,\n responseSpec: OpenAPIV3.ResponseObject,\n status: string,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n transformers: Transformers,\n example: any,\n) => {\n Object.keys(responseSpec.content as object).forEach((mediaName) => {\n if (mediaName === jsonMediaType) {\n return;\n }\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.example === undefined\n ) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = {};\n }\n\n let transformed: boolean = false;\n\n transformers.forEach(({ regex, transformer }) => {\n if (!transformed && regex.test(mediaType)) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = transformer(example);\n\n transformed = true;\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!transformed) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = example;\n }\n });\n });\n};\n\nconst extendComponentExamples = (\n spec: Partial<OpenAPIV3.Document>,\n exampleName: string,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n) => {\n if (typeof spec.components !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components = {};\n }\n\n if (typeof spec.components.examples !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components.examples = {};\n }\n\n if (spec.components.examples[exampleName] === undefined && examples[exampleName] !== undefined) {\n // eslint-disable-next-line no-param-reassign\n spec.components.examples[exampleName] = examples[exampleName] as OpenAPIV3.ExampleObject;\n }\n};\n\nconst prepareResponseExamples = (\n spec: Partial<OpenAPIV3.Document>,\n methodSpec: OpenAPIV3.OperationObject,\n status: string,\n mediaType: string,\n transformers: Transformers,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n // eslint-disable-next-line sonarjs/cognitive-complexity\n) => {\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.examples === undefined) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).examples = {};\n }\n\n const transformedExamples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n } = {};\n\n Object.entries(examples).forEach(([exampleName, example]) => {\n let transformed: boolean = false;\n\n transformers.forEach(({ regex, transformer }) => {\n if (!transformed && regex.test(mediaType)) {\n let data: any = \"\";\n\n if (spec.components?.examples?.[exampleName]) {\n data = (spec.components.examples[exampleName] as OpenAPIV3.ExampleObject).value;\n } else if ((example as OpenAPIV3.ReferenceObject).$ref) {\n data = (\n spec.components?.examples?.[\n (example as OpenAPIV3.ReferenceObject).$ref.replace(\"#/components/examples/\", \"\")\n ] as OpenAPIV3.ExampleObject\n ).value;\n } else if (typeof (example as OpenAPIV3.ExampleObject).value === \"string\") {\n data = (example as OpenAPIV3.ExampleObject).value;\n }\n\n transformedExamples[exampleName] = {\n value: transformer(data),\n };\n\n transformed = true;\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!transformed) {\n transformedExamples[exampleName] = spec.components?.examples?.[exampleName] === undefined\n ? example\n : {\n $ref: `#/components/examples/${exampleName}`,\n };\n }\n });\n\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).examples = transformedExamples;\n};\n\nconst extendSwaggerWithMediaTypeExamples = (\n spec: Partial<OpenAPIV3.Document>,\n methodSpec: OpenAPIV3.OperationObject,\n status: string,\n responseSpec: OpenAPIV3.ResponseObject,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n pathKey: string,\n transformers: Transformers,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n) => {\n const examplesName = `${toHeaderCase(pathKey.trim().replace(\"/\", \"\"))}`;\n\n Object.keys(responseSpec.content as object).forEach((mediaName) => {\n if (mediaName === jsonMediaType) {\n return;\n }\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n extendComponentExamples(spec, examplesName, examples);\n\n prepareResponseExamples(spec, methodSpec, status, mediaType, transformers, examples);\n });\n });\n};\n\n// eslint-disable-next-line sonarjs/cognitive-complexity\nexport default function extendSwaggerSpec(\n spec: Partial<OpenAPIV3.Document>,\n allowedMediaTypes?: { [key: string]: boolean },\n transformers: Transformers = [\n {\n regex: /xml/,\n transformer: (value: XmlElement | XmlElement[] | undefined) => xml.toXML(value, {\n header: true,\n indent: \" \",\n }),\n },\n {\n regex: /yaml|yml/,\n transformer: (value) => stringify(value, { indent: 2 }),\n },\n ],\n): Partial<OpenAPIV3.Document> {\n if (typeof spec === \"object\" && typeof spec.paths === \"object\") {\n Object.entries(spec.paths).forEach(([pathKey, pathSpec]) => {\n Object.values(pathSpec as OpenAPIV3.OperationObject & OpenAPIV3.PathsObject).forEach((methodSpec) => {\n if (typeof (methodSpec as OpenAPIV3.OperationObject).responses === \"object\") {\n Object.entries((methodSpec as OpenAPIV3.OperationObject).responses).forEach(([status, responseSpec]) => {\n if (typeof (responseSpec as OpenAPIV3.ResponseObject).content === \"object\") {\n const { examples, example } = extendSwaggerWithMediaTypeSchema(\n methodSpec as OpenAPIV3.OperationObject,\n responseSpec as OpenAPIV3.ResponseObject,\n allowedMediaTypes,\n pathKey,\n spec,\n status,\n );\n\n if (example !== undefined) {\n extendSwaggerWithMediaTypeExample(\n methodSpec as OpenAPIV3.OperationObject,\n responseSpec as OpenAPIV3.ResponseObject,\n status,\n allowedMediaTypes,\n transformers,\n example,\n );\n } else if (examples !== undefined) {\n extendSwaggerWithMediaTypeExamples(\n spec,\n methodSpec as OpenAPIV3.OperationObject,\n status,\n responseSpec as OpenAPIV3.ResponseObject,\n allowedMediaTypes,\n pathKey,\n transformers,\n examples,\n );\n }\n }\n });\n }\n });\n });\n }\n\n return spec;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { parse as urlParse } from \"node:url\";\n\ntype IncomingApiRequest<TApiRequest = IncomingMessage> = TApiRequest & {\n body?: any;\n query?: any;\n};\n\nexport const jsonResponse = (response: ServerResponse, status: number, data?: unknown): void => {\n response.statusCode = status;\n response.setHeader(\"Content-Type\", \"application/json\");\n response.end(data ? JSON.stringify(data) : \"\");\n};\n\nexport const parseBody = async (request: IncomingApiRequest): Promise<any> => {\n if (request.body) {\n return request.body;\n }\n\n const buffers = [];\n\n // eslint-disable-next-line no-restricted-syntax\n for await (const chunk of request) {\n buffers.push(chunk);\n }\n\n const data = Buffer.concat(buffers).toString();\n\n return data ? JSON.parse(data) : null;\n};\n\nexport const parseQuery = (request: IncomingApiRequest): unknown => {\n if (request.query) {\n return request.query;\n }\n\n return urlParse(request.url ?? \"\", true).query;\n};\n\nexport const toHeaderCase = (string_: string): string => string_\n .toLowerCase()\n .replaceAll(/[^\\s\\w]/g, \" \") // Remove all non-word characters\n .trimEnd() // Remove trailing spaces\n .replaceAll(/\\s+|_/g, \"-\") // Replace multiple spaces or underline with a single hyphen\n .replaceAll(/\\b\\w/g, (c) => c.toUpperCase());\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/serializers/transformer/yaml.ts","../src/swagger/api/swagger-handler.ts","../src/swagger/extend-swagger-spec.ts","../src/utils.ts"],"names":["stringify","yamlTransformer","data","yaml_default","modelsToOpenApi","debug","merge","existsSync","readFileSync","path","xml","toHeaderCase","string_","c","jsonMediaType","prepareStatusContent","methodSpec","status","mediaType","extendComponentSchemas","spec","schemaName","schema","extendResponseSchema","schemaIsArray","extendSwaggerWithMediaTypeSchema","responseSpec","allowedMediaTypes","pathKey","example","examples","mediaName","contentSpec","allowed","extendSwaggerWithMediaTypeExample","transformers","transformed","regex","transformer","extendComponentExamples","exampleName","prepareResponseExamples","transformedExamples","extendSwaggerWithMediaTypeExamples","examplesName","extendSwaggerSpec","value","pathSpec","swaggerCrudDebug","swaggerHandler","options","swaggerFilePath","crud","specs","request","response","swaggerPath","fileContents","crudSwagger","modelsOpenApi","error","swagger_handler_default"],"mappings":"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","sourcesContent":["import { stringify } from \"yaml\";\n\nimport type { Serializer } from \"../types\";\n\nconst yamlTransformer: Serializer = (data) => stringify(data, { indent: 2 });\n\nexport default yamlTransformer;\n","// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies\nimport type { ModelsToOpenApiParameters, SwaggerModelsConfig } from \"@visulima/crud\";\n// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies\nimport { modelsToOpenApi } from \"@visulima/crud\";\nimport debug from \"debug\";\nimport merge from \"lodash.merge\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport path from \"node:path\";\nimport type { OpenAPIV3 } from \"openapi-types\";\n\nimport yamlTransformer from \"../../serializers/transformer/yaml\";\nimport extendSwaggerSpec from \"../extend-swagger-spec\";\n\n// eslint-disable-next-line testing-library/no-debugging-utils\nconst swaggerCrudDebug = debug(\"visulima:api-platform:swagger:crud:get-static-properties-swagger\");\n\nconst swaggerHandler = <M extends string, PrismaClient>(\n options: Partial<SwaggerHandlerOptions<M, PrismaClient>> = {},\n): ((request: IncomingMessage, response: ServerResponse) => Promise<void>) => {\n const {\n allowedMediaTypes = {\n \"application/json\": true,\n },\n swaggerFilePath,\n crud,\n specs,\n } = options;\n\n return async <Request extends IncomingMessage, Response extends ServerResponse>(request: Request, response: Response) => {\n const swaggerPath = path.join(process.cwd(), swaggerFilePath ?? \"swagger/swagger.json\");\n\n if (!existsSync(swaggerPath)) {\n throw new Error(`Swagger file not found at \"${swaggerPath}\".`);\n }\n\n const fileContents = readFileSync(swaggerPath, \"utf8\");\n\n let spec = extendSwaggerSpec(JSON.parse(fileContents) as OpenAPIV3.Document, allowedMediaTypes) as OpenAPIV3.Document;\n let crudSwagger: Partial<OpenAPIV3.Document> = {};\n\n if (crud !== undefined) {\n try {\n const modelsOpenApi = await modelsToOpenApi(crud);\n\n crudSwagger = {\n components: { schemas: modelsOpenApi.schemas, examples: modelsOpenApi.examples },\n tags: modelsOpenApi.tags,\n paths: modelsOpenApi.paths,\n };\n\n crudSwagger = extendSwaggerSpec(crudSwagger, allowedMediaTypes);\n\n swaggerCrudDebug(JSON.stringify(crudSwagger, null, 2));\n\n spec = merge(spec, crudSwagger);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.log(error);\n\n throw new Error(\"Please install @visulima/crud to use the crud swagger generator.\");\n }\n }\n\n if (Array.isArray(specs)) {\n specs.forEach((value) => {\n spec = merge(spec, extendSwaggerSpec(value, allowedMediaTypes));\n });\n }\n\n let data: Buffer | Uint8Array | string;\n\n if (typeof request.headers.accept === \"string\" && /yaml|yml/.test(request.headers.accept)) {\n response.setHeader(\"Content-Type\", request.headers.accept);\n\n data = yamlTransformer(spec);\n } else {\n response.setHeader(\"Content-Type\", \"application/json\");\n\n data = JSON.stringify(spec, null, 2);\n }\n\n response.statusCode = 200;\n response.end(data);\n };\n};\n\nexport type SwaggerHandlerOptions<M extends string, PrismaClient> = {\n allowedMediaTypes: { [key: string]: boolean };\n swaggerFilePath: string;\n crud: Exclude<ModelsToOpenApiParameters<M, PrismaClient>, \"swagger\"> & {\n swagger?: {\n models?: SwaggerModelsConfig<M>;\n };\n };\n specs?: Partial<OpenAPIV3.Document>[];\n};\n\nexport default swaggerHandler;\n","import type { XmlElement } from \"jstoxml\";\nimport xml from \"jstoxml\";\nimport type { OpenAPIV3 } from \"openapi-types\";\nimport { stringify } from \"yaml\";\n\nimport { toHeaderCase } from \"../utils\";\n\ntype Transformers = { regex: RegExp; transformer: (data: any) => string }[];\n\nconst jsonMediaType = \"application/json\";\n\nconst prepareStatusContent = (methodSpec: OpenAPIV3.OperationObject, status: string, mediaType: string) => {\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content === undefined) {\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content = {};\n }\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType] === undefined) {\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] = {} as OpenAPIV3.MediaTypeObject;\n }\n};\n\nconst extendComponentSchemas = (spec: Partial<OpenAPIV3.Document>, schemaName: string, schema: OpenAPIV3.SchemaObject) => {\n if (typeof spec.components !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components = {};\n }\n\n if (typeof spec.components.schemas !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components.schemas = {};\n }\n\n if (spec.components.schemas[schemaName] === undefined) {\n // eslint-disable-next-line no-param-reassign\n spec.components.schemas[schemaName] = schema;\n }\n};\n\nconst extendResponseSchema = (methodSpec: OpenAPIV3.OperationObject, status: string, mediaType: string, schemaName: string, schemaIsArray: boolean) => {\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.schema === undefined) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).schema = {} as OpenAPIV3.SchemaObject;\n }\n\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).schema = schemaIsArray\n ? {\n type: \"array\",\n items: {\n $ref: `#/components/schemas/${schemaName}`,\n },\n }\n : {\n $ref: `#/components/schemas/${schemaName}`,\n };\n};\n\nconst extendSwaggerWithMediaTypeSchema = (\n methodSpec: OpenAPIV3.OperationObject,\n responseSpec: OpenAPIV3.ResponseObject,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n pathKey: string,\n spec: Partial<OpenAPIV3.Document>,\n status: string,\n): {\n example?: any;\n examples?: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n };\n} => {\n let example: any | undefined;\n let examples:\n | {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n }\n | undefined;\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n Object.entries(responseSpec.content as object).forEach(([mediaName, contentSpec]) => {\n if (typeof contentSpec.schema === \"object\") {\n const { schema } = contentSpec;\n\n if (mediaName === jsonMediaType && contentSpec.examples !== undefined) {\n examples = contentSpec.examples;\n } else if (mediaName === jsonMediaType && contentSpec.example !== undefined) {\n example = contentSpec.example;\n }\n\n const schemaIsArray = (schema as OpenAPIV3.SchemaObject).type === \"array\";\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n let schemaName: string;\n\n if (schema?.$ref === undefined) {\n // eslint-disable-next-line max-len\n schemaName = `${toHeaderCase(pathKey.trim().replace(\"/\", \"\"))}${mediaType === \"application/ld+json\" ? \".jsonld\" : \"\"}`;\n\n extendComponentSchemas(spec as OpenAPIV3.Document, schemaName, schema as OpenAPIV3.SchemaObject);\n } else {\n // eslint-disable-next-line max-len\n schemaName = (schema as OpenAPIV3.ReferenceObject).$ref.replace(\"#/components/schemas/\", \"\");\n }\n\n extendResponseSchema(methodSpec, status, mediaType, schemaName, schemaIsArray);\n });\n }\n });\n\n return { examples, example };\n};\n\nconst extendSwaggerWithMediaTypeExample = (\n methodSpec: OpenAPIV3.OperationObject,\n responseSpec: OpenAPIV3.ResponseObject,\n status: string,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n transformers: Transformers,\n example: any,\n) => {\n Object.keys(responseSpec.content as object).forEach((mediaName) => {\n if (mediaName === jsonMediaType) {\n return;\n }\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.example\n === undefined\n ) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = {};\n }\n\n let transformed: boolean = false;\n\n transformers.forEach(({ regex, transformer }) => {\n if (!transformed && regex.test(mediaType)) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = transformer(example);\n\n transformed = true;\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!transformed) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = example;\n }\n });\n });\n};\n\nconst extendComponentExamples = (\n spec: Partial<OpenAPIV3.Document>,\n exampleName: string,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n) => {\n if (typeof spec.components !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components = {};\n }\n\n if (typeof spec.components.examples !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components.examples = {};\n }\n\n if (spec.components.examples[exampleName] === undefined && examples[exampleName] !== undefined) {\n // eslint-disable-next-line no-param-reassign\n spec.components.examples[exampleName] = examples[exampleName] as OpenAPIV3.ExampleObject;\n }\n};\n\nconst prepareResponseExamples = (\n spec: Partial<OpenAPIV3.Document>,\n methodSpec: OpenAPIV3.OperationObject,\n status: string,\n mediaType: string,\n transformers: Transformers,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n // eslint-disable-next-line sonarjs/cognitive-complexity\n) => {\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.examples === undefined) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).examples = {};\n }\n\n const transformedExamples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n } = {};\n\n Object.entries(examples).forEach(([exampleName, example]) => {\n let transformed: boolean = false;\n\n transformers.forEach(({ regex, transformer }) => {\n if (!transformed && regex.test(mediaType)) {\n let data: any = \"\";\n\n if (spec.components?.examples?.[exampleName]) {\n data = (spec.components.examples[exampleName] as OpenAPIV3.ExampleObject).value;\n } else if ((example as OpenAPIV3.ReferenceObject).$ref) {\n data = (\n spec.components?.examples?.[\n (example as OpenAPIV3.ReferenceObject).$ref.replace(\"#/components/examples/\", \"\")\n ] as OpenAPIV3.ExampleObject\n ).value;\n } else if (typeof (example as OpenAPIV3.ExampleObject).value === \"string\") {\n data = (example as OpenAPIV3.ExampleObject).value;\n }\n\n transformedExamples[exampleName] = {\n value: transformer(data),\n };\n\n transformed = true;\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!transformed) {\n transformedExamples[exampleName] = spec.components?.examples?.[exampleName] === undefined\n ? example\n : {\n $ref: `#/components/examples/${exampleName}`,\n };\n }\n });\n\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).examples = transformedExamples;\n};\n\nconst extendSwaggerWithMediaTypeExamples = (\n spec: Partial<OpenAPIV3.Document>,\n methodSpec: OpenAPIV3.OperationObject,\n status: string,\n responseSpec: OpenAPIV3.ResponseObject,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n pathKey: string,\n transformers: Transformers,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n) => {\n const examplesName = `${toHeaderCase(pathKey.trim().replace(\"/\", \"\"))}`;\n\n Object.keys(responseSpec.content as object).forEach((mediaName) => {\n if (mediaName === jsonMediaType) {\n return;\n }\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n extendComponentExamples(spec, examplesName, examples);\n\n prepareResponseExamples(spec, methodSpec, status, mediaType, transformers, examples);\n });\n });\n};\n\n// eslint-disable-next-line sonarjs/cognitive-complexity\nexport default function extendSwaggerSpec(\n spec: Partial<OpenAPIV3.Document>,\n allowedMediaTypes?: { [key: string]: boolean },\n transformers: Transformers = [\n {\n regex: /xml/,\n transformer: (value: XmlElement | XmlElement[] | undefined) => xml.toXML(value, {\n header: true,\n indent: \" \",\n }),\n },\n {\n regex: /yaml|yml/,\n transformer: (value) => stringify(value, { indent: 2 }),\n },\n ],\n): Partial<OpenAPIV3.Document> {\n if (typeof spec === \"object\" && typeof spec.paths === \"object\") {\n Object.entries(spec.paths).forEach(([pathKey, pathSpec]) => {\n Object.values(pathSpec as OpenAPIV3.OperationObject & OpenAPIV3.PathsObject).forEach((methodSpec) => {\n if (typeof (methodSpec as OpenAPIV3.OperationObject).responses === \"object\") {\n Object.entries((methodSpec as OpenAPIV3.OperationObject).responses).forEach(([status, responseSpec]) => {\n if (typeof (responseSpec as OpenAPIV3.ResponseObject).content === \"object\") {\n const { examples, example } = extendSwaggerWithMediaTypeSchema(\n methodSpec as OpenAPIV3.OperationObject,\n responseSpec as OpenAPIV3.ResponseObject,\n allowedMediaTypes,\n pathKey,\n spec,\n status,\n );\n\n if (example !== undefined) {\n extendSwaggerWithMediaTypeExample(\n methodSpec as OpenAPIV3.OperationObject,\n responseSpec as OpenAPIV3.ResponseObject,\n status,\n allowedMediaTypes,\n transformers,\n example,\n );\n } else if (examples !== undefined) {\n extendSwaggerWithMediaTypeExamples(\n spec,\n methodSpec as OpenAPIV3.OperationObject,\n status,\n responseSpec as OpenAPIV3.ResponseObject,\n allowedMediaTypes,\n pathKey,\n transformers,\n examples,\n );\n }\n }\n });\n }\n });\n });\n }\n\n return spec;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { parse as urlParse } from \"node:url\";\n\ntype IncomingApiRequest<TApiRequest = IncomingMessage> = TApiRequest & {\n body?: any;\n query?: any;\n};\n\nexport const jsonResponse = (response: ServerResponse, status: number, data?: unknown): void => {\n response.statusCode = status;\n response.setHeader(\"Content-Type\", \"application/json\");\n response.end(data ? JSON.stringify(data) : \"\");\n};\n\nexport const parseBody = async (request: IncomingApiRequest): Promise<any> => {\n if (request.body) {\n return request.body;\n }\n\n const buffers = [];\n\n // eslint-disable-next-line no-restricted-syntax\n for await (const chunk of request) {\n buffers.push(chunk);\n }\n\n const data = Buffer.concat(buffers).toString();\n\n return data ? JSON.parse(data) : null;\n};\n\nexport const parseQuery = (request: IncomingApiRequest): unknown => {\n if (request.query) {\n return request.query;\n }\n\n return urlParse(request.url ?? \"\", true).query;\n};\n\nexport const toHeaderCase = (string_: string): string => string_\n .toLowerCase()\n .replaceAll(/[^\\s\\w]/g, \" \") // Remove all non-word characters\n .trimEnd() // Remove trailing spaces\n .replaceAll(/\\s+|_/g, \"-\") // Replace multiple spaces or underline with a single hyphen\n .replaceAll(/\\b\\w/g, (c) => c.toUpperCase());\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/serializers/transformer/yaml.ts","../src/swagger/api/swagger-handler.ts","../src/swagger/extend-swagger-spec.ts","../src/utils.ts"],"names":["stringify","yamlTransformer","data","yaml_default","modelsToOpenApi","debug","merge","existsSync","readFileSync","path","xml","toHeaderCase","string_","c","jsonMediaType","prepareStatusContent","methodSpec","status","mediaType","extendComponentSchemas","spec","schemaName","schema","extendResponseSchema","schemaIsArray","extendSwaggerWithMediaTypeSchema","responseSpec","allowedMediaTypes","pathKey","example","examples","mediaName","contentSpec","allowed","extendSwaggerWithMediaTypeExample","transformers","transformed","regex","transformer","extendComponentExamples","exampleName","prepareResponseExamples","transformedExamples","extendSwaggerWithMediaTypeExamples","examplesName","extendSwaggerSpec","value","pathSpec","swaggerCrudDebug","swaggerHandler","options","swaggerFilePath","crud","specs","request","response","swaggerPath","fileContents","crudSwagger","modelsOpenApi","error","swagger_handler_default"],"mappings":"AAAA,OAAS,aAAAA,MAAiB,OAI1B,IAAMC,EAA+BC,GAASF,EAAUE,EAAM,CAAE,OAAQ,CAAE,CAAC,EAEpEC,EAAQF,ECHf,OAAS,mBAAAG,MAAuB,iBAChC,OAAOC,MAAW,QAClB,OAAOC,MAAW,eAClB,OAAS,cAAAC,EAAY,gBAAAC,MAAoB,KAEzC,OAAOC,MAAU,OCPjB,OAAOC,MAAS,UAEhB,OAAS,aAAAV,MAAiB,OCoCnB,IAAMW,EAAgBC,GAA4BA,EACpD,YAAY,EACZ,WAAW,WAAY,GAAG,EAC1B,QAAQ,EACR,WAAW,SAAU,GAAG,EACxB,WAAW,QAAUC,GAAMA,EAAE,YAAY,CAAC,EDnC/C,IAAMC,EAAgB,mBAEhBC,EAAuB,CAACC,EAAuCC,EAAgBC,IAAsB,CACjGF,EAAW,UAAmDC,CAAM,EAA+B,UAAY,SAE/GD,EAAW,UAAmDC,CAAM,EAA+B,QAAU,CAAC,GAG9GD,EAAW,UAAmDC,CAAM,EAA+B,UAAUC,CAAS,IAAM,SAGxHF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EAAI,CAAC,EAExB,EAEMC,EAAyB,CAACC,EAAmCC,EAAoBC,IAAmC,CAClH,OAAOF,EAAK,YAAe,WAE3BA,EAAK,WAAa,CAAC,GAGnB,OAAOA,EAAK,WAAW,SAAY,WAEnCA,EAAK,WAAW,QAAU,CAAC,GAG3BA,EAAK,WAAW,QAAQC,CAAU,IAAM,SAExCD,EAAK,WAAW,QAAQC,CAAU,EAAIC,EAE9C,EAEMC,EAAuB,CAACP,EAAuCC,EAAgBC,EAAmBG,EAAoBG,IAA2B,CACnJT,EAAqBC,EAAYC,EAAQC,CAAS,EAE5CF,EAAW,UAAmDC,CAAM,EAA+B,UAAUC,CAAS,GAAG,SAAW,SAI5HF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,OAAS,CAAC,GAMNF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,OAASM,EACL,CACE,KAAM,QACN,MAAO,CACH,KAAM,wBAAwBH,GAClC,CACJ,EACE,CACE,KAAM,wBAAwBA,GAClC,CACR,EAEMI,EAAmC,CACrCT,EACAU,EACAC,EACAC,EACAR,EACAH,IAMC,CACD,IAAIY,EACAC,EAOJ,cAAO,QAAQJ,EAAa,OAAiB,EAAE,QAAQ,CAAC,CAACK,EAAWC,CAAW,IAAM,CACjF,GAAI,OAAOA,EAAY,QAAW,SAAU,CACxC,GAAM,CAAE,OAAAV,CAAO,EAAIU,EAEfD,IAAcjB,GAAiBkB,EAAY,WAAa,OACxDF,EAAWE,EAAY,SAChBD,IAAcjB,GAAiBkB,EAAY,UAAY,SAC9DH,EAAUG,EAAY,SAG1B,IAAMR,EAAiBF,EAAkC,OAAS,QAElE,OAAO,QAAQK,GAAqB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAACT,EAAWe,CAAO,IAAM,CACtE,GAAI,CAACA,EACD,OAGJ,IAAIZ,EAEAC,GAAQ,OAAS,QAEjBD,EAAa,GAAGV,EAAaiB,EAAQ,KAAK,EAAE,QAAQ,IAAK,EAAE,CAAC,IAAIV,IAAc,sBAAwB,UAAY,KAElHC,EAAuBC,EAA4BC,EAAYC,CAAgC,GAG/FD,EAAcC,EAAqC,KAAK,QAAQ,wBAAyB,EAAE,EAG/FC,EAAqBP,EAAYC,EAAQC,EAAWG,EAAYG,CAAa,CACjF,CAAC,EAET,CAAC,EAEM,CAAE,SAAAM,EAAU,QAAAD,CAAQ,CAC/B,EAEMK,EAAoC,CACtClB,EACAU,EACAT,EACAU,EACAQ,EACAN,IACC,CACD,OAAO,KAAKH,EAAa,OAAiB,EAAE,QAASK,GAAc,CAC3DA,IAAcjB,GAIlB,OAAO,QAAQa,GAAqB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAACT,EAAWe,CAAO,IAAM,CACtE,GAAI,CAACA,EACD,OAGJlB,EAAqBC,EAAYC,EAAQC,CAAS,EAG5CF,EAAW,UAAmDC,CAAM,EAA+B,UAAUC,CAAS,GAAG,UAAY,SAK7HF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,QAAU,CAAC,GAGjB,IAAIkB,EAAuB,GAE3BD,EAAa,QAAQ,CAAC,CAAE,MAAAE,EAAO,YAAAC,CAAY,IAAM,CACzC,CAACF,GAAeC,EAAM,KAAKnB,CAAS,IAI1BF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,QAAUoB,EAAYT,CAAO,EAE/BO,EAAc,GAEtB,CAAC,EAGIA,IAISpB,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,QAAUW,EAEpB,CAAC,CACL,CAAC,CACL,EAEMU,EAA0B,CAC5BnB,EACAoB,EACAV,IAGC,CACG,OAAOV,EAAK,YAAe,WAE3BA,EAAK,WAAa,CAAC,GAGnB,OAAOA,EAAK,WAAW,UAAa,WAEpCA,EAAK,WAAW,SAAW,CAAC,GAG5BA,EAAK,WAAW,SAASoB,CAAW,IAAM,QAAaV,EAASU,CAAW,IAAM,SAEjFpB,EAAK,WAAW,SAASoB,CAAW,EAAIV,EAASU,CAAW,EAEpE,EAEMC,EAA0B,CAC5BrB,EACAJ,EACAC,EACAC,EACAiB,EACAL,IAIC,CACDf,EAAqBC,EAAYC,EAAQC,CAAS,EAE5CF,EAAW,UAAmDC,CAAM,EAA+B,UAAUC,CAAS,GAAG,WAAa,SAI9HF,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,SAAW,CAAC,GAGlB,IAAMwB,EAEF,CAAC,EAEL,OAAO,QAAQZ,CAAQ,EAAE,QAAQ,CAAC,CAACU,EAAaX,CAAO,IAAM,CACzD,IAAIO,EAAuB,GAE3BD,EAAa,QAAQ,CAAC,CAAE,MAAAE,EAAO,YAAAC,CAAY,IAAM,CAC7C,GAAI,CAACF,GAAeC,EAAM,KAAKnB,CAAS,EAAG,CACvC,IAAIhB,EAAY,GAEZkB,EAAK,YAAY,WAAWoB,CAAW,EACvCtC,EAAQkB,EAAK,WAAW,SAASoB,CAAW,EAA8B,MAClEX,EAAsC,KAC9C3B,GACIkB,EAAK,YAAY,WACZS,EAAsC,KAAK,QAAQ,yBAA0B,EAAE,CACpF,GACF,MACK,OAAQA,EAAoC,OAAU,WAC7D3B,EAAQ2B,EAAoC,OAGhDa,EAAoBF,CAAW,EAAI,CAC/B,MAAOF,EAAYpC,CAAI,CAC3B,EAEAkC,EAAc,GAEtB,CAAC,EAGIA,IACDM,EAAoBF,CAAW,EAAIpB,EAAK,YAAY,WAAWoB,CAAW,IAAM,OAC1EX,EACA,CACE,KAAM,yBAAyBW,GACnC,EAEZ,CAAC,EAKSxB,EAAW,UAAmDC,CAAM,EAA+B,QAGvGC,CAAS,EACb,SAAWwB,CACjB,EAEMC,EAAqC,CACvCvB,EACAJ,EACAC,EACAS,EACAC,EACAC,EACAO,EACAL,IAGC,CACD,IAAMc,EAAe,GAAGjC,EAAaiB,EAAQ,KAAK,EAAE,QAAQ,IAAK,EAAE,CAAC,IAEpE,OAAO,KAAKF,EAAa,OAAiB,EAAE,QAASK,GAAc,CAC3DA,IAAcjB,GAIlB,OAAO,QAAQa,GAAqB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAACT,EAAWe,CAAO,IAAM,CACjEA,IAILM,EAAwBnB,EAAMwB,EAAcd,CAAQ,EAEpDW,EAAwBrB,EAAMJ,EAAYC,EAAQC,EAAWiB,EAAcL,CAAQ,EACvF,CAAC,CACL,CAAC,CACL,EAGe,SAARe,EACHzB,EACAO,EACAQ,EAA6B,CACzB,CACI,MAAO,MACP,YAAcW,GAAiDpC,EAAI,MAAMoC,EAAO,CAC5E,OAAQ,GACR,OAAQ,IACZ,CAAC,CACL,EACA,CACI,MAAO,WACP,YAAcA,GAAU9C,EAAU8C,EAAO,CAAE,OAAQ,CAAE,CAAC,CAC1D,CACJ,EAC2B,CAC3B,OAAI,OAAO1B,GAAS,UAAY,OAAOA,EAAK,OAAU,UAClD,OAAO,QAAQA,EAAK,KAAK,EAAE,QAAQ,CAAC,CAACQ,EAASmB,CAAQ,IAAM,CACxD,OAAO,OAAOA,CAA6D,EAAE,QAAS/B,GAAe,CAC7F,OAAQA,EAAyC,WAAc,UAC/D,OAAO,QAASA,EAAyC,SAAS,EAAE,QAAQ,CAAC,CAACC,EAAQS,CAAY,IAAM,CACpG,GAAI,OAAQA,EAA0C,SAAY,SAAU,CACxE,GAAM,CAAE,SAAAI,EAAU,QAAAD,CAAQ,EAAIJ,EAC1BT,EACAU,EACAC,EACAC,EACAR,EACAH,CACJ,EAEIY,IAAY,OACZK,EACIlB,EACAU,EACAT,EACAU,EACAQ,EACAN,CACJ,EACOC,IAAa,QACpBa,EACIvB,EACAJ,EACAC,EACAS,EACAC,EACAC,EACAO,EACAL,CACJ,EAGZ,CAAC,CAET,CAAC,CACL,CAAC,EAGEV,CACX,CDxXA,IAAM4B,EAAmB3C,EAAM,kEAAkE,EAE3F4C,EAAiB,CACnBC,EAA2D,CAAC,IACc,CAC1E,GAAM,CACF,kBAAAvB,EAAoB,CAChB,mBAAoB,EACxB,EACA,gBAAAwB,EACA,KAAAC,EACA,MAAAC,CACJ,EAAIH,EAEJ,MAAO,OAAyEI,EAAkBC,IAAuB,CACrH,IAAMC,EAAc/C,EAAK,KAAK,QAAQ,IAAI,EAAG0C,GAAmB,sBAAsB,EAEtF,GAAI,CAAC5C,EAAWiD,CAAW,EACvB,MAAM,IAAI,MAAM,8BAA8BA,KAAe,EAGjE,IAAMC,EAAejD,EAAagD,EAAa,MAAM,EAEjDpC,EAAOyB,EAAkB,KAAK,MAAMY,CAAY,EAAyB9B,CAAiB,EAC1F+B,EAA2C,CAAC,EAEhD,GAAIN,IAAS,OACT,GAAI,CACA,IAAMO,EAAgB,MAAMvD,EAAgBgD,CAAI,EAEhDM,EAAc,CACV,WAAY,CAAE,QAASC,EAAc,QAAS,SAAUA,EAAc,QAAS,EAC/E,KAAMA,EAAc,KACpB,MAAOA,EAAc,KACzB,EAEAD,EAAcb,EAAkBa,EAAa/B,CAAiB,EAE9DqB,EAAiB,KAAK,UAAUU,EAAa,KAAM,CAAC,CAAC,EAErDtC,EAAOd,EAAMc,EAAMsC,CAAW,CAClC,OAASE,EAAP,CAEE,cAAQ,IAAIA,CAAK,EAEX,IAAI,MAAM,kEAAkE,CACtF,CAGA,MAAM,QAAQP,CAAK,GACnBA,EAAM,QAASP,GAAU,CACrB1B,EAAOd,EAAMc,EAAMyB,EAAkBC,EAAOnB,CAAiB,CAAC,CAClE,CAAC,EAGL,IAAIzB,EAEA,OAAOoD,EAAQ,QAAQ,QAAW,UAAY,WAAW,KAAKA,EAAQ,QAAQ,MAAM,GACpFC,EAAS,UAAU,eAAgBD,EAAQ,QAAQ,MAAM,EAEzDpD,EAAOC,EAAgBiB,CAAI,IAE3BmC,EAAS,UAAU,eAAgB,kBAAkB,EAErDrD,EAAO,KAAK,UAAUkB,EAAM,KAAM,CAAC,GAGvCmC,EAAS,WAAa,IACtBA,EAAS,IAAIrD,CAAI,CACrB,CACJ,EAaO2D,EAAQZ","sourcesContent":["import { stringify } from \"yaml\";\n\nimport type { Serializer } from \"../types\";\n\nconst yamlTransformer: Serializer = (data) => stringify(data, { indent: 2 });\n\nexport default yamlTransformer;\n","// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies\nimport type { ModelsToOpenApiParameters, SwaggerModelsConfig } from \"@visulima/crud\";\n// eslint-disable-next-line unicorn/prevent-abbreviations,import/no-extraneous-dependencies\nimport { modelsToOpenApi } from \"@visulima/crud\";\nimport debug from \"debug\";\nimport merge from \"lodash.merge\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport path from \"node:path\";\nimport type { OpenAPIV3 } from \"openapi-types\";\n\nimport yamlTransformer from \"../../serializers/transformer/yaml\";\nimport extendSwaggerSpec from \"../extend-swagger-spec\";\n\n// eslint-disable-next-line testing-library/no-debugging-utils\nconst swaggerCrudDebug = debug(\"visulima:api-platform:swagger:crud:get-static-properties-swagger\");\n\nconst swaggerHandler = <M extends string, PrismaClient>(\n options: Partial<SwaggerHandlerOptions<M, PrismaClient>> = {},\n): ((request: IncomingMessage, response: ServerResponse) => Promise<void>) => {\n const {\n allowedMediaTypes = {\n \"application/json\": true,\n },\n swaggerFilePath,\n crud,\n specs,\n } = options;\n\n return async <Request extends IncomingMessage, Response extends ServerResponse>(request: Request, response: Response) => {\n const swaggerPath = path.join(process.cwd(), swaggerFilePath ?? \"swagger/swagger.json\");\n\n if (!existsSync(swaggerPath)) {\n throw new Error(`Swagger file not found at \"${swaggerPath}\".`);\n }\n\n const fileContents = readFileSync(swaggerPath, \"utf8\");\n\n let spec = extendSwaggerSpec(JSON.parse(fileContents) as OpenAPIV3.Document, allowedMediaTypes) as OpenAPIV3.Document;\n let crudSwagger: Partial<OpenAPIV3.Document> = {};\n\n if (crud !== undefined) {\n try {\n const modelsOpenApi = await modelsToOpenApi(crud);\n\n crudSwagger = {\n components: { schemas: modelsOpenApi.schemas, examples: modelsOpenApi.examples },\n tags: modelsOpenApi.tags,\n paths: modelsOpenApi.paths,\n };\n\n crudSwagger = extendSwaggerSpec(crudSwagger, allowedMediaTypes);\n\n swaggerCrudDebug(JSON.stringify(crudSwagger, null, 2));\n\n spec = merge(spec, crudSwagger);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.log(error);\n\n throw new Error(\"Please install @visulima/crud to use the crud swagger generator.\");\n }\n }\n\n if (Array.isArray(specs)) {\n specs.forEach((value) => {\n spec = merge(spec, extendSwaggerSpec(value, allowedMediaTypes));\n });\n }\n\n let data: Buffer | Uint8Array | string;\n\n if (typeof request.headers.accept === \"string\" && /yaml|yml/.test(request.headers.accept)) {\n response.setHeader(\"Content-Type\", request.headers.accept);\n\n data = yamlTransformer(spec);\n } else {\n response.setHeader(\"Content-Type\", \"application/json\");\n\n data = JSON.stringify(spec, null, 2);\n }\n\n response.statusCode = 200;\n response.end(data);\n };\n};\n\nexport type SwaggerHandlerOptions<M extends string, PrismaClient> = {\n allowedMediaTypes: { [key: string]: boolean };\n swaggerFilePath: string;\n crud: Exclude<ModelsToOpenApiParameters<M, PrismaClient>, \"swagger\"> & {\n swagger?: {\n models?: SwaggerModelsConfig<M>;\n };\n };\n specs?: Partial<OpenAPIV3.Document>[];\n};\n\nexport default swaggerHandler;\n","import type { XmlElement } from \"jstoxml\";\nimport xml from \"jstoxml\";\nimport type { OpenAPIV3 } from \"openapi-types\";\nimport { stringify } from \"yaml\";\n\nimport { toHeaderCase } from \"../utils\";\n\ntype Transformers = { regex: RegExp; transformer: (data: any) => string }[];\n\nconst jsonMediaType = \"application/json\";\n\nconst prepareStatusContent = (methodSpec: OpenAPIV3.OperationObject, status: string, mediaType: string) => {\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content === undefined) {\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content = {};\n }\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType] === undefined) {\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] = {} as OpenAPIV3.MediaTypeObject;\n }\n};\n\nconst extendComponentSchemas = (spec: Partial<OpenAPIV3.Document>, schemaName: string, schema: OpenAPIV3.SchemaObject) => {\n if (typeof spec.components !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components = {};\n }\n\n if (typeof spec.components.schemas !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components.schemas = {};\n }\n\n if (spec.components.schemas[schemaName] === undefined) {\n // eslint-disable-next-line no-param-reassign\n spec.components.schemas[schemaName] = schema;\n }\n};\n\nconst extendResponseSchema = (methodSpec: OpenAPIV3.OperationObject, status: string, mediaType: string, schemaName: string, schemaIsArray: boolean) => {\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.schema === undefined) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).schema = {} as OpenAPIV3.SchemaObject;\n }\n\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).schema = schemaIsArray\n ? {\n type: \"array\",\n items: {\n $ref: `#/components/schemas/${schemaName}`,\n },\n }\n : {\n $ref: `#/components/schemas/${schemaName}`,\n };\n};\n\nconst extendSwaggerWithMediaTypeSchema = (\n methodSpec: OpenAPIV3.OperationObject,\n responseSpec: OpenAPIV3.ResponseObject,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n pathKey: string,\n spec: Partial<OpenAPIV3.Document>,\n status: string,\n): {\n example?: any;\n examples?: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n };\n} => {\n let example: any | undefined;\n let examples:\n | {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n }\n | undefined;\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n Object.entries(responseSpec.content as object).forEach(([mediaName, contentSpec]) => {\n if (typeof contentSpec.schema === \"object\") {\n const { schema } = contentSpec;\n\n if (mediaName === jsonMediaType && contentSpec.examples !== undefined) {\n examples = contentSpec.examples;\n } else if (mediaName === jsonMediaType && contentSpec.example !== undefined) {\n example = contentSpec.example;\n }\n\n const schemaIsArray = (schema as OpenAPIV3.SchemaObject).type === \"array\";\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n let schemaName: string;\n\n if (schema?.$ref === undefined) {\n // eslint-disable-next-line max-len\n schemaName = `${toHeaderCase(pathKey.trim().replace(\"/\", \"\"))}${mediaType === \"application/ld+json\" ? \".jsonld\" : \"\"}`;\n\n extendComponentSchemas(spec as OpenAPIV3.Document, schemaName, schema as OpenAPIV3.SchemaObject);\n } else {\n // eslint-disable-next-line max-len\n schemaName = (schema as OpenAPIV3.ReferenceObject).$ref.replace(\"#/components/schemas/\", \"\");\n }\n\n extendResponseSchema(methodSpec, status, mediaType, schemaName, schemaIsArray);\n });\n }\n });\n\n return { examples, example };\n};\n\nconst extendSwaggerWithMediaTypeExample = (\n methodSpec: OpenAPIV3.OperationObject,\n responseSpec: OpenAPIV3.ResponseObject,\n status: string,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n transformers: Transformers,\n example: any,\n) => {\n Object.keys(responseSpec.content as object).forEach((mediaName) => {\n if (mediaName === jsonMediaType) {\n return;\n }\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.example === undefined\n ) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = {};\n }\n\n let transformed: boolean = false;\n\n transformers.forEach(({ regex, transformer }) => {\n if (!transformed && regex.test(mediaType)) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = transformer(example);\n\n transformed = true;\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!transformed) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).example = example;\n }\n });\n });\n};\n\nconst extendComponentExamples = (\n spec: Partial<OpenAPIV3.Document>,\n exampleName: string,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n) => {\n if (typeof spec.components !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components = {};\n }\n\n if (typeof spec.components.examples !== \"object\") {\n // eslint-disable-next-line no-param-reassign\n spec.components.examples = {};\n }\n\n if (spec.components.examples[exampleName] === undefined && examples[exampleName] !== undefined) {\n // eslint-disable-next-line no-param-reassign\n spec.components.examples[exampleName] = examples[exampleName] as OpenAPIV3.ExampleObject;\n }\n};\n\nconst prepareResponseExamples = (\n spec: Partial<OpenAPIV3.Document>,\n methodSpec: OpenAPIV3.OperationObject,\n status: string,\n mediaType: string,\n transformers: Transformers,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n // eslint-disable-next-line sonarjs/cognitive-complexity\n) => {\n prepareStatusContent(methodSpec, status, mediaType);\n\n if (((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content?.[mediaType]?.examples === undefined) {\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).examples = {};\n }\n\n const transformedExamples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n } = {};\n\n Object.entries(examples).forEach(([exampleName, example]) => {\n let transformed: boolean = false;\n\n transformers.forEach(({ regex, transformer }) => {\n if (!transformed && regex.test(mediaType)) {\n let data: any = \"\";\n\n if (spec.components?.examples?.[exampleName]) {\n data = (spec.components.examples[exampleName] as OpenAPIV3.ExampleObject).value;\n } else if ((example as OpenAPIV3.ReferenceObject).$ref) {\n data = (\n spec.components?.examples?.[\n (example as OpenAPIV3.ReferenceObject).$ref.replace(\"#/components/examples/\", \"\")\n ] as OpenAPIV3.ExampleObject\n ).value;\n } else if (typeof (example as OpenAPIV3.ExampleObject).value === \"string\") {\n data = (example as OpenAPIV3.ExampleObject).value;\n }\n\n transformedExamples[exampleName] = {\n value: transformer(data),\n };\n\n transformed = true;\n }\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!transformed) {\n transformedExamples[exampleName] = spec.components?.examples?.[exampleName] === undefined\n ? example\n : {\n $ref: `#/components/examples/${exampleName}`,\n };\n }\n });\n\n (\n (\n // eslint-disable-next-line no-param-reassign\n ((methodSpec.responses as unknown as OpenAPIV3.ResponsesObject)[status] as OpenAPIV3.ResponseObject).content as {\n [key: string]: OpenAPIV3.MediaTypeObject;\n }\n )[mediaType] as OpenAPIV3.MediaTypeObject\n ).examples = transformedExamples;\n};\n\nconst extendSwaggerWithMediaTypeExamples = (\n spec: Partial<OpenAPIV3.Document>,\n methodSpec: OpenAPIV3.OperationObject,\n status: string,\n responseSpec: OpenAPIV3.ResponseObject,\n allowedMediaTypes: { [p: string]: boolean } | undefined,\n pathKey: string,\n transformers: Transformers,\n examples: {\n [media: string]: OpenAPIV3.ExampleObject | OpenAPIV3.ReferenceObject;\n },\n) => {\n const examplesName = `${toHeaderCase(pathKey.trim().replace(\"/\", \"\"))}`;\n\n Object.keys(responseSpec.content as object).forEach((mediaName) => {\n if (mediaName === jsonMediaType) {\n return;\n }\n\n Object.entries(allowedMediaTypes ?? {}).forEach(([mediaType, allowed]) => {\n if (!allowed) {\n return;\n }\n\n extendComponentExamples(spec, examplesName, examples);\n\n prepareResponseExamples(spec, methodSpec, status, mediaType, transformers, examples);\n });\n });\n};\n\n// eslint-disable-next-line sonarjs/cognitive-complexity\nexport default function extendSwaggerSpec(\n spec: Partial<OpenAPIV3.Document>,\n allowedMediaTypes?: { [key: string]: boolean },\n transformers: Transformers = [\n {\n regex: /xml/,\n transformer: (value: XmlElement | XmlElement[] | undefined) => xml.toXML(value, {\n header: true,\n indent: \" \",\n }),\n },\n {\n regex: /yaml|yml/,\n transformer: (value) => stringify(value, { indent: 2 }),\n },\n ],\n): Partial<OpenAPIV3.Document> {\n if (typeof spec === \"object\" && typeof spec.paths === \"object\") {\n Object.entries(spec.paths).forEach(([pathKey, pathSpec]) => {\n Object.values(pathSpec as OpenAPIV3.OperationObject & OpenAPIV3.PathsObject).forEach((methodSpec) => {\n if (typeof (methodSpec as OpenAPIV3.OperationObject).responses === \"object\") {\n Object.entries((methodSpec as OpenAPIV3.OperationObject).responses).forEach(([status, responseSpec]) => {\n if (typeof (responseSpec as OpenAPIV3.ResponseObject).content === \"object\") {\n const { examples, example } = extendSwaggerWithMediaTypeSchema(\n methodSpec as OpenAPIV3.OperationObject,\n responseSpec as OpenAPIV3.ResponseObject,\n allowedMediaTypes,\n pathKey,\n spec,\n status,\n );\n\n if (example !== undefined) {\n extendSwaggerWithMediaTypeExample(\n methodSpec as OpenAPIV3.OperationObject,\n responseSpec as OpenAPIV3.ResponseObject,\n status,\n allowedMediaTypes,\n transformers,\n example,\n );\n } else if (examples !== undefined) {\n extendSwaggerWithMediaTypeExamples(\n spec,\n methodSpec as OpenAPIV3.OperationObject,\n status,\n responseSpec as OpenAPIV3.ResponseObject,\n allowedMediaTypes,\n pathKey,\n transformers,\n examples,\n );\n }\n }\n });\n }\n });\n });\n }\n\n return spec;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { parse as urlParse } from \"node:url\";\n\ntype IncomingApiRequest<TApiRequest = IncomingMessage> = TApiRequest & {\n body?: any;\n query?: any;\n};\n\nexport const jsonResponse = (response: ServerResponse, status: number, data?: unknown): void => {\n response.statusCode = status;\n response.setHeader(\"Content-Type\", \"application/json\");\n response.end(data ? JSON.stringify(data) : \"\");\n};\n\nexport const parseBody = async (request: IncomingApiRequest): Promise<any> => {\n if (request.body) {\n return request.body;\n }\n\n const buffers = [];\n\n // eslint-disable-next-line no-restricted-syntax\n for await (const chunk of request) {\n buffers.push(chunk);\n }\n\n const data = Buffer.concat(buffers).toString();\n\n return data ? JSON.parse(data) : null;\n};\n\nexport const parseQuery = (request: IncomingApiRequest): unknown => {\n if (request.query) {\n return request.query;\n }\n\n return urlParse(request.url ?? \"\", true).query;\n};\n\nexport const toHeaderCase = (string_: string): string => string_\n .toLowerCase()\n .replaceAll(/[^\\s\\w]/g, \" \") // Remove all non-word characters\n .trimEnd() // Remove trailing spaces\n .replaceAll(/\\s+|_/g, \"-\") // Replace multiple spaces or underline with a single hyphen\n .replaceAll(/\\b\\w/g, (c) => c.toUpperCase());\n"]}
|
|
@@ -4,21 +4,21 @@ var u = require('chalk');
|
|
|
4
4
|
var child_process = require('child_process');
|
|
5
5
|
var fs = require('fs');
|
|
6
6
|
var path = require('path');
|
|
7
|
-
var
|
|
7
|
+
var d = require('process');
|
|
8
8
|
var jsdocOpenApi = require('@visulima/jsdoc-open-api');
|
|
9
9
|
var readdir = require('@visulima/readdir');
|
|
10
10
|
|
|
11
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
12
|
|
|
13
13
|
var u__default = /*#__PURE__*/_interopDefault(u);
|
|
14
|
-
var
|
|
14
|
+
var d__default = /*#__PURE__*/_interopDefault(d);
|
|
15
15
|
|
|
16
16
|
var Y=(e,o)=>{if(o.length===0)throw new Error("must include atleast one key to map");let t=e.toString();return o.forEach(r=>{t=r.optional?t.replace("(?:\\/([^\\/]+?))?\\",`/:${r.name}?`):t.replace("(?:([^\\/]+?))",`:${r.name}`);}),t.replace("/?(?=\\/|$)/i","").replace("/^","").replaceAll(/\\/gi,"").replaceAll(/\/{2,}/gi,"/")},P=Y;var z=(e,o)=>{if(typeof e=="string")return e;if(e.fast_slash)return "";if(e.fast_star)return "*";let t="";o.length>0&&(t=P(e,o));let r=/^\/\^((?:\\[$()*+./?[\\\]^{|}]|[^$()*+./?[\\\]^{|}])*)\$\//.exec(e.toString().replace("\\/?","").replace("(?=\\/|$)","$"));return Array.isArray(r)&&r.length>1?r[1].replaceAll(/\\(.)/g,"$1").slice(1):t?t.slice(1):e.toString()},S=z;var Q=(e,o,t)=>{let r=e.route.stack.at(-1),a=o.map(i=>({name:i.name,in:"path",required:!i.optional})),s=e.route.stack.filter(i=>i?.handle?.metadata);if(s.length>1)throw new Error("Only one metadata middleware is allowed per route");let n=(t+e.route.path).replaceAll(/\/{2,}/gi,"/");return s.length===0?{path:n,pathParams:a,method:r.method}:{path:n,pathParams:a,method:r.method,metadata:s[0].handle.metadata}},T=(e,o,t,r)=>{r=[...r,...t.keys],t.name==="router"&&t.handle&&t.handle.stack.forEach(a=>{o=o||"",T(e,`${o}/${S(t.regexp,t.keys)}`,a,r);}),!(!t.route||t.route.stack.length===0)&&e.push(Q(t,r,o));},V=e=>{let o=e._router||e.router,t=[];return o.stack.forEach(r=>{T(t,"",r,[]);}),t},k=V;var Z=e=>{let o=[];return k(e).forEach(t=>{o.push({path:t.path,method:t.method.toUpperCase(),tags:[],file:"unknown"});}),o},D=Z;var $=e=>e.replaceAll(/ \(.*\)/g,"").trim(),j=e=>e.trim().split(" ")[1].slice(1,-1),ee=e=>{let t=e.printRoutes().replaceAll(/[─│└├]/g," ").trimEnd().split(`
|
|
17
|
-
`),r=t.reduce((s,n,i)=>{let p=$(n);if($(t[i-1]??"")===p){let X=s.filter(A=>A.index<i&&A.segment===p),{methods:w}=X.at(-1);return w!==null&&w.push(j(n)),s}let l=n.replaceAll(/ \(.*\)/g,"").match(/ /g);if(l===null)throw new Error("Invalid spaces");let f=l.length/4,m=n.includes("("),
|
|
18
|
-
`),console.log(f),fs.rmSync(path.join(a,"framework-list"),{recursive:!0});}let c=i?path.join(a,"framework-list",r.replace(a,"").replace(".ts",".js")):r,{default:l}=await import(c);s=await E(["AsyncFunction","Function"].includes(l.constructor.name)?await l():H(l,e),e,t.verbose??!1);}finally{i&&fs.rmSync(path.join(a,"framework-list"),{recursive:!0});}}if(s===null)throw new Error(`Framework "${e}" is not supported.`);if(Array.isArray(t.includePaths)&&t.includePaths.length>0&&(s=t.includePaths.flatMap(n=>s.filter(i=>i.path.startsWith(n)))),Array.isArray(t.excludePaths)&&t.excludePaths.length>0&&(s=t.excludePaths.flatMap(n=>s.filter(i=>!i.path.startsWith(n)))),typeof t.group=="string"&&t.group!==""){console.log();let n=B(s,p=>t.group==="path"?p.path.replace("/pages","").split("/")[1]:p.tags[0]??"unsorted"),i=0;n.forEach((p,c)=>{i>0&&console.log();let l=(
|
|
17
|
+
`),r=t.reduce((s,n,i)=>{let p=$(n);if($(t[i-1]??"")===p){let X=s.filter(A=>A.index<i&&A.segment===p),{methods:w}=X.at(-1);return w!==null&&w.push(j(n)),s}let l=n.replaceAll(/ \(.*\)/g,"").match(/ /g);if(l===null)throw new Error("Invalid spaces");let f=l.length/4,m=n.includes("("),y=m?[j(n)]:null;return s.push({segment:p,index:i,depth:f,isRoute:m,methods:y}),s},[]),a=[];return r.filter(s=>s.isRoute).forEach(s=>{let i=[...r.filter(p=>p.index<s.index&&p.depth<s.depth).filter((p,c,l)=>!l.find(f=>f.depth===p.depth&&f.index>p.index)).map(p=>p.segment),s.segment].join("");if(s.methods===null)throw new Error("Invalid methods");s.methods.forEach(p=>{a.push({path:i,method:p.toUpperCase(),tags:[],file:"unknown"});});}),a},O=ee;var te=e=>{let t=e._core.router.routes,r=[];return [...t.keys()].forEach(a=>{t.get(a).routes.forEach(s=>{r.push({path:s.path,method:s.route.method.toUpperCase(),tags:[],file:"unknown"});});}),r},v=te;var re=e=>{let o=[];return e.middleware.filter(t=>t.router).flatMap(t=>t.router.stack).forEach(t=>{o.push({path:t.path,method:t.methods.join("|").toUpperCase(),tags:[],file:"unknown"});}),o},b=re;var C=/\.(js|ts|mjs|cjs)$/,ae=(e,o,t=!1)=>{let r=[],a=jsdocOpenApi.parseFile(e,jsdocOpenApi.jsDocumentCommentsToOpenApi,t);r=[...r,...a.map(i=>i.spec)];let s=jsdocOpenApi.parseFile(e,jsdocOpenApi.swaggerJsDocumentCommentsToOpenApi,t);r=[...r,...s.map(i=>i.spec)];let n=[];return r.length===0?(fs.readFileSync(e,"utf8").split(/\r?\n/).forEach(p=>{let c=/[=aces|]+\s["'|](GET|POST|PUT|PATCH|HEAD|DELETE|OPTIONS)["'|]/.exec(p);if(c){let[,l]=c;l==="GET"&&(l="GET|HEAD"),n.push({method:l,path:e.replace(o,"").replace(C,"").replaceAll("\\","/"),tags:[],file:e.replace(`${d__default.default.cwd()}${d__default.default.platform==="win32"?"\\":"/"}`,"")});}}),n.length===0&&n.push({method:"GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS",path:e.replace(o,"").replace(C,"").replaceAll("\\","/"),tags:[],file:e.replace(`${d__default.default.cwd()}${d__default.default.platform==="win32"?"\\":"/"}`,"")}),n):(r.forEach(i=>{Object.entries(i.paths).forEach(([c,l])=>{Object.entries(l).forEach(([m,y])=>{n.push({path:c.replaceAll("\\","/"),method:m.toUpperCase(),tags:y.tags,file:e.replace(`${d__default.default.cwd()}${d__default.default.platform==="win32"?"\\":"/"}`,"")});});});}),n)},L=ae;var g=[".js",".ts",".mjs",".cjs"],M=e=>{let o=path.parse(e);for(;o.base&&o.root!==o.dir;){if(fs.readdirSync(o.dir).find(a=>a==="package.json"))return o.dir;o=path.parse(o.dir);}return null},I=e=>{let o=`${e}/package.json`,t=JSON.parse(fs.readFileSync(o).toString()),{dependencies:r}=t;return r.express?"express":r.koa&&(r["@koa/router"]||r["koa-router"])?"koa":r.next?"next":r["@hapi/hapi"]?"hapi":r.fastify?"fastify":null},H=(e,o)=>Object.keys(e).length===0?null:o==="hapi"?typeof e.app?.app=="string"?e.app:e:e.app??e;var G=e=>{try{return fs.statSync(e).isDirectory()}catch{return !1}},ue=async(e="",o=!1)=>{let t=path.join(e,"pages/api");return !G(t)&&(t=path.join(e,"src/pages/api"),!G(t))?[]:readdir.collect(t,{extensions:g,includeDirs:!1,minimatchOptions:{match:{debug:o,matchBase:!0},skip:{debug:o,matchBase:!0}}})},_=ue;async function E(e,o,t){if(o==="express")return D(e);if(o==="koa")return b(e);if(o==="hapi")return v(e);if(o==="fastify")return O(e);if(o==="next"){let r=await _(e,t);if(r.length===0)throw new Error(`No API routes found, in "${e}".`);return r.flatMap(a=>L(a,e,t))}return null}var fe=(e,o)=>{let t=new Map;return e.forEach(r=>{let a=o(r),s=t.get(a);s?s.push(r):t.set(a,[r]);}),t},B=fe;var me=(e,o)=>{let t={GET:u__default.default.blue,POST:u__default.default.yellow,PATCH:u__default.default.yellow,PUT:u__default.default.yellow,DELETE:u__default.default.redBright,OPTIONS:u__default.default.hex("#6C7280"),ANY:u__default.default.redBright,HEAD:u__default.default.hex("#6C7280")},r;if(e==="GET|HEAD")r=`${u__default.default.blue("GET")}${u__default.default.grey("|HEAD")}`;else {let c=t[e](e);r=e==="GET"?`${c}${u__default.default.grey("|HEAD")}`:c;}let a=e==="GET"?6:14-e.length,s=Array.from({length:a}).fill(" ").join(""),n=process.stdout.columns-16-o.length-4,i=n>0?Array.from({length:n}).fill(".").join(""):"",p=o.split("/").map(c=>["[",":"].includes(c[0]??"")?u__default.default.yellowBright(c):c).join("/");return ` ${r}${s}${p}${u__default.default.grey(i)}`},de=(e,o={})=>e.map(t=>{if(!(Array.isArray(o.methods)&&o.methods.includes(t.method)))return t.method==="GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS"&&(t.method="ANY"),me(t.method,t.path.replace("/pages",""))}).filter(Boolean),x=de;var ye=async(e,o,t={})=>{let r=path.join(d__default.default.cwd(),o);if(!fs.existsSync(r))throw new Error("No such file, invalid path provided.");let a=M(r);if(!a)throw new Error("Please initialize local package.json.");if(e===void 0){let n=I(a);if(!n)throw new Error("Couldn't detect supported back-end framework.");e=n;}let s=null;if(e==="next")s=await E(r,"next",t.verbose??!1);else {if(!fs.statSync(r).isFile())throw new Error(`${r} is directory, but file expected.`);if(!g.includes(path.extname(r)))throw new Error("Please specify application .ts/.js/.mjs/.cjs file.");let n=`${a}/.env`;fs.existsSync(n)&&(await import(`${a}/node_modules/dotenv/lib/main.js`)).config({path:n});let i=path.extname(r)===".ts",p=path.join(a,"node_modules/.bin/tsc");if(i&&!fs.existsSync(p))throw new Error(`Please install typescript in ${a}`);try{if(i)try{child_process.execSync(`${p} --outDir framework-list >&2`,{cwd:a});}catch(f){console.log(`TSC compilation failed. Please resolve issues in your project.
|
|
18
|
+
`),console.log(f),fs.rmSync(path.join(a,"framework-list"),{recursive:!0});}let c=i?path.join(a,"framework-list",r.replace(a,"").replace(".ts",".js")):r,{default:l}=await import(c);s=await E(["AsyncFunction","Function"].includes(l.constructor.name)?await l():H(l,e),e,t.verbose??!1);}finally{i&&fs.rmSync(path.join(a,"framework-list"),{recursive:!0});}}if(s===null)throw new Error(`Framework "${e}" is not supported.`);if(Array.isArray(t.includePaths)&&t.includePaths.length>0&&(s=t.includePaths.flatMap(n=>s.filter(i=>i.path.startsWith(n)))),Array.isArray(t.excludePaths)&&t.excludePaths.length>0&&(s=t.excludePaths.flatMap(n=>s.filter(i=>!i.path.startsWith(n)))),typeof t.group=="string"&&t.group!==""){console.log();let n=B(s,p=>t.group==="path"?p.path.replace("/pages","").split("/")[1]:p.tags[0]??"unsorted"),i=0;n.forEach((p,c)=>{i>0&&console.log();let l=(d__default.default.stdout.columns-16-c.length)/2,f=l>0?Array.from({length:l}).fill(" ").join(""):"";console.log(f+u__default.default.bold.underline(c)),x(p,t).forEach(m=>{console.log(m);}),i+=1;});}else console.log(),x(s,t).forEach(n=>{console.log(n);});console.log(`
|
|
19
19
|
Listed ${u__default.default.greenBright(String(s.length))} HTTP ${s.length===1?"route":"routes"}.
|
|
20
20
|
`);},nt=ye;
|
|
21
21
|
|
|
22
22
|
exports.a = nt;
|
|
23
23
|
//# sourceMappingURL=out.js.map
|
|
24
|
-
//# sourceMappingURL=chunk-
|
|
24
|
+
//# sourceMappingURL=chunk-RK2WQGNS.js.map
|