init base app modules
This commit is contained in:
		
							
								
								
									
										68
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					node_modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# mac
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.env*
 | 
				
			||||||
 | 
					!.env*example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dist
 | 
				
			||||||
 | 
					build
 | 
				
			||||||
 | 
					logs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.turbo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pack-dist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# astro
 | 
				
			||||||
 | 
					.astro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# next
 | 
				
			||||||
 | 
					.next
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# nuxt
 | 
				
			||||||
 | 
					.nuxt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# vercel
 | 
				
			||||||
 | 
					.vercel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# vuepress
 | 
				
			||||||
 | 
					.vuepress/dist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# coverage
 | 
				
			||||||
 | 
					coverage/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# typescript
 | 
				
			||||||
 | 
					*.tsbuildinfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# debug logs
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					*.tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# vscode
 | 
				
			||||||
 | 
					.vscode/*
 | 
				
			||||||
 | 
					!.vscode/settings.json
 | 
				
			||||||
 | 
					!.vscode/tasks.json
 | 
				
			||||||
 | 
					!.vscode/launch.json
 | 
				
			||||||
 | 
					!.vscode/extensions.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# idea
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# system
 | 
				
			||||||
 | 
					Thumbs.db
 | 
				
			||||||
 | 
					ehthumbs.db
 | 
				
			||||||
 | 
					Desktop.ini
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# temp files
 | 
				
			||||||
 | 
					*.tmp
 | 
				
			||||||
 | 
					*.temp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# local development
 | 
				
			||||||
 | 
					*.local
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public/r
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.pnpm-store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					storage/
 | 
				
			||||||
							
								
								
									
										3
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
 | 
				
			||||||
 | 
					//registry.npmjs.org/:_authToken=${NPM_TOKEN}
 | 
				
			||||||
 | 
					ignore-workspace-root-check=true
 | 
				
			||||||
							
								
								
									
										25
									
								
								apps/aliyun-ai/bun.config.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								apps/aliyun-ai/bun.config.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					// @ts-check
 | 
				
			||||||
 | 
					import { resolvePath } from '@kevisual/use-config/env';
 | 
				
			||||||
 | 
					import { execSync } from 'node:child_process';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const entry = 'src/index.ts';
 | 
				
			||||||
 | 
					const naming = 'app';
 | 
				
			||||||
 | 
					const external = ['sequelize', 'pg', 'sqlite3', 'minio', '@kevisual/router', 'pm2'];
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @type {import('bun').BuildConfig}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					await Bun.build({
 | 
				
			||||||
 | 
					  target: 'node',
 | 
				
			||||||
 | 
					  format: 'esm',
 | 
				
			||||||
 | 
					  entrypoints: [resolvePath(entry, { meta: import.meta })],
 | 
				
			||||||
 | 
					  outdir: resolvePath('./dist', { meta: import.meta }),
 | 
				
			||||||
 | 
					  naming: {
 | 
				
			||||||
 | 
					    entry: `${naming}.js`,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  external: external,
 | 
				
			||||||
 | 
					  env: 'KEVISUAL_*',
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// const cmd = `dts -i src/index.ts -o app.d.ts`;
 | 
				
			||||||
 | 
					// const cmd = `dts -i ${entry} -o ${naming}.d.ts`;
 | 
				
			||||||
 | 
					// execSync(cmd, { stdio: 'inherit' });
 | 
				
			||||||
							
								
								
									
										27
									
								
								apps/aliyun-ai/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								apps/aliyun-ai/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "aliyun-ai",
 | 
				
			||||||
 | 
					  "version": "0.0.1",
 | 
				
			||||||
 | 
					  "description": "",
 | 
				
			||||||
 | 
					  "main": "index.js",
 | 
				
			||||||
 | 
					  "basename": "/root/aliyun-ai",
 | 
				
			||||||
 | 
					  "app": {
 | 
				
			||||||
 | 
					    "key": "aliyun-ai",
 | 
				
			||||||
 | 
					    "entry": "dist/app.js",
 | 
				
			||||||
 | 
					    "type": "system-app"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "files": [
 | 
				
			||||||
 | 
					    "dist"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "dev": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0  bun --watch src/dev.ts ",
 | 
				
			||||||
 | 
					    "build": "rimraf dist && bun run bun.config.mjs",
 | 
				
			||||||
 | 
					    "clean": "rm -rf dist",
 | 
				
			||||||
 | 
					    "pub": "npm run build && envision pack -p -u"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "keywords": [],
 | 
				
			||||||
 | 
					  "author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
 | 
				
			||||||
 | 
					  "license": "MIT",
 | 
				
			||||||
 | 
					  "packageManager": "pnpm@10.12.1",
 | 
				
			||||||
 | 
					  "type": "module",
 | 
				
			||||||
 | 
					  "devDependencies": {}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								apps/aliyun-ai/src/app.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								apps/aliyun-ai/src/app.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					import { app } from '@/modules/router.ts';
 | 
				
			||||||
 | 
					import { oss } from '@/modules/minio.ts';
 | 
				
			||||||
 | 
					import { config } from '@/modules/config.ts';
 | 
				
			||||||
 | 
					export { app, config, oss };
 | 
				
			||||||
							
								
								
									
										6
									
								
								apps/aliyun-ai/src/dev.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								apps/aliyun-ai/src/dev.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					import { app } from './index.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app.listen(4000, () => {
 | 
				
			||||||
 | 
					  console.log('Server is running on http://localhost:4000');
 | 
				
			||||||
 | 
					  console.log('Press Ctrl+C to stop the server');
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										5
									
								
								apps/aliyun-ai/src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								apps/aliyun-ai/src/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					import { app } from './app.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import './routes/create-audio.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { app };
 | 
				
			||||||
							
								
								
									
										75
									
								
								apps/aliyun-ai/src/routes/create-audio.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								apps/aliyun-ai/src/routes/create-audio.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					import { app, config, oss } from '../app.ts';
 | 
				
			||||||
 | 
					import { dashscopeTTS } from '@/examples/dash-scope/tts.ts';
 | 
				
			||||||
 | 
					import { randomLetter } from '@/utils/random.ts';
 | 
				
			||||||
 | 
					import dayjs from 'dayjs';
 | 
				
			||||||
 | 
					type DashScopeTTSResponse = {
 | 
				
			||||||
 | 
					  output?: {
 | 
				
			||||||
 | 
					    finish_reason?: string;
 | 
				
			||||||
 | 
					    audio?: {
 | 
				
			||||||
 | 
					      expires_at?: number;
 | 
				
			||||||
 | 
					      data?: string;
 | 
				
			||||||
 | 
					      id?: string;
 | 
				
			||||||
 | 
					      url?: string;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  usage?: {
 | 
				
			||||||
 | 
					    input_tokens_details?: {
 | 
				
			||||||
 | 
					      text_tokens?: number;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    total_tokens?: number;
 | 
				
			||||||
 | 
					    output_tokens?: number;
 | 
				
			||||||
 | 
					    input_tokens?: number;
 | 
				
			||||||
 | 
					    output_tokens_details?: {
 | 
				
			||||||
 | 
					      audio_tokens?: number;
 | 
				
			||||||
 | 
					      text_tokens?: number;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  request_id?: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					app
 | 
				
			||||||
 | 
					  .route({
 | 
				
			||||||
 | 
					    path: 'aliyun-ai',
 | 
				
			||||||
 | 
					    key: 'createVideos',
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  .define(async (ctx) => {
 | 
				
			||||||
 | 
					    const { text, model, save = 'none' } = ctx.query;
 | 
				
			||||||
 | 
					    if (!text) {
 | 
				
			||||||
 | 
					      ctx.throw(400, 'Text and model are required parameters');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const value: DashScopeTTSResponse = await dashscopeTTS({
 | 
				
			||||||
 | 
					      text,
 | 
				
			||||||
 | 
					      voice: model || 'Chelsie',
 | 
				
			||||||
 | 
					      token: config.BAILIAN_API_KEY,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    const url = value?.output?.audio?.url;
 | 
				
			||||||
 | 
					    const fileName = `audio-${randomLetter(32)}.wav`;
 | 
				
			||||||
 | 
					    const username = 'share';
 | 
				
			||||||
 | 
					    const today = dayjs().format('YYYY-MM-DD');
 | 
				
			||||||
 | 
					    // 使用用户名和日期作为文件夹路径
 | 
				
			||||||
 | 
					    const filePath = `${username}/storage/aliyun-ai/audio/${today}/${fileName}`;
 | 
				
			||||||
 | 
					    if (url) {
 | 
				
			||||||
 | 
					      ctx.body = {
 | 
				
			||||||
 | 
					        audioUrl: url,
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (save === 'minio' && url) {
 | 
				
			||||||
 | 
					      // 读取文件url地址的数据,并保存到 MinIO, 文件是 音频 wave 格式
 | 
				
			||||||
 | 
					      const audioData = await fetch(url).then((res) => res.arrayBuffer());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // 将音频数据转换为 Buffer 并上传到 MinIO
 | 
				
			||||||
 | 
					      const buffer = Buffer.from(audioData);
 | 
				
			||||||
 | 
					      await oss.client.putObject(oss.bucketName, filePath, buffer, null, {
 | 
				
			||||||
 | 
					        'Content-Type': 'audio/wav',
 | 
				
			||||||
 | 
					        'app-source': 'aliyun-ai',
 | 
				
			||||||
 | 
					        share: 'public',
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      console.log('Audio file uploaded to MinIO:', filePath);
 | 
				
			||||||
 | 
					      // @ts-ignore
 | 
				
			||||||
 | 
					      ctx.body.minio = filePath;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 如果没有 url,抛出错误
 | 
				
			||||||
 | 
					    if (!url) {
 | 
				
			||||||
 | 
					      ctx.throw(500, 'Failed to create audio');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  .addTo(app);
 | 
				
			||||||
							
								
								
									
										25
									
								
								bun.config.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								bun.config.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					// @ts-check
 | 
				
			||||||
 | 
					import { resolvePath } from '@kevisual/use-config/env';
 | 
				
			||||||
 | 
					import { execSync } from 'node:child_process';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const entry = 'src/index.ts';
 | 
				
			||||||
 | 
					const naming = 'app';
 | 
				
			||||||
 | 
					const external = ['sequelize', 'pg', 'sqlite3', 'minio', '@kevisual/router', 'pm2'];
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @type {import('bun').BuildConfig}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					await Bun.build({
 | 
				
			||||||
 | 
					  target: 'node',
 | 
				
			||||||
 | 
					  format: 'esm',
 | 
				
			||||||
 | 
					  entrypoints: [resolvePath(entry, { meta: import.meta })],
 | 
				
			||||||
 | 
					  outdir: resolvePath('./dist', { meta: import.meta }),
 | 
				
			||||||
 | 
					  naming: {
 | 
				
			||||||
 | 
					    entry: `${naming}.js`,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  external: external,
 | 
				
			||||||
 | 
					  env: 'KEVISUAL_*',
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// const cmd = `dts -i src/index.ts -o app.d.ts`;
 | 
				
			||||||
 | 
					const cmd = `dts -i ${entry} -o ${naming}.d.ts`;
 | 
				
			||||||
 | 
					execSync(cmd, { stdio: 'inherit' });
 | 
				
			||||||
							
								
								
									
										66
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "ai-pages-services",
 | 
				
			||||||
 | 
					  "version": "0.0.1",
 | 
				
			||||||
 | 
					  "description": "",
 | 
				
			||||||
 | 
					  "main": "index.js",
 | 
				
			||||||
 | 
					  "basename": "/root/ai-pages-services",
 | 
				
			||||||
 | 
					  "app": {
 | 
				
			||||||
 | 
					    "key": "ai-pages-services",
 | 
				
			||||||
 | 
					    "entry": "dist/app.js",
 | 
				
			||||||
 | 
					    "type": "system-app"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "files": [
 | 
				
			||||||
 | 
					    "dist"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "dev": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0  bun --watch src/dev.ts ",
 | 
				
			||||||
 | 
					    "build": "rimraf dist && bun run bun.config.mjs",
 | 
				
			||||||
 | 
					    "test": "tsx  test/**/*.ts",
 | 
				
			||||||
 | 
					    "clean": "rm -rf dist",
 | 
				
			||||||
 | 
					    "pub": "npm run build && envision pack -p -u",
 | 
				
			||||||
 | 
					    "cmd": "tsx cmd/index.ts "
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "keywords": [],
 | 
				
			||||||
 | 
					  "author": "abearxiong <xiongxiao@xiongxiao.me>",
 | 
				
			||||||
 | 
					  "license": "MIT",
 | 
				
			||||||
 | 
					  "type": "module",
 | 
				
			||||||
 | 
					  "types": "types/index.d.ts",
 | 
				
			||||||
 | 
					  "publishConfig": {
 | 
				
			||||||
 | 
					    "access": "public"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@kevisual/code-center-module": "0.0.23",
 | 
				
			||||||
 | 
					    "@kevisual/router": "0.0.22",
 | 
				
			||||||
 | 
					    "@kevisual/use-config": "^1.0.18",
 | 
				
			||||||
 | 
					    "cookie": "^1.0.2",
 | 
				
			||||||
 | 
					    "dayjs": "^1.11.13",
 | 
				
			||||||
 | 
					    "formidable": "^3.5.4",
 | 
				
			||||||
 | 
					    "lodash-es": "^4.17.21"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "@kevisual/context": "^0.0.3",
 | 
				
			||||||
 | 
					    "@kevisual/logger": "^0.0.4",
 | 
				
			||||||
 | 
					    "@kevisual/oss": "^0.0.12",
 | 
				
			||||||
 | 
					    "@kevisual/types": "^0.0.10",
 | 
				
			||||||
 | 
					    "@kevisual/use-config": "^1.0.19",
 | 
				
			||||||
 | 
					    "@types/bun": "^1.2.16",
 | 
				
			||||||
 | 
					    "@types/crypto-js": "^4.2.2",
 | 
				
			||||||
 | 
					    "@types/formidable": "^3.4.5",
 | 
				
			||||||
 | 
					    "@types/lodash-es": "^4.17.12",
 | 
				
			||||||
 | 
					    "@types/node": "^24.0.3",
 | 
				
			||||||
 | 
					    "commander": "^14.0.0",
 | 
				
			||||||
 | 
					    "concurrently": "^9.1.2",
 | 
				
			||||||
 | 
					    "cross-env": "^7.0.3",
 | 
				
			||||||
 | 
					    "inquire": "^0.4.8",
 | 
				
			||||||
 | 
					    "ioredis": "^5.6.1",
 | 
				
			||||||
 | 
					    "minio": "^8.0.5",
 | 
				
			||||||
 | 
					    "nanoid": "^5.1.5",
 | 
				
			||||||
 | 
					    "nodemon": "^3.1.10",
 | 
				
			||||||
 | 
					    "pg": "^8.16.1",
 | 
				
			||||||
 | 
					    "rimraf": "^6.0.1",
 | 
				
			||||||
 | 
					    "sequelize": "^6.37.7",
 | 
				
			||||||
 | 
					    "tape": "^5.9.0",
 | 
				
			||||||
 | 
					    "typescript": "^5.8.3"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "packageManager": "pnpm@10.12.1"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2789
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2789
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2
									
								
								pnpm-workspace.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								pnpm-workspace.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					packages:
 | 
				
			||||||
 | 
					  - 'apps/*'
 | 
				
			||||||
							
								
								
									
										30
									
								
								src/examples/dash-scope/tts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/examples/dash-scope/tts.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					// 使用DashScope API进行TTS (文本转语音) 请求
 | 
				
			||||||
 | 
					export const dashscopeTTS = async ({ text, voice = 'Chelsie', token }) => {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const response = await fetch('https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation', {
 | 
				
			||||||
 | 
					      method: 'POST',
 | 
				
			||||||
 | 
					      headers: {
 | 
				
			||||||
 | 
					        Authorization: `Bearer ${token}`,
 | 
				
			||||||
 | 
					        'Content-Type': 'application/json',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      body: JSON.stringify({
 | 
				
			||||||
 | 
					        // model: 'qwen-tts',
 | 
				
			||||||
 | 
					        model: 'qwen-tts-latest',
 | 
				
			||||||
 | 
					        input: {
 | 
				
			||||||
 | 
					          text,
 | 
				
			||||||
 | 
					          voice,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!response.ok) {
 | 
				
			||||||
 | 
					      throw new Error(`HTTP error! Status: ${response.status}`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const data = await response.json();
 | 
				
			||||||
 | 
					    return data;
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    console.error('TTS 请求失败:', error);
 | 
				
			||||||
 | 
					    throw error;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										4
									
								
								src/modules/config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/modules/config.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					import { useConfig } from '@kevisual/use-config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const config = useConfig();
 | 
				
			||||||
 | 
					export const isDev = config.ENV === 'development';
 | 
				
			||||||
							
								
								
									
										6
									
								
								src/modules/logger.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/modules/logger.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					import { Logger } from '@kevisual/logger';
 | 
				
			||||||
 | 
					import { config } from './config.ts';
 | 
				
			||||||
 | 
					export const logger = new Logger({
 | 
				
			||||||
 | 
					  level: config.LOG_LEVEL || 'info',
 | 
				
			||||||
 | 
					  showTime: true,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										41
									
								
								src/modules/minio.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/modules/minio.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					import { Client, ClientOptions } from 'minio';
 | 
				
			||||||
 | 
					import { config } from './config.ts';
 | 
				
			||||||
 | 
					import { OssBase } from '@kevisual/oss/services';
 | 
				
			||||||
 | 
					import { useContextKey } from '@kevisual/context';
 | 
				
			||||||
 | 
					const minioConfig = {
 | 
				
			||||||
 | 
					  endPoint: config.MINIO_ENDPOINT || 'localhost',
 | 
				
			||||||
 | 
					  port: parseInt(config.MINIO_PORT || '9000'),
 | 
				
			||||||
 | 
					  useSSL: config.MINIO_USE_SSL === 'true',
 | 
				
			||||||
 | 
					  accessKey: config.MINIO_ACCESS_KEY,
 | 
				
			||||||
 | 
					  secretKey: config.MINIO_SECRET_KEY,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					export const minioClient = useContextKey('minioClient', () => {
 | 
				
			||||||
 | 
					  return new Client(minioConfig);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const bucketName = config.MINIO_BUCKET_NAME || 'resources';
 | 
				
			||||||
 | 
					if (!minioClient) {
 | 
				
			||||||
 | 
					  throw new Error('Minio client not initialized');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const check = () => {
 | 
				
			||||||
 | 
					  // 验证权限
 | 
				
			||||||
 | 
					  (async () => {
 | 
				
			||||||
 | 
					    const bucketExists = await minioClient.bucketExists(bucketName);
 | 
				
			||||||
 | 
					    if (!bucketExists) {
 | 
				
			||||||
 | 
					      await minioClient.makeBucket(bucketName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    console.log('bucketExists', bucketExists);
 | 
				
			||||||
 | 
					    // const res = await minioClient.putObject(bucketName, 'root/test/0.0.1/a.txt', 'test');
 | 
				
			||||||
 | 
					    // console.log('minio putObject', res);
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const oss = useContextKey(
 | 
				
			||||||
 | 
					  'oss',
 | 
				
			||||||
 | 
					  new OssBase({
 | 
				
			||||||
 | 
					    client: minioClient,
 | 
				
			||||||
 | 
					    bucketName: bucketName,
 | 
				
			||||||
 | 
					    prefix: '',
 | 
				
			||||||
 | 
					  }),
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/modules/notify.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/modules/notify.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					export const notify = () => {
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/modules/redis.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/modules/redis.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					import { Redis } from 'ioredis';
 | 
				
			||||||
 | 
					import { config } from './config.ts';
 | 
				
			||||||
 | 
					import { useContextKey } from '@kevisual/context';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const redisConfig = {
 | 
				
			||||||
 | 
					  host: config.REDIS_HOST || 'localhost',
 | 
				
			||||||
 | 
					  port: parseInt(config.REDIS_PORT || '6379'),
 | 
				
			||||||
 | 
					  password: config.REDIS_PASSWORD,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					export const createRedisClient = (options = {}) => {
 | 
				
			||||||
 | 
					  const redisClient = new Redis({
 | 
				
			||||||
 | 
					    host: 'localhost', // Redis 服务器的主机名或 IP 地址
 | 
				
			||||||
 | 
					    port: 6379, // Redis 服务器的端口号
 | 
				
			||||||
 | 
					    // password: 'your_password', // Redis 的密码 (如果有)
 | 
				
			||||||
 | 
					    db: 0, // 要使用的 Redis 数据库索引 (0-15)
 | 
				
			||||||
 | 
					    keyPrefix: '', // key 前缀
 | 
				
			||||||
 | 
					    retryStrategy(times) {
 | 
				
			||||||
 | 
					      // 连接重试策略
 | 
				
			||||||
 | 
					      return Math.min(times * 50, 2000); // 每次重试时延迟增加
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    maxRetriesPerRequest: null, // 允许请求重试的次数 (如果需要无限次重试)
 | 
				
			||||||
 | 
					    ...redisConfig,
 | 
				
			||||||
 | 
					    ...options,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  redisClient.on('connect', () => {
 | 
				
			||||||
 | 
					    console.log('Redis client connected successfully');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  redisClient.on('error', (err) => {
 | 
				
			||||||
 | 
					    console.error('Redis client error:', err);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  return redisClient;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					// 配置 Redis 连接
 | 
				
			||||||
 | 
					export const redis = useContextKey('redis', () => createRedisClient());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 初始化 Redis 客户端
 | 
				
			||||||
 | 
					// export const redisPublisher = createRedisClient(); // 用于发布消息
 | 
				
			||||||
 | 
					// export const redisSubscriber = createRedisClient(); // 用于订阅消息
 | 
				
			||||||
							
								
								
									
										6
									
								
								src/modules/router.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/modules/router.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					import { App } from '@kevisual/router';
 | 
				
			||||||
 | 
					import { useContextKey } from '@kevisual/context';
 | 
				
			||||||
 | 
					const init = () => {
 | 
				
			||||||
 | 
					  return new App();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					export const app = useContextKey('app', init);
 | 
				
			||||||
							
								
								
									
										34
									
								
								src/modules/sequelize.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/modules/sequelize.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import { Sequelize } from 'sequelize';
 | 
				
			||||||
 | 
					import { config } from './config.ts';
 | 
				
			||||||
 | 
					import { useContextKey } from '@kevisual/context';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type PostgresConfig = {
 | 
				
			||||||
 | 
					  postgres: {
 | 
				
			||||||
 | 
					    username: string;
 | 
				
			||||||
 | 
					    password: string;
 | 
				
			||||||
 | 
					    host: string;
 | 
				
			||||||
 | 
					    port: number;
 | 
				
			||||||
 | 
					    database: string;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					if (!config.POSTGRES_PASSWORD || !config.POSTGRES_USER) {
 | 
				
			||||||
 | 
					  console.error('postgres config is required password and user');
 | 
				
			||||||
 | 
					  process.exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const postgresConfig = {
 | 
				
			||||||
 | 
					  username: config.POSTGRES_USER,
 | 
				
			||||||
 | 
					  password: config.POSTGRES_PASSWORD,
 | 
				
			||||||
 | 
					  host: config.POSTGRES_HOST || 'localhost',
 | 
				
			||||||
 | 
					  port: parseInt(config.POSTGRES_PORT || '5432'),
 | 
				
			||||||
 | 
					  database: config.POSTGRES_DB || 'postgres',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const init = async () => {
 | 
				
			||||||
 | 
					  return new Sequelize({
 | 
				
			||||||
 | 
					    dialect: 'postgres',
 | 
				
			||||||
 | 
					    ...postgresConfig,
 | 
				
			||||||
 | 
					    // logging: false,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const sequelize = useContextKey('sequelize', () => init());
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/modules/user.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/modules/user.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					import { sequelize, User, UserInit, Org, OrgInit } from '@kevisual/code-center-module';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { sequelize, User, UserInit, Org, OrgInit };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const init = () => {
 | 
				
			||||||
 | 
					  UserInit();
 | 
				
			||||||
 | 
					  OrgInit();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					init();
 | 
				
			||||||
							
								
								
									
										26
									
								
								src/utils/random.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/utils/random.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					import { customAlphabet } from 'nanoid';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const letter = 'abcdefghijklmnopqrstuvwxyz';
 | 
				
			||||||
 | 
					export const number = '0123456789';
 | 
				
			||||||
 | 
					const alphanumeric = `${letter}${number}`;
 | 
				
			||||||
 | 
					export const alphanumericWithDash = `${alphanumeric}-`;
 | 
				
			||||||
 | 
					export const uuid = customAlphabet(letter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const nanoid = customAlphabet(alphanumeric, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const nanoidWithDash = customAlphabet(alphanumericWithDash, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 创建一个随机的 id,以字母开头的字符串
 | 
				
			||||||
 | 
					 * @param number
 | 
				
			||||||
 | 
					 * @returns
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const randomId = (number: number) => {
 | 
				
			||||||
 | 
					  const _letter = uuid(1);
 | 
				
			||||||
 | 
					  return `${_letter}${nanoid(number)}`;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const randomLetter = (number: number = 8, opts?: { before?: string; after?: string }) => {
 | 
				
			||||||
 | 
					  const { before = '', after = '' } = opts || {};
 | 
				
			||||||
 | 
					  return `${before}${uuid(number)}${after}`;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										19
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "extends": "@kevisual/types/json/backend.json",
 | 
				
			||||||
 | 
					  "compilerOptions": {
 | 
				
			||||||
 | 
					    "baseUrl": ".",
 | 
				
			||||||
 | 
					    "typeRoots": [
 | 
				
			||||||
 | 
					      "./node_modules/@types",
 | 
				
			||||||
 | 
					      "./node_modules/@kevisual"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "paths": {
 | 
				
			||||||
 | 
					      "@/*": [
 | 
				
			||||||
 | 
					        "src/*"
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "include": [
 | 
				
			||||||
 | 
					    "src/**/*",
 | 
				
			||||||
 | 
					    "apps/**/*",
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user