{"version":3,"sources":["../../src/swagger/index.ts","../../src/swagger/parameters.ts","../../src/swagger/routes.ts","../../src/swagger/schemas.ts","../../src/swagger/spec.ts","../../src/swagger/express.ts"],"sourcesContent":["export * from \"./express\";\r\nexport * from \"./parameters\";\r\nexport * from \"./routes\";\r\nexport * from \"./schemas\";\r\nexport * from \"./spec\";\r\nexport * from \"./types\";\r\n","import type { OpenApiParameter } from \"./types\";\r\n\r\nexport const maxQueryParameter: OpenApiParameter = {\r\n  name: \"max\",\r\n  in: \"query\",\r\n  description: \"Maximum number of records to return.\",\r\n  required: false,\r\n  schema: {\r\n    type: \"integer\",\r\n    example: 10,\r\n  },\r\n};\r\n\r\nexport const offsetQueryParameter: OpenApiParameter = {\r\n  name: \"offset\",\r\n  in: \"query\",\r\n  description: \"Number of records to skip.\",\r\n  required: false,\r\n  schema: {\r\n    type: \"integer\",\r\n    example: 0,\r\n  },\r\n};\r\n\r\nexport const sortByQueryParameter: OpenApiParameter = {\r\n  name: \"sortBy\",\r\n  in: \"query\",\r\n  description: \"Field name to sort by.\",\r\n  required: false,\r\n  schema: {\r\n    type: \"string\",\r\n    example: \"createdAt\",\r\n  },\r\n};\r\n\r\nexport const sortOrderQueryParameter: OpenApiParameter = {\r\n  name: \"sortOrder\",\r\n  in: \"query\",\r\n  description: \"Sort direction.\",\r\n  required: false,\r\n  schema: {\r\n    type: \"string\",\r\n    enum: [\"asc\", \"desc\"],\r\n    example: \"desc\",\r\n  },\r\n};\r\n\r\nexport const qQueryParameter: OpenApiParameter = {\r\n  name: \"q\",\r\n  in: \"query\",\r\n  description: \"Search keyword.\",\r\n  required: false,\r\n  schema: {\r\n    type: \"string\",\r\n    example: \"student\",\r\n  },\r\n};\r\n\r\nexport const searchQueryParameter: OpenApiParameter = {\r\n  name: \"search\",\r\n  in: \"query\",\r\n  description: \"Search keyword. Alias for q.\",\r\n  required: false,\r\n  schema: {\r\n    type: \"string\",\r\n    example: \"student\",\r\n  },\r\n};\r\n\r\nexport const swaggerQueryParameters = {\r\n  Max: maxQueryParameter,\r\n  Offset: offsetQueryParameter,\r\n  SortBy: sortByQueryParameter,\r\n  SortOrder: sortOrderQueryParameter,\r\n  Q: qQueryParameter,\r\n  Search: searchQueryParameter,\r\n} as const;\r\n","import type { SwaggerRouteOptions } from \"./types\";\r\n\r\nexport function swaggerRoute(\r\n  options: SwaggerRouteOptions,\r\n): Record<string, unknown> {\r\n  const method = options.method ?? \"get\";\r\n  const tags = options.tags ?? (options.tag ? [options.tag] : undefined);\r\n  const operation: Record<string, unknown> = {\r\n    ...(tags ? { tags } : {}),\r\n    ...(options.summary ? { summary: options.summary } : {}),\r\n    ...(options.description ? { description: options.description } : {}),\r\n    ...(options.parameters ? { parameters: options.parameters } : {}),\r\n    ...(options.requestBodySchemaRef\r\n      ? {\r\n          requestBody: {\r\n            required: true,\r\n            content: {\r\n              \"application/json\": {\r\n                schema: { $ref: options.requestBodySchemaRef },\r\n              },\r\n            },\r\n          },\r\n        }\r\n      : {}),\r\n    responses: {\r\n      200: {\r\n        description: options.responseDescription ?? \"Successful response\",\r\n        content: {\r\n          \"application/json\": {\r\n            schema: {\r\n              $ref:\r\n                options.responseSchemaRef ??\r\n                \"#/components/schemas/SuccessResponse\",\r\n            },\r\n          },\r\n        },\r\n      },\r\n    },\r\n  };\r\n\r\n  return {\r\n    [options.path]: {\r\n      [method]: operation,\r\n    },\r\n  };\r\n}\r\n\r\nexport function swaggerRoutes(\r\n  routes: SwaggerRouteOptions[],\r\n): Record<string, unknown> {\r\n  return routes.reduce<Record<string, unknown>>((paths, route) => {\r\n    const nextPath = swaggerRoute(route);\r\n\r\n    for (const [path, methods] of Object.entries(nextPath)) {\r\n      paths[path] = {\r\n        ...((paths[path] as Record<string, unknown> | undefined) ?? {}),\r\n        ...(methods as Record<string, unknown>),\r\n      };\r\n    }\r\n\r\n    return paths;\r\n  }, {});\r\n}\r\n","import type { OpenApiSchema } from \"./types\";\r\n\r\nconst timestampSchema: OpenApiSchema = {\r\n  type: \"string\",\r\n  example: \"2026-04-27 21:59:03\",\r\n  description: \"Cambodia local date and time in YYYY-MM-DD HH:mm:ss format.\",\r\n};\r\n\r\nexport const successResponseSchema: OpenApiSchema = {\r\n  type: \"object\",\r\n  required: [\"success\", \"statusCode\", \"message\", \"data\", \"total\", \"timestamp\"],\r\n  properties: {\r\n    success: { type: \"boolean\", example: true },\r\n    statusCode: { type: \"integer\", example: 200 },\r\n    message: { type: \"string\", example: \"Request successful\" },\r\n    data: {\r\n      description: \"Response payload.\",\r\n      nullable: true,\r\n    },\r\n    total: {\r\n      type: \"integer\",\r\n      example: 20,\r\n      description: \"Total returned records. Single-object responses use 1.\",\r\n    },\r\n    timestamp: timestampSchema,\r\n  },\r\n};\r\n\r\nexport const errorResponseSchema: OpenApiSchema = {\r\n  type: \"object\",\r\n  required: [\"success\", \"message\", \"error\", \"timestamp\"],\r\n  properties: {\r\n    success: { type: \"boolean\", example: false },\r\n    message: { type: \"string\", example: \"Something went wrong\" },\r\n    error: { type: \"string\", example: \"INTERNAL_SERVER_ERROR\" },\r\n    details: {\r\n      description: \"Optional error details.\",\r\n      nullable: true,\r\n    },\r\n    timestamp: timestampSchema,\r\n  },\r\n};\r\n\r\nexport const validationErrorResponseSchema: OpenApiSchema = {\r\n  type: \"object\",\r\n  required: [\"success\", \"message\", \"errors\", \"timestamp\"],\r\n  properties: {\r\n    success: { type: \"boolean\", example: false },\r\n    message: { type: \"string\", example: \"Validation failed\" },\r\n    errors: {\r\n      type: \"array\",\r\n      items: {\r\n        type: \"object\",\r\n        required: [\"field\", \"message\"],\r\n        properties: {\r\n          field: { type: \"string\", example: \"email\" },\r\n          message: { type: \"string\", example: \"Email is required\" },\r\n        },\r\n      },\r\n    },\r\n    timestamp: timestampSchema,\r\n  },\r\n};\r\n\r\nexport const paginationMetadataSchema: OpenApiSchema = {\r\n  type: \"object\",\r\n  required: [\"max\", \"offset\", \"total\", \"hasNextPage\", \"hasPreviousPage\"],\r\n  properties: {\r\n    max: { type: \"integer\", example: 10 },\r\n    offset: { type: \"integer\", example: 0 },\r\n    total: { type: \"integer\", example: 100 },\r\n    hasNextPage: { type: \"boolean\", example: true },\r\n    hasPreviousPage: { type: \"boolean\", example: false },\r\n  },\r\n};\r\n\r\nexport const paginatedResponseSchema: OpenApiSchema = {\r\n  allOf: [\r\n    successResponseSchema,\r\n    {\r\n      type: \"object\",\r\n      required: [\"total\"],\r\n      properties: {\r\n        total: {\r\n          type: \"integer\",\r\n          example: 100,\r\n          description: \"Total records before pagination.\",\r\n        },\r\n      },\r\n    },\r\n  ],\r\n};\r\n\r\nexport const swaggerSchemas = {\r\n  SuccessResponse: successResponseSchema,\r\n  ErrorResponse: errorResponseSchema,\r\n  ValidationErrorResponse: validationErrorResponseSchema,\r\n  PaginatedResponse: paginatedResponseSchema,\r\n  PaginationMeta: paginationMetadataSchema,\r\n} as const;\r\n","import { swaggerQueryParameters } from \"./parameters\";\r\nimport { swaggerRoutes } from \"./routes\";\r\nimport { swaggerSchemas } from \"./schemas\";\r\nimport type { CreateSwaggerSpecOptions, OpenApiDocument } from \"./types\";\r\n\r\nexport function createSwaggerSpec(\r\n  options: CreateSwaggerSpecOptions,\r\n): OpenApiDocument {\r\n  const routePaths = options.routes ? swaggerRoutes(options.routes) : {};\r\n\r\n  return {\r\n    openapi: options.openapi ?? \"3.0.3\",\r\n    info: {\r\n      title: options.title,\r\n      version: options.version,\r\n      ...(options.description ? { description: options.description } : {}),\r\n    },\r\n    ...(options.servers ? { servers: options.servers } : {}),\r\n    ...(options.tags ? { tags: options.tags } : {}),\r\n    paths: {\r\n      ...routePaths,\r\n      ...(options.paths ?? {}),\r\n    },\r\n    components: {\r\n      ...options.components,\r\n      schemas: {\r\n        ...swaggerSchemas,\r\n        ...options.components?.schemas,\r\n      },\r\n      parameters: {\r\n        ...swaggerQueryParameters,\r\n        ...options.components?.parameters,\r\n      },\r\n    },\r\n  };\r\n}\r\n","import { createSwaggerSpec } from \"./spec\";\r\nimport type {\r\n  ExpressLikeApp,\r\n  OpenApiDocument,\r\n  SetupSwaggerDocsOptions,\r\n} from \"./types\";\r\n\r\ntype SwaggerUiExpress = {\r\n  serve: unknown;\r\n  setup: (spec: OpenApiDocument, options?: Record<string, unknown>) => unknown;\r\n};\r\n\r\nasync function loadSwaggerUiExpress(): Promise<SwaggerUiExpress> {\r\n  try {\r\n    const dynamicImport = new Function(\r\n      \"specifier\",\r\n      \"return import(specifier)\",\r\n    ) as (specifier: string) => Promise<{ default?: unknown }>;\r\n    const module = await dynamicImport(\"swagger-ui-express\");\r\n    return (module.default ?? module) as SwaggerUiExpress;\r\n  } catch (error) {\r\n    void error;\r\n    throw new Error(\r\n      \"setupSwaggerDocs() requires the optional peer dependency swagger-ui-express. Install it with: npm install swagger-ui-express\",\r\n    );\r\n  }\r\n}\r\n\r\nexport function setupSwaggerDocs(\r\n  app: ExpressLikeApp,\r\n  options: SetupSwaggerDocsOptions,\r\n): Promise<OpenApiDocument> {\r\n  return setupSwaggerDocsAsync(app, options);\r\n}\r\n\r\nasync function setupSwaggerDocsAsync(\r\n  app: ExpressLikeApp,\r\n  options: SetupSwaggerDocsOptions,\r\n): Promise<OpenApiDocument> {\r\n  const docsPath = options.path ?? \"/api-docs\";\r\n  const spec = options.spec ?? createSwaggerSpec(options);\r\n  const swaggerUi = await loadSwaggerUiExpress();\r\n\r\n  app.use(\r\n    docsPath,\r\n    swaggerUi.serve,\r\n    swaggerUi.setup(spec, options.swaggerUiOptions),\r\n  );\r\n\r\n  return spec;\r\n}\r\n"],"mappings":"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","names":["module"]}