index.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import { OpenAPIHono } from '@hono/zod-openapi'
  2. import { swaggerUI } from '@hono/swagger-ui'
  3. import { errorHandler, initializeDataSource } from '@d8d/shared-utils'
  4. import { userRoutesMt as userModuleRoutes, roleRoutesMt as roleModuleRoutes } from '@d8d/core-module-mt/user-module-mt'
  5. import { authRoutes as authModuleRoutes } from '@d8d/core-module-mt/auth-module-mt'
  6. import { fileRoutesMt as fileModuleRoutes } from '@d8d/core-module-mt/file-module-mt'
  7. import { tenantRoutes } from '@d8d/tenant-module-mt'
  8. import { AuthContext } from '@d8d/shared-types'
  9. import { AppDataSource } from '@d8d/shared-utils'
  10. import { Hono } from 'hono'
  11. import { UserEntityMt, RoleMt } from '@d8d/user-module-mt'
  12. import { FileMt } from '@d8d/file-module-mt'
  13. import { TenantEntityMt } from '@d8d/tenant-module-mt'
  14. import { SystemConfigMt } from '@d8d/core-module-mt/system-config-module-mt'
  15. // 导入已实现的包实体
  16. import { AreaEntityMt } from '@d8d/geo-areas-mt'
  17. import { PaymentMtEntity } from '@d8d/mini-payment-mt'
  18. import { Advertisement, AdvertisementType } from '@d8d/advertisements-module-mt'
  19. import { DeliveryAddressMt } from '@d8d/delivery-address-module-mt'
  20. import { GoodsMt, GoodsCategoryMt } from '@d8d/goods-module-mt'
  21. import { MerchantMt } from '@d8d/merchant-module-mt'
  22. import { OrderMt, OrderGoodsMt, OrderRefundMt } from '@d8d/orders-module-mt'
  23. import { SupplierMt } from '@d8d/supplier-module-mt'
  24. import { CreditBalanceMt, CreditBalanceLogMt } from '@d8d/credit-balance-module-mt'
  25. import { creditBalanceRoutes as creditBalanceModuleRoutes } from '@d8d/credit-balance-module-mt'
  26. import { FeieConfigMt, FeiePrintTaskMt, FeiePrinterMt } from '@d8d/feie-printer-module-mt'
  27. import { createFeieRoutes } from '@d8d/feie-printer-module-mt'
  28. initializeDataSource([
  29. // 已实现的包实体
  30. UserEntityMt, RoleMt, FileMt,
  31. TenantEntityMt,
  32. AreaEntityMt, PaymentMtEntity,
  33. Advertisement, AdvertisementType,
  34. DeliveryAddressMt,
  35. GoodsMt, GoodsCategoryMt,
  36. MerchantMt,
  37. OrderMt, OrderGoodsMt, OrderRefundMt,
  38. SupplierMt, SystemConfigMt,
  39. CreditBalanceMt, CreditBalanceLogMt,
  40. FeieConfigMt, FeiePrintTaskMt, FeiePrinterMt
  41. ])
  42. if(!AppDataSource || !AppDataSource.isInitialized) {
  43. await AppDataSource.initialize();
  44. console.log('数据库初始化完成')
  45. }
  46. // 初始化飞鹅打印防退款延迟调度器
  47. try {
  48. const { DelaySchedulerService } = await import('@d8d/feie-printer-module-mt');
  49. const { createFeieRoutes } = await import('@d8d/feie-printer-module-mt');
  50. // 获取所有有飞鹅配置的租户
  51. const systemConfigRepository = AppDataSource.getRepository('system_config_mt');
  52. const configs = await systemConfigRepository.find({
  53. where: {
  54. configKey: 'feie.api.user'
  55. }
  56. });
  57. // 为每个有配置的租户启动调度器
  58. for (const config of configs) {
  59. const tenantId = config.tenantId;
  60. // 动态获取飞鹅配置
  61. const configKeys = [
  62. 'feie.api.user',
  63. 'feie.api.ukey',
  64. 'feie.api.base_url',
  65. 'feie.api.timeout',
  66. 'feie.api.max_retries'
  67. ];
  68. const tenantConfigs = await systemConfigRepository.find({
  69. where: {
  70. tenantId,
  71. configKey: configKeys
  72. }
  73. });
  74. const configMap: Record<string, string> = {};
  75. tenantConfigs.forEach((config: any) => {
  76. configMap[config.configKey] = config.configValue;
  77. });
  78. const user = configMap['feie.api.user'];
  79. const ukey = configMap['feie.api.ukey'];
  80. if (user && ukey) {
  81. const feieConfig = {
  82. user,
  83. ukey,
  84. baseUrl: configMap['feie.api.base_url'] || 'https://api.feieyun.cn/Api/Open/',
  85. timeout: parseInt(configMap['feie.api.timeout'] || '10000', 10),
  86. maxRetries: parseInt(configMap['feie.api.max_retries'] || '3', 10)
  87. };
  88. const delaySchedulerService = new DelaySchedulerService(AppDataSource, feieConfig, tenantId);
  89. await delaySchedulerService.start();
  90. console.log(`[租户${tenantId}] 防退款延迟打印调度器已启动`);
  91. }
  92. }
  93. console.log('飞鹅打印防退款延迟调度器初始化完成');
  94. } catch (error) {
  95. console.warn('飞鹅打印防退款延迟调度器初始化失败,延迟打印功能可能不可用:', error);
  96. }
  97. const app = new Hono();
  98. const api = new OpenAPIHono<AuthContext>()
  99. api.onError(errorHandler)
  100. // Rate limiting
  101. api.use('/api/v1/*', async (_, next) => {
  102. // 实现速率限制逻辑
  103. await next()
  104. })
  105. // 数据库初始化中间件
  106. // api.use('/api/v1/*', async (c, next) => {
  107. // await next();
  108. // })
  109. // 注册Bearer认证方案
  110. api.openAPIRegistry.registerComponent('securitySchemes','bearerAuth',{
  111. type:'http',
  112. scheme:'bearer',
  113. bearerFormat:'JWT',
  114. description:'使用JWT进行认证'
  115. })
  116. // OpenAPI documentation endpoint
  117. // !import.meta.env.PROD
  118. if(1){
  119. // api.doc31('/doc', {
  120. // openapi: '3.1.0',
  121. // info: {
  122. // title: 'API Documentation',
  123. // version: '1.0.0'
  124. // },
  125. // security: [{
  126. // bearerAuth: []
  127. // }]
  128. // // servers: [{ url: '/api/v1' }]
  129. // })
  130. api.get('/doc', (c) => {
  131. const config = {
  132. openapi: '3.1.0',
  133. info: {
  134. title: 'API Documentation',
  135. version: '1.0.0'
  136. },
  137. security: [{
  138. bearerAuth: []
  139. }]
  140. // servers: [{ url: '/api/v1' }]
  141. };
  142. try {
  143. const document = api.getOpenAPI31Document(config);
  144. return c.json(document);
  145. } catch (e: any) {
  146. return c.json({
  147. error: 'OpenAPI document generation failed',
  148. message: e.message || 'Unknown error',
  149. stack: e.stack
  150. }, 500)
  151. }
  152. })
  153. app.get('/ui', swaggerUI({
  154. url: '/doc',
  155. persistAuthorization: true,
  156. manuallySwaggerUIHtml: () => `
  157. <div>
  158. <div id="swagger-ui"></div>
  159. <link rel="stylesheet" href="https://ai-oss.d8d.fun/swagger-ui-dist/swagger-ui.css" />
  160. <script src="https://ai-oss.d8d.fun/swagger-ui-dist/swagger-ui-bundle.js" crossorigin="anonymous"></script>
  161. <script>
  162. window.onload = () => {
  163. window.ui = SwaggerUIBundle({
  164. dom_id: '#swagger-ui',
  165. url: '/doc',
  166. persistAuthorization: true
  167. })
  168. }
  169. </script>
  170. </div>
  171. `
  172. }))
  173. }
  174. export const userRoutes = api.route('/api/v1/users', userModuleRoutes)
  175. export const authRoutes = api.route('/api/v1/auth', authModuleRoutes)
  176. export const fileApiRoutes = api.route('/api/v1/files', fileModuleRoutes)
  177. export const roleRoutes = api.route('/api/v1/roles', roleModuleRoutes)
  178. export const tenantApiRoutes = api.route('/api/v1/tenants', tenantRoutes)
  179. // 导入已实现的包路由
  180. import { areasRoutesMt, adminAreasRoutesMt } from '@d8d/geo-areas-mt'
  181. import { PaymentMtRoutes as PaymentRoutes } from '@d8d/mini-payment-mt'
  182. import { advertisementRoutes, advertisementTypeRoutes } from '@d8d/advertisements-module-mt'
  183. import { userDeliveryAddressRoutesMt as userDeliveryAddressRoutes, adminDeliveryAddressRoutesMt as adminDeliveryAddressRoutes } from '@d8d/delivery-address-module-mt'
  184. import {
  185. adminGoodsCategoriesRoutesMt as adminGoodsCategoriesRoutes,
  186. adminGoodsRoutesMt as adminGoodsRoutes,
  187. userGoodsCategoriesRoutesMt,
  188. publicGoodsRoutesMt,
  189. publicGoodsRandomRoutesMt
  190. } from '@d8d/goods-module-mt'
  191. import { userMerchantRoutes as merchantRoutes } from '@d8d/merchant-module-mt'
  192. import {
  193. userOrderRoutes,
  194. // userOrderItemsRoutes, userRefundsRoutes,
  195. adminOrderRoutes, adminOrderItemsRoutes, adminRefundsRoutes } from '@d8d/orders-module-mt'
  196. import { userSupplierRoutes } from '@d8d/supplier-module-mt'
  197. import { systemConfigRoutesMt } from '@d8d/core-module-mt/system-config-module-mt'
  198. // 注册已实现的包路由
  199. export const areaApiRoutes = api.route('/api/v1/areas', areasRoutesMt)
  200. export const adminAreaApiRoutes = api.route('/api/v1/admin/areas', adminAreasRoutesMt)
  201. export const paymentApiRoutes = api.route('/api/v1/payments', PaymentRoutes)
  202. export const advertisementApiRoutes = api.route('/api/v1/advertisements', advertisementRoutes)
  203. export const advertisementTypeApiRoutes = api.route('/api/v1/advertisement-types', advertisementTypeRoutes)
  204. export const deliveryAddressApiRoutes = api.route('/api/v1/delivery-addresses', userDeliveryAddressRoutes)
  205. export const adminDeliveryAddressApiRoutes = api.route('/api/v1/admin/delivery-addresses', adminDeliveryAddressRoutes)
  206. export const goodsCategoryApiRoutes = api.route('/api/v1/goods-categories', userGoodsCategoriesRoutesMt)
  207. export const adminGoodsCategoryApiRoutes = api.route('/api/v1/admin/goods-categories', adminGoodsCategoriesRoutes)
  208. export const adminGoodsApiRoutes = api.route('/api/v1/admin/goods', adminGoodsRoutes)
  209. export const goodsApiRoutes = api.route('/api/v1/goods', publicGoodsRoutesMt)
  210. export const merchantApiRoutes = api.route('/api/v1/merchants', merchantRoutes)
  211. export const orderApiRoutes = api.route('/api/v1/orders', userOrderRoutes)
  212. // export const orderGoodsApiRoutes = api.route('/api/v1/orders-goods', userOrderItemsRoutes)
  213. // export const orderRefundApiRoutes = api.route('/api/v1/orders-refund', userRefundsRoutes)
  214. export const creditBalanceApiRoutes = api.route('/api/v1/credit-balance', creditBalanceModuleRoutes)
  215. export const adminOrderApiRoutes = api.route('/api/v1/admin/orders', adminOrderRoutes)
  216. export const adminOrderGoodsApiRoutes = api.route('/api/v1/admin/orders-goods', adminOrderItemsRoutes)
  217. export const adminOrderRefundApiRoutes = api.route('/api/v1/admin/orders-refund', adminRefundsRoutes)
  218. export const supplierApiRoutes = api.route('/api/v1/suppliers', userSupplierRoutes)
  219. export const adminSystemConfigApiRoutes = api.route('/api/v1/admin/system-configs', systemConfigRoutesMt)
  220. // 创建飞鹅打印路由
  221. const feieRoutes = createFeieRoutes(AppDataSource)
  222. export const feieApiRoutes = api.route('/api/v1/feie', feieRoutes)
  223. export type AuthRoutes = typeof authRoutes
  224. export type UserRoutes = typeof userRoutes
  225. export type FileRoutes = typeof fileApiRoutes
  226. export type RoleRoutes = typeof roleRoutes
  227. export type AdvertisementRoutes = typeof advertisementApiRoutes
  228. export type AdvertisementTypeRoutes = typeof advertisementTypeApiRoutes
  229. export type GoodsCategoryRoutes = typeof goodsCategoryApiRoutes
  230. export type GoodsRoutes = typeof goodsApiRoutes
  231. export type SupplierRoutes = typeof supplierApiRoutes
  232. export type MerchantRoutes = typeof merchantApiRoutes
  233. export type DeliveryAddressRoutes = typeof deliveryAddressApiRoutes
  234. export type AdminDeliveryAddressRoutes = typeof adminDeliveryAddressApiRoutes
  235. export type OrderRoutes = typeof orderApiRoutes
  236. // export type OrderGoodsRoutes = typeof orderGoodsApiRoutes
  237. // export type OrderRefundRoutes = typeof orderRefundApiRoutes
  238. export type AdminOrderRoutes = typeof adminOrderApiRoutes
  239. export type AdminOrderGoodsRoutes = typeof adminOrderGoodsApiRoutes
  240. export type AdminOrderRefundRoutes = typeof adminOrderRefundApiRoutes
  241. export type AreaRoutes = typeof areaApiRoutes
  242. export type AdminAreaRoutes = typeof adminAreaApiRoutes
  243. export type PaymentRoutes = typeof paymentApiRoutes
  244. export type CreditBalanceRoutes = typeof creditBalanceApiRoutes
  245. export type FeieRoutes = typeof feieApiRoutes
  246. app.route('/', api)
  247. export default app