diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..8dac1b5 --- /dev/null +++ b/.cursorrules @@ -0,0 +1,64 @@ +# .cursorrules + +# Code Generation and Modification Rules +- When generating or modifying code, strictly adhere to the user-specified task requirements and do not add extra functionality, edge cases, or unrequested sanity code. +- Keep code concise, including only the minimum required to complete the task. +- Avoid generating files, classes, functions, or configuration that are not explicitly required. +- If the task does not clearly specify implementation details, prioritize the simplest, most direct solution. +- When generating business logic code, do not generate sample code or unit test code unless explicitly requested by the user. + +# CSS Style Rules +- All CSS styles must use Tailwind CSS 3.x syntax. +- Use of native CSS (e.g., style attributes or .css files) or other CSS frameworks (e.g., less) is prohibited. +- If Tailwind CSS configuration is required, ensure that the syntax of the latest stable version of Tailwind CSS 3.x is used. + +# HTML and Component Tag Rules +- When generating HTML or components, all meaningful tags (such as div , section , button , etc.) must include a data-alt="xxxx" attribute describing the tag's purpose. +- The value of the data-alt attribute should be concise, clear, and accurately reflect the tag's function or purpose (e.g., "main-content" or "submit-button"). +- Examples: +-
...
+- +- Avoid adding data-alt to meaningless tags (such as empty divs or simple containers) unless explicitly specified. + +# Feature Solution Design Rules +- When writing a feature solution for a particular function, always provide up to three optimal implementation options in plain text. +- Each solution should briefly describe its core concept, advantages and disadvantages, and applicable scenarios. - Wait until the user explicitly agrees or selects a solution before generating the corresponding code. +- Avoid verbose solution descriptions, limiting them to 3-5 sentences per solution. + +# Comment Style +- For fields, properties, or small code blocks, use concise documentation comments in the /** xxx */ style to describe their core purpose. +- For complex functions, use full JSDoc comments in the following format: +- Start with /** and include * to align each line. +- Include @description to describe the function's main functionality. +- For each parameter, use the @param {type} name - description format to clearly indicate its type and purpose. +- For return values, use the @returns {type} - description format to describe the return value. +- If a function throws an exception, use @throws {Error} - description to indicate the possible exception. +- If appropriate, include @example to provide a brief usage example. +- Example: +/** +* Calculates the sum of two numbers. +* @param {number} a - The first number. +* @param {number} b - The second number. +* @returns {number} - The sum of a and b. +* @throws {Error} - If inputs are not numbers. +* @example +* sum(2, 3); // Returns 5 +*/ +- Avoid lengthy comments for simple code (such as getters/setters or single-line functions). +- Comments should be concise and avoid lengthy descriptions. +- Ensure that comments are comprehensive. + +# Code Analysis Rules +- When analyzing code, allow sufficient time to ensure that the results are accurate and comprehensive. +- Provide complete analysis results, covering all relevant details but without irrelevant speculation or assumptions. +- If the analysis involves potential problems, list the specific problems and provide concise solution suggestions. +- Analyze but don't directly modify files to generate code. Instead, provide suggestions and let users choose whether to copy and use. + +# General Preferences +- Follow the latest stable TypeScript syntax (currently 5.x). +- Use camelCase for variable and function names, and PascalCase for class and interface names. +- Prefer const to declare variables, using let only when reassigning values; avoid using var. +- Follow Airbnb TypeScript standards for coding style (e.g., 4-space indentation, single quotes). +- Avoid generating console.log or debugging code unless explicitly requested by the user. +- Unless explicitly requested by the user, combine hook handlers where possible. +- Always use async over .then for asynchronous functions. diff --git a/api/request.ts b/api/request.ts index d49ec19..421a929 100644 --- a/api/request.ts +++ b/api/request.ts @@ -13,7 +13,7 @@ const request: AxiosInstance = axios.create({ request.interceptors.request.use( (config: InternalAxiosRequestConfig) => { // 从 localStorage 获取 token - const token = localStorage.getItem('token') || 'mock-token'; + const token = localStorage?.getItem('token') || 'mock-token'; if (token && config.headers) { (config.headers as AxiosHeaders).set('Authorization', `Bearer ${token}`); } @@ -35,7 +35,7 @@ request.interceptors.response.use( switch (error.response.status) { case 401: // 未授权,清除 token 并跳转到登录页 - localStorage.removeItem('token'); + localStorage?.removeItem('token'); window.location.href = '/login'; break; case 403: @@ -91,7 +91,7 @@ export async function streamJsonPost( onJson: (json: T) => void ) { try { - const token = localStorage.getItem('token') || 'mock-token'; + const token = localStorage?.getItem('token') || 'mock-token'; const response = await fetch(`${BASE_URL}${url}`, { method: 'POST', headers: { @@ -116,7 +116,7 @@ export async function streamJsonPost( try { while (true) { const { done, value } = await reader.read(); - + if (done) { // Process any remaining data in the buffer if (buffer.trim()) { @@ -261,4 +261,4 @@ export const downloadStream = async ( }; // 导出 request 实例 -export default request; \ No newline at end of file +export default request; diff --git a/api/video_flow.ts b/api/video_flow.ts index 2d71a90..181fc55 100644 --- a/api/video_flow.ts +++ b/api/video_flow.ts @@ -577,7 +577,7 @@ export const generateScriptStream = async (request: { /** 剧本提示词 */ prompt: string; }) => { - return post>('/movie/generate_script_stream', request,{ + return post>('/text_to_script/generate_script_stream', request,{ responseType: 'stream', }); }; diff --git a/app/service/test/Script.test.ts b/app/service/test/Script.test.ts new file mode 100644 index 0000000..b89797c --- /dev/null +++ b/app/service/test/Script.test.ts @@ -0,0 +1,46 @@ +import { generateScriptStream } from '../../../api/video_flow'; + +describe('ScriptService 业务逻辑测试', () => { + describe('generateScriptStream 真实接口测试', () => { + it('应该成功调用 generateScriptStream 接口并输出流数据', async () => { + /** + * 测试 generateScriptStream 流式接口,持续监听数据直到流结束 + */ + const stream = await generateScriptStream({ + prompt: '一个年轻人在咖啡店里等待他的约会对象,心情紧张地摆弄着手机。' + }); + + let allData = ''; + let isSuccessful: boolean | undefined = undefined; + let message: string | undefined = undefined; + + // 假设 stream 是一个异步可迭代对象 + try { + for await (const chunk of stream.data) { + console.log(chunk); + + if (typeof chunk.data === 'string') { + allData += chunk.data; + } + if (typeof chunk.successful === 'boolean') { + isSuccessful = chunk.successful; + } + if (typeof chunk.message === 'string') { + message = chunk.message; + } + } + } catch (err) { + console.error('流式接口监听出错:', err); + throw err; + } + + // 输出流式数据及状态 + console.log('generateScriptStream 流式数据:', allData); + console.log('响应状态:', isSuccessful); + console.log('响应消息:', message); + + expect(allData).toBeDefined(); + expect(typeof isSuccessful).toBe('boolean'); + }); + }); +}); diff --git a/app/service/test/ScriptService.test.ts b/app/service/test/ScriptService.test.ts deleted file mode 100644 index 28e6390..0000000 --- a/app/service/test/ScriptService.test.ts +++ /dev/null @@ -1,484 +0,0 @@ -import { generateScriptStream, applyScriptToShot, getProjectScript } from '../../../api/video_flow'; -import { ScriptEditUseCase } from '../usecase/ScriptEditUseCase'; -import { ScriptSlice, ScriptSliceType } from '../domain/valueObject'; - -// Mock API模块 -jest.mock('@/api/video_flow', () => ({ - generateScriptStream: jest.fn(), - applyScriptToShot: jest.fn(), - getProjectScript: jest.fn(), -})); - -// Mock UseCase模块 -jest.mock('../usecase/ScriptEditUseCase'); - -describe('ScriptService 业务逻辑测试', () => { - let mockScriptEditUseCase: jest.Mocked; - - // 测试数据 - const mockScriptSlices: ScriptSlice[] = [ - { - id: 'slice1', - type: ScriptSliceType.role, - text: '你好,我是主角', - metaData: { speaker: '主角', emotion: '友好' } - }, - { - id: 'slice2', - type: ScriptSliceType.scene, - text: '场景:阳光明媚的公园', - metaData: { location: '公园', weather: '晴天' } - }, - { - id: 'slice3', - type: ScriptSliceType.text, - text: '这是一个温馨的故事', - metaData: { style: '温馨' } - } - ]; - - const mockStreamData = [ - { id: 'slice1', type: 'role', text: '你好,我是主角', metaData: { speaker: '主角' } }, - { id: 'slice2', type: 'scene', text: '场景:阳光明媚的公园', metaData: { location: '公园' } }, - { id: 'slice3', type: 'text', text: '这是一个温馨的故事', metaData: { style: '温馨' } } - ]; - - beforeEach(() => { - jest.clearAllMocks(); - - // 设置Mock UseCase实例 - mockScriptEditUseCase = { - generateScript: jest.fn(), - applyScript: jest.fn(), - updateScriptSlice: jest.fn(), - getScriptSlices: jest.fn(), - toString: jest.fn(), - } as any; - - // 设置Mock构造函数 - (ScriptEditUseCase as jest.MockedClass).mockImplementation(() => mockScriptEditUseCase); - - // 设置默认的Mock返回值 - mockScriptEditUseCase.getScriptSlices.mockReturnValue(mockScriptSlices); - mockScriptEditUseCase.toString.mockReturnValue('你好,我是主角\n场景:阳光明媚的公园\n这是一个温馨的故事'); - mockScriptEditUseCase.updateScriptSlice.mockReturnValue(true); - mockScriptEditUseCase.generateScript.mockResolvedValue(); - mockScriptEditUseCase.applyScript.mockResolvedValue(); - - // Mock流式数据 - (generateScriptStream as jest.Mock).mockResolvedValue(mockStreamData); - (applyScriptToShot as jest.Mock).mockResolvedValue({ - successful: true, - data: { success: true }, - }); - (getProjectScript as jest.Mock).mockResolvedValue({ - successful: true, - data: { - prompt: '创建一个关于友谊的温馨故事', - scriptText: '你好,我是主角\n场景:阳光明媚的公园\n这是一个温馨的故事' - } - }); - }); - - describe('剧本业务流程测试', () => { - it('应该完成完整的剧本编辑流程:根据提示词生成剧本→修改提示词重新生成→重置提示词重新生成→修改剧本→应用剧本', async () => { - // 1. 用户操作:根据提示词生成新剧本 - const initialPrompt = '创建一个关于友谊的温馨故事'; - - // 模拟AI生成剧本的流式数据 - const mockStream = (async function* () { - for (const data of mockStreamData) { - yield data; - } - })(); - - (generateScriptStream as jest.Mock).mockResolvedValue(mockStream); - mockScriptEditUseCase.generateScript.mockImplementation(async (prompt) => { - // 模拟流式处理 - for await (const chunk of mockStream) { - // 这里可以模拟逐步添加剧本片段 - } - }); - - // 创建剧本编辑用例并生成剧本 - const scriptEditUseCase = new ScriptEditUseCase(''); - await scriptEditUseCase.generateScript(initialPrompt); - - expect(ScriptEditUseCase).toHaveBeenCalledWith(''); - expect(mockScriptEditUseCase.generateScript).toHaveBeenCalledWith(initialPrompt); - - // 验证生成的剧本内容 - const generatedScript = scriptEditUseCase.toString(); - expect(generatedScript).toContain('你好,我是主角'); - expect(generatedScript).toContain('场景:阳光明媚的公园'); - - // 验证剧本片段 - const scriptSlices = scriptEditUseCase.getScriptSlices(); - expect(scriptSlices).toHaveLength(3); - expect(scriptSlices[0].type).toBe(ScriptSliceType.role); - expect(scriptSlices[1].type).toBe(ScriptSliceType.scene); - - // 2. 用户操作:修改提示词重新生成剧本 - const modifiedPrompt = '创建一个关于冒险的刺激故事'; - - // 模拟修改后的剧本数据 - const modifiedScriptSlices: ScriptSlice[] = [ - { - id: 'slice1', - type: ScriptSliceType.role, - text: '我们出发吧!', - metaData: { speaker: '冒险者', emotion: '兴奋' } - }, - { - id: 'slice2', - type: ScriptSliceType.scene, - text: '场景:神秘的森林', - metaData: { location: '森林', atmosphere: '神秘' } - }, - { - id: 'slice3', - type: ScriptSliceType.text, - text: '这是一个充满挑战的冒险', - metaData: { style: '冒险' } - } - ]; - - mockScriptEditUseCase.getScriptSlices.mockReturnValue(modifiedScriptSlices); - mockScriptEditUseCase.toString.mockReturnValue('我们出发吧!\n场景:神秘的森林\n这是一个充满挑战的冒险'); - - // 重新生成剧本 - await scriptEditUseCase.generateScript(modifiedPrompt); - - expect(mockScriptEditUseCase.generateScript).toHaveBeenCalledWith(modifiedPrompt); - - // 验证修改后的剧本内容 - const modifiedScript = scriptEditUseCase.toString(); - expect(modifiedScript).toContain('我们出发吧!'); - expect(modifiedScript).toContain('神秘的森林'); - expect(modifiedScript).toContain('充满挑战的冒险'); - - // 3. 用户操作:重置提示词重新生成剧本 - const resetPrompt = '创建一个关于友谊的温馨故事'; // 回到初始提示词 - - // 模拟重置后的剧本数据(回到初始状态) - mockScriptEditUseCase.getScriptSlices.mockReturnValue(mockScriptSlices); - mockScriptEditUseCase.toString.mockReturnValue('你好,我是主角\n场景:阳光明媚的公园\n这是一个温馨的故事'); - - // 重置并重新生成剧本 - await scriptEditUseCase.generateScript(resetPrompt); - - expect(mockScriptEditUseCase.generateScript).toHaveBeenCalledWith(resetPrompt); - - // 验证重置后的剧本内容 - const resetScript = scriptEditUseCase.toString(); - expect(resetScript).toContain('你好,我是主角'); - expect(resetScript).toContain('阳光明媚的公园'); - expect(resetScript).toContain('温馨的故事'); - - // 4. 用户操作:修改剧本片段 - const updatedText = '你好,我是勇敢的主角'; - const updatedMetaData = { speaker: '主角', emotion: '勇敢' }; - - // 修改第一个剧本片段 - const updateSuccess = scriptEditUseCase.updateScriptSlice('slice1', updatedText, updatedMetaData); - expect(updateSuccess).toBe(true); - expect(mockScriptEditUseCase.updateScriptSlice).toHaveBeenCalledWith('slice1', updatedText, updatedMetaData); - - // 验证修改后的片段 - const updatedSlices = scriptEditUseCase.getScriptSlices(); - // 注意:mock返回的数据不会因为updateScriptSlice调用而改变 - // 这里只是验证getScriptSlices被正确调用 - expect(updatedSlices).toEqual(mockScriptSlices); - - // 5. 用户操作:应用剧本到分镜 - // 应用剧本 - await scriptEditUseCase.applyScript(); - - expect(mockScriptEditUseCase.applyScript).toHaveBeenCalled(); - - // 验证API调用 - expect(applyScriptToShot).toHaveBeenCalledWith({ - scriptSlices: updatedSlices - }); - }); - - it('应该验证剧本生成的不同提示词效果', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - - // 测试不同类型的提示词 - const testPrompts = [ - '创建一个浪漫的爱情故事', - '创建一个悬疑的侦探故事', - '创建一个科幻的未来故事' - ]; - - for (const prompt of testPrompts) { - await scriptEditUseCase.generateScript(prompt); - expect(mockScriptEditUseCase.generateScript).toHaveBeenCalledWith(prompt); - } - - // 验证每个提示词都被正确处理 - expect(mockScriptEditUseCase.generateScript).toHaveBeenCalledTimes(testPrompts.length); - }); - - it('应该验证剧本片段的修改和更新', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - await scriptEditUseCase.generateScript('测试剧本'); - - // 测试修改不同类型的剧本片段 - const testUpdates = [ - { - id: 'slice1', - text: '修改后的对话', - metaData: { speaker: '新角色', emotion: '愤怒' } - }, - { - id: 'slice2', - text: '修改后的场景描述', - metaData: { location: '新地点', weather: '雨天' } - }, - { - id: 'slice3', - text: '修改后的文本内容', - metaData: { style: '新风格', tone: '严肃' } - } - ]; - - for (const update of testUpdates) { - const success = scriptEditUseCase.updateScriptSlice(update.id, update.text, update.metaData); - expect(success).toBe(true); - expect(mockScriptEditUseCase.updateScriptSlice).toHaveBeenCalledWith( - update.id, - update.text, - update.metaData - ); - } - - // 验证所有修改都被正确处理 - expect(mockScriptEditUseCase.updateScriptSlice).toHaveBeenCalledTimes(testUpdates.length); - }); - - it('应该处理剧本编辑流程中的错误情况', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - - // 模拟生成剧本失败 - mockScriptEditUseCase.generateScript.mockRejectedValue(new Error('AI生成失败')); - - await expect(scriptEditUseCase.generateScript('测试提示词')).rejects.toThrow('AI生成失败'); - - // 模拟更新剧本片段失败 - mockScriptEditUseCase.updateScriptSlice.mockReturnValue(false); - - const updateResult = scriptEditUseCase.updateScriptSlice('nonexistent', '新文本'); - expect(updateResult).toBe(false); - - // 模拟应用剧本失败 - mockScriptEditUseCase.applyScript.mockRejectedValue(new Error('应用剧本失败')); - - await expect(scriptEditUseCase.applyScript()).rejects.toThrow('应用剧本失败'); - }); - }); - - describe('剧本流式生成测试', () => { - it('应该正确处理流式剧本生成', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - - // 模拟流式数据生成 - const streamChunks = [ - { id: 'slice1', type: 'role', text: '第一段对话', metaData: { speaker: '角色1' } }, - { id: 'slice2', type: 'scene', text: '场景描述', metaData: { location: '地点1' } }, - { id: 'slice3', type: 'text', text: '叙述文本', metaData: { style: '风格1' } } - ]; - - let chunkIndex = 0; - const mockStream = (async function* () { - for (const chunk of streamChunks) { - yield chunk; - chunkIndex++; - } - })(); - - (generateScriptStream as jest.Mock).mockResolvedValue(mockStream); - - // 模拟流式处理 - mockScriptEditUseCase.generateScript.mockImplementation(async (prompt) => { - for await (const chunk of mockStream) { - // 模拟逐步处理每个片段 - // 注意:这里不需要验证chunk,因为mockStream已经包含了正确的数据 - } - }); - - await scriptEditUseCase.generateScript('流式生成测试'); - - expect(mockScriptEditUseCase.generateScript).toHaveBeenCalledWith('流式生成测试'); - expect(chunkIndex).toBe(streamChunks.length); - }); - - it('应该处理流式生成中的错误', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - - // 模拟流式数据生成失败 - const mockErrorStream = (async function* () { - throw new Error('流式生成错误'); - })(); - - (generateScriptStream as jest.Mock).mockResolvedValue(mockErrorStream); - - mockScriptEditUseCase.generateScript.mockImplementation(async () => { - for await (const chunk of mockErrorStream) { - // 这里不会执行,因为流会抛出错误 - } - }); - - await expect(scriptEditUseCase.generateScript('错误测试')).rejects.toThrow('流式生成错误'); - }); - }); - - describe('剧本应用测试', () => { - it('应该成功应用剧本到分镜', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - - // 先生成剧本 - await scriptEditUseCase.generateScript('应用测试'); - - // 应用剧本 - await scriptEditUseCase.applyScript(); - - expect(mockScriptEditUseCase.applyScript).toHaveBeenCalled(); - }); - - it('应该处理应用剧本失败的情况', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - - // 模拟应用失败 - (applyScriptToShot as jest.Mock).mockResolvedValue({ - successful: false, - message: '应用剧本失败', - }); - - mockScriptEditUseCase.applyScript.mockRejectedValue(new Error('应用失败')); - - await expect(scriptEditUseCase.applyScript()).rejects.toThrow('应用失败'); - }); - }); - - describe('剧本状态管理测试', () => { - it('应该正确管理剧本的生成状态', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - - // 设置初始状态为空数组 - mockScriptEditUseCase.getScriptSlices.mockReturnValue([]); - - // 初始状态应该是空的 - const initialSlices = scriptEditUseCase.getScriptSlices(); - expect(initialSlices).toEqual([]); - - // 生成剧本后应该有内容 - await scriptEditUseCase.generateScript('状态测试'); - - // 重新设置mock返回值为有内容的数组 - mockScriptEditUseCase.getScriptSlices.mockReturnValue(mockScriptSlices); - - const generatedSlices = scriptEditUseCase.getScriptSlices(); - expect(generatedSlices).toEqual(mockScriptSlices); - - // 修改后状态应该更新 - scriptEditUseCase.updateScriptSlice('slice1', '新文本', undefined); - - expect(mockScriptEditUseCase.updateScriptSlice).toHaveBeenCalledWith('slice1', '新文本', undefined); - }); - - it('应该验证剧本文本的完整性', async () => { - const scriptEditUseCase = new ScriptEditUseCase(''); - - await scriptEditUseCase.generateScript('完整性测试'); - - const scriptText = scriptEditUseCase.toString(); - const scriptSlices = scriptEditUseCase.getScriptSlices(); - - // 验证文本包含所有片段的内容 - for (const slice of scriptSlices) { - expect(scriptText).toContain(slice.text); - } - - // 验证片段数量与文本行数匹配 - const textLines = scriptText.split('\n').filter(line => line.trim()); - expect(textLines.length).toBeGreaterThan(0); - }); - - it('应该根据项目ID获取已存在的剧本数据', async () => { - const projectId = 'test-project-123'; - - // 模拟API返回项目剧本数据(只包含提示词和剧本文本) - const mockProjectScriptData = { - prompt: '创建一个关于冒险的故事', - scriptText: '我们出发吧!\n场景:神秘的森林\n这是一个充满挑战的冒险' - }; - - (getProjectScript as jest.Mock).mockResolvedValue({ - successful: true, - data: mockProjectScriptData - }); - - // 创建剧本编辑用例并模拟解析逻辑 - const scriptEditUseCase = new ScriptEditUseCase(mockProjectScriptData.scriptText); - - // 模拟解析后的剧本片段(这是UseCase内部逻辑的结果) - const mockParsedSlices = [ - { - id: 'slice1', - type: ScriptSliceType.role, - text: '我们出发吧!', - metaData: { speaker: '冒险者', emotion: '兴奋' } - }, - { - id: 'slice2', - type: ScriptSliceType.scene, - text: '场景:神秘的森林', - metaData: { location: '森林', atmosphere: '神秘' } - }, - { - id: 'slice3', - type: ScriptSliceType.text, - text: '这是一个充满挑战的冒险', - metaData: { style: '冒险' } - } - ]; - - // 模拟从项目获取剧本数据 - const response = await getProjectScript({ projectId }); - - expect(response.successful).toBe(true); - expect(response.data.prompt).toBe('创建一个关于冒险的故事'); - expect(response.data.scriptText).toContain('我们出发吧!'); - - // 验证API只返回提示词和剧本文本,不包含解析后的片段 - expect(response.data).not.toHaveProperty('scriptSlices'); - - // 验证UseCase能够正确解析剧本文本 - const parsedSlices = scriptEditUseCase.getScriptSlices(); - // 注意:由于ScriptValueObject.parseFromString目前是TODO,这里只是验证调用不会出错 - expect(Array.isArray(parsedSlices)).toBe(true); - - // 验证API调用参数 - expect(getProjectScript).toHaveBeenCalledWith({ projectId }); - }); - - it('应该处理获取项目剧本失败的情况', async () => { - const projectId = 'invalid-project'; - - // 模拟API失败 - (getProjectScript as jest.Mock).mockResolvedValue({ - successful: false, - message: '项目不存在' - }); - - await expect(getProjectScript({ projectId })).resolves.toEqual({ - successful: false, - message: '项目不存在' - }); - - expect(getProjectScript).toHaveBeenCalledWith({ projectId }); - }); - }); -}); diff --git a/app/service/uml/script.plantuml b/app/service/uml/script.plantuml new file mode 100644 index 0000000..3be22ab --- /dev/null +++ b/app/service/uml/script.plantuml @@ -0,0 +1,42 @@ +@startuml 剧本生成 +title 剧本生成与视频制作流程 + +object "用户输入想法" +object "调用剧本生成接口" +object "暂停生成过程" +object "用户修改想法" +object "作废旧的生成结果" +object "继续生成剧本" +object "剧本生成完成" +object "创建项目" +object "保存到数据库" +object "想法锁定" +object "用户手动修改剧本" +object "AI修改已有剧本" +object "用户点击应用" +object "走后端异步任务生成视频" + + +"用户输入想法" --> "调用剧本生成接口" +"调用剧本生成接口" --> "暂停生成过程" : 用户触发暂停? +"调用剧本生成接口" --> "继续生成剧本" : 用户不暂停 + +"暂停生成过程" --> "用户修改想法" +"用户修改想法" --> "作废旧的生成结果" +"作废旧的生成结果" --> "调用剧本生成接口" + +"继续生成剧本" --> "剧本生成完成" + +"剧本生成完成" --> "创建项目" +"创建项目" --> "保存到数据库" +"保存到数据库" --> "想法锁定" + +"想法锁定" --> "用户手动修改剧本" +"想法锁定" --> "AI修改已有剧本" +"用户手动修改剧本" --> "用户点击应用" +"AI修改已有剧本" --> "用户点击应用" + +"用户点击应用" --> "走后端异步任务生成视频" + +@enduml +' https://www.plantuml.com/plantuml/uml/ZLJRJl904BxVfsXwpmly5xzuwMDuu4A3ccXz042bW1m89Hge4ZHO4gKs4WHQbPVfp9QtiCaOMpPRyOPavZlixCv7qwVQzebsTfXLe6IX-SoD7keDfkrhsSnAov_L0kjoUTy4_St_C76IuyCAOySx1vbTJL6vCKHz6dosu6A0XJ6Es-eF5ZY548wROMq0zOU8WPqyv4p2WaKnT5O5PtzXep4NdSD1mEtXjSKxvwJcNWllp9ZQixWt8emcY32gEM7sLVWRm_GkUEwoF-TTEtRUuXP6Dw0xs7QmQeFRYZ2QRMdamEw8qsEf0kKXtK6SOdFhkpzzHRCaegJd-JaKFN2Di8ozwyI1Heq_lS1x7aS3t_EWtAVhqAfKnfXiCqegzV-tjIH2f9IjI_cdS3h8UeHwanWRQvnawucS_5cLR1YJdaW6adJ8ciHEpaiojEwncEmI9985Z4cwH1SojreIGvO_IPFOGYBPQasKv7ZAsFAe9fkGIXPXqMeTdycwHF_Blo2TETeBlt7i2m00 diff --git a/package-lock.json b/package-lock.json index 3e3b7d6..c4ca8f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -130,7 +130,6 @@ }, "node_modules/@ampproject/remapping": { "version": "2.3.0", - "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -239,7 +238,6 @@ }, "node_modules/@babel/code-frame": { "version": "7.27.1", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", @@ -252,7 +250,6 @@ }, "node_modules/@babel/compat-data": { "version": "7.28.0", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -260,7 +257,6 @@ }, "node_modules/@babel/core": { "version": "7.28.0", - "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -291,7 +287,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -304,7 +299,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -312,7 +306,6 @@ }, "node_modules/@babel/generator": { "version": "7.28.0", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.28.0", @@ -327,7 +320,6 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.27.2", @@ -342,7 +334,6 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { "version": "5.1.1", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" @@ -352,7 +343,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -360,7 +350,6 @@ }, "node_modules/@babel/helper-globals": { "version": "7.28.0", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -368,7 +357,6 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.27.1", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -380,7 +368,6 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.27.3", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", @@ -406,7 +393,6 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -414,7 +400,6 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.27.1", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -422,7 +407,6 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.27.1", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -430,7 +414,6 @@ }, "node_modules/@babel/helpers": { "version": "7.28.2", - "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", @@ -442,7 +425,6 @@ }, "node_modules/@babel/parser": { "version": "7.28.0", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.28.0" @@ -704,7 +686,6 @@ }, "node_modules/@babel/template": { "version": "7.27.2", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -717,7 +698,6 @@ }, "node_modules/@babel/traverse": { "version": "7.28.0", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -734,7 +714,6 @@ }, "node_modules/@babel/types": { "version": "7.28.2", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -1738,6 +1717,17 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", + "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", @@ -8225,6 +8215,28 @@ "@types/ms": "*" } }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", @@ -8303,6 +8315,13 @@ "pretty-format": "^30.0.0" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT", + "peer": true + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -8956,12 +8975,187 @@ "win32" ] }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, "node_modules/@webgpu/types": { "version": "0.1.63", "resolved": "https://registry.npmmirror.com/@webgpu/types/-/types-0.1.63.tgz", "integrity": "sha512-s9Kuh0nE/2+nKrvmKNMB2fE5Zlr3DL2t3OFKM55v5jRcfCOxbkOHhQoshoFum5mmXIfEtRXtLCWmkeTJsVjE9w==", "license": "BSD-3-Clause" }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0", + "peer": true + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz", @@ -8974,6 +9168,19 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -8999,6 +9206,48 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT", + "peer": true + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -9666,7 +9915,6 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "dev": true, "license": "MIT" }, "node_modules/busboy": { @@ -9896,6 +10144,16 @@ "node": ">= 6" } }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0" + } + }, "node_modules/ci-info": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", @@ -10145,7 +10403,6 @@ }, "node_modules/convert-source-map": { "version": "2.0.0", - "dev": true, "license": "MIT" }, "node_modules/copy-to-clipboard": { @@ -10904,6 +11161,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT", + "peer": true + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -11553,6 +11817,16 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -11670,6 +11944,23 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "peer": true + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -11955,7 +12246,6 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -13955,6 +14245,37 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/jiti": { "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", @@ -13984,7 +14305,6 @@ }, "node_modules/jsesc": { "version": "3.1.0", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -14001,7 +14321,6 @@ }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", - "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { @@ -14132,6 +14451,16 @@ "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==", "license": "MIT" }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -14464,7 +14793,6 @@ }, "node_modules/merge-stream": { "version": "2.0.0", - "dev": true, "license": "MIT" }, "node_modules/merge2": { @@ -15259,6 +15587,13 @@ "node": ">= 0.6" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT", + "peer": true + }, "node_modules/next": { "version": "13.5.1", "resolved": "https://registry.npmjs.org/next/-/next-13.5.1.tgz", @@ -16382,6 +16717,16 @@ "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==", "license": "MIT" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/rc-cascader": { "version": "3.34.0", "resolved": "https://registry.npmmirror.com/rc-cascader/-/rc-cascader-3.34.0.tgz", @@ -17700,6 +18045,16 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/reselect": { "version": "5.1.1", "resolved": "https://registry.npmmirror.com/reselect/-/reselect-5.1.1.tgz", @@ -17911,6 +18266,63 @@ "loose-envify": "^1.1.0" } }, + "node_modules/schema-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT", + "peer": true + }, "node_modules/scroll": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/scroll/-/scroll-3.0.1.tgz", @@ -17950,6 +18362,16 @@ "node": ">=10" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "license": "MIT", @@ -18126,7 +18548,6 @@ }, "node_modules/source-map": { "version": "0.6.1", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -18141,6 +18562,17 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -18784,6 +19216,67 @@ "node": ">=6" } }, + "node_modules/terser": { + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.14.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT", + "peer": true + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -19583,6 +20076,103 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, + "node_modules/webpack": { + "version": "5.101.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.0.tgz", + "integrity": "sha512-B4t+nJqytPeuZlHuIKTbalhljIFXeNRqrUGAQgTGlfOl2lXXKXw+yZu6bicycP+PUlM44CxBjCFD6aciKFT3LQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.2", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.2", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.1", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/watchpack": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "license": "MIT", + "peer": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -19827,7 +20417,6 @@ }, "node_modules/yallist": { "version": "3.1.1", - "dev": true, "license": "ISC" }, "node_modules/yaml": {