diff --git a/.vscode/adonis.code-snippets b/.vscode/adonis.code-snippets new file mode 100644 index 0000000..3ab8928 --- /dev/null +++ b/.vscode/adonis.code-snippets @@ -0,0 +1,36 @@ +{ + "Adonis Controller and Route": { + "scope": "typescript", + "prefix": "apic", + "body": [ + "import { throttle } from \"#start/limiter.ts\"", + "import type { HttpContext } from \"@adonisjs/core/http\"", + "import router from \"@adonisjs/core/services/router\"", + "import vine from \"@vinejs/vine\"", + "", + "export const ${1:controller_name}_validator = vine.compile(", + " vine.object({})", + ")", + "", + "export default class ${1:controller_name} {", + " public async handle(context: HttpContext): Promise<{", + " __response: unknown", + " __status: 200", + " }> {", + " const payload = await context.request.validateUsing(${1:controller_name}_validator)", + " return context.response.ok(payload)", + " }", + "}", + "", + "router", + " .get(\"${2:/router-path}\", [${1:controller_name}])", + " .use(throttle)", + " .openapi({", + " description: \"Description.\",", + " tags: [\"tag\"],", + " })", + "", + ], + "description": "Adonis Controller and Route", + }, +} diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile index 0d2649c..cb97ef0 100644 --- a/apps/api/Dockerfile +++ b/apps/api/Dockerfile @@ -20,10 +20,11 @@ COPY turbo.json turbo.json FROM node-pnpm AS runner ENV NODE_ENV=production -ENV HOSTNAME=0.0.0.0 +ENV HOST=0.0.0.0 RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 applicationrunner USER applicationrunner COPY --from=installer --chown=applicationrunner:nodejs /usr/src/app ./ WORKDIR /usr/src/app/apps/api +RUN node --run tuyau CMD ["node", "--import=tsx", "./bin/server.ts"] diff --git a/apps/api/app/controllers/health/__tests__/get.test.ts b/apps/api/app/controllers/health/__tests__/get_health_controller.test.ts similarity index 100% rename from apps/api/app/controllers/health/__tests__/get.test.ts rename to apps/api/app/controllers/health/__tests__/get_health_controller.test.ts diff --git a/apps/api/app/controllers/wikipedia/pages/[id]/__tests__/get.test.ts b/apps/api/app/controllers/wikipedia/pages/[id]/__tests__/get_wikipedia_page_by_id.test.ts similarity index 100% rename from apps/api/app/controllers/wikipedia/pages/[id]/__tests__/get.test.ts rename to apps/api/app/controllers/wikipedia/pages/[id]/__tests__/get_wikipedia_page_by_id.test.ts diff --git a/apps/api/app/controllers/wikipedia/pages/__tests__/get.test.ts b/apps/api/app/controllers/wikipedia/pages/__tests__/get_wikipedia_pages.test.ts similarity index 100% rename from apps/api/app/controllers/wikipedia/pages/__tests__/get.test.ts rename to apps/api/app/controllers/wikipedia/pages/__tests__/get_wikipedia_pages.test.ts diff --git a/apps/api/app/controllers/wikipedia/pages/get_wikipedia_pages.ts b/apps/api/app/controllers/wikipedia/pages/get_wikipedia_pages.ts index e413bcc..dbbc371 100644 --- a/apps/api/app/controllers/wikipedia/pages/get_wikipedia_pages.ts +++ b/apps/api/app/controllers/wikipedia/pages/get_wikipedia_pages.ts @@ -14,13 +14,7 @@ export const get_wikipedia_pages_validator = vine.compile( .transform((value) => { return sanitizePageTitle(value) }), - limit: vine - .number() - .parse((value) => { - return value ?? 5 - }) - .withoutDecimals() - .range([1, 100]), + limit: vine.number().withoutDecimals().range([1, 100]).optional(), }), ) @@ -34,7 +28,7 @@ export default class get_wikipedia_pages { ) const pages = await Page.query() .whereLike("title", `${payload.title}%`) - .limit(payload.limit) + .limit(payload.limit ?? 5) return context.response.ok(pages) } } diff --git a/apps/api/start/routes.ts b/apps/api/start/routes.ts index 9d5a67d..401a963 100644 --- a/apps/api/start/routes.ts +++ b/apps/api/start/routes.ts @@ -2,8 +2,29 @@ * Routes file * * The routes file is used for defining the HTTP routes. + * Routes are loaded automatically from "app/controllers". */ -import "#app/controllers/health/get_health_controller.ts" -import "#app/controllers/wikipedia/pages/[id]/get_wikipedia_page_by_id.ts" -import "#app/controllers/wikipedia/pages/get_wikipedia_pages.ts" +import fs from "node:fs" +import path from "node:path" + +const CONTROLLERS_DIRECTORY_URL = new URL( + "../app/controllers/", + import.meta.url, +) + +const controllers = ( + await fs.promises.readdir(CONTROLLERS_DIRECTORY_URL, { + recursive: true, + withFileTypes: true, + }) +).filter((item) => { + return item.isFile() && !item.name.includes(".test.") +}) + +await Promise.all( + controllers.map(async (controller) => { + const controllerPath = path.join(controller.parentPath, controller.name) + await import(controllerPath) + }), +) diff --git a/patches/@tuyau__openapi@0.2.0.patch b/patches/@tuyau__openapi@0.2.0.patch index 6fffea8..fe7c050 100644 --- a/patches/@tuyau__openapi@0.2.0.patch +++ b/patches/@tuyau__openapi@0.2.0.patch @@ -1,5 +1,5 @@ diff --git a/build/chunk-DFECKFQT.js b/build/chunk-DFECKFQT.js -index 0740bf03f8c9de643f09fdcf02c43e40eb5efa55..ff348509b0e77b0b98e6e6db57c3355e3e0914f7 100644 +index 0740bf03f8c9de643f09fdcf02c43e40eb5efa55..c17063ca57f8d4049907c7ccf2218cbaaa6bcc93 100644 --- a/build/chunk-DFECKFQT.js +++ b/build/chunk-DFECKFQT.js @@ -266,7 +266,7 @@ var OpenApiGenerator = class { @@ -11,3 +11,11 @@ index 0740bf03f8c9de643f09fdcf02c43e40eb5efa55..ff348509b0e77b0b98e6e6db57c3355e continue; if (type2.isArray()) { properties2[propName] = { +@@ -464,7 +464,6 @@ var OpenApiGenerator = class { + const openApiDoc = defu(this.config.openapi?.documentation, { + openapi: "3.1.0", + info: { title: "AdonisJS API", version: "1.0.0" }, +- servers: [{ url: "http://localhost:3333" }], + paths: {} + }); + this.#generateApiDoc({ definition, openApiDoc }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ec80ab0..9e58be3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -252,7 +252,7 @@ patchedDependencies: hash: zzabo2h6qjt52qr7ntgx4dwdpa path: patches/@tuyau__core@0.1.4.patch '@tuyau/openapi@0.2.0': - hash: i6nyw7jxy3i3iokbuvzj62ysse + hash: kpo4zegzfda7iottgrth73vipq path: patches/@tuyau__openapi@0.2.0.patch importers: @@ -321,7 +321,7 @@ importers: version: 0.1.4(patch_hash=zzabo2h6qjt52qr7ntgx4dwdpa)(@adonisjs/core@6.12.1(@adonisjs/assembler@7.7.0(typescript@5.5.4))(@vinejs/vine@2.1.0)) '@tuyau/openapi': specifier: 'catalog:' - version: 0.2.0(patch_hash=i6nyw7jxy3i3iokbuvzj62ysse)(@tuyau/core@0.1.4(patch_hash=zzabo2h6qjt52qr7ntgx4dwdpa)(@adonisjs/core@6.12.1(@adonisjs/assembler@7.7.0(typescript@5.5.4))(@vinejs/vine@2.1.0))) + version: 0.2.0(patch_hash=kpo4zegzfda7iottgrth73vipq)(@tuyau/core@0.1.4(patch_hash=zzabo2h6qjt52qr7ntgx4dwdpa)(@adonisjs/core@6.12.1(@adonisjs/assembler@7.7.0(typescript@5.5.4))(@vinejs/vine@2.1.0))) '@tuyau/utils': specifier: 'catalog:' version: 0.0.4 @@ -12595,7 +12595,7 @@ snapshots: '@adonisjs/core': 6.12.1(@adonisjs/assembler@7.7.0(typescript@5.5.4))(@vinejs/vine@2.1.0) ts-morph: 22.0.0 - '@tuyau/openapi@0.2.0(patch_hash=i6nyw7jxy3i3iokbuvzj62ysse)(@tuyau/core@0.1.4(patch_hash=zzabo2h6qjt52qr7ntgx4dwdpa)(@adonisjs/core@6.12.1(@adonisjs/assembler@7.7.0(typescript@5.5.4))(@vinejs/vine@2.1.0)))': + '@tuyau/openapi@0.2.0(patch_hash=kpo4zegzfda7iottgrth73vipq)(@tuyau/core@0.1.4(patch_hash=zzabo2h6qjt52qr7ntgx4dwdpa)(@adonisjs/core@6.12.1(@adonisjs/assembler@7.7.0(typescript@5.5.4))(@vinejs/vine@2.1.0)))': dependencies: '@tuyau/core': 0.1.4(patch_hash=zzabo2h6qjt52qr7ntgx4dwdpa)(@adonisjs/core@6.12.1(@adonisjs/assembler@7.7.0(typescript@5.5.4))(@vinejs/vine@2.1.0)) defu: 6.1.4