diff --git a/.gitignore b/.gitignore index d912149efb..b48434c4af 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ trivy_report* compiled packages/cli/src/modules/my-feature .secrets +packages/testing/**/.cursor/rules/ diff --git a/cypress/e2e/15-scheduler-node.cy.ts b/cypress/e2e/15-scheduler-node.cy.ts index 65f0904543..24f68f4103 100644 --- a/cypress/e2e/15-scheduler-node.cy.ts +++ b/cypress/e2e/15-scheduler-node.cy.ts @@ -3,7 +3,9 @@ import { WorkflowPage, NDV } from '../pages'; const workflowPage = new WorkflowPage(); const ndv = new NDV(); -describe('Schedule Trigger node', () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('Schedule Trigger node', () => { beforeEach(() => { workflowPage.actions.visit(); }); diff --git a/cypress/e2e/2270-ADO-opening-webhook-ndv-marks-workflow-as-unsaved.cy.ts b/cypress/e2e/2270-ADO-opening-webhook-ndv-marks-workflow-as-unsaved.cy.ts index 05cb3c32d1..6c0b724b86 100644 --- a/cypress/e2e/2270-ADO-opening-webhook-ndv-marks-workflow-as-unsaved.cy.ts +++ b/cypress/e2e/2270-ADO-opening-webhook-ndv-marks-workflow-as-unsaved.cy.ts @@ -4,7 +4,9 @@ import { NDV, WorkflowPage } from '../pages'; const workflowPage = new WorkflowPage(); const ndv = new NDV(); -describe('ADO-2270 Save button resets on webhook node open', () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('ADO-2270 Save button resets on webhook node open', () => { it('should not reset the save button if webhook node is opened and closed', () => { workflowPage.actions.visit(); workflowPage.actions.addInitialNodeToCanvas(WEBHOOK_NODE_NAME); diff --git a/cypress/e2e/28-debug.cy.ts b/cypress/e2e/28-debug.cy.ts index aee5c651b6..79d13b6382 100644 --- a/cypress/e2e/28-debug.cy.ts +++ b/cypress/e2e/28-debug.cy.ts @@ -10,7 +10,9 @@ const workflowPage = new WorkflowPage(); const ndv = new NDV(); const executionsTab = new WorkflowExecutionsTab(); -describe('Debug', () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('Debug', () => { beforeEach(() => { cy.enableFeature('debugInEditor'); }); diff --git a/cypress/e2e/35-admin-user-smoke-test.cy.ts b/cypress/e2e/35-admin-user-smoke-test.cy.ts index 6bb31ae1c2..f267852fc3 100644 --- a/cypress/e2e/35-admin-user-smoke-test.cy.ts +++ b/cypress/e2e/35-admin-user-smoke-test.cy.ts @@ -1,6 +1,8 @@ const url = '/settings'; -describe('Admin user', { disableAutoLogin: true }, () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('Admin user', { disableAutoLogin: true }, () => { it('should see same Settings sub menu items as instance owner', () => { cy.signinAsOwner(); cy.visit(url); diff --git a/cypress/e2e/37-become-creator-cta.cy.ts b/cypress/e2e/37-become-creator-cta.cy.ts index 931208e5f3..8c10c2ebd0 100644 --- a/cypress/e2e/37-become-creator-cta.cy.ts +++ b/cypress/e2e/37-become-creator-cta.cy.ts @@ -7,7 +7,9 @@ import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows'; const WorkflowsPage = new WorkflowsPageClass(); -describe('Become creator CTA', () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('Become creator CTA', () => { it('should not show the CTA if user is not eligible', () => { interceptCtaRequestWithResponse(false).as('cta'); cy.visit(WorkflowsPage.url); diff --git a/cypress/e2e/39-projects.cy.ts b/cypress/e2e/39-projects.cy.ts index ef974ff41f..71e061fd02 100644 --- a/cypress/e2e/39-projects.cy.ts +++ b/cypress/e2e/39-projects.cy.ts @@ -34,7 +34,9 @@ const credentialsModal = new CredentialsModal(); const ndv = new NDV(); const mainSidebar = new MainSidebar(); -describe('Projects', { disableAutoLogin: true }, () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('Projects', { disableAutoLogin: true }, () => { describe('when starting from scratch', () => { beforeEach(() => { cy.resetDatabase(); diff --git a/cypress/e2e/45-ai-assistant.cy.ts b/cypress/e2e/45-ai-assistant.cy.ts index 21caea250e..dab0d36147 100644 --- a/cypress/e2e/45-ai-assistant.cy.ts +++ b/cypress/e2e/45-ai-assistant.cy.ts @@ -1,3 +1,4 @@ +/* eslint-disable n8n-local-rules/no-skipped-tests */ import { type ICredentialType } from 'n8n-workflow'; import { clickCreateNewCredential, openCredentialSelect } from '../composables/ndv'; @@ -13,7 +14,8 @@ const credentialsPage = new CredentialsPage(); const credentialsModal = new CredentialsModal(); const nodeCreatorFeature = new NodeCreator(); -describe('AI Assistant::disabled', () => { +// Migrated to Playwright +describe.skip('AI Assistant::disabled', () => { beforeEach(() => { aiAssistant.actions.disableAssistant(); wf.actions.visit(); @@ -34,7 +36,7 @@ describe('AI Assistant::enabled', () => { aiAssistant.actions.disableAssistant(); }); - it('renders placeholder UI', () => { + it.skip('renders placeholder UI', () => { aiAssistant.getters.askAssistantCanvasActionButton().should('be.visible'); aiAssistant.getters.askAssistantCanvasActionButton().click(); aiAssistant.getters.askAssistantChat().should('be.visible'); @@ -80,7 +82,7 @@ describe('AI Assistant::enabled', () => { }); }); - it('should start chat session from node error view', () => { + it.skip('should start chat session from node error view', () => { cy.intercept('POST', '/rest/ai/chat', { statusCode: 200, fixture: 'aiAssistant/responses/simple_message_response.json', @@ -98,7 +100,7 @@ describe('AI Assistant::enabled', () => { aiAssistant.getters.nodeErrorViewAssistantButton().should('be.disabled'); }); - it('should render chat input correctly', () => { + it.skip('should render chat input correctly', () => { cy.intercept('POST', '/rest/ai/chat', { statusCode: 200, fixture: 'aiAssistant/responses/simple_message_response.json', @@ -131,7 +133,7 @@ describe('AI Assistant::enabled', () => { }); }); - it('should render and handle quick replies', () => { + it.skip('should render and handle quick replies', () => { cy.intercept('POST', '/rest/ai/chat', { statusCode: 200, fixture: 'aiAssistant/responses/quick_reply_message_response.json', @@ -148,7 +150,7 @@ describe('AI Assistant::enabled', () => { aiAssistant.getters.chatMessagesUser().eq(0).should('contain.text', "Sure, let's do it"); }); - it('should warn before starting a new session', () => { + it.skip('should warn before starting a new session', () => { cy.intercept('POST', '/rest/ai/chat', { statusCode: 200, fixture: 'aiAssistant/responses/simple_message_response.json', @@ -273,7 +275,7 @@ describe('AI Assistant::enabled', () => { ); }); - it('should end chat session when `end_session` event is received', () => { + it.skip('should end chat session when `end_session` event is received', () => { cy.intercept('POST', '/rest/ai/chat', { statusCode: 200, fixture: 'aiAssistant/responses/end_session_response.json', diff --git a/cypress/e2e/46-n8n.io-iframe.cy.ts b/cypress/e2e/46-n8n.io-iframe.cy.ts index 8d31fb251e..8c31feed12 100644 --- a/cypress/e2e/46-n8n.io-iframe.cy.ts +++ b/cypress/e2e/46-n8n.io-iframe.cy.ts @@ -2,7 +2,9 @@ import { WorkflowsPage } from '../pages'; const workflowsPage = new WorkflowsPage(); -describe('n8n.io iframe', () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('n8n.io iframe', () => { describe('when telemetry is disabled', () => { it('should not load the iframe when visiting /home/workflows', () => { cy.overrideSettings({ telemetry: { enabled: false } }); diff --git a/cypress/e2e/716-AI-bug-correctly-set-up-agent-model-shows-error.cy.ts b/cypress/e2e/716-AI-bug-correctly-set-up-agent-model-shows-error.cy.ts index 350dc78d6c..bd5bac6736 100644 --- a/cypress/e2e/716-AI-bug-correctly-set-up-agent-model-shows-error.cy.ts +++ b/cypress/e2e/716-AI-bug-correctly-set-up-agent-model-shows-error.cy.ts @@ -6,7 +6,9 @@ import { } from '../composables/workflow'; import { AGENT_NODE_NAME, AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME } from '../constants'; -describe('AI-716 Correctly set up agent model shows error', () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('AI-716 Correctly set up agent model shows error', () => { beforeEach(() => { cy.visit(getCredentialsPageUrl()); createNewCredential('OpenAi', 'OpenAI Account', 'API Key', 'sk-123', true); diff --git a/cypress/e2e/9999-SUG-38-inline-expression-preview.cy.ts b/cypress/e2e/9999-SUG-38-inline-expression-preview.cy.ts index b7d17f780d..a90f4df449 100644 --- a/cypress/e2e/9999-SUG-38-inline-expression-preview.cy.ts +++ b/cypress/e2e/9999-SUG-38-inline-expression-preview.cy.ts @@ -11,7 +11,9 @@ import { } from '../composables/workflow'; import Workflow from '../fixtures/Test_9999-SUG-38.json'; -describe('SUG-38 Inline expression previews are not displayed in NDV', () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('SUG-38 Inline expression previews are not displayed in NDV', () => { it("should show resolved inline expression preview in NDV if the node's input data is populated", () => { navigateToNewWorkflowPage(); pasteWorkflow(Workflow); diff --git a/cypress/e2e/env-feature-flags.cy.ts b/cypress/e2e/env-feature-flags.cy.ts index 55bbfb78d7..5b38e99b66 100644 --- a/cypress/e2e/env-feature-flags.cy.ts +++ b/cypress/e2e/env-feature-flags.cy.ts @@ -1,4 +1,6 @@ -describe('Environment Feature Flags', () => { +// Migrated to Playwright +// eslint-disable-next-line n8n-local-rules/no-skipped-tests +describe.skip('Environment Feature Flags', () => { it('should set feature flags at runtime and load it back in envFeatureFlags from backend settings', () => { cy.setEnvFeatureFlags({ N8N_ENV_FEAT_TEST: true, diff --git a/packages/testing/playwright/Types.ts b/packages/testing/playwright/Types.ts index 0648aa22eb..3f4cee5403 100644 --- a/packages/testing/playwright/Types.ts +++ b/packages/testing/playwright/Types.ts @@ -1,6 +1,152 @@ +import type { FrontendSettings } from '@n8n/api-types'; + export class TestError extends Error { constructor(message: string) { super(message); this.name = 'TestError'; } } + +/** + * Test requirements for Playwright tests. + * + * This interface allows you to declaratively specify all test setup requirements + * in one place, making tests more readable and maintainable. + * If a workflow is specified, the starting point for the test is now the canvas after the workflow is imported. + * + * @example + * ```typescript + * const requirements: TestRequirements = { + * config: { + * features: { + * aiAssistant: true, + * debugInEditor: true, + * sharing: true + * }, + * settings: { telemetry: { enabled: false } } + * }, + * workflow: { + * 'ai_assistant_test_workflow.json': 'AI Assistant Test Workflow' + * }, + * intercepts: { + * 'ai-chat': { + * url: '*\/rest/ai/chat', + * response: { sessionId: '1', messages: [] } + * } + * }, + * storage: { + * 'n8n-telemetry': '{"enabled": true}' + * } + * }; + * ``` + */ +export interface TestRequirements { + /** + * Configuration settings for the test environment + */ + config?: { + /** Frontend settings to override (merged with default settings) */ + settings?: Partial; + + /** Feature flags to enable/disable for the test */ + features?: Record; + }; + + /** + * API route intercepts and their mock responses + * + * @example + * ```typescript + * intercepts: { + * 'ai-chat': { + * url: '*\/rest/ai/chat', + * response: { + * sessionId: '1', + * messages: [{ role: 'assistant', type: 'message', text: 'Hello!' }] + * } + * }, + * 'become-creator': { + * url: '*\/rest/cta/become-creator', + * response: true + * }, + * 'credentials-test': { + * url: '*\/rest/credentials/test', + * response: { data: { status: 'success', message: 'Tested successfully' } } + * } + * } + * ``` + */ + intercepts?: Record; + + /** + * Single workflow to import for the test + * + * Key: Import file location (relative to workflows folder) + * Value: Name to give the workflow when imported + * + * Note: Only one workflow is supported. Multiple workflows will throw an error. + * + * @example + * ```typescript + * workflow: { + * 'ai_assistant_test_workflow.json': 'AI Assistant Test Workflow' + * } + * ``` + */ + workflow?: Record; + + /** + * Browser storage values to set before the test + * + * Supports localStorage, sessionStorage, and other browser storage APIs + * + * @example + * ```typescript + * storage: { + * 'n8n-telemetry': '{"enabled": true}', + * 'n8n-instance-id': 'test-instance-id' + * } + * ``` + */ + storage?: Record; +} + +/** + * Configuration for API route interception in Playwright + * + * @example + * ```typescript + * { + * url: '*\/rest/ai/chat', + * response: { sessionId: '1', messages: [] }, + * status: 200 + * } + * ``` + * + * @example Network error simulation + * ```typescript + * { + * url: '*\/rest/credentials/test', + * forceNetworkError: true + * } + * ``` + */ +export interface InterceptConfig { + /** URL pattern to intercept (supports wildcards) */ + url: string; + + /** Mock response data */ + response?: unknown; + + /** HTTP status code to return (default: 200) */ + status?: number; + + /** HTTP headers to return */ + headers?: Record; + + /** Content type for the response (default: 'application/json') */ + contentType?: string; + + /** Force network error instead of mock response */ + forceNetworkError?: boolean; +} diff --git a/packages/testing/playwright/composables/ProductionChecklist.ts b/packages/testing/playwright/composables/ProductionChecklist.ts deleted file mode 100644 index 9e8bc3c0ca..0000000000 --- a/packages/testing/playwright/composables/ProductionChecklist.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Page } from '@playwright/test'; - -export const getSuggestedActionsButton = (page: Page) => page.getByTestId('suggested-action-count'); -export const getSuggestedActionItem = (page: Page, text?: string) => { - const items = page.getByTestId('suggested-action-item'); - if (text) { - return items.getByText(text); - } - return items; -}; -export const getSuggestedActionsPopover = (page: Page) => - page.locator('[data-reka-popper-content-wrapper=""]').filter({ hasText: /./ }); - -export const getErrorActionItem = (page: Page) => - getSuggestedActionItem(page, 'Set up error notifications'); - -export const getTimeSavedActionItem = (page: Page) => - getSuggestedActionItem(page, 'Track time saved'); - -export const getEvaluationsActionItem = (page: Page) => - getSuggestedActionItem(page, 'Test reliability of AI steps'); - -export const getIgnoreAllButton = (page: Page) => page.getByTestId('suggested-action-ignore-all'); diff --git a/packages/testing/playwright/composables/WorkflowActivationModal.ts b/packages/testing/playwright/composables/WorkflowActivationModal.ts deleted file mode 100644 index 1ab8e79178..0000000000 --- a/packages/testing/playwright/composables/WorkflowActivationModal.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { expect } from '@playwright/test'; -import type { Page } from '@playwright/test'; - -export const getActivationModal = (page: Page) => page.getByTestId('activation-modal'); - -export const closeActivationModal = async (page: Page) => { - await expect(getActivationModal(page)).toBeVisible(); - - // click checkbox so it does not show again - await getActivationModal(page).getByText("Don't show again").click(); - - // confirm modal - await getActivationModal(page).getByRole('button', { name: 'Got it' }).click(); -}; diff --git a/packages/testing/playwright/composables/WorkflowComposer.ts b/packages/testing/playwright/composables/WorkflowComposer.ts index b458c96cbd..56617f37b4 100644 --- a/packages/testing/playwright/composables/WorkflowComposer.ts +++ b/packages/testing/playwright/composables/WorkflowComposer.ts @@ -1,3 +1,5 @@ +import { nanoid } from 'nanoid'; + import type { n8nPage } from '../pages/n8nPage'; /** @@ -47,7 +49,7 @@ export class WorkflowComposer { fileName: string, name?: string, ): Promise<{ workflowName: string }> { - const workflowName = name ?? `Imported Workflow ${Date.now()}`; + const workflowName = name ?? `Imported Workflow ${nanoid(8)}`; await this.n8n.goHome(); await this.n8n.workflows.clickAddWorkflowButton(); await this.n8n.canvas.importWorkflow(fileName, workflowName); diff --git a/packages/testing/playwright/composables/WorkflowSettingsModal.ts b/packages/testing/playwright/composables/WorkflowSettingsModal.ts deleted file mode 100644 index bc2e3fc56d..0000000000 --- a/packages/testing/playwright/composables/WorkflowSettingsModal.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { expect } from '@playwright/test'; -import type { Page } from '@playwright/test'; - -// Helper to open workflow settings modal -export const openWorkflowSettings = async (page: Page) => { - await page.getByTestId('workflow-menu').click(); - await page.getByTestId('workflow-menu-item-settings').click(); - await expect(page.getByTestId('workflow-settings-dialog')).toBeVisible(); -}; diff --git a/packages/testing/playwright/config/intercepts.ts b/packages/testing/playwright/config/intercepts.ts index 418ddf1b7f..b003feba3d 100644 --- a/packages/testing/playwright/config/intercepts.ts +++ b/packages/testing/playwright/config/intercepts.ts @@ -1,18 +1,36 @@ -import type { FrontendSettings } from '@n8n/api-types'; import type { BrowserContext, Route } from '@playwright/test'; import cloneDeep from 'lodash/cloneDeep'; import merge from 'lodash/merge'; -export let settings: Partial; +const contextSettings = new Map>>(); + +export function setContextSettings( + context: BrowserContext, + settings: Partial>, +) { + contextSettings.set(context, settings); +} + +export function getContextSettings(context: BrowserContext) { + return contextSettings.get(context); +} export async function setupDefaultInterceptors(target: BrowserContext) { + // Global /rest/settings intercept - always active like Cypress await target.route('**/rest/settings', async (route: Route) => { try { const originalResponse = await route.fetch(); const originalJson = await originalResponse.json(); + // Get settings stored for this specific context + const testSettings = getContextSettings(target); + + // Deep merge test settings with backend settings (like Cypress) const modifiedData = { - data: merge(cloneDeep(originalJson.data), settings), + data: + testSettings && Object.keys(testSettings).length > 0 + ? merge(cloneDeep(originalJson.data), testSettings) + : originalJson.data, }; await route.fulfill({ diff --git a/packages/testing/playwright/eslint.config.mjs b/packages/testing/playwright/eslint.config.mjs index b17831d95f..8d34fd44c7 100644 --- a/packages/testing/playwright/eslint.config.mjs +++ b/packages/testing/playwright/eslint.config.mjs @@ -5,7 +5,7 @@ export default [ ...baseConfig, playwrightPlugin.configs['flat/recommended'], { - ignores: ['playwright-report/**/*'], + ignores: ['playwright-report/**/*', 'ms-playwright-cache/**/*'], }, { rules: { @@ -22,6 +22,43 @@ export default [ 'playwright/max-nested-describe': 'warn', 'playwright/no-conditional-in-test': 'error', 'playwright/no-skipped-test': 'warn', + // Allow any naming convention for TestRequirements object properties + // This is specifically for workflow filenames and intercept keys that may not follow camelCase + '@typescript-eslint/naming-convention': [ + 'error', + { + selector: 'default', + format: ['camelCase'], + leadingUnderscore: 'allow', + trailingUnderscore: 'allow', + }, + { + selector: 'variable', + format: ['camelCase', 'UPPER_CASE'], + }, + { + selector: 'typeLike', + format: ['PascalCase'], + }, + { + selector: 'property', + format: ['camelCase', 'snake_case', 'UPPER_CASE'], + filter: { + // Allow any format for properties in TestRequirements objects (workflow files, intercept keys, etc.) + regex: '^(workflow|intercepts|storage|config)$', + match: false, + }, + }, + { + selector: 'objectLiteralProperty', + format: null, // Allow any format for object literal properties in TestRequirements + filter: { + // This allows workflow filenames and intercept keys to use any naming convention + regex: '\\.(json|spec\\.ts)$|[a-zA-Z0-9_-]+', + match: true, + }, + }, + ], 'import-x/no-extraneous-dependencies': [ 'error', { diff --git a/packages/testing/playwright/fixtures/base.ts b/packages/testing/playwright/fixtures/base.ts index ce36e83fdf..efe63d2a57 100644 --- a/packages/testing/playwright/fixtures/base.ts +++ b/packages/testing/playwright/fixtures/base.ts @@ -1,4 +1,4 @@ -import { test as base, expect, type TestInfo } from '@playwright/test'; +import { test as base, expect } from '@playwright/test'; import type { N8NStack } from 'n8n-containers/n8n-test-container-creation'; import { createN8NStack } from 'n8n-containers/n8n-test-container-creation'; import { ContainerTestHelpers } from 'n8n-containers/n8n-test-container-helpers'; @@ -7,12 +7,14 @@ import { setTimeout as wait } from 'node:timers/promises'; import { setupDefaultInterceptors } from '../config/intercepts'; import { n8nPage } from '../pages/n8nPage'; import { ApiHelpers } from '../services/api-helper'; -import { TestError } from '../Types'; +import { TestError, type TestRequirements } from '../Types'; +import { setupTestRequirements } from '../utils/requirements'; type TestFixtures = { n8n: n8nPage; api: ApiHelpers; baseURL: string; + setupRequirements: (requirements: TestRequirements) => Promise; }; type WorkerFixtures = { @@ -40,8 +42,10 @@ interface ContainerConfig { export const test = base.extend({ // Container configuration from the project use options containerConfig: [ - async ({}, use, testInfo: TestInfo) => { - const config = (testInfo.project.use?.containerConfig as ContainerConfig) || {}; + async ({}, use, workerInfo) => { + const config = + (workerInfo.project.use as unknown as { containerConfig?: ContainerConfig }) + ?.containerConfig ?? {}; config.env = { ...config.env, E2E_TESTS: 'true', @@ -122,6 +126,11 @@ export const test = base.extend({ // Browser, baseURL, and dbSetup are required here to ensure they run first. // This is how Playwright does dependency graphs context: async ({ context, browser, baseURL, dbSetup }, use) => { + // Dependencies: browser, baseURL, dbSetup (ensure they run first) + void browser; + void baseURL; + void dbSetup; + await setupDefaultInterceptors(context); await use(context); }, @@ -145,6 +154,14 @@ export const test = base.extend({ const api = new ApiHelpers(context.request); await use(api); }, + + setupRequirements: async ({ page, context }, use) => { + const setupFunction = async (requirements: TestRequirements): Promise => { + await setupTestRequirements(page, context, requirements); + }; + + await use(setupFunction); + }, }); export { expect }; diff --git a/packages/testing/playwright/package.json b/packages/testing/playwright/package.json index a5b7396e6b..787dfdf4ce 100644 --- a/packages/testing/playwright/package.json +++ b/packages/testing/playwright/package.json @@ -28,6 +28,8 @@ "eslint-plugin-playwright": "2.2.2", "generate-schema": "2.6.0", "n8n-containers": "workspace:*", - "tsx": "catalog:" + "nanoid": "catalog:", + "tsx": "catalog:", + "@n8n/api-types": "workspace:^" } } diff --git a/packages/testing/playwright/pages/AIAssistantPage.ts b/packages/testing/playwright/pages/AIAssistantPage.ts new file mode 100644 index 0000000000..613818c4b7 --- /dev/null +++ b/packages/testing/playwright/pages/AIAssistantPage.ts @@ -0,0 +1,66 @@ +import { BasePage } from './BasePage'; + +export class AIAssistantPage extends BasePage { + getAskAssistantFloatingButton() { + return this.page.getByTestId('ask-assistant-floating-button'); + } + + getAskAssistantCanvasActionButton() { + return this.page.getByTestId('ask-assistant-canvas-action-button'); + } + + getAskAssistantChat() { + return this.page.getByTestId('ask-assistant-chat'); + } + + getPlaceholderMessage() { + return this.page.getByTestId('placeholder-message'); + } + + getChatInput() { + return this.page.getByTestId('chat-input'); + } + + getSendMessageButton() { + return this.page.getByTestId('send-message-button'); + } + + getCloseChatButton() { + return this.page.getByTestId('close-chat-button'); + } + + getAskAssistantSidebarResizer() { + return this.page + .getByTestId('ask-assistant-sidebar') + .locator('[class*="_resizer"][data-dir="left"]') + .first(); + } + + getNodeErrorViewAssistantButton() { + return this.page.getByTestId('node-error-view-ask-assistant-button').locator('button').first(); + } + + getChatMessagesAll() { + return this.page.locator('[data-test-id^="chat-message"]'); + } + + getChatMessagesAssistant() { + return this.page.getByTestId('chat-message-assistant'); + } + + getChatMessagesUser() { + return this.page.getByTestId('chat-message-user'); + } + + getChatMessagesSystem() { + return this.page.getByTestId('chat-message-system'); + } + + getQuickReplyButtons() { + return this.page.getByTestId('quick-replies').locator('button'); + } + + getNewAssistantSessionModal() { + return this.page.getByTestId('new-assistant-session-modal'); + } +} diff --git a/packages/testing/playwright/pages/BecomeCreatorCTAPage.ts b/packages/testing/playwright/pages/BecomeCreatorCTAPage.ts new file mode 100644 index 0000000000..cccd1f8381 --- /dev/null +++ b/packages/testing/playwright/pages/BecomeCreatorCTAPage.ts @@ -0,0 +1,15 @@ +import { BasePage } from './BasePage'; + +export class BecomeCreatorCTAPage extends BasePage { + getBecomeTemplateCreatorCta() { + return this.page.getByTestId('become-template-creator-cta'); + } + + getCloseBecomeTemplateCreatorCtaButton() { + return this.page.getByTestId('close-become-template-creator-cta'); + } + + async closeBecomeTemplateCreatorCta() { + await this.getCloseBecomeTemplateCreatorCtaButton().click(); + } +} diff --git a/packages/testing/playwright/pages/CanvasPage.ts b/packages/testing/playwright/pages/CanvasPage.ts index 943f6de7cc..8092a81d1e 100644 --- a/packages/testing/playwright/pages/CanvasPage.ts +++ b/packages/testing/playwright/pages/CanvasPage.ts @@ -1,4 +1,5 @@ import type { Locator } from '@playwright/test'; +import { nanoid } from 'nanoid'; import { BasePage } from './BasePage'; import { resolveFromRoot } from '../utils/path-helper'; @@ -8,6 +9,10 @@ export class CanvasPage extends BasePage { return this.page.getByRole('button', { name: 'Save' }); } + workflowSaveButton(): Locator { + return this.page.getByTestId('workflow-save-button'); + } + canvasAddButton(): Locator { return this.page.getByTestId('canvas-add-button'); } @@ -132,7 +137,6 @@ export class CanvasPage extends BasePage { async clickExecutionsTab(): Promise { await this.page.getByRole('radio', { name: 'Executions' }).click(); } - async setWorkflowName(name: string): Promise { await this.clickByTestId('inline-edit-preview'); await this.fillByTestId('inline-edit-input', name); @@ -161,7 +165,6 @@ export class CanvasPage extends BasePage { getWorkflowTags() { return this.page.getByTestId('workflow-tags').locator('.el-tag'); } - async activateWorkflow() { const responsePromise = this.page.waitForResponse( (response) => @@ -170,4 +173,90 @@ export class CanvasPage extends BasePage { await this.page.getByTestId('workflow-activate-switch').click(); await responsePromise; } + + async clickZoomToFitButton(): Promise { + await this.clickByTestId('zoom-to-fit'); + } + + /** + * Get node issues for a specific node + */ + getNodeIssuesByName(nodeName: string) { + return this.nodeByName(nodeName).getByTestId('node-issues'); + } + + /** + * Add tags to the workflow + * @param count - The number of tags to add + * @returns An array of tag names + */ + async addTags(count: number = 1): Promise { + const tags: string[] = []; + + for (let i = 0; i < count; i++) { + const tag = `tag-${nanoid(8)}-${i}`; + tags.push(tag); + + if (i === 0) { + await this.clickByText('Add tag'); + } else { + await this.page + .getByTestId('tags-dropdown') + .getByText(tags[i - 1]) + .click(); + } + + await this.page.getByRole('combobox').first().fill(tag); + await this.page.getByRole('combobox').first().press('Enter'); + } + + await this.page.click('body'); + + return tags; + } + + // Production Checklist methods + getProductionChecklistButton(): Locator { + return this.page.getByTestId('suggested-action-count'); + } + + getProductionChecklistPopover(): Locator { + return this.page.locator('[data-reka-popper-content-wrapper=""]').filter({ hasText: /./ }); + } + + getProductionChecklistActionItem(text?: string): Locator { + const items = this.page.getByTestId('suggested-action-item'); + if (text) { + return items.getByText(text); + } + return items; + } + + getProductionChecklistIgnoreAllButton(): Locator { + return this.page.getByTestId('suggested-action-ignore-all'); + } + + getErrorActionItem(): Locator { + return this.getProductionChecklistActionItem('Set up error notifications'); + } + + getTimeSavedActionItem(): Locator { + return this.getProductionChecklistActionItem('Track time saved'); + } + + getEvaluationsActionItem(): Locator { + return this.getProductionChecklistActionItem('Test reliability of AI steps'); + } + + async clickProductionChecklistButton(): Promise { + await this.getProductionChecklistButton().click(); + } + + async clickProductionChecklistIgnoreAll(): Promise { + await this.getProductionChecklistIgnoreAllButton().click(); + } + + async clickProductionChecklistAction(actionText: string): Promise { + await this.getProductionChecklistActionItem(actionText).click(); + } } diff --git a/packages/testing/playwright/pages/IframePage.ts b/packages/testing/playwright/pages/IframePage.ts new file mode 100644 index 0000000000..9a93651594 --- /dev/null +++ b/packages/testing/playwright/pages/IframePage.ts @@ -0,0 +1,15 @@ +import { BasePage } from './BasePage'; + +export class IframePage extends BasePage { + getIframe() { + return this.page.locator('iframe'); + } + + getIframeBySrc(src: string) { + return this.page.locator(`iframe[src="${src}"]`); + } + + async waitForIframeRequest(url: string) { + await this.page.waitForResponse(url); + } +} diff --git a/packages/testing/playwright/pages/NodeDisplayViewPage.ts b/packages/testing/playwright/pages/NodeDisplayViewPage.ts index efe02c4a15..4e80d641f6 100644 --- a/packages/testing/playwright/pages/NodeDisplayViewPage.ts +++ b/packages/testing/playwright/pages/NodeDisplayViewPage.ts @@ -35,4 +35,16 @@ export class NodeDisplayViewPage extends BasePage { async close() { await this.clickBackToCanvasButton(); } + + async execute() { + await this.clickByTestId('node-execute-button'); + } + + getOutputPanel() { + return this.page.getByTestId('output-panel'); + } + + getParameterExpressionPreviewValue() { + return this.page.getByTestId('parameter-expression-preview-value'); + } } diff --git a/packages/testing/playwright/pages/SettingsPage.ts b/packages/testing/playwright/pages/SettingsPage.ts new file mode 100644 index 0000000000..35e80f24cd --- /dev/null +++ b/packages/testing/playwright/pages/SettingsPage.ts @@ -0,0 +1,15 @@ +import { BasePage } from './BasePage'; + +export class SettingsPage extends BasePage { + getMenuItems() { + return this.page.getByTestId('menu-item'); + } + + getMenuItem(id: string) { + return this.page.getByTestId('menu-item').getByTestId(id); + } + + async goToSettings() { + await this.page.goto('/settings'); + } +} diff --git a/packages/testing/playwright/pages/VersionsPage.ts b/packages/testing/playwright/pages/VersionsPage.ts new file mode 100644 index 0000000000..3e55f467a8 --- /dev/null +++ b/packages/testing/playwright/pages/VersionsPage.ts @@ -0,0 +1,35 @@ +import { BasePage } from './BasePage'; + +export class VersionsPage extends BasePage { + getVersionUpdatesPanelOpenButton() { + return this.page.getByTestId('version-update-next-versions-link'); + } + + getVersionUpdatesPanel() { + return this.page.getByTestId('version-updates-panel'); + } + + getVersionUpdatesPanelCloseButton() { + return this.getVersionUpdatesPanel().getByRole('button', { name: 'Close' }); + } + + getVersionCard() { + return this.page.getByTestId('version-card'); + } + + getWhatsNewMenuItem() { + return this.page.getByTestId('menu-item').getByTestId('whats-new'); + } + + async openWhatsNewMenu() { + await this.getWhatsNewMenuItem().click(); + } + + async openVersionUpdatesPanel() { + await this.getVersionUpdatesPanelOpenButton().click(); + } + + async closeVersionUpdatesPanel() { + await this.getVersionUpdatesPanelCloseButton().click(); + } +} diff --git a/packages/testing/playwright/pages/WorkflowActivationModal.ts b/packages/testing/playwright/pages/WorkflowActivationModal.ts new file mode 100644 index 0000000000..f1cd78cc0a --- /dev/null +++ b/packages/testing/playwright/pages/WorkflowActivationModal.ts @@ -0,0 +1,31 @@ +import type { Locator } from '@playwright/test'; + +import { BasePage } from './BasePage'; + +export class WorkflowActivationModal extends BasePage { + getModal(): Locator { + return this.page.getByTestId('activation-modal'); + } + + getDontShowAgainCheckbox(): Locator { + return this.getModal().getByText("Don't show again"); + } + + getGotItButton(): Locator { + return this.getModal().getByRole('button', { name: 'Got it' }); + } + + async close(): Promise { + await this.getDontShowAgainCheckbox().click(); + + await this.getGotItButton().click(); + } + + async clickDontShowAgain(): Promise { + await this.getDontShowAgainCheckbox().click(); + } + + async clickGotIt(): Promise { + await this.getGotItButton().click(); + } +} diff --git a/packages/testing/playwright/pages/WorkflowSettingsModal.ts b/packages/testing/playwright/pages/WorkflowSettingsModal.ts new file mode 100644 index 0000000000..6485b9d03a --- /dev/null +++ b/packages/testing/playwright/pages/WorkflowSettingsModal.ts @@ -0,0 +1,39 @@ +import type { Locator } from '@playwright/test'; + +import { BasePage } from './BasePage'; + +export class WorkflowSettingsModal extends BasePage { + getModal(): Locator { + return this.page.getByTestId('workflow-settings-dialog'); + } + + getWorkflowMenu(): Locator { + return this.page.getByTestId('workflow-menu'); + } + + getSettingsMenuItem(): Locator { + return this.page.getByTestId('workflow-menu-item-settings'); + } + + getErrorWorkflowField(): Locator { + return this.page.getByTestId('workflow-settings-error-workflow'); + } + + getSaveButton(): Locator { + return this.page.getByRole('button', { name: 'Save' }); + } + + async open(): Promise { + await this.getWorkflowMenu().click(); + await this.getSettingsMenuItem().click(); + } + + async clickSave(): Promise { + await this.getSaveButton().click(); + } + + async selectErrorWorkflow(workflowName: string): Promise { + await this.getErrorWorkflowField().click(); + await this.page.getByRole('option', { name: workflowName }).first().click(); + } +} diff --git a/packages/testing/playwright/pages/n8nPage.ts b/packages/testing/playwright/pages/n8nPage.ts index 8904a879dd..c4167f2979 100644 --- a/packages/testing/playwright/pages/n8nPage.ts +++ b/packages/testing/playwright/pages/n8nPage.ts @@ -1,12 +1,19 @@ import type { Page } from '@playwright/test'; +import { AIAssistantPage } from './AIAssistantPage'; +import { BecomeCreatorCTAPage } from './BecomeCreatorCTAPage'; import { CanvasPage } from './CanvasPage'; import { CredentialsPage } from './CredentialsPage'; import { ExecutionsPage } from './ExecutionsPage'; +import { IframePage } from './IframePage'; import { NodeDisplayViewPage } from './NodeDisplayViewPage'; import { NotificationsPage } from './NotificationsPage'; import { ProjectSettingsPage } from './ProjectSettingsPage'; +import { SettingsPage } from './SettingsPage'; import { SidebarPage } from './SidebarPage'; +import { VersionsPage } from './VersionsPage'; +import { WorkflowActivationModal } from './WorkflowActivationModal'; +import { WorkflowSettingsModal } from './WorkflowSettingsModal'; import { WorkflowSharingModal } from './WorkflowSharingModal'; import { WorkflowsPage } from './WorkflowsPage'; import { CanvasComposer } from '../composables/CanvasComposer'; @@ -18,18 +25,28 @@ export class n8nPage { readonly page: Page; // Pages + readonly aiAssistant: AIAssistantPage; + readonly becomeCreatorCTA: BecomeCreatorCTAPage; readonly canvas: CanvasPage; + + readonly iframe: IframePage; readonly ndv: NodeDisplayViewPage; readonly projectSettings: ProjectSettingsPage; + readonly settings: SettingsPage; + readonly versions: VersionsPage; readonly workflows: WorkflowsPage; readonly notifications: NotificationsPage; readonly credentials: CredentialsPage; readonly executions: ExecutionsPage; readonly sideBar: SidebarPage; + // Modals + readonly workflowActivationModal: WorkflowActivationModal; + readonly workflowSettingsModal: WorkflowSettingsModal; + readonly workflowSharingModal: WorkflowSharingModal; + // Composables readonly workflowComposer: WorkflowComposer; - readonly workflowSharingModal: WorkflowSharingModal; readonly projectComposer: ProjectComposer; readonly canvasComposer: CanvasComposer; @@ -37,9 +54,15 @@ export class n8nPage { this.page = page; // Pages + this.aiAssistant = new AIAssistantPage(page); + this.becomeCreatorCTA = new BecomeCreatorCTAPage(page); this.canvas = new CanvasPage(page); + + this.iframe = new IframePage(page); this.ndv = new NodeDisplayViewPage(page); this.projectSettings = new ProjectSettingsPage(page); + this.settings = new SettingsPage(page); + this.versions = new VersionsPage(page); this.workflows = new WorkflowsPage(page); this.notifications = new NotificationsPage(page); this.credentials = new CredentialsPage(page); @@ -47,6 +70,10 @@ export class n8nPage { this.sideBar = new SidebarPage(page); this.workflowSharingModal = new WorkflowSharingModal(page); + // Modals + this.workflowActivationModal = new WorkflowActivationModal(page); + this.workflowSettingsModal = new WorkflowSettingsModal(page); + // Composables this.workflowComposer = new WorkflowComposer(this); this.projectComposer = new ProjectComposer(this); diff --git a/packages/testing/playwright/services/api-helper.ts b/packages/testing/playwright/services/api-helper.ts index 6a62db7bf4..13c55f9778 100644 --- a/packages/testing/playwright/services/api-helper.ts +++ b/packages/testing/playwright/services/api-helper.ts @@ -144,6 +144,41 @@ export class ApiHelpers { }); } + // ===== FEATURE FLAG METHODS ===== + + async setEnvFeatureFlags(flags: Record): Promise<{ + data: { + success: boolean; + message: string; + flags: Record; + }; + }> { + const response = await this.request.patch('/rest/e2e/env-feature-flags', { + data: { flags }, + }); + return await response.json(); + } + + async clearEnvFeatureFlags(): Promise<{ + data: { + success: boolean; + message: string; + flags: Record; + }; + }> { + const response = await this.request.patch('/rest/e2e/env-feature-flags', { + data: { flags: {} }, + }); + return await response.json(); + } + + async getEnvFeatureFlags(): Promise<{ + data: Record; + }> { + const response = await this.request.get('/rest/e2e/env-feature-flags'); + return await response.json(); + } + // ===== CONVENIENCE METHODS ===== async enableFeature(feature: string): Promise { diff --git a/packages/testing/playwright/tests/cli-workflows/workflow-tests.spec.ts b/packages/testing/playwright/tests/cli-workflows/workflow-tests.spec.ts index fbcb4cfa8b..d16ffe20df 100644 --- a/packages/testing/playwright/tests/cli-workflows/workflow-tests.spec.ts +++ b/packages/testing/playwright/tests/cli-workflows/workflow-tests.spec.ts @@ -4,7 +4,7 @@ import { test, expect } from '@playwright/test'; import { execSync } from 'child_process'; import * as fs from 'fs'; // @ts-expect-error - 'generate-schema' is not typed, so we ignore the TS error. -import GenerateSchema from 'generate-schema'; +import generateSchema from 'generate-schema'; import * as path from 'path'; import { findPackagesRoot } from '../../utils/path-helper'; @@ -136,7 +136,7 @@ test.describe('Workflow Tests', () => { // Optionally, validate the output against a JSON schema snapshot if enabled. if (SCHEMA_MODE && result.data && workflow.enableSchemaValidation) { - const schema = GenerateSchema.json(result.data); + const schema = generateSchema.json(result.data); expect(JSON.stringify(schema, null, 2)).toMatchSnapshot( `workflow-${workflow.id}-schema.snap`, ); diff --git a/packages/testing/playwright/tests/ui/1-workflows.spec.ts b/packages/testing/playwright/tests/ui/1-workflows.spec.ts index 3958fd26b2..e9fac563f7 100644 --- a/packages/testing/playwright/tests/ui/1-workflows.spec.ts +++ b/packages/testing/playwright/tests/ui/1-workflows.spec.ts @@ -1,3 +1,5 @@ +import { nanoid } from 'nanoid'; + import { test, expect } from '../../fixtures/base'; const NOTIFICATIONS = { @@ -18,7 +20,9 @@ test.describe('Workflows', () => { await expect(n8n.canvas.getWorkflowTags()).toHaveText(['some-tag-1', 'some-tag-2']); }); - test('should create a new workflow using add workflow button', async ({ n8n }) => { + test('should create a new workflow using add workflow button and save successfully', async ({ + n8n, + }) => { await n8n.workflows.clickAddWorkflowButton(); const workflowName = `Test Workflow ${Date.now()}`; @@ -31,9 +35,9 @@ test.describe('Workflows', () => { }); test('should search for workflows', async ({ n8n }) => { - const date = Date.now(); - const specificName = `Specific Test ${date}`; - const genericName = `Generic Test ${date}`; + const uniqueId = nanoid(8); + const specificName = `Specific Test ${uniqueId}`; + const genericName = `Generic Test ${uniqueId}`; await n8n.workflowComposer.createWorkflow(specificName); await n8n.goHome(); @@ -47,7 +51,7 @@ test.describe('Workflows', () => { // Search with partial term await n8n.workflows.clearSearch(); - await n8n.workflows.searchWorkflows(date.toString()); + await n8n.workflows.searchWorkflows(uniqueId); await expect(n8n.workflows.getWorkflowItems()).toHaveCount(2); // Search for non-existent diff --git a/packages/testing/playwright/tests/ui/15-scheduler-node.spec.ts b/packages/testing/playwright/tests/ui/15-scheduler-node.spec.ts new file mode 100644 index 0000000000..e4769f3b26 --- /dev/null +++ b/packages/testing/playwright/tests/ui/15-scheduler-node.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from '../../fixtures/base'; + +test.describe('Schedule Trigger node', () => { + test.beforeEach(async ({ n8n }) => { + await n8n.goHome(); + }); + + test('should execute schedule trigger node and return timestamp in output', async ({ n8n }) => { + await n8n.workflows.clickAddWorkflowButton(); + await n8n.canvas.addNode('Schedule Trigger'); + + await n8n.ndv.execute(); + + await expect(n8n.ndv.getOutputPanel()).toContainText('timestamp'); + + await n8n.ndv.clickBackToCanvasButton(); + }); +}); diff --git a/packages/testing/playwright/tests/ui/2270-ADO-opening-webhook-ndv-marks-workflow-as-unsaved.spec.ts b/packages/testing/playwright/tests/ui/2270-ADO-opening-webhook-ndv-marks-workflow-as-unsaved.spec.ts new file mode 100644 index 0000000000..331320c7c1 --- /dev/null +++ b/packages/testing/playwright/tests/ui/2270-ADO-opening-webhook-ndv-marks-workflow-as-unsaved.spec.ts @@ -0,0 +1,20 @@ +import { test, expect } from '../../fixtures/base'; + +test.describe('ADO-2270 Save button resets on webhook node open', () => { + test('should not reset the save button if webhook node is opened and closed', async ({ n8n }) => { + await n8n.goHome(); + + await n8n.workflows.clickAddWorkflowButton(); + await n8n.canvas.addNode('Webhook'); + + await n8n.page.keyboard.press('Escape'); + + await n8n.canvas.clickSaveWorkflowButton(); + + await n8n.canvas.openNode('Webhook'); + + await n8n.ndv.clickBackToCanvasButton(); + + await expect(n8n.canvas.workflowSaveButton()).toContainText('Saved'); + }); +}); diff --git a/packages/testing/playwright/tests/ui/35-admin-user-smoke-test.spec.ts b/packages/testing/playwright/tests/ui/35-admin-user-smoke-test.spec.ts new file mode 100644 index 0000000000..b957571d1f --- /dev/null +++ b/packages/testing/playwright/tests/ui/35-admin-user-smoke-test.spec.ts @@ -0,0 +1,15 @@ +import { test, expect } from '../../fixtures/base'; + +test.describe('Admin user', () => { + test('should see same Settings sub menu items as instance owner', async ({ n8n, api }) => { + await api.setupTest('signin-only', 'owner'); + await n8n.settings.goToSettings(); + + const ownerMenuItems = await n8n.settings.getMenuItems().count(); + + await api.setupTest('signin-only', 'admin'); + await n8n.settings.goToSettings(); + + await expect(n8n.settings.getMenuItems()).toHaveCount(ownerMenuItems); + }); +}); diff --git a/packages/testing/playwright/tests/ui/45-ai-assistant.spec.ts b/packages/testing/playwright/tests/ui/45-ai-assistant.spec.ts new file mode 100644 index 0000000000..88c016b45b --- /dev/null +++ b/packages/testing/playwright/tests/ui/45-ai-assistant.spec.ts @@ -0,0 +1,276 @@ +import { test, expect } from '../../fixtures/base'; +import type { TestRequirements } from '../../Types'; + +const aiDisabledRequirements: TestRequirements = { + config: { + features: { aiAssistant: false }, + }, +}; + +const aiEnabledRequirements: TestRequirements = { + config: { + features: { aiAssistant: true }, + }, +}; + +const aiEnabledWithWorkflowRequirements: TestRequirements = { + config: { + features: { aiAssistant: true }, + }, + workflow: { + 'ai_assistant_test_workflow.json': 'AI_Assistant_Test_Workflow', + }, + intercepts: { + aiChat: { + url: '**/rest/ai/chat', + response: { + sessionId: '1', + messages: [ + { + role: 'assistant', + type: 'message', + text: 'Hey, this is an assistant message', + }, + ], + }, + }, + }, +}; + +const aiEnabledWithQuickRepliesRequirements: TestRequirements = { + config: { + features: { aiAssistant: true }, + }, + workflow: { + 'ai_assistant_test_workflow.json': 'AI_Assistant_Test_Workflow', + }, + intercepts: { + aiChat: { + url: '**/rest/ai/chat', + response: { + sessionId: '1', + messages: [ + { + role: 'assistant', + type: 'message', + text: 'Hey, this is an assistant message', + quickReplies: [ + { + text: "Sure, let's do it", + type: 'yes', + }, + { + text: "Nah, doesn't sound good", + type: 'no', + }, + ], + }, + ], + }, + }, + }, +}; + +const aiEnabledWithEndSessionRequirements: TestRequirements = { + config: { + features: { aiAssistant: true }, + }, + workflow: { + 'ai_assistant_test_workflow.json': 'AI_Assistant_Test_Workflow', + }, + intercepts: { + aiChat: { + url: '**/rest/ai/chat', + response: { + sessionId: '1', + messages: [ + { + role: 'assistant', + type: 'message', + title: 'Glad to Help', + text: "I'm glad I could help. If you have any more questions or need further assistance with your n8n workflows, feel free to ask!", + }, + { + role: 'assistant', + type: 'event', + eventName: 'end-session', + }, + ], + }, + }, + }, +}; + +test.describe('AI Assistant::disabled', () => { + test('does not show assistant button if feature is disabled', async ({ + n8n, + setupRequirements, + }) => { + await setupRequirements(aiDisabledRequirements); + await expect(n8n.aiAssistant.getAskAssistantFloatingButton()).toHaveCount(0); + }); +}); + +test.describe('AI Assistant::enabled', () => { + test('renders placeholder UI', async ({ n8n, setupRequirements }) => { + await setupRequirements(aiEnabledRequirements); + await n8n.page.goto('/workflow/new'); + + await expect(n8n.aiAssistant.getAskAssistantCanvasActionButton()).toBeVisible(); + + await n8n.aiAssistant.getAskAssistantCanvasActionButton().click(); + + await expect(n8n.aiAssistant.getAskAssistantChat()).toBeVisible(); + + await expect(n8n.aiAssistant.getPlaceholderMessage()).toBeVisible(); + + await expect(n8n.aiAssistant.getChatInput()).toBeVisible(); + + await expect(n8n.aiAssistant.getSendMessageButton()).toBeDisabled(); + + await expect(n8n.aiAssistant.getCloseChatButton()).toBeVisible(); + + await n8n.aiAssistant.getCloseChatButton().click(); + + await expect(n8n.aiAssistant.getAskAssistantChat()).toBeHidden(); + }); + + test('should show resizer when chat is open', async ({ n8n, setupRequirements }) => { + await setupRequirements(aiEnabledRequirements); + await n8n.page.goto('/workflow/new'); + + await n8n.aiAssistant.getAskAssistantCanvasActionButton().click(); + + await expect(n8n.aiAssistant.getAskAssistantSidebarResizer()).toBeVisible(); + + await expect(n8n.aiAssistant.getAskAssistantChat()).toBeVisible(); + + await n8n.aiAssistant.getAskAssistantSidebarResizer().hover(); + + await n8n.aiAssistant.getCloseChatButton().click(); + }); + + test('should start chat session from node error view', async ({ n8n, setupRequirements }) => { + await setupRequirements(aiEnabledWithWorkflowRequirements); + + await n8n.canvas.openNode('Stop and Error'); + + await n8n.ndv.execute(); + + await expect(n8n.aiAssistant.getNodeErrorViewAssistantButton()).toBeVisible(); + await expect(n8n.aiAssistant.getNodeErrorViewAssistantButton()).toBeEnabled(); + + await n8n.aiAssistant.getNodeErrorViewAssistantButton().click(); + + await expect(n8n.aiAssistant.getChatMessagesAll()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatMessagesAll()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatMessagesAll().first()).toContainText( + 'Hey, this is an assistant message', + ); + + await expect(n8n.aiAssistant.getNodeErrorViewAssistantButton()).toBeDisabled(); + }); + + test('should render chat input correctly', async ({ n8n, setupRequirements }) => { + await setupRequirements(aiEnabledWithWorkflowRequirements); + + await n8n.aiAssistant.getAskAssistantCanvasActionButton().click(); + + await expect(n8n.aiAssistant.getAskAssistantChat()).toBeVisible(); + await expect(n8n.aiAssistant.getChatInput()).toBeVisible(); + + await expect(n8n.aiAssistant.getSendMessageButton()).toBeDisabled(); + + await n8n.aiAssistant.getChatInput().fill('Test message'); + + await expect(n8n.aiAssistant.getChatInput()).toHaveValue('Test message'); + + await expect(n8n.aiAssistant.getSendMessageButton()).toBeEnabled(); + + await n8n.aiAssistant.getSendMessageButton().click(); + + await expect(n8n.aiAssistant.getChatMessagesUser()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatMessagesUser()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatInput()).toHaveValue(''); + }); + + test('should render and handle quick replies', async ({ n8n, setupRequirements }) => { + await setupRequirements(aiEnabledWithQuickRepliesRequirements); + + await n8n.canvas.openNode('Stop and Error'); + + await n8n.ndv.execute(); + + await n8n.aiAssistant.getNodeErrorViewAssistantButton().click(); + + await expect(n8n.aiAssistant.getQuickReplyButtons()).toHaveCount(2); + + await expect(n8n.aiAssistant.getQuickReplyButtons()).toHaveCount(2); + + await n8n.aiAssistant.getQuickReplyButtons().first().click(); + + await expect(n8n.aiAssistant.getChatMessagesUser()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatMessagesUser()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatMessagesUser().first()).toContainText("Sure, let's do it"); + }); + + test('should warn before starting a new session', async ({ n8n, setupRequirements }) => { + await setupRequirements(aiEnabledWithWorkflowRequirements); + + await n8n.canvas.openNode('Edit Fields'); + + await n8n.ndv.execute(); + + await n8n.aiAssistant.getNodeErrorViewAssistantButton().click(); + + await expect(n8n.aiAssistant.getChatMessagesAll()).toHaveCount(1); + + await n8n.aiAssistant.getCloseChatButton().click(); + + await n8n.ndv.clickBackToCanvasButton(); + + await n8n.canvas.openNode('Stop and Error'); + + await n8n.ndv.execute(); + + await n8n.aiAssistant.getNodeErrorViewAssistantButton().click(); + + await expect(n8n.aiAssistant.getNewAssistantSessionModal()).toBeVisible(); + + await n8n.aiAssistant + .getNewAssistantSessionModal() + .getByRole('button', { name: 'Start new session' }) + .click(); + + await expect(n8n.aiAssistant.getChatMessagesAll()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatMessagesAll()).toHaveCount(1); + }); + + test('should end chat session when `end_session` event is received', async ({ + n8n, + setupRequirements, + }) => { + await setupRequirements(aiEnabledWithEndSessionRequirements); + + await n8n.canvas.openNode('Stop and Error'); + + await n8n.ndv.execute(); + + await n8n.aiAssistant.getNodeErrorViewAssistantButton().click(); + + await expect(n8n.aiAssistant.getChatMessagesSystem()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatMessagesSystem()).toHaveCount(1); + + await expect(n8n.aiAssistant.getChatMessagesSystem().first()).toContainText( + 'session has ended', + ); + }); +}); diff --git a/packages/testing/playwright/tests/ui/46-n8n-io-iframe.spec.ts b/packages/testing/playwright/tests/ui/46-n8n-io-iframe.spec.ts new file mode 100644 index 0000000000..1ff4635da0 --- /dev/null +++ b/packages/testing/playwright/tests/ui/46-n8n-io-iframe.spec.ts @@ -0,0 +1,72 @@ +import { test, expect } from '../../fixtures/base'; +import type { TestRequirements } from '../../Types'; + +const telemetryDisabledRequirements: TestRequirements = { + config: { + settings: { + telemetry: { enabled: false }, + }, + }, + storage: { + 'n8n-telemetry': JSON.stringify({ enabled: false }), + }, +}; + +const telemetryEnabledRequirements: TestRequirements = { + config: { + settings: { + telemetry: { enabled: true }, + instanceId: 'test-instance-id', + }, + }, + storage: { + 'n8n-telemetry': JSON.stringify({ enabled: true }), + 'n8n-instance-id': 'test-instance-id', + }, + intercepts: { + iframeRequest: { + url: 'https://n8n.io/self-install*', + response: 'Test iframe content', + contentType: 'text/html', + }, + }, +}; + +test.describe('n8n.io iframe', () => { + test.describe('when telemetry is disabled', () => { + test('should not load the iframe when visiting /home/workflows', async ({ + n8n, + setupRequirements, + }) => { + await setupRequirements(telemetryDisabledRequirements); + + await n8n.page.goto('/'); + await n8n.page.waitForLoadState(); + await expect(n8n.iframe.getIframe()).not.toBeAttached(); + }); + }); + + test.describe('when telemetry is enabled', () => { + test('should load the iframe when visiting /home/workflows @auth:owner', async ({ + n8n, + setupRequirements, + api, + }) => { + await setupRequirements(telemetryEnabledRequirements); + + // Get current user ID from the API + const currentUser = await api.get('/rest/login'); + const testInstanceId = 'test-instance-id'; + const testUserId = currentUser.id; + const iframeUrl = `https://n8n.io/self-install?instanceId=${testInstanceId}&userId=${testUserId}`; + + await n8n.page.goto('/'); + await n8n.page.waitForLoadState(); + + const iframeElement = n8n.iframe.getIframeBySrc(iframeUrl); + await expect(iframeElement).toBeAttached(); + + await expect(iframeElement).toHaveAttribute('src', iframeUrl); + }); + }); +}); diff --git a/packages/testing/playwright/tests/ui/53-workflow-production-checklist.spec.ts b/packages/testing/playwright/tests/ui/53-workflow-production-checklist.spec.ts index cbbd00bc67..11159b6e02 100644 --- a/packages/testing/playwright/tests/ui/53-workflow-production-checklist.spec.ts +++ b/packages/testing/playwright/tests/ui/53-workflow-production-checklist.spec.ts @@ -1,14 +1,3 @@ -import { - getErrorActionItem, - getEvaluationsActionItem, - getIgnoreAllButton, - getSuggestedActionItem, - getSuggestedActionsButton, - getSuggestedActionsPopover, - getTimeSavedActionItem, -} from '../../composables/ProductionChecklist'; -import { closeActivationModal } from '../../composables/WorkflowActivationModal'; -import { openWorkflowSettings } from '../../composables/WorkflowSettingsModal'; import { test, expect } from '../../fixtures/base'; const SCHEDULE_TRIGGER_NODE_NAME = 'Schedule Trigger'; @@ -22,35 +11,29 @@ test.describe('Workflow Production Checklist', () => { test('should show suggested actions automatically when workflow is first activated', async ({ n8n, }) => { - // Add a schedule trigger node (activatable) await n8n.canvas.addNodeAndCloseNDV(SCHEDULE_TRIGGER_NODE_NAME); await n8n.canvas.saveWorkflow(); - // Verify suggested actions button is not visible - await expect(getSuggestedActionsButton(n8n.page)).toBeHidden(); + await expect(n8n.canvas.getProductionChecklistButton()).toBeHidden(); - // Activate the workflow await n8n.canvas.activateWorkflow(); - // Activation Modal should be visible since it's first activation - await closeActivationModal(n8n.page); + await expect(n8n.workflowActivationModal.getModal()).toBeVisible(); + await n8n.workflowActivationModal.close(); - // Verify suggested actions button and popover is visible - await expect(getSuggestedActionsButton(n8n.page)).toBeVisible(); - await expect(getSuggestedActionsPopover(n8n.page)).toBeVisible(); - await expect(getSuggestedActionItem(n8n.page)).toHaveCount(2); - await expect(getErrorActionItem(n8n.page)).toBeVisible(); - await expect(getTimeSavedActionItem(n8n.page)).toBeVisible(); + await expect(n8n.canvas.getProductionChecklistButton()).toBeVisible(); + await expect(n8n.canvas.getProductionChecklistPopover()).toBeVisible(); + await expect(n8n.canvas.getProductionChecklistActionItem()).toHaveCount(2); + await expect(n8n.canvas.getErrorActionItem()).toBeVisible(); + await expect(n8n.canvas.getTimeSavedActionItem()).toBeVisible(); }); test('should display evaluations action when AI node exists and feature is enabled', async ({ n8n, api, }) => { - // Enable evaluations feature await api.enableFeature('evaluation'); - // Add schedule trigger and AI node await n8n.canvas.addNodeAndCloseNDV(SCHEDULE_TRIGGER_NODE_NAME); await n8n.canvas.addNodeAndCloseNDV('OpenAI', 'Create an assistant'); @@ -58,56 +41,50 @@ test.describe('Workflow Production Checklist', () => { await n8n.canvas.saveWorkflow(); await n8n.canvas.activateWorkflow(); - await closeActivationModal(n8n.page); + await expect(n8n.workflowActivationModal.getModal()).toBeVisible(); + await n8n.workflowActivationModal.close(); - // Suggested actions should be open - await expect(getSuggestedActionsPopover(n8n.page)).toBeVisible(); - await expect(getSuggestedActionItem(n8n.page)).toHaveCount(3); + await expect(n8n.canvas.getProductionChecklistPopover()).toBeVisible(); + await expect(n8n.canvas.getProductionChecklistActionItem()).toHaveCount(3); - // Verify evaluations action is present - await expect(getEvaluationsActionItem(n8n.page)).toBeVisible(); - await getEvaluationsActionItem(n8n.page).click(); + await expect(n8n.canvas.getEvaluationsActionItem()).toBeVisible(); + await n8n.canvas.getEvaluationsActionItem().click(); - // Verify navigation to evaluations page await expect(n8n.page).toHaveURL(/\/evaluation/); }); test('should open workflow settings modal when error workflow action is clicked', async ({ n8n, }) => { - // Add schedule trigger await n8n.canvas.addNodeAndCloseNDV(SCHEDULE_TRIGGER_NODE_NAME); await n8n.canvas.saveWorkflow(); await n8n.canvas.activateWorkflow(); - await closeActivationModal(n8n.page); + await expect(n8n.workflowActivationModal.getModal()).toBeVisible(); + await n8n.workflowActivationModal.close(); - await expect(getSuggestedActionsPopover(n8n.page)).toBeVisible(); + await expect(n8n.canvas.getProductionChecklistPopover()).toBeVisible(); - // Click error workflow action - const errorAction = getErrorActionItem(n8n.page); + const errorAction = n8n.canvas.getErrorActionItem(); await expect(errorAction).toBeVisible(); await errorAction.click(); - // Verify workflow settings modal opens await expect(n8n.page.getByTestId('workflow-settings-dialog')).toBeVisible(); await expect(n8n.page.getByTestId('workflow-settings-error-workflow')).toBeVisible(); }); test('should open workflow settings modal when time saved action is clicked', async ({ n8n }) => { - // Add schedule trigger await n8n.canvas.addNodeAndCloseNDV(SCHEDULE_TRIGGER_NODE_NAME); await n8n.canvas.saveWorkflow(); await n8n.canvas.activateWorkflow(); - await closeActivationModal(n8n.page); + await expect(n8n.workflowActivationModal.getModal()).toBeVisible(); + await n8n.workflowActivationModal.close(); - await expect(getSuggestedActionsPopover(n8n.page)).toBeVisible(); + await expect(n8n.canvas.getProductionChecklistPopover()).toBeVisible(); - // Click time saved action - const timeAction = getTimeSavedActionItem(n8n.page); + const timeAction = n8n.canvas.getTimeSavedActionItem(); await expect(timeAction).toBeVisible(); await timeAction.click(); - // Verify workflow settings modal opens await expect(n8n.page.getByTestId('workflow-settings-dialog')).toBeVisible(); }); @@ -115,73 +92,64 @@ test.describe('Workflow Production Checklist', () => { await n8n.canvas.addNodeAndCloseNDV(SCHEDULE_TRIGGER_NODE_NAME); await n8n.canvas.saveWorkflow(); await n8n.canvas.activateWorkflow(); - await closeActivationModal(n8n.page); + await expect(n8n.workflowActivationModal.getModal()).toBeVisible(); + await n8n.workflowActivationModal.close(); - // Suggested actions popover should be open - await expect(getSuggestedActionsPopover(n8n.page)).toBeVisible(); + await expect(n8n.canvas.getProductionChecklistPopover()).toBeVisible(); - // Verify error workflow action is visible - await expect(getSuggestedActionItem(n8n.page).first()).toContainText('error'); - await getSuggestedActionItem(n8n.page).first().getByTitle('Ignore').click(); - await n8n.page.waitForTimeout(500); // items disappear after timeout, not arbitrary - await expect(getErrorActionItem(n8n.page)).toBeHidden(); + await expect(n8n.canvas.getProductionChecklistActionItem().first()).toContainText('error'); + await n8n.canvas.getProductionChecklistActionItem().first().getByTitle('Ignore').click(); + await expect(n8n.canvas.getErrorActionItem()).toBeHidden(); - // Close and reopen popover await n8n.page.locator('body').click({ position: { x: 0, y: 0 } }); - await getSuggestedActionsButton(n8n.page).click(); + await n8n.canvas.clickProductionChecklistButton(); - // Verify error workflow action is still no longer visible - await expect(getErrorActionItem(n8n.page)).toBeHidden(); - await expect(getTimeSavedActionItem(n8n.page)).toBeVisible(); + await expect(n8n.canvas.getErrorActionItem()).toBeHidden(); + await expect(n8n.canvas.getTimeSavedActionItem()).toBeVisible(); }); test('should show completed state for configured actions', async ({ n8n }) => { - // Add schedule trigger and activate workflow await n8n.canvas.addNodeAndCloseNDV(SCHEDULE_TRIGGER_NODE_NAME); await n8n.canvas.saveWorkflow(); await n8n.canvas.activateWorkflow(); - await closeActivationModal(n8n.page); + await expect(n8n.workflowActivationModal.getModal()).toBeVisible(); + await n8n.workflowActivationModal.close(); - // Open workflow settings and set error workflow - await openWorkflowSettings(n8n.page); + await n8n.workflowSettingsModal.open(); + await expect(n8n.workflowSettingsModal.getModal()).toBeVisible(); - // Set an error workflow (we'll use a dummy value) - await n8n.page.getByTestId('workflow-settings-error-workflow').click(); - await n8n.page.getByRole('option', { name: 'My workflow' }).first().click(); - await n8n.page.getByRole('button', { name: 'Save' }).click(); + await n8n.workflowSettingsModal.selectErrorWorkflow('My workflow'); + await n8n.workflowSettingsModal.clickSave(); await expect(n8n.page.getByTestId('workflow-settings-dialog')).toBeHidden(); - // Open suggested actions - await getSuggestedActionsButton(n8n.page).click(); - await expect(getSuggestedActionsPopover(n8n.page)).toBeVisible(); + await n8n.canvas.clickProductionChecklistButton(); + await expect(n8n.canvas.getProductionChecklistPopover()).toBeVisible(); - // Verify error workflow action shows as completed await expect( - getSuggestedActionItem(n8n.page).first().locator('svg[data-icon="circle-check"]'), + n8n.canvas + .getProductionChecklistActionItem() + .first() + .locator('svg[data-icon="circle-check"]'), ).toBeVisible(); }); test('should allow ignoring all actions with confirmation', async ({ n8n }) => { - // Add schedule trigger await n8n.canvas.addNodeAndCloseNDV(SCHEDULE_TRIGGER_NODE_NAME); await n8n.canvas.saveWorkflow(); await n8n.canvas.activateWorkflow(); - await closeActivationModal(n8n.page); + await expect(n8n.workflowActivationModal.getModal()).toBeVisible(); + await n8n.workflowActivationModal.close(); - // Suggested actions should be open - await expect(getSuggestedActionsPopover(n8n.page)).toBeVisible(); + await expect(n8n.canvas.getProductionChecklistPopover()).toBeVisible(); - // Click ignore all button - await getIgnoreAllButton(n8n.page).click(); + await n8n.canvas.clickProductionChecklistIgnoreAll(); - // Confirm in the dialog await expect(n8n.page.locator('.el-message-box')).toBeVisible(); await n8n.page .locator('.el-message-box__btns button') .filter({ hasText: /ignore for all workflows/i }) .click(); - // Verify suggested actions button is no longer visible - await expect(getSuggestedActionsButton(n8n.page)).toBeHidden(); + await expect(n8n.canvas.getProductionChecklistButton()).toBeHidden(); }); }); diff --git a/packages/testing/playwright/tests/ui/716-AI-bug-correctly-set-up-agent-model-shows-error.spec.ts b/packages/testing/playwright/tests/ui/716-AI-bug-correctly-set-up-agent-model-shows-error.spec.ts new file mode 100644 index 0000000000..7f8231867c --- /dev/null +++ b/packages/testing/playwright/tests/ui/716-AI-bug-correctly-set-up-agent-model-shows-error.spec.ts @@ -0,0 +1,20 @@ +import { test, expect } from '../../fixtures/base'; + +test.describe('AI-716 Correctly set up agent model shows error', () => { + test('should not show error when adding a sub-node with credential set-up', async ({ n8n }) => { + await n8n.goHome(); + await n8n.workflows.clickAddWorkflowButton(); + + await n8n.canvas.addNode('AI Agent'); + + await n8n.page.keyboard.press('Escape'); + + await n8n.canvas.addNode('OpenAI Chat Model'); + + await n8n.credentials.createAndSaveNewCredential('apiKey', 'sk-123'); + + await n8n.page.keyboard.press('Escape'); + + await expect(n8n.canvas.getNodeIssuesByName('OpenAI Chat Model')).toHaveCount(0); + }); +}); diff --git a/packages/testing/playwright/tests/ui/9999-SUG-38-inline-expression-preview.spec.ts b/packages/testing/playwright/tests/ui/9999-SUG-38-inline-expression-preview.spec.ts new file mode 100644 index 0000000000..61f6ca6064 --- /dev/null +++ b/packages/testing/playwright/tests/ui/9999-SUG-38-inline-expression-preview.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '../../fixtures/base'; +import type { TestRequirements } from '../../Types'; + +const requirements: TestRequirements = { + workflow: { + 'Test_9999_SUG_38.json': 'SUG_38_Test_Workflow', + }, +}; + +test.describe('SUG-38 Inline expression previews are not displayed in NDV', () => { + test("should show resolved inline expression preview in NDV if the node's input data is populated", async ({ + n8n, + setupRequirements, + }) => { + await setupRequirements(requirements); + + await n8n.canvas.clickZoomToFitButton(); + + await n8n.workflowComposer.executeWorkflowAndWaitForNotification( + 'Workflow executed successfully', + ); + + await n8n.canvas.openNode('Repro1'); + + await expect(n8n.ndv.getParameterExpressionPreviewValue()).toBeVisible(); + + await expect(n8n.ndv.getParameterExpressionPreviewValue()).toHaveText('hello there'); + }); +}); diff --git a/packages/testing/playwright/tests/ui/authenticated.spec.ts b/packages/testing/playwright/tests/ui/authenticated.spec.ts index 2ca4a01092..611a7b77f1 100644 --- a/packages/testing/playwright/tests/ui/authenticated.spec.ts +++ b/packages/testing/playwright/tests/ui/authenticated.spec.ts @@ -1,26 +1,18 @@ import { test, expect } from '../../fixtures/base'; -test('default signin is as owner', async ({ n8n }) => { - await n8n.goHome(); - await expect(n8n.page).toHaveURL(/\/workflow/); -}); +test.describe('Authentication', () => { + const testCases = [ + { role: 'default', expectedUrl: /\/workflow/, auth: '' }, + { role: 'owner', expectedUrl: /\/workflow/, auth: '@auth:owner' }, + { role: 'admin', expectedUrl: /\/workflow/, auth: '@auth:admin' }, + { role: 'member', expectedUrl: /\/workflow/, auth: '@auth:member' }, + { role: 'none', expectedUrl: /\/signin/, auth: '@auth:none' }, + ]; -test('owner can access dashboard @auth:owner', async ({ n8n }) => { - await n8n.goHome(); - await expect(n8n.page).toHaveURL(/\/workflow/); -}); - -test('admin can access dashboard @auth:admin', async ({ n8n }) => { - await n8n.goHome(); - await expect(n8n.page).toHaveURL(/\/workflow/); -}); - -test('member can access dashboard @auth:member', async ({ n8n }) => { - await n8n.goHome(); - await expect(n8n.page).toHaveURL(/\/workflow/); -}); - -test('no auth can not access dashboard @auth:none', async ({ n8n }) => { - await n8n.goHome(); - await expect(n8n.page).toHaveURL(/\/signin/); + for (const { role, expectedUrl, auth } of testCases) { + test(`${role} authentication ${auth}`, async ({ n8n }) => { + await n8n.goHome(); + await expect(n8n.page).toHaveURL(expectedUrl); + }); + } }); diff --git a/packages/testing/playwright/tests/ui/env-feature-flags.spec.ts b/packages/testing/playwright/tests/ui/env-feature-flags.spec.ts new file mode 100644 index 0000000000..06d94c7103 --- /dev/null +++ b/packages/testing/playwright/tests/ui/env-feature-flags.spec.ts @@ -0,0 +1,44 @@ +import { test, expect } from '../../fixtures/base'; + +test.describe + .serial('Environment Feature Flags', () => { + test('should set feature flags at runtime and load it back in envFeatureFlags from backend settings', async ({ + api, + }) => { + const setResponse = await api.setEnvFeatureFlags({ + N8N_ENV_FEAT_TEST: 'true', + }); + + expect(setResponse.data.success).toBe(true); + expect(setResponse.data.message).toBe('Environment feature flags updated'); + + expect(setResponse.data.flags).toBeInstanceOf(Object); + expect(setResponse.data.flags['N8N_ENV_FEAT_TEST']).toBe('true'); + + const currentFlags = await api.getEnvFeatureFlags(); + + expect(currentFlags).toBeInstanceOf(Object); + expect(currentFlags.data['N8N_ENV_FEAT_TEST']).toBe('true'); + }); + + test('should reset feature flags at runtime', async ({ api }) => { + const setResponse1 = await api.setEnvFeatureFlags({ + N8N_ENV_FEAT_TEST: 'true', + }); + + expect(setResponse1.data.success).toBe(true); + expect(setResponse1.data.flags['N8N_ENV_FEAT_TEST']).toBe('true'); + + const clearResponse = await api.clearEnvFeatureFlags(); + + expect(clearResponse.data.success).toBe(true); + + expect(clearResponse.data.flags).toBeInstanceOf(Object); + expect(clearResponse.data.flags['N8N_ENV_FEAT_TEST']).toBeUndefined(); + + const currentFlags = await api.getEnvFeatureFlags(); + + expect(currentFlags).toBeInstanceOf(Object); + expect(currentFlags.data['N8N_ENV_FEAT_TEST']).toBeUndefined(); + }); + }); diff --git a/packages/testing/playwright/tests/ui/pdf.spec.ts b/packages/testing/playwright/tests/ui/pdf.spec.ts index 248ed83af4..221dcbd321 100644 --- a/packages/testing/playwright/tests/ui/pdf.spec.ts +++ b/packages/testing/playwright/tests/ui/pdf.spec.ts @@ -1,9 +1,7 @@ import { expect, test } from '../../fixtures/base'; -// Example of importing a workflow from a file test.describe('PDF Test', () => { - // eslint-disable-next-line playwright/no-skipped-test - test.skip('Can read and write PDF files and extract text', async ({ n8n }) => { + test('Can read and write PDF files and extract text', async ({ n8n }) => { await n8n.goHome(); await n8n.workflows.clickAddWorkflowButton(); await n8n.canvas.importWorkflow('test_pdf_workflow.json', 'PDF Workflow'); diff --git a/packages/testing/playwright/utils/path-helper.ts b/packages/testing/playwright/utils/path-helper.ts index 2e5d4ef84f..ad417c064c 100644 --- a/packages/testing/playwright/utils/path-helper.ts +++ b/packages/testing/playwright/utils/path-helper.ts @@ -44,5 +44,6 @@ const playwrightRoot = findProjectRoot('playwright.config.ts'); * @returns An absolute path to the file or directory. */ export function resolveFromRoot(...pathSegments: string[]): string { + // eslint-disable-next-line n8n-local-rules/no-argument-spread return path.join(playwrightRoot, ...pathSegments); } diff --git a/packages/testing/playwright/utils/requirements.ts b/packages/testing/playwright/utils/requirements.ts new file mode 100644 index 0000000000..ce16210d0a --- /dev/null +++ b/packages/testing/playwright/utils/requirements.ts @@ -0,0 +1,70 @@ +import type { Page, BrowserContext } from '@playwright/test'; + +import { setContextSettings } from '../config/intercepts'; +import { n8nPage } from '../pages/n8nPage'; +import { ApiHelpers } from '../services/api-helper'; +import { TestError, type TestRequirements } from '../Types'; + +export async function setupTestRequirements( + page: Page, + context: BrowserContext, + requirements: TestRequirements, +): Promise { + const n8n = new n8nPage(page); + const api = new ApiHelpers(context.request); + + // 1. Setup frontend settings override + if (requirements.config?.settings) { + // Store settings for this context + setContextSettings(context, requirements.config.settings); + } + + // 2. Setup feature flags + if (requirements.config?.features) { + for (const [feature, enabled] of Object.entries(requirements.config.features)) { + if (enabled) { + await api.enableFeature(feature); + } else { + await api.disableFeature(feature); + } + } + } + + // 3. Setup API intercepts + if (requirements.intercepts) { + for (const [name, config] of Object.entries(requirements.intercepts)) { + await page.route(config.url, async (route) => { + await route.fulfill({ + status: config.status ?? 200, + contentType: config.contentType ?? 'application/json', + body: + typeof config.response === 'string' ? config.response : JSON.stringify(config.response), + }); + }); + } + } + + // 4. Setup workflows + if (requirements.workflow) { + for (const [name, workflowData] of Object.entries(requirements.workflow)) { + try { + // Import workflow using the n8n page object + await n8n.goHome(); + await n8n.workflows.clickAddWorkflowButton(); + await n8n.canvas.importWorkflow(name, workflowData); + } catch (error) { + throw new TestError(`Failed to create workflow ${name}: ${String(error)}`); + } + } + } + + // 5. Setup browser storage + if (requirements.storage) { + await context.addInitScript((storage) => { + // Set localStorage items + for (const [key, value] of Object.entries(storage)) { + window.localStorage.setItem(key, value); + } + }, requirements.storage); + } +} diff --git a/packages/testing/playwright/workflows/Manual_wait_set.json b/packages/testing/playwright/workflows/Manual_wait_set.json new file mode 100644 index 0000000000..3d30b448b1 --- /dev/null +++ b/packages/testing/playwright/workflows/Manual_wait_set.json @@ -0,0 +1,72 @@ +{ + "name": "Manual wait set", + "nodes": [ + { + "parameters": { + "amount": 2, + "unit": "seconds" + }, + "id": "ed6e0168-1145-43d0-9082-970b8a8f3cb5", + "name": "Wait", + "type": "n8n-nodes-base.wait", + "typeVersion": 1, + "position": [900, 580], + "webhookId": "0f6f94a4-c28d-46f9-8468-6ab315a9fec9" + }, + { + "parameters": {}, + "id": "59467b99-4e7c-4f19-8fc2-4329788f0951", + "name": "Manual", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [680, 580] + }, + { + "parameters": { + "options": {} + }, + "id": "6ddf089f-4d01-4691-928f-6de168e3b089", + "name": "Set", + "type": "n8n-nodes-base.set", + "typeVersion": 1, + "position": [1120, 580] + } + ], + "pinData": {}, + "connections": { + "Wait": { + "main": [ + [ + { + "node": "Set", + "type": "main", + "index": 0 + } + ] + ] + }, + "Manual": { + "main": [ + [ + { + "node": "Wait", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "saveExecutionProgress": true, + "saveManualExecutions": true, + "callerPolicy": "workflowsFromSameOwner" + }, + "versionId": "f11ff1bf-4273-46cb-bbec-65c7b2fa13cb", + "id": "1037", + "meta": { + "instanceId": "8a47b83b4479b11330fdf21ccc96d4a8117035a968612e452b4c87bfd09c16c7" + }, + "tags": [] +} diff --git a/packages/testing/playwright/workflows/Test_9999_SUG_38.json b/packages/testing/playwright/workflows/Test_9999_SUG_38.json new file mode 100644 index 0000000000..952b9734e6 --- /dev/null +++ b/packages/testing/playwright/workflows/Test_9999_SUG_38.json @@ -0,0 +1,80 @@ +{ + "nodes": [ + { + "parameters": {}, + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [-240, 180], + "id": "cd9b8124-567e-43d9-b4d1-638b111cd049", + "name": "When clicking ‘Execute workflow’" + }, + { + "parameters": { + "assignments": { + "assignments": [ + { + "id": "3a40d9f2-0eed-4a92-9287-9d6ec9ce90e8", + "name": "message", + "value": "hello there", + "type": "string" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.set", + "typeVersion": 3.4, + "position": [-20, 180], + "id": "6e58ae14-4851-4e9d-9465-4155b6e2f278", + "name": "Edit Fields1" + }, + { + "parameters": { + "assignments": { + "assignments": [ + { + "id": "9e957377-c5f2-4254-89d8-334d32a8cfb6", + "name": "test", + "value": "={{ $json.message }}", + "type": "string" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.set", + "typeVersion": 3.4, + "position": [200, 180], + "id": "c4e9d792-51e9-4296-ba66-afac3cf378dd", + "name": "Repro1" + } + ], + "connections": { + "When clicking ‘Execute workflow’": { + "main": [ + [ + { + "node": "Edit Fields1", + "type": "main", + "index": 0 + } + ] + ] + }, + "Edit Fields1": { + "main": [ + [ + { + "node": "Repro1", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "pinData": {}, + "meta": { + "instanceId": "cdc3bfdf3e6244f221ab6e71b2115a631406ae45a034bfca5e9731cf64f4eb64" + } +} diff --git a/packages/testing/playwright/workflows/Webhook_set_pinned.json b/packages/testing/playwright/workflows/Webhook_set_pinned.json new file mode 100644 index 0000000000..153948f31a --- /dev/null +++ b/packages/testing/playwright/workflows/Webhook_set_pinned.json @@ -0,0 +1,61 @@ +{ + "nodes": [ + { + "parameters": { + "options": {} + }, + "id": "bd816131-d8ad-4b4c-90d6-59fdab2e6307", + "name": "Set", + "type": "n8n-nodes-base.set", + "typeVersion": 1, + "position": [720, 460] + }, + { + "parameters": { + "httpMethod": "POST", + "path": "23fc3930-b8f9-41d9-89db-b647291a2201", + "options": {} + }, + "id": "82fe0f6c-854a-4eb9-b311-d7b43025c047", + "name": "Webhook", + "type": "n8n-nodes-base.webhook", + "typeVersion": 1, + "position": [460, 460], + "webhookId": "23fc3930-b8f9-41d9-89db-b647291a2201" + } + ], + "connections": { + "Webhook": { + "main": [ + [ + { + "node": "Set", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "pinData": { + "Webhook": [ + { + "headers": { + "host": "localhost:5678", + "content-length": "37", + "accept": "*/*", + "content-type": "application/json", + "accept-encoding": "gzip" + }, + "params": {}, + "query": {}, + "body": { + "here": "be", + "dragons": true + }, + "webhookUrl": "http://localhost:5678/webhook-test/23fc3930-b8f9-41d9-89db-b647291a2201", + "executionMode": "test" + } + ] + } +} diff --git a/packages/testing/playwright/workflows/ai_assistant_test_workflow.json b/packages/testing/playwright/workflows/ai_assistant_test_workflow.json new file mode 100644 index 0000000000..027d2fe607 --- /dev/null +++ b/packages/testing/playwright/workflows/ai_assistant_test_workflow.json @@ -0,0 +1,76 @@ +{ + "nodes": [ + { + "parameters": {}, + "id": "ebfced75-2ce1-4c41-a971-6c3b83522c4d", + "name": "When clicking 'Execute workflow'", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [360, 220] + }, + { + "parameters": { + "errorMessage": "This is an error message" + }, + "id": "f2e60459-401a-49d5-acfc-7b2b31cfdcf7", + "name": "Stop and Error", + "type": "n8n-nodes-base.stopAndError", + "typeVersion": 1, + "position": [1020, 220] + }, + { + "parameters": { + "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n item.json.myNewField = 1;\n}\n\nreturn $input.all();" + }, + "id": "b54d4db9-b257-41a8-862f-26d293115bad", + "name": "Code", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [840, 320] + }, + { + "parameters": { + "assignments": { + "assignments": [ + { + "id": "053ada73-f7db-4e6a-8cc8-85756cc6ca4e", + "name": "age", + "value": "={{ 32asd }}", + "type": "number" + } + ] + }, + "options": {} + }, + "id": "5fd89612-a871-4679-b7b0-d659e09c6a0e", + "name": "Edit Fields", + "type": "n8n-nodes-base.set", + "typeVersion": 3.4, + "position": [600, 100] + } + ], + "connections": { + "When clicking 'Execute workflow'": { + "main": [ + [ + { + "node": "Stop and Error", + "type": "main", + "index": 0 + }, + { + "node": "Code", + "type": "main", + "index": 0 + }, + { + "node": "Edit Fields", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "pinData": {} +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5537cd7d9..42048b157e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -441,7 +441,7 @@ importers: version: 0.6.5 jest-mock-extended: specifier: ^3.0.4 - version: 3.0.4(jest@29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)))(typescript@5.9.2) + version: 3.0.4(jest@29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)))(typescript@5.9.2) madge: specifier: ^8.0.0 version: 8.0.0(typescript@5.9.2) @@ -539,10 +539,10 @@ importers: version: link:../permissions '@n8n/typeorm': specifier: 'catalog:' - version: 0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.14)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + version: 0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.14)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) jest-mock-extended: specifier: ^3.0.4 - version: 3.0.4(jest@29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)))(typescript@5.9.2) + version: 3.0.4(jest@29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)))(typescript@5.9.2) n8n-workflow: specifier: workspace:^ version: link:../../workflow @@ -667,7 +667,7 @@ importers: version: link:../permissions '@n8n/typeorm': specifier: 'catalog:' - version: 0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.14)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + version: 0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.14)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) class-validator: specifier: 0.14.0 version: 0.14.0 @@ -819,7 +819,7 @@ importers: version: 16.2.0 tsup: specifier: 'catalog:' - version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.1))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) + version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.9))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) typescript: specifier: 5.9.2 version: 5.9.2 @@ -828,7 +828,7 @@ importers: version: 8.35.0(eslint@9.29.0(jiti@1.21.7))(typescript@5.9.2) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) packages/@n8n/extension-sdk: dependencies: @@ -841,7 +841,7 @@ importers: version: link:../typescript-config '@vitejs/plugin-vue': specifier: catalog:frontend - version: 5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) '@vue/tsconfig': specifier: catalog:frontend version: 0.7.0(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)) @@ -853,7 +853,7 @@ importers: version: 4.19.3 vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vue: specifier: catalog:frontend version: 3.5.13(typescript@5.9.2) @@ -905,7 +905,7 @@ importers: version: 0.0.3(patch_hash=083a73709a54db57b092d986b43d27ddda3cb8008f9510e98bc9e6da0e1cbb62) vitest-mock-extended: specifier: 'catalog:' - version: 3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) packages/@n8n/json-schema-to-zod: devDependencies: @@ -1032,7 +1032,7 @@ importers: version: link:../json-schema-to-zod '@n8n/typeorm': specifier: 0.3.20-12 - version: 0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mongodb@6.11.0(@aws-sdk/credential-providers@3.808.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.8.3))(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.12)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + version: 0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mongodb@6.11.0(@aws-sdk/credential-providers@3.808.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.8.3))(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.12)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) '@n8n/typescript-config': specifier: workspace:* version: link:../typescript-config @@ -1180,13 +1180,13 @@ importers: version: 3.2.12 jest-mock-extended: specifier: ^3.0.4 - version: 3.0.4(jest@29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)))(typescript@5.9.2) + version: 3.0.4(jest@29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)))(typescript@5.9.2) n8n-core: specifier: workspace:* version: link:../../core tsup: specifier: 'catalog:' - version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.1))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) + version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.9))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) packages/@n8n/permissions: dependencies: @@ -1235,7 +1235,7 @@ importers: version: 8.6.4(storybook@8.6.4(prettier@3.3.3))(vue@3.5.13(typescript@5.9.2)) '@storybook/vue3-vite': specifier: ^8.6.4 - version: 8.6.4(storybook@8.6.4(prettier@3.3.3))(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 8.6.4(storybook@8.6.4(prettier@3.3.3))(vite@7.0.0(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) chromatic: specifier: ^11.27.0 version: 11.27.0 @@ -1338,16 +1338,16 @@ importers: version: 14.6.1(@testing-library/dom@10.4.0) tsup: specifier: 'catalog:' - version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.1))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) + version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.9))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) typescript: specifier: 5.9.2 version: 5.9.2 vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) packages/@n8n/vitest-config: devDependencies: @@ -1356,10 +1356,10 @@ importers: version: link:../typescript-config vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) packages/cli: dependencies: @@ -1422,7 +1422,7 @@ importers: version: link:../@n8n/task-runner '@n8n/typeorm': specifier: 'catalog:' - version: 0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.14)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + version: 0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.14)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) '@n8n_io/ai-assistant-sdk': specifier: 'catalog:' version: 1.15.0 @@ -1917,7 +1917,7 @@ importers: version: link:../../@n8n/typescript-config '@vitejs/plugin-vue': specifier: catalog:frontend - version: 5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) '@vue/tsconfig': specifier: catalog:frontend version: 0.7.0(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)) @@ -1926,7 +1926,7 @@ importers: version: 6.0.1 vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vue: specifier: catalog:frontend version: 3.5.13(typescript@5.9.2) @@ -1981,22 +1981,22 @@ importers: version: link:../../../@n8n/vitest-config '@vitejs/plugin-vue': specifier: catalog:frontend - version: 5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) '@vitest/coverage-v8': specifier: 'catalog:' - version: 3.2.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 3.2.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) unplugin-icons: specifier: ^0.19.0 version: 0.19.0(@vue/compiler-sfc@3.5.13) vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vite-plugin-dts: specifier: ^4.5.3 - version: 4.5.3(@types/node@20.19.1)(rollup@4.44.0)(typescript@5.9.2)(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 4.5.3(@types/node@20.19.9)(rollup@4.46.2)(typescript@5.9.2)(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vue-tsc: specifier: ^2.2.8 version: 2.2.8(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.9.2) @@ -2023,7 +2023,7 @@ importers: version: 8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.9.2)) '@vitejs/plugin-vue': specifier: catalog:frontend - version: 5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) '@vue/tsconfig': specifier: catalog:frontend version: 0.7.0(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)) @@ -2032,16 +2032,16 @@ importers: version: 10.11.0(vue@3.5.13(typescript@5.9.2)) tsup: specifier: 'catalog:' - version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.1))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) + version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.9))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) typescript: specifier: 5.9.2 version: 5.9.2 vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vue: specifier: catalog:frontend version: 3.5.13(typescript@5.9.2) @@ -2156,10 +2156,10 @@ importers: version: 2.11.0 '@vitejs/plugin-vue': specifier: catalog:frontend - version: 5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) '@vitest/coverage-v8': specifier: 'catalog:' - version: 3.2.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 3.2.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) autoprefixer: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.49) @@ -2171,22 +2171,22 @@ importers: version: 1.89.2 tailwindcss: specifier: ^3.4.3 - version: 3.4.3(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + version: 3.4.3(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) unplugin-icons: specifier: catalog:frontend version: 0.19.0(@vue/compiler-sfc@3.5.13) unplugin-vue-components: specifier: catalog:frontend - version: 0.27.3(@babel/parser@7.27.5)(rollup@4.44.0)(vue@3.5.13(typescript@5.9.2)) + version: 0.27.3(@babel/parser@7.27.5)(rollup@4.46.2)(vue@3.5.13(typescript@5.9.2)) vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest-mock-extended: specifier: 'catalog:' - version: 3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) vue-tsc: specifier: ^2.2.8 version: 2.2.8(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.9.2) @@ -2220,7 +2220,7 @@ importers: version: 8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.9.2)) '@vitejs/plugin-vue': specifier: catalog:frontend - version: 5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) '@vue/tsconfig': specifier: catalog:frontend version: 0.7.0(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)) @@ -2229,16 +2229,16 @@ importers: version: 10.11.0(vue@3.5.13(typescript@5.9.2)) tsup: specifier: 'catalog:' - version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.1))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) + version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.9))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) typescript: specifier: 5.9.2 version: 5.9.2 vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vue: specifier: catalog:frontend version: 3.5.13(typescript@5.9.2) @@ -2293,16 +2293,16 @@ importers: version: 14.6.1(@testing-library/dom@10.4.0) tsup: specifier: 'catalog:' - version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.1))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) + version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.9))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) typescript: specifier: 5.9.2 version: 5.9.2 vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) packages/frontend/@n8n/stores: dependencies: @@ -2330,7 +2330,7 @@ importers: version: 8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.9.2)) '@vitejs/plugin-vue': specifier: catalog:frontend - version: 5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) '@vue/tsconfig': specifier: catalog:frontend version: 0.7.0(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)) @@ -2342,16 +2342,16 @@ importers: version: 2.2.4(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)) tsup: specifier: 'catalog:' - version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.1))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) + version: 8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.9))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2) typescript: specifier: 5.9.2 version: 5.9.2 vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vue: specifier: catalog:frontend version: 3.5.13(typescript@5.9.2) @@ -2670,13 +2670,13 @@ importers: version: 10.0.0 '@vitejs/plugin-legacy': specifier: ^6.0.2 - version: 6.0.2(terser@5.16.1)(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 6.0.2(terser@5.16.1)(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) '@vitejs/plugin-vue': specifier: catalog:frontend - version: 5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) + version: 5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2)) '@vitest/coverage-v8': specifier: 'catalog:' - version: 3.2.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 3.2.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) browserslist-to-esbuild: specifier: ^2.1.1 version: 2.1.1(browserslist@4.24.4) @@ -2691,25 +2691,25 @@ importers: version: 0.19.0(@vue/compiler-sfc@3.5.13) unplugin-vue-components: specifier: catalog:frontend - version: 0.27.3(@babel/parser@7.27.5)(rollup@4.44.0)(vue@3.5.13(typescript@5.9.2)) + version: 0.27.3(@babel/parser@7.27.5)(rollup@4.46.2)(vue@3.5.13(typescript@5.9.2)) vite: specifier: 'catalog:' - version: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vite-plugin-node-polyfills: specifier: ^0.24.0 - version: 0.24.0(rollup@4.44.0)(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 0.24.0(rollup@4.46.2)(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) vite-plugin-static-copy: specifier: 2.2.0 - version: 2.2.0(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 2.2.0(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) vite-svg-loader: specifier: 5.1.0 version: 5.1.0(vue@3.5.13(typescript@5.9.2)) vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest-mock-extended: specifier: 'catalog:' - version: 3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) vue-tsc: specifier: ^2.2.8 version: 2.2.8(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.9.2) @@ -3066,6 +3066,9 @@ importers: '@currents/playwright': specifier: ^1.15.3 version: 1.15.3(magicast@0.3.5) + '@n8n/api-types': + specifier: workspace:^ + version: link:../../@n8n/api-types '@playwright/test': specifier: 1.54.2 version: 1.54.2 @@ -3081,6 +3084,9 @@ importers: n8n-containers: specifier: workspace:* version: link:../containers + nanoid: + specifier: 'catalog:' + version: 3.3.8 tsx: specifier: 'catalog:' version: 4.19.3 @@ -3171,10 +3177,10 @@ importers: version: 0.4.14 vitest: specifier: 'catalog:' - version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + version: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vitest-mock-extended: specifier: 'catalog:' - version: 3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + version: 3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) packages: @@ -4359,6 +4365,9 @@ packages: '@emnapi/runtime@1.4.3': resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + '@emnapi/runtime@1.4.5': + resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==} + '@emnapi/wasi-threads@1.0.2': resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} @@ -4968,6 +4977,9 @@ packages: resolution: {integrity: sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -4980,15 +4992,21 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/source-map@0.3.6': - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + '@jridgewell/source-map@0.3.10': + resolution: {integrity: sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==} '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -6287,101 +6305,201 @@ packages: cpu: [arm] os: [android] + '@rollup/rollup-android-arm-eabi@4.46.2': + resolution: {integrity: sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm64@4.44.0': resolution: {integrity: sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==} cpu: [arm64] os: [android] + '@rollup/rollup-android-arm64@4.46.2': + resolution: {integrity: sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==} + cpu: [arm64] + os: [android] + '@rollup/rollup-darwin-arm64@4.44.0': resolution: {integrity: sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==} cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-arm64@4.46.2': + resolution: {integrity: sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.44.0': resolution: {integrity: sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==} cpu: [x64] os: [darwin] + '@rollup/rollup-darwin-x64@4.46.2': + resolution: {integrity: sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-freebsd-arm64@4.44.0': resolution: {integrity: sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==} cpu: [arm64] os: [freebsd] + '@rollup/rollup-freebsd-arm64@4.46.2': + resolution: {integrity: sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==} + cpu: [arm64] + os: [freebsd] + '@rollup/rollup-freebsd-x64@4.44.0': resolution: {integrity: sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==} cpu: [x64] os: [freebsd] + '@rollup/rollup-freebsd-x64@4.46.2': + resolution: {integrity: sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==} + cpu: [x64] + os: [freebsd] + '@rollup/rollup-linux-arm-gnueabihf@4.44.0': resolution: {integrity: sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-gnueabihf@4.46.2': + resolution: {integrity: sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.44.0': resolution: {integrity: sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.46.2': + resolution: {integrity: sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.44.0': resolution: {integrity: sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.46.2': + resolution: {integrity: sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-musl@4.44.0': resolution: {integrity: sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-musl@4.46.2': + resolution: {integrity: sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-loongarch64-gnu@4.44.0': resolution: {integrity: sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==} cpu: [loong64] os: [linux] + '@rollup/rollup-linux-loongarch64-gnu@4.46.2': + resolution: {integrity: sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==} + cpu: [loong64] + os: [linux] + '@rollup/rollup-linux-powerpc64le-gnu@4.44.0': resolution: {integrity: sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==} cpu: [ppc64] os: [linux] + '@rollup/rollup-linux-ppc64-gnu@4.46.2': + resolution: {integrity: sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.44.0': resolution: {integrity: sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.46.2': + resolution: {integrity: sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.44.0': resolution: {integrity: sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.46.2': + resolution: {integrity: sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.44.0': resolution: {integrity: sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==} cpu: [s390x] os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.46.2': + resolution: {integrity: sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.44.0': resolution: {integrity: sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-gnu@4.46.2': + resolution: {integrity: sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-musl@4.44.0': resolution: {integrity: sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-musl@4.46.2': + resolution: {integrity: sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==} + cpu: [x64] + os: [linux] + '@rollup/rollup-win32-arm64-msvc@4.44.0': resolution: {integrity: sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==} cpu: [arm64] os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.46.2': + resolution: {integrity: sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.44.0': resolution: {integrity: sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==} cpu: [ia32] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.46.2': + resolution: {integrity: sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.44.0': resolution: {integrity: sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==} cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.46.2': + resolution: {integrity: sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==} + cpu: [x64] + os: [win32] + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} @@ -7367,12 +7485,18 @@ packages: '@types/node-fetch@2.6.12': resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} + '@types/node-fetch@2.6.13': + resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} + '@types/node@20.17.57': resolution: {integrity: sha512-f3T4y6VU4fVQDKVqJV4Uppy8c1p/sVvS3peyqxyWnzkqXFJLRU7Y1Bl7rMS1Qe9z0v4M6McY0Fp9yBsgHJUsWQ==} '@types/node@20.19.1': resolution: {integrity: sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==} + '@types/node@20.19.9': + resolution: {integrity: sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==} + '@types/nodemailer@6.4.14': resolution: {integrity: sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA==} @@ -8399,6 +8523,9 @@ packages: axios@1.10.0: resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==} + axios@1.11.0: + resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} + axios@1.8.3: resolution: {integrity: sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==} @@ -9793,6 +9920,10 @@ packages: resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + dotenv@8.6.0: resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} engines: {node: '>=10'} @@ -10526,6 +10657,15 @@ packages: fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -10535,9 +10675,6 @@ packages: debug: optional: true - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - for-each@0.3.5: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} @@ -13600,6 +13737,10 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} @@ -14418,6 +14559,11 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rollup@4.46.2: + resolution: {integrity: sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + route-recognizer@0.3.4: resolution: {integrity: sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==} @@ -14765,6 +14911,7 @@ packages: source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions sparse-bitfield@3.0.3: resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} @@ -15451,8 +15598,8 @@ packages: '@swc/wasm': optional: true - ts-pattern@5.7.1: - resolution: {integrity: sha512-EGs8PguQqAAUIcQfK4E9xdXxB6s2GK4sJfT/vcc9V1ELIvC4LH/zXu2t/5fajtv6oiRCxdv7BgtVK3vWgROxag==} + ts-pattern@5.8.0: + resolution: {integrity: sha512-kIjN2qmWiHnhgr5DAkAafF9fwb0T5OhMVSWrm8XEdTFnX6+wfXwYOFjeF86UZ54vduqiR7BfqScFmXSzSaH8oA==} ts-toolbelt@9.6.0: resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==} @@ -16398,8 +16545,8 @@ packages: utf-8-validate: optional: true - ws@8.18.2: - resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==} + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -16581,6 +16728,11 @@ packages: peerDependencies: zod: ^3.24.1 + zod-to-json-schema@3.24.6: + resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==} + peerDependencies: + zod: ^3.24.1 + zod@3.25.67: resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} @@ -16623,8 +16775,8 @@ snapshots: '@anthropic-ai/sdk@0.27.3(encoding@0.1.13)': dependencies: - '@types/node': 20.19.1 - '@types/node-fetch': 2.6.12 + '@types/node': 20.19.9 + '@types/node-fetch': 2.6.13 abort-controller: 3.0.0 agentkeepalive: 4.6.0 form-data-encoder: 1.7.2 @@ -18495,8 +18647,8 @@ snapshots: '@browserbasehq/sdk@2.6.0(encoding@0.1.13)': dependencies: - '@types/node': 20.19.1 - '@types/node-fetch': 2.6.12 + '@types/node': 20.19.9 + '@types/node-fetch': 2.6.13 abort-controller: 3.0.0 agentkeepalive: 4.6.0 form-data-encoder: 1.7.2 @@ -18514,9 +18666,9 @@ snapshots: dotenv: 16.5.0 openai: 5.12.2(ws@8.18.2)(zod@3.25.67) sharp: 0.33.5 - ws: 8.18.2 + ws: 8.18.3 zod: 3.25.67 - zod-to-json-schema: 3.24.5(zod@3.25.67) + zod-to-json-schema: 3.24.6(zod@3.25.67) transitivePeerDependencies: - bufferutil - encoding @@ -18689,14 +18841,14 @@ snapshots: '@commander-js/extra-typings': 12.1.0(commander@12.1.0) '@currents/commit-info': 1.0.1-beta.0 async-retry: 1.3.3 - axios: 1.10.0(debug@4.4.1) - axios-retry: 4.5.0(axios@1.10.0(debug@4.4.1)) + axios: 1.11.0(debug@4.4.1) + axios-retry: 4.5.0(axios@1.11.0(debug@4.4.1)) c12: 1.11.2(magicast@0.3.5) chalk: 4.1.2 commander: 12.1.0 date-fns: 2.30.0 debug: 4.4.1(supports-color@8.1.1) - dotenv: 16.5.0 + dotenv: 16.6.1 execa: 9.6.0 getos: 3.2.1 https-proxy-agent: 7.0.6 @@ -18718,8 +18870,8 @@ snapshots: stack-utils: 2.0.6 tmp: 0.2.4 tmp-promise: 3.0.3 - ts-pattern: 5.7.1 - ws: 8.18.2 + ts-pattern: 5.8.0 + ws: 8.18.3 transitivePeerDependencies: - bufferutil - magicast @@ -18798,6 +18950,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.4.5': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/wasi-threads@1.0.2': dependencies: tslib: 2.8.1 @@ -19115,7 +19272,7 @@ snapshots: '@ibm-cloud/watsonx-ai@1.1.2': dependencies: - '@types/node': 20.19.1 + '@types/node': 20.19.9 extend: 3.0.2 ibm-cloud-sdk-core: 5.3.2 transitivePeerDependencies: @@ -19215,7 +19372,7 @@ snapshots: '@img/sharp-wasm32@0.33.5': dependencies: - '@emnapi/runtime': 1.4.3 + '@emnapi/runtime': 1.4.5 optional: true '@img/sharp-win32-ia32@0.33.5': @@ -19317,7 +19474,7 @@ snapshots: - supports-color - ts-node - '@jest/core@29.6.2(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2))': + '@jest/core@29.6.2(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2))': dependencies: '@jest/console': 29.6.2 '@jest/reporters': 29.6.2 @@ -19331,7 +19488,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.5.0 - jest-config: 29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + jest-config: 29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) jest-haste-map: 29.6.2 jest-message-util: 29.6.2 jest-regex-util: 29.4.3 @@ -19478,6 +19635,11 @@ snapshots: '@types/yargs': 17.0.19 chalk: 4.1.2 + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -19488,22 +19650,29 @@ snapshots: '@jridgewell/set-array@1.2.1': {} - '@jridgewell/source-map@0.3.6': + '@jridgewell/source-map@0.3.10': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.4': {} + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.29': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.4 optional: true '@js-joda/core@5.6.1': {} @@ -19625,7 +19794,7 @@ snapshots: playwright: 1.54.2 redis: 4.6.12 weaviate-client: 3.6.2(encoding@0.1.13) - ws: 8.18.2 + ws: 8.18.3 transitivePeerDependencies: - '@langchain/anthropic' - '@langchain/aws' @@ -19724,7 +19893,7 @@ snapshots: uuid: 10.0.0 zod: 3.25.67 optionalDependencies: - zod-to-json-schema: 3.24.5(zod@3.25.67) + zod-to-json-schema: 3.24.6(zod@3.25.67) transitivePeerDependencies: - react @@ -19846,23 +20015,23 @@ snapshots: '@types/react': 18.0.27 react: 18.2.0 - '@microsoft/api-extractor-model@7.30.4(@types/node@20.19.1)': + '@microsoft/api-extractor-model@7.30.4(@types/node@20.19.9)': dependencies: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.12.0(@types/node@20.19.1) + '@rushstack/node-core-library': 5.12.0(@types/node@20.19.9) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.52.1(@types/node@20.19.1)': + '@microsoft/api-extractor@7.52.1(@types/node@20.19.9)': dependencies: - '@microsoft/api-extractor-model': 7.30.4(@types/node@20.19.1) + '@microsoft/api-extractor-model': 7.30.4(@types/node@20.19.9) '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.12.0(@types/node@20.19.1) + '@rushstack/node-core-library': 5.12.0(@types/node@20.19.9) '@rushstack/rig-package': 0.5.3 - '@rushstack/terminal': 0.15.1(@types/node@20.19.1) - '@rushstack/ts-command-line': 4.23.6(@types/node@20.19.1) + '@rushstack/terminal': 0.15.1(@types/node@20.19.9) + '@rushstack/ts-command-line': 4.23.6(@types/node@20.19.9) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.10 @@ -19967,7 +20136,7 @@ snapshots: esprima-next: 5.8.4 recast: 0.22.0 - '@n8n/typeorm@0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mongodb@6.11.0(@aws-sdk/credential-providers@3.808.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.8.3))(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.12)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2))': + '@n8n/typeorm@0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mongodb@6.11.0(@aws-sdk/credential-providers@3.808.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.8.3))(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.12)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2))': dependencies: '@n8n/p-retry': 6.2.0-2 '@sqltools/formatter': 1.2.5 @@ -19995,11 +20164,11 @@ snapshots: pg: 8.12.0 redis: 4.6.12 sqlite3: 5.1.7 - ts-node: 10.9.2(@types/node@20.19.1)(typescript@5.9.2) + ts-node: 10.9.2(@types/node@20.19.9)(typescript@5.9.2) transitivePeerDependencies: - supports-color - '@n8n/typeorm@0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.14)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2))': + '@n8n/typeorm@0.3.20-12(@sentry/node@9.42.1)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.11.0)(pg@8.12.0)(redis@4.6.14)(sqlite3@5.1.7)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2))': dependencies: '@n8n/p-retry': 6.2.0-2 '@sqltools/formatter': 1.2.5 @@ -20026,7 +20195,7 @@ snapshots: pg: 8.12.0 redis: 4.6.14 sqlite3: 5.1.7 - ts-node: 10.9.2(@types/node@20.19.1)(typescript@5.9.2) + ts-node: 10.9.2(@types/node@20.19.9)(typescript@5.9.2) transitivePeerDependencies: - supports-color @@ -20685,82 +20854,142 @@ snapshots: '@codemirror/state': 6.4.1 '@codemirror/view': 6.26.3 - '@rollup/plugin-inject@5.0.5(rollup@4.44.0)': + '@rollup/plugin-inject@5.0.5(rollup@4.46.2)': dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.44.0) + '@rollup/pluginutils': 5.1.4(rollup@4.46.2) estree-walker: 2.0.2 magic-string: 0.30.17 optionalDependencies: - rollup: 4.44.0 + rollup: 4.46.2 - '@rollup/pluginutils@5.1.4(rollup@4.44.0)': + '@rollup/pluginutils@5.1.4(rollup@4.46.2)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.2 optionalDependencies: - rollup: 4.44.0 + rollup: 4.46.2 '@rollup/rollup-android-arm-eabi@4.44.0': optional: true + '@rollup/rollup-android-arm-eabi@4.46.2': + optional: true + '@rollup/rollup-android-arm64@4.44.0': optional: true + '@rollup/rollup-android-arm64@4.46.2': + optional: true + '@rollup/rollup-darwin-arm64@4.44.0': optional: true + '@rollup/rollup-darwin-arm64@4.46.2': + optional: true + '@rollup/rollup-darwin-x64@4.44.0': optional: true + '@rollup/rollup-darwin-x64@4.46.2': + optional: true + '@rollup/rollup-freebsd-arm64@4.44.0': optional: true + '@rollup/rollup-freebsd-arm64@4.46.2': + optional: true + '@rollup/rollup-freebsd-x64@4.44.0': optional: true + '@rollup/rollup-freebsd-x64@4.46.2': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.44.0': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.46.2': + optional: true + '@rollup/rollup-linux-arm-musleabihf@4.44.0': optional: true + '@rollup/rollup-linux-arm-musleabihf@4.46.2': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.44.0': optional: true + '@rollup/rollup-linux-arm64-gnu@4.46.2': + optional: true + '@rollup/rollup-linux-arm64-musl@4.44.0': optional: true + '@rollup/rollup-linux-arm64-musl@4.46.2': + optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.44.0': optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.46.2': + optional: true + '@rollup/rollup-linux-powerpc64le-gnu@4.44.0': optional: true + '@rollup/rollup-linux-ppc64-gnu@4.46.2': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.44.0': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.46.2': + optional: true + '@rollup/rollup-linux-riscv64-musl@4.44.0': optional: true + '@rollup/rollup-linux-riscv64-musl@4.46.2': + optional: true + '@rollup/rollup-linux-s390x-gnu@4.44.0': optional: true + '@rollup/rollup-linux-s390x-gnu@4.46.2': + optional: true + '@rollup/rollup-linux-x64-gnu@4.44.0': optional: true + '@rollup/rollup-linux-x64-gnu@4.46.2': + optional: true + '@rollup/rollup-linux-x64-musl@4.44.0': optional: true + '@rollup/rollup-linux-x64-musl@4.46.2': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.44.0': optional: true + '@rollup/rollup-win32-arm64-msvc@4.46.2': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.44.0': optional: true + '@rollup/rollup-win32-ia32-msvc@4.46.2': + optional: true + '@rollup/rollup-win32-x64-msvc@4.44.0': optional: true + '@rollup/rollup-win32-x64-msvc@4.46.2': + optional: true + '@rtsao/scc@1.1.0': {} '@rudderstack/rudder-sdk-node@2.1.4(tslib@2.8.1)': @@ -20783,7 +21012,7 @@ snapshots: - debug - supports-color - '@rushstack/node-core-library@5.12.0(@types/node@20.19.1)': + '@rushstack/node-core-library@5.12.0(@types/node@20.19.9)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -20794,23 +21023,23 @@ snapshots: resolve: 1.22.10 semver: 7.7.2 optionalDependencies: - '@types/node': 20.19.1 + '@types/node': 20.19.9 '@rushstack/rig-package@0.5.3': dependencies: resolve: 1.22.10 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.15.1(@types/node@20.19.1)': + '@rushstack/terminal@0.15.1(@types/node@20.19.9)': dependencies: - '@rushstack/node-core-library': 5.12.0(@types/node@20.19.1) + '@rushstack/node-core-library': 5.12.0(@types/node@20.19.9) supports-color: 8.1.1 optionalDependencies: - '@types/node': 20.19.1 + '@types/node': 20.19.9 - '@rushstack/ts-command-line@4.23.6(@types/node@20.19.1)': + '@rushstack/ts-command-line@4.23.6(@types/node@20.19.9)': dependencies: - '@rushstack/terminal': 0.15.1(@types/node@20.19.1) + '@rushstack/terminal': 0.15.1(@types/node@20.19.9) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.1 @@ -21516,13 +21745,13 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - '@storybook/builder-vite@8.6.4(storybook@8.6.4(prettier@3.3.3))(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))': + '@storybook/builder-vite@8.6.4(storybook@8.6.4(prettier@3.3.3))(vite@7.0.0(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))': dependencies: '@storybook/csf-plugin': 8.6.4(storybook@8.6.4(prettier@3.3.3)) browser-assert: 1.2.1 storybook: 8.6.4(prettier@3.3.3) ts-dedent: 2.2.0 - vite: 7.0.0(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 7.0.0(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) '@storybook/components@8.6.4(storybook@8.6.4(prettier@3.3.3))': dependencies: @@ -21540,7 +21769,7 @@ snapshots: recast: 0.23.6 semver: 7.7.2 util: 0.12.5 - ws: 8.17.1 + ws: 8.18.3 optionalDependencies: prettier: 3.3.3 transitivePeerDependencies: @@ -21596,15 +21825,15 @@ snapshots: dependencies: storybook: 8.6.4(prettier@3.3.3) - '@storybook/vue3-vite@8.6.4(storybook@8.6.4(prettier@3.3.3))(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2))': + '@storybook/vue3-vite@8.6.4(storybook@8.6.4(prettier@3.3.3))(vite@7.0.0(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2))': dependencies: - '@storybook/builder-vite': 8.6.4(storybook@8.6.4(prettier@3.3.3))(vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + '@storybook/builder-vite': 8.6.4(storybook@8.6.4(prettier@3.3.3))(vite@7.0.0(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) '@storybook/vue3': 8.6.4(storybook@8.6.4(prettier@3.3.3))(vue@3.5.13(typescript@5.9.2)) find-package-json: 1.2.0 magic-string: 0.30.17 storybook: 8.6.4(prettier@3.3.3) typescript: 5.9.2 - vite: 7.0.0(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 7.0.0(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vue-component-meta: 2.1.10(typescript@5.9.2) vue-docgen-api: 4.76.0(vue@3.5.13(typescript@5.9.2)) transitivePeerDependencies: @@ -21655,7 +21884,7 @@ snapshots: '@supabase/node-fetch': 2.6.15 '@types/phoenix': 1.6.6 '@types/ws': 8.18.1(patch_hash=682b44b740be55e5d7018e6fe335880851dadf2524b6c723c9ed0c29cb2fa7fb) - ws: 8.18.2 + ws: 8.18.3 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -22109,6 +22338,11 @@ snapshots: '@types/node': 20.19.1 form-data: 4.0.4 + '@types/node-fetch@2.6.13': + dependencies: + '@types/node': 20.19.9 + form-data: 4.0.4 + '@types/node@20.17.57': dependencies: undici-types: 6.19.8 @@ -22117,6 +22351,10 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/node@20.19.9': + dependencies: + undici-types: 6.21.0 + '@types/nodemailer@6.4.14': dependencies: '@types/node': 20.17.57 @@ -22558,7 +22796,7 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.9.2': optional: true - '@vitejs/plugin-legacy@6.0.2(terser@5.16.1)(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))': + '@vitejs/plugin-legacy@6.0.2(terser@5.16.1)(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))': dependencies: '@babel/core': 7.26.10 '@babel/preset-env': 7.26.9(@babel/core@7.26.10) @@ -22569,16 +22807,16 @@ snapshots: regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.16.1 - vite: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2))': + '@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))(vue@3.5.13(typescript@5.9.2))': dependencies: - vite: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vue: 3.5.13(typescript@5.9.2) - '@vitest/coverage-v8@3.2.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))': + '@vitest/coverage-v8@3.2.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -22593,7 +22831,7 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vitest: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) transitivePeerDependencies: - supports-color @@ -22611,13 +22849,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.3(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))': + '@vitest/mocker@3.1.3(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))': dependencies: '@vitest/spy': 3.1.3 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) '@vitest/pretty-format@2.0.5': dependencies: @@ -23332,16 +23570,16 @@ snapshots: axe-core@4.7.2: {} - axios-retry@4.5.0(axios@1.10.0(debug@4.4.1)): - dependencies: - axios: 1.10.0(debug@4.4.1) - is-retry-allowed: 2.2.0 - axios-retry@4.5.0(axios@1.10.0): dependencies: axios: 1.10.0 is-retry-allowed: 2.2.0 + axios-retry@4.5.0(axios@1.11.0(debug@4.4.1)): + dependencies: + axios: 1.11.0(debug@4.4.1) + is-retry-allowed: 2.2.0 + axios-retry@4.5.0(axios@1.8.3): dependencies: axios: 1.8.3 @@ -23349,7 +23587,7 @@ snapshots: axios@1.10.0: dependencies: - follow-redirects: 1.15.9(debug@4.3.6) + follow-redirects: 1.15.9(debug@4.4.1) form-data: 4.0.4 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -23363,17 +23601,25 @@ snapshots: transitivePeerDependencies: - debug - axios@1.10.0(debug@4.4.0): + axios@1.11.0: dependencies: - follow-redirects: 1.15.9(debug@4.4.0) + follow-redirects: 1.15.11(debug@4.4.1) form-data: 4.0.4 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - axios@1.10.0(debug@4.4.1): + axios@1.11.0(debug@4.4.0): dependencies: - follow-redirects: 1.15.9(debug@4.4.1) + follow-redirects: 1.15.11(debug@4.4.0) + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + axios@1.11.0(debug@4.4.1): + dependencies: + follow-redirects: 1.15.11(debug@4.4.1) form-data: 4.0.4 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -23381,7 +23627,7 @@ snapshots: axios@1.8.3: dependencies: - follow-redirects: 1.15.9(debug@4.3.6) + follow-redirects: 1.15.9(debug@4.4.1) form-data: 4.0.4 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -23740,7 +23986,7 @@ snapshots: chokidar: 4.0.3 confbox: 0.1.8 defu: 6.1.4 - dotenv: 16.5.0 + dotenv: 16.6.1 giget: 1.2.5 jiti: 1.21.7 mlly: 1.7.4 @@ -23898,7 +24144,7 @@ snapshots: character-parser@2.2.0: dependencies: - is-regex: 1.1.4 + is-regex: 1.2.1 chardet@0.7.0: {} @@ -25005,6 +25251,8 @@ snapshots: dotenv@16.5.0: {} + dotenv@16.6.1: {} + dotenv@8.6.0: {} dreamopt@0.8.0: @@ -25916,6 +26164,10 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fdir@6.4.6(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + fecha@4.2.3: {} fengari-interop@0.1.3(fengari@0.1.4): @@ -26049,22 +26301,22 @@ snapshots: fn.name@1.1.0: {} + follow-redirects@1.15.11(debug@4.4.0): + optionalDependencies: + debug: 4.4.0 + + follow-redirects@1.15.11(debug@4.4.1): + optionalDependencies: + debug: 4.4.1(supports-color@8.1.1) + follow-redirects@1.15.9(debug@4.3.6): optionalDependencies: debug: 4.3.6 - follow-redirects@1.15.9(debug@4.4.0): - optionalDependencies: - debug: 4.4.0 - follow-redirects@1.15.9(debug@4.4.1): optionalDependencies: debug: 4.4.1(supports-color@8.1.1) - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -26783,19 +27035,19 @@ snapshots: ibm-cloud-sdk-core@5.3.2: dependencies: '@types/debug': 4.1.12 - '@types/node': 20.19.1 + '@types/node': 20.19.9 '@types/tough-cookie': 4.0.5 - axios: 1.10.0(debug@4.4.1) + axios: 1.11.0(debug@4.4.1) camelcase: 6.3.0 debug: 4.4.1(supports-color@8.1.1) - dotenv: 16.5.0 + dotenv: 16.6.1 extend: 3.0.2 file-type: 16.5.4 form-data: 4.0.4 isstream: 0.1.2 jsonwebtoken: 9.0.2 mime-types: 2.1.35 - retry-axios: 2.6.0(axios@1.10.0) + retry-axios: 2.6.0(axios@1.11.0) tough-cookie: 4.1.4 transitivePeerDependencies: - supports-color @@ -27326,16 +27578,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)): + jest-cli@29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)): dependencies: - '@jest/core': 29.6.2(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + '@jest/core': 29.6.2(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) '@jest/test-result': 29.6.2 '@jest/types': 29.6.1 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 import-local: 3.1.0 - jest-config: 29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + jest-config: 29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) jest-util: 29.6.2 jest-validate: 29.6.2 prompts: 2.4.2 @@ -27408,7 +27660,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)): + jest-config@29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)): dependencies: '@babel/core': 7.26.10 '@jest/test-sequencer': 29.6.2 @@ -27434,7 +27686,38 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.19.1 - ts-node: 10.9.2(@types/node@20.19.1)(typescript@5.9.2) + ts-node: 10.9.2(@types/node@20.19.9)(typescript@5.9.2) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-config@29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)): + dependencies: + '@babel/core': 7.26.10 + '@jest/test-sequencer': 29.6.2 + '@jest/types': 29.6.1 + babel-jest: 29.6.2(@babel/core@7.26.10) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.6.2 + jest-environment-node: 29.6.2 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.2 + jest-runner: 29.6.2 + jest-util: 29.6.2 + jest-validate: 29.6.2 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.19.9 + ts-node: 10.9.2(@types/node@20.19.9)(typescript@5.9.2) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -27537,7 +27820,7 @@ snapshots: jest-message-util@29.5.0: dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 '@jest/types': 29.6.1 '@types/stack-utils': 2.0.1 chalk: 4.1.2 @@ -27549,7 +27832,7 @@ snapshots: jest-message-util@29.6.2: dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 '@jest/types': 29.6.1 '@types/stack-utils': 2.0.1 chalk: 4.1.2 @@ -27565,9 +27848,9 @@ snapshots: ts-essentials: 7.0.3(typescript@5.9.2) typescript: 5.9.2 - jest-mock-extended@3.0.4(jest@29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)))(typescript@5.9.2): + jest-mock-extended@3.0.4(jest@29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)))(typescript@5.9.2): dependencies: - jest: 29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + jest: 29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) ts-essentials: 7.0.3(typescript@5.9.2) typescript: 5.9.2 @@ -27737,12 +28020,12 @@ snapshots: - supports-color - ts-node - jest@29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)): + jest@29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)): dependencies: - '@jest/core': 29.6.2(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + '@jest/core': 29.6.2(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) '@jest/types': 29.6.1 import-local: 3.1.0 - jest-cli: 29.6.2(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + jest-cli: 29.6.2(@types/node@20.19.9)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -27840,7 +28123,7 @@ snapshots: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - ws: 8.17.1 + ws: 8.18.3 xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -29567,7 +29850,7 @@ snapshots: openai@5.12.2(ws@8.18.2)(zod@3.25.67): optionalDependencies: - ws: 8.18.2 + ws: 8.18.3 zod: 3.25.67 openapi-sampler@1.5.1: @@ -29710,7 +29993,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -29895,6 +30178,8 @@ snapshots: picomatch@4.0.2: {} + picomatch@4.0.3: {} + pidtree@0.6.0: {} pify@2.3.0: {} @@ -29992,13 +30277,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.5.6 - postcss-load-config@4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)): + postcss-load-config@4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)): dependencies: lilconfig: 3.1.3 yaml: 2.3.4 optionalDependencies: postcss: 8.5.6 - ts-node: 10.9.2(@types/node@20.19.1)(typescript@5.9.2) + ts-node: 10.9.2(@types/node@20.19.9)(typescript@5.9.2) postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3): dependencies: @@ -30355,7 +30640,7 @@ snapshots: pyodide@0.28.0: dependencies: - ws: 8.18.2 + ws: 8.18.3 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -30769,9 +31054,9 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 - retry-axios@2.6.0(axios@1.10.0): + retry-axios@2.6.0(axios@1.11.0): dependencies: - axios: 1.10.0 + axios: 1.11.0 retry-request@7.0.2(encoding@0.1.13): dependencies: @@ -30856,6 +31141,32 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.44.0 fsevents: 2.3.3 + rollup@4.46.2: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.46.2 + '@rollup/rollup-android-arm64': 4.46.2 + '@rollup/rollup-darwin-arm64': 4.46.2 + '@rollup/rollup-darwin-x64': 4.46.2 + '@rollup/rollup-freebsd-arm64': 4.46.2 + '@rollup/rollup-freebsd-x64': 4.46.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.46.2 + '@rollup/rollup-linux-arm-musleabihf': 4.46.2 + '@rollup/rollup-linux-arm64-gnu': 4.46.2 + '@rollup/rollup-linux-arm64-musl': 4.46.2 + '@rollup/rollup-linux-loongarch64-gnu': 4.46.2 + '@rollup/rollup-linux-ppc64-gnu': 4.46.2 + '@rollup/rollup-linux-riscv64-gnu': 4.46.2 + '@rollup/rollup-linux-riscv64-musl': 4.46.2 + '@rollup/rollup-linux-s390x-gnu': 4.46.2 + '@rollup/rollup-linux-x64-gnu': 4.46.2 + '@rollup/rollup-linux-x64-musl': 4.46.2 + '@rollup/rollup-win32-arm64-msvc': 4.46.2 + '@rollup/rollup-win32-ia32-msvc': 4.46.2 + '@rollup/rollup-win32-x64-msvc': 4.46.2 + fsevents: 2.3.3 + route-recognizer@0.3.4: {} router@2.2.0: @@ -31232,7 +31543,7 @@ snapshots: queue-microtask: 1.2.3 randombytes: 2.1.0 readable-stream: 3.6.0 - ws: 8.17.1 + ws: 8.18.3 transitivePeerDependencies: - bufferutil - supports-color @@ -31825,7 +32136,7 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)): + tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -31844,7 +32155,7 @@ snapshots: postcss: 8.5.6 postcss-import: 15.1.0(postcss@8.5.6) postcss-js: 4.0.1(postcss@8.5.6) - postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2)) + postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2)) postcss-nested: 6.0.1(postcss@8.5.6) postcss-selector-parser: 6.1.2 resolve: 1.22.10 @@ -31924,7 +32235,7 @@ snapshots: terser@5.16.1: dependencies: - '@jridgewell/source-map': 0.3.6 + '@jridgewell/source-map': 0.3.10 acorn: 8.14.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -32187,14 +32498,14 @@ snapshots: yn: 3.1.1 optional: true - ts-node@10.9.2(@types/node@20.19.1)(typescript@5.9.2): + ts-node@10.9.2(@types/node@20.19.9)(typescript@5.9.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.19.1 + '@types/node': 20.19.9 acorn: 8.14.0 acorn-walk: 8.3.4 arg: 4.1.3 @@ -32206,7 +32517,7 @@ snapshots: yn: 3.1.1 optional: true - ts-pattern@5.7.1: {} + ts-pattern@5.8.0: {} ts-toolbelt@9.6.0: {} @@ -32246,7 +32557,7 @@ snapshots: tsscmp@1.0.6: {} - tsup@8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.1))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2): + tsup@8.5.0(@microsoft/api-extractor@7.52.1(@types/node@20.19.9))(jiti@1.21.7)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.9.2): dependencies: bundle-require: 5.1.0(esbuild@0.24.2) cac: 6.7.14 @@ -32266,7 +32577,7 @@ snapshots: tinyglobby: 0.2.14 tree-kill: 1.2.2 optionalDependencies: - '@microsoft/api-extractor': 7.52.1(@types/node@20.19.1) + '@microsoft/api-extractor': 7.52.1(@types/node@20.19.9) postcss: 8.5.6 typescript: 5.9.2 transitivePeerDependencies: @@ -32369,7 +32680,7 @@ snapshots: typed-array-byte-length@1.0.1: dependencies: call-bind: 1.0.8 - for-each: 0.3.3 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.0.3 is-typed-array: 1.1.13 @@ -32386,7 +32697,7 @@ snapshots: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 - for-each: 0.3.3 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.0.3 is-typed-array: 1.1.13 @@ -32404,7 +32715,7 @@ snapshots: typed-array-length@1.0.6: dependencies: call-bind: 1.0.8 - for-each: 0.3.3 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.0.3 is-typed-array: 1.1.13 @@ -32518,10 +32829,10 @@ snapshots: transitivePeerDependencies: - supports-color - unplugin-vue-components@0.27.3(@babel/parser@7.27.5)(rollup@4.44.0)(vue@3.5.13(typescript@5.9.2)): + unplugin-vue-components@0.27.3(@babel/parser@7.27.5)(rollup@4.46.2)(vue@3.5.13(typescript@5.9.2)): dependencies: '@antfu/utils': 0.7.10 - '@rollup/pluginutils': 5.1.4(rollup@4.44.0) + '@rollup/pluginutils': 5.1.4(rollup@4.46.2) chokidar: 4.0.3 debug: 4.4.1(supports-color@8.1.1) fast-glob: 3.3.3 @@ -32679,13 +32990,13 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@3.1.3(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3): + vite-node@3.1.3(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3): dependencies: cac: 6.7.14 debug: 4.4.1(supports-color@8.1.1) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) transitivePeerDependencies: - '@types/node' - jiti @@ -32700,10 +33011,10 @@ snapshots: - tsx - yaml - vite-plugin-dts@4.5.3(@types/node@20.19.1)(rollup@4.44.0)(typescript@5.9.2)(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)): + vite-plugin-dts@4.5.3(@types/node@20.19.9)(rollup@4.46.2)(typescript@5.9.2)(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)): dependencies: - '@microsoft/api-extractor': 7.52.1(@types/node@20.19.1) - '@rollup/pluginutils': 5.1.4(rollup@4.44.0) + '@microsoft/api-extractor': 7.52.1(@types/node@20.19.9) + '@rollup/pluginutils': 5.1.4(rollup@4.46.2) '@volar/typescript': 2.4.12 '@vue/language-core': 2.2.0(typescript@5.9.2) compare-versions: 6.1.1 @@ -32713,34 +33024,34 @@ snapshots: magic-string: 0.30.17 typescript: 5.9.2 optionalDependencies: - vite: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite-plugin-node-polyfills@0.24.0(rollup@4.44.0)(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)): + vite-plugin-node-polyfills@0.24.0(rollup@4.46.2)(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)): dependencies: - '@rollup/plugin-inject': 5.0.5(rollup@4.44.0) + '@rollup/plugin-inject': 5.0.5(rollup@4.46.2) node-stdlib-browser: 1.3.1 - vite: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) transitivePeerDependencies: - rollup - vite-plugin-static-copy@2.2.0(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)): + vite-plugin-static-copy@2.2.0(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)): dependencies: chokidar: 4.0.1 fast-glob: 3.3.3 fs-extra: 11.3.0 picocolors: 1.1.1 - vite: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) vite-svg-loader@5.1.0(vue@3.5.13(typescript@5.9.2)): dependencies: svgo: 3.3.2 vue: 3.5.13(typescript@5.9.2) - vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3): + vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3): dependencies: esbuild: 0.24.2 fdir: 6.4.6(picomatch@4.0.2) @@ -32749,39 +33060,39 @@ snapshots: rollup: 4.44.0 tinyglobby: 0.2.14 optionalDependencies: - '@types/node': 20.19.1 + '@types/node': 20.19.9 fsevents: 2.3.3 jiti: 1.21.7 sass: 1.89.2 terser: 5.16.1 tsx: 4.19.3 - vite@7.0.0(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3): + vite@7.0.0(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3): dependencies: esbuild: 0.24.2 - fdir: 6.4.6(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.44.0 + rollup: 4.46.2 tinyglobby: 0.2.14 optionalDependencies: - '@types/node': 20.19.1 + '@types/node': 20.19.9 fsevents: 2.3.3 jiti: 1.21.7 sass: 1.89.2 terser: 5.16.1 tsx: 4.19.3 - vitest-mock-extended@3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)): + vitest-mock-extended@3.1.0(typescript@5.9.2)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)): dependencies: ts-essentials: 10.0.2(typescript@5.9.2) typescript: 5.9.2 - vitest: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vitest: 3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) - vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3): + vitest@3.1.3(@types/debug@4.1.12)(@types/node@20.19.9)(jiti@1.21.7)(jsdom@23.0.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3): dependencies: '@vitest/expect': 3.1.3 - '@vitest/mocker': 3.1.3(vite@6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) + '@vitest/mocker': 3.1.3(vite@6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.1.3 '@vitest/snapshot': 3.1.3 @@ -32798,12 +33109,12 @@ snapshots: tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) - vite-node: 3.1.3(@types/node@20.19.1)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite: 6.3.5(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) + vite-node: 3.1.3(@types/node@20.19.9)(jiti@1.21.7)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 20.19.1 + '@types/node': 20.19.9 jsdom: 23.0.1 transitivePeerDependencies: - jiti @@ -32966,7 +33277,7 @@ snapshots: wait-on@8.0.2(debug@4.4.0): dependencies: - axios: 1.10.0(debug@4.4.0) + axios: 1.11.0(debug@4.4.0) joi: 17.13.3 lodash: 4.17.21 minimist: 1.2.8 @@ -33107,7 +33418,7 @@ snapshots: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 - for-each: 0.3.3 + for-each: 0.3.5 gopd: 1.2.0 has-tostringtag: 1.0.2 @@ -33243,7 +33554,7 @@ snapshots: ws@8.17.1: {} - ws@8.18.2: {} + ws@8.18.3: {} xlsx@https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz: {} @@ -33408,6 +33719,10 @@ snapshots: dependencies: zod: 3.25.67 + zod-to-json-schema@3.24.6(zod@3.25.67): + dependencies: + zod: 3.25.67 + zod@3.25.67: {} zx@8.1.4: