|
@@ -1,8 +1,35 @@
|
|
|
import { createRoute, OpenAPIHono } from '@hono/zod-openapi'
|
|
import { createRoute, OpenAPIHono } from '@hono/zod-openapi'
|
|
|
import { z } from 'zod'
|
|
import { z } from 'zod'
|
|
|
|
|
+import { AppDataSource } from '../data-source'
|
|
|
|
|
+import { HTTPException } from 'hono/http-exception';
|
|
|
|
|
+
|
|
|
|
|
+interface Migration {
|
|
|
|
|
+ name: string;
|
|
|
|
|
+ timestamp: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+interface MigrationResult {
|
|
|
|
|
+ migrations: Migration[];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+interface ExecutedMigration {
|
|
|
|
|
+ name: string;
|
|
|
|
|
+ timestamp: string;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+interface PendingMigration {
|
|
|
|
|
+ name: string;
|
|
|
|
|
+ status: string;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+interface MigrationHistory {
|
|
|
|
|
+ executed: ExecutedMigration[];
|
|
|
|
|
+ pending: PendingMigration[];
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
const app = new OpenAPIHono()
|
|
const app = new OpenAPIHono()
|
|
|
|
|
|
|
|
|
|
+// Base route
|
|
|
const QuerySchema = z.object({
|
|
const QuerySchema = z.object({
|
|
|
name: z.string().optional().openapi({
|
|
name: z.string().optional().openapi({
|
|
|
param: {
|
|
param: {
|
|
@@ -19,7 +46,24 @@ const ResponseSchema = z.object({
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
-const route = createRoute({
|
|
|
|
|
|
|
+const MigrationResponseSchema = z.object({
|
|
|
|
|
+ success: z.boolean(),
|
|
|
|
|
+ message: z.string(),
|
|
|
|
|
+ migrations: z.array(z.string()).optional()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const MigrationHistoryResponseSchema = z.object({
|
|
|
|
|
+ executed: z.array(z.object({
|
|
|
|
|
+ name: z.string(),
|
|
|
|
|
+ timestamp: z.string()
|
|
|
|
|
+ })),
|
|
|
|
|
+ pending: z.array(z.object({
|
|
|
|
|
+ name: z.string(),
|
|
|
|
|
+ status: z.string()
|
|
|
|
|
+ }))
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const baseRoute = createRoute({
|
|
|
method: 'get',
|
|
method: 'get',
|
|
|
path: '/',
|
|
path: '/',
|
|
|
request: {
|
|
request: {
|
|
@@ -40,10 +84,113 @@ const route = createRoute({
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
-const routes = app.openapi(route, (c) => {
|
|
|
|
|
|
|
+const runMigrationRoute = createRoute({
|
|
|
|
|
+ method: 'post',
|
|
|
|
|
+ path: '/migrations/run',
|
|
|
|
|
+ responses: {
|
|
|
|
|
+ 200: {
|
|
|
|
|
+ content: {
|
|
|
|
|
+ 'application/json': {
|
|
|
|
|
+ schema: MigrationResponseSchema
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ description: 'Migrations executed successfully'
|
|
|
|
|
+ },
|
|
|
|
|
+ 500: {
|
|
|
|
|
+ description: 'Migration failed'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const revertMigrationRoute = createRoute({
|
|
|
|
|
+ method: 'post',
|
|
|
|
|
+ path: '/migrations/revert',
|
|
|
|
|
+ responses: {
|
|
|
|
|
+ 200: {
|
|
|
|
|
+ content: {
|
|
|
|
|
+ 'application/json': {
|
|
|
|
|
+ schema: MigrationResponseSchema
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ description: 'Migration reverted successfully'
|
|
|
|
|
+ },
|
|
|
|
|
+ 500: {
|
|
|
|
|
+ description: 'Revert failed'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+app.openapi(baseRoute, (c) => {
|
|
|
const { name } = c.req.valid('query')
|
|
const { name } = c.req.valid('query')
|
|
|
return c.json({ message: `Hello from API${name ? `, ${name}` : ''}` })
|
|
return c.json({ message: `Hello from API${name ? `, ${name}` : ''}` })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+app.openapi(runMigrationRoute, async (c) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const migrations = await AppDataSource.runMigrations()
|
|
|
|
|
+ return c.json({
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ message: 'Migrations executed successfully',
|
|
|
|
|
+ migrations: migrations.map((m: Migration) => m.name)
|
|
|
|
|
+ })
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ throw new HTTPException(500, {cause: error})
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+app.openapi(revertMigrationRoute, async (c) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await AppDataSource.undoLastMigration()
|
|
|
|
|
+ const migrations = await AppDataSource.showMigrations()
|
|
|
|
|
+ return c.json({
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ message: 'Migration reverted successfully',
|
|
|
|
|
+ migrations: migrations
|
|
|
|
|
+ })
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ throw error
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const migrationHistoryRoute = createRoute({
|
|
|
|
|
+ method: 'get',
|
|
|
|
|
+ path: '/migrations/history',
|
|
|
|
|
+ responses: {
|
|
|
|
|
+ 200: {
|
|
|
|
|
+ content: {
|
|
|
|
|
+ 'application/json': {
|
|
|
|
|
+ schema: MigrationHistoryResponseSchema
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ description: 'Migration history retrieved successfully'
|
|
|
|
|
+ },
|
|
|
|
|
+ 500: {
|
|
|
|
|
+ description: 'Failed to get migration history'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// app.openapi(migrationHistoryRoute, async (c) => {
|
|
|
|
|
+// try {
|
|
|
|
|
+// // Get executed migrations from database
|
|
|
|
|
+// // const executedMigrations = await AppDataSource.query('SELECT * FROM migrations')
|
|
|
|
|
+
|
|
|
|
|
+// // Get pending migrations from TypeORM
|
|
|
|
|
+// const pendingMigrations = await AppDataSource.showMigrations()
|
|
|
|
|
+
|
|
|
|
|
+// const result: MigrationHistory = {
|
|
|
|
|
+// // executed: executedMigrations.map((m: any) => ({
|
|
|
|
|
+// // name: m.name,
|
|
|
|
|
+// // timestamp: new Date(m.timestamp).toISOString()
|
|
|
|
|
+// // })),
|
|
|
|
|
+// pending: pendingMigrations
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// return c.json(result)
|
|
|
|
|
+// } catch (error) {
|
|
|
|
|
+// throw new HTTPException(500,{cause: error})
|
|
|
|
|
+// }
|
|
|
|
|
+// })
|
|
|
|
|
+
|
|
|
export default app
|
|
export default app
|
|
|
-export type AppType = typeof routes
|
|
|
|
|
|
|
+export type AppType = typeof app
|