Closed bompi88 closed 1 year ago
Hello there bompi88 👋
Thank you for opening your very first issue in this project.
We will try to get back to you as soon as we can.👀
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days
this would be actually very nice, i am making a template now
this would be actually very nice, i am making a template now
Does the template for Azure Functions v4 has been completed already ?
Thanks
i made this, but it's not complete. You'll have to adjust this to your usecase
/* tslint:disable */
/* eslint-disable */
import { Controller, ValidationService, FieldErrors, ValidateError, TsoaRoute, HttpStatusCodeLiteral, TsoaResponse, fetchMiddlewares } from '@tsoa/runtime'
{{#each controllers}}
import { {{name}} } from '{{modulePath}}'
{{/each}}
import { app, HttpHandler, HttpMethod, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions'
import * as fs from 'fs'
import * as intercept from 'azure-function-log-intercept'
const models: TsoaRoute.Models = {
{{#each models}}
{{@key}}: {
{{#if enums}}
dataType: "refEnum",
enums: {{{json enums}}},
{{/if}}
{{#if properties}}
dataType: "refObject",
properties: {
{{#each properties}}
{{@key}}: {{{json this}}},
{{/each}}
},
additionalProperties: {{{json additionalProperties}}},
{{/if}}
{{#if type}}
dataType: "refAlias",
type: {{{json type}}},
{{/if}}
},
{{/each}}
}
const validationService = new ValidationService(models)
{{#each controllers}}
{{#each actions}}
app.http('{{name}}', {
methods: ['{{method}}'.toUpperCase() as HttpMethod ],
authLevel: 'function',
route: convertToAzureFunctionRoute('{{fullPath}}'),
handler: globalErrorHandler(async (request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> => {
intercept(context)
const args = {
{{#each parameters}}
{{@key}}: {{{json this}}},
{{/each}}
}
const validatedArgs = await getValidatedArgs(args, request)
const controller = new {{../name}}()
return {
{{#if successStatus}}
status: {{successStatus}},
{{/if}}
jsonBody: await controller.{{name}}.apply(controller, validatedArgs)
}
})
})
{{/each}}
{{/each}}
const SWAGGER_UI_ROUTE = process.env.SWAGGER_UI_ROUTE || 'v3/swagger-ui'
const SWAGGER_UI_INDEX_LOCATION = process.env.SWAGGER_LOCATION || 'public/swagger-ui.html'
const SWAGGER_UI_HTML = fs.readFileSync(SWAGGER_UI_INDEX_LOCATION).toString()
app.get('getSwaggerUI', {
authLevel: 'anonymous',
route: SWAGGER_UI_ROUTE,
handler: async (
request: HttpRequest,
context: InvocationContext,
): Promise<HttpResponseInit> => {
return {
headers: [['Content-Type', 'text/html']],
body: SWAGGER_UI_HTML,
}
},
})
function convertToAzureFunctionRoute(path: string): string {
return path.slice(1).replace(/:(\w+)|:(\w+)\//g, '{$1}')
.replace('{id}', '{id:int}')
}
async function getValidatedArgs(args: any, request: HttpRequest): Promise<any[]> {
const fieldErrors: FieldErrors = {}
let queryParams = {}
for (let [key, value] of request.query) {
queryParams[key] = value
}
let body = {}
try {
body = await request.json()
} catch {}
const values = Object.keys(args).map((key) => {
const name = args[key].name
switch (args[key].in) {
case 'request':
// return request
throw new Error("needs to be implemented")
case 'query':
return validationService.ValidateParam(args[key], parseAzureQueryParameter(request.query.get(name)), name, fieldErrors, undefined, {{{json minimalSwaggerConfig}}})
case 'queries':
return validationService.ValidateParam(args[key], queryParams, name, fieldErrors, undefined, {{{json minimalSwaggerConfig}}})
case 'path':
return validationService.ValidateParam(args[key], request.params[name], name, fieldErrors, undefined, {{{json minimalSwaggerConfig}}})
case 'header':
// return validationService.ValidateParam(args[key], request.headers.get(name), name, fieldErrors, undefined, {{{json minimalSwaggerConfig}}})
throw new Error("needs to be implemented")
case 'body':
// return validationService.ValidateParam(args[key], body, name, fieldErrors, undefined, {{{json minimalSwaggerConfig}}})
throw new Error("needs to be implemented")
case 'body-prop':
return validationService.ValidateParam(args[key], parseAzureQueryParameter(body[name]), name, fieldErrors, 'body.', {{{json minimalSwaggerConfig}}})
case 'formData':
// if (args[key].dataType === 'file') {
// return validationService.ValidateParam(args[key], request.file, name, fieldErrors, undefined, {{{json minimalSwaggerConfig}}})
// } else if (args[key].dataType === 'array' && args[key].array.dataType === 'file') {
// return validationService.ValidateParam(args[key], request.files, name, fieldErrors, undefined, {{{json minimalSwaggerConfig}}})
// } else {
// return validationService.ValidateParam(args[key], request.body[name], name, fieldErrors, undefined, {{{json minimalSwaggerConfig}}})
// }
throw new Error("needs to be implemented")
case 'res':
// return responder(response)
throw new Error("needs to be implemented")
}
})
if (Object.keys(fieldErrors).length > 0) {
throw new ValidateError(fieldErrors, '')
}
return values
}
function parseAzureQueryParameter(value: string): unknown {
if (value == null) {
return undefined
}
if (value.includes(',')) {
return value.split(',')
}
return value
}
export function globalErrorHandler(trigger: HttpHandler) {
return async (
req: HttpRequest,
context: InvocationContext,
): Promise<HttpResponseInit> => {
try {
return await trigger(req, context)
} catch (err) {
if (err instanceof ValidateError) {
return new InvalidParameterException(getErrorFieldsString(err.fields)).response
} else {
throw err
}
}
}
}
function getErrorFieldsString(fieldErrors: FieldErrors): string {
return Object.keys(fieldErrors)
.map((key) => `${key}=${fieldErrors[key].value}: ${fieldErrors[key].message}`)
.join('; ')
}
Create a route generation option for Azure functions v4.
Sorting
I'm submitting a ...
I confirm that I
Possible Solution
Add a suitable template for Azure functions entry file.