first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,261 @@
import { getConfigFromMetaTag, getAndParseConfigFromMetaTag } from '../metaTagConfig';
describe('metaTagConfig', () => {
beforeEach(() => {
document.head.innerHTML = '';
vi.clearAllMocks();
});
/**
* Helper function to create and insert a meta tag into the document head
*/
function createMetaTag(configName: string, content?: string): void {
const metaTag = document.createElement('meta');
metaTag.setAttribute('name', `n8n:config:${configName}`);
if (content !== undefined) {
metaTag.setAttribute('content', content);
}
document.head.appendChild(metaTag);
}
/**
* Helper function to create a meta tag with base64-encoded content
*/
function createMetaTagWithBase64Content(configName: string, value: string): void {
const base64Value = btoa(value);
createMetaTag(configName, base64Value);
}
/**
* Helper function to create a meta tag with JSON content (base64-encoded)
*/
function createMetaTagWithJsonContent(configName: string, value: unknown): void {
const jsonString = JSON.stringify(value);
createMetaTagWithBase64Content(configName, jsonString);
}
describe('getConfigFromMetaTag', () => {
it('should return null when meta tag does not exist', () => {
const result = getConfigFromMetaTag('testConfig');
expect(result).toBeNull();
});
it('should return null when meta tag exists but has no content attribute', () => {
createMetaTag('testConfig');
const result = getConfigFromMetaTag('testConfig');
expect(result).toBeNull();
});
it('should return null when meta tag has empty content attribute', () => {
createMetaTag('testConfig', '');
const result = getConfigFromMetaTag('testConfig');
expect(result).toBeNull();
});
it('should decode and return base64 content successfully', () => {
const originalValue = 'Hello World';
createMetaTagWithBase64Content('testConfig', originalValue);
const result = getConfigFromMetaTag('testConfig');
expect(result).toBe(originalValue);
});
it('should handle complex string content correctly', () => {
const originalValue = 'This is a test with special chars: !@#$%^&*()';
createMetaTagWithBase64Content('complexConfig', originalValue);
const result = getConfigFromMetaTag('complexConfig');
expect(result).toBe(originalValue);
});
it('should return null and log warning when base64 decoding fails', () => {
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
createMetaTag('invalidConfig', 'invalid-base64!!!');
const result = getConfigFromMetaTag('invalidConfig');
expect(result).toBeNull();
expect(consoleSpy).toHaveBeenCalledWith(
'Failed to read n8n config for "n8n:config:invalidConfig":',
expect.any(Error),
);
consoleSpy.mockRestore();
});
it.each([
{ name: 'config1', value: 'value1' },
{ name: 'config2', value: 'value2' },
{ name: 'special-config', value: 'special-value' },
])('should handle different config names correctly: $name', ({ name, value }) => {
createMetaTagWithBase64Content(name, value);
const result = getConfigFromMetaTag(name);
expect(result).toBe(value);
});
});
describe('getAndParseConfigFromMetaTag', () => {
it('should return null when meta tag does not exist', () => {
const result = getAndParseConfigFromMetaTag('nonExistentConfig');
expect(result).toBeNull();
});
it('should return null when getConfigFromMetaTag returns null', () => {
createMetaTag('emptyConfig');
const result = getAndParseConfigFromMetaTag('emptyConfig');
expect(result).toBeNull();
});
it('should parse and return valid JSON object', () => {
const originalObject = {
key1: 'value1',
key2: 42,
key3: true,
nested: { prop: 'nestedValue' },
};
createMetaTagWithJsonContent('jsonConfig', originalObject);
const result = getAndParseConfigFromMetaTag<typeof originalObject>('jsonConfig');
expect(result).toEqual(originalObject);
});
it('should parse and return valid JSON array', () => {
const originalArray = [1, 2, 3, { name: 'test' }];
createMetaTagWithJsonContent('arrayConfig', originalArray);
const result = getAndParseConfigFromMetaTag<typeof originalArray>('arrayConfig');
expect(result).toEqual(originalArray);
});
it('should parse and return primitive JSON values', () => {
const testCases = [
{ value: 'simple string', name: 'stringConfig' },
{ value: 42, name: 'numberConfig' },
{ value: true, name: 'booleanConfig' },
{ value: null, name: 'nullConfig' },
];
testCases.forEach((testCase) => {
createMetaTagWithJsonContent(testCase.name, testCase.value);
const result = getAndParseConfigFromMetaTag(testCase.name);
expect(result).toEqual(testCase.value);
});
});
it('should return null and log warning when JSON parsing fails', () => {
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const invalidJson = 'this is not json';
createMetaTagWithBase64Content('invalidJsonConfig', invalidJson);
const result = getAndParseConfigFromMetaTag('invalidJsonConfig');
expect(result).toBeNull();
expect(consoleSpy).toHaveBeenCalledWith(
'Failed to parse n8n config for "n8n:config:invalidJsonConfig":',
expect.any(Error),
);
consoleSpy.mockRestore();
});
it('should handle complex nested objects with type safety', () => {
interface TestConfig {
api: {
url: string;
version: number;
features: string[];
};
user: {
id: number;
permissions: Record<string, boolean>;
};
}
const originalConfig: TestConfig = {
api: {
url: 'https://api.example.com',
version: 2,
features: ['feature1', 'feature2'],
},
user: {
id: 123,
permissions: {
read: true,
write: false,
admin: false,
},
},
};
createMetaTagWithJsonContent('complexConfig', originalConfig);
const result = getAndParseConfigFromMetaTag<TestConfig>('complexConfig');
expect(result).toEqual(originalConfig);
assert(result);
// Type assertions to ensure type safety works
expect(result.api.url).toBe('https://api.example.com');
expect(result.user.permissions.read).toBe(true);
expect(result.api.features).toHaveLength(2);
});
it('should handle empty JSON objects and arrays', () => {
const testCases = [
{ value: {}, name: 'emptyObject' },
{ value: [], name: 'emptyArray' },
];
testCases.forEach((testCase) => {
createMetaTagWithJsonContent(testCase.name, testCase.value);
const result = getAndParseConfigFromMetaTag(testCase.name);
expect(result).toEqual(testCase.value);
});
});
});
describe('integration tests', () => {
it('should handle multiple config retrieval operations', () => {
const configs = {
stringConfig: 'test string',
objectConfig: { key: 'value', num: 42 },
arrayConfig: [1, 2, 3],
};
Object.entries(configs).forEach(([name, value]) => {
if (typeof value === 'string') {
createMetaTagWithBase64Content(name, value);
} else {
createMetaTagWithJsonContent(name, value);
}
});
const stringResult = getConfigFromMetaTag('stringConfig');
expect(stringResult).toBe('test string');
const objectResult = getAndParseConfigFromMetaTag('objectConfig');
expect(objectResult).toEqual({ key: 'value', num: 42 });
const arrayResult = getAndParseConfigFromMetaTag('arrayConfig');
expect(arrayResult).toEqual([1, 2, 3]);
});
it('should handle edge case of config name with special characters', () => {
const configName = 'config-with-dashes_and_underscores.123';
const configValue = { test: true };
createMetaTagWithJsonContent(configName, configValue);
const result = getAndParseConfigFromMetaTag(configName);
expect(result).toEqual(configValue);
});
});
});
@@ -0,0 +1,7 @@
import '@testing-library/jest-dom';
import { configure } from '@testing-library/vue';
// Avoid tests failing because of difference between local and GitHub actions timezone
process.env.TZ = 'UTC';
configure({ testIdAttribute: 'data-test-id' });
@@ -0,0 +1,54 @@
export const STORES = {
COMMUNITY_NODES: 'communityNodes',
ROOT: 'root',
SETTINGS: 'settings',
UI: 'ui',
USERS: 'users',
WORKFLOWS: 'workflows',
WORKFLOWS_LIST: 'workflowsList',
WORKFLOWS_V2: 'workflowsV2',
WORKFLOWS_EE: 'workflowsEE',
WORKFLOW_DOCUMENTS: 'workflowDocuments',
EXECUTIONS: 'executions',
NDV: 'ndv',
TEMPLATES: 'templates',
NODE_TYPES: 'nodeTypes',
CREDENTIALS: 'credentials',
TAGS: 'tags',
ANNOTATION_TAGS: 'annotationTags',
VERSIONS: 'versions',
NODE_CREATOR: 'nodeCreator',
WEBHOOKS: 'webhooks',
HISTORY: 'history',
CLOUD_PLAN: 'cloudPlan',
RBAC: 'rbac',
PUSH: 'push',
COLLABORATION: 'collaboration',
ASSISTANT: 'assistant',
BUILDER: 'builder',
CHAT_PANEL: 'chatPanel',
CHAT_PANEL_STATE: 'chatPanelState',
BECOME_TEMPLATE_CREATOR: 'becomeTemplateCreator',
PROJECTS: 'projects',
API_KEYS: 'apiKeys',
EVALUATION: 'evaluation',
FOLDERS: 'folders',
MODULES: 'modules',
FOCUS_PANEL: 'focusPanel',
WORKFLOW_STATE: 'workflowState',
AI_TEMPLATES_STARTER_COLLECTION: 'aiTemplatesStarterCollection',
PERSONALIZED_TEMPLATES: 'personalizedTemplates',
EXPERIMENT_READY_TO_RUN_WORKFLOWS: 'readyToRunWorkflows',
EXPERIMENT_READY_TO_RUN_WORKFLOWS_V2: 'readyToRunWorkflowsV2',
EXPERIMENT_TEMPLATE_RECO_V2: 'templateRecoV2',
PERSONALIZED_TEMPLATES_V3: 'personalizedTemplatesV3',
READY_TO_RUN: 'readyToRun',
TEMPLATES_DATA_QUALITY: 'templatesDataQuality',
BANNERS: 'banners',
CONSENT: 'consent',
CHAT_HUB: 'chatHub',
EXPERIMENT_EMPTY_STATE_BUILDER_PROMPT: 'emptyStateBuilderPrompt',
EXPERIMENT_CREDENTIALS_APP_SELECTION: 'credentialsAppSelection',
SETUP_PANEL: 'setupPanel',
FOCUSED_NODES: 'focusedNodes',
} as const;
@@ -0,0 +1 @@
export * from './constants';
@@ -0,0 +1,46 @@
function getTagName(configName: string): string {
return `n8n:config:${configName}`;
}
/**
* Utility function to read and decode base64-encoded configuration values from meta tags
*/
export function getConfigFromMetaTag(configName: string): string | null {
const tagName = getTagName(configName);
try {
const metaTag = document.querySelector(`meta[name="${tagName}"]`);
if (!metaTag) {
return null;
}
const encodedContent = metaTag.getAttribute('content');
if (!encodedContent) {
return null;
}
// Decode base64 content
const content = atob(encodedContent);
return content;
} catch (error) {
console.warn(`Failed to read n8n config for "${tagName}":`, error);
return null;
}
}
/**
* Utility function to read and parse configuration values from meta tags
*/
export function getAndParseConfigFromMetaTag<T>(configName: string): T | null {
const config = getConfigFromMetaTag(configName);
if (!config) {
return null;
}
try {
return JSON.parse(config) as T;
} catch (error) {
console.warn(`Failed to parse n8n config for "${getTagName(configName)}":`, error);
return null;
}
}
+19
View File
@@ -0,0 +1,19 @@
/// <reference types="vite/client" />
export {};
declare global {
interface ImportMeta {
env: {
DEV: boolean;
PROD: boolean;
NODE_ENV: 'development' | 'production';
VUE_APP_URL_BASE_API: string;
};
}
interface Window {
BASE_PATH: string;
REST_ENDPOINT: string;
}
}
@@ -0,0 +1,189 @@
import { setActivePinia, createPinia } from 'pinia';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { nextTick } from 'vue';
import {
type IAgentRequestStoreState,
type IAgentRequest,
useAgentRequestStore,
} from './useAgentRequestStore';
// Mock localStorage
let mockLocalStorageValue: IAgentRequestStoreState = {};
const NODE_NAME = 'Test Node';
const NODE_ID_1 = '123e4567-e89b-12d3-a456-426614174000';
const NODE_ID_2 = '987fcdeb-51a2-43d7-b654-987654321000';
const NODE_ID_3 = '456abcde-f789-12d3-a456-426614174000';
vi.mock('@vueuse/core', () => ({
useLocalStorage: vi.fn((_key, defaultValue) => {
if (Object.keys(mockLocalStorageValue).length === 0) {
Object.assign(mockLocalStorageValue, structuredClone(defaultValue));
}
return {
value: mockLocalStorageValue,
};
}),
}));
describe('agentRequest.store', () => {
beforeEach(() => {
mockLocalStorageValue = {};
setActivePinia(createPinia());
});
describe('Initialization', () => {
it('initializes with empty state when localStorage is empty', () => {
const store = useAgentRequestStore();
expect(store.agentRequests.value).toEqual({});
});
it('initializes with data from localStorage', () => {
const mockData: IAgentRequestStoreState = {
'workflow-1': {
[NODE_ID_1]: { query: { [NODE_NAME]: { param1: 'value1' } } },
},
};
mockLocalStorageValue = mockData;
const store = useAgentRequestStore();
expect(store.agentRequests.value).toEqual(mockData);
});
});
describe('Getters', () => {
it('gets parameter overrides for a node', () => {
const store = useAgentRequestStore();
store.setAgentRequestForNode('workflow-1', NODE_ID_1, {
query: { [NODE_NAME]: { param1: 'value1', param2: 'value2' } },
});
const overrides = store.getAgentRequests('workflow-1', NODE_ID_1);
expect(overrides).toEqual({ [NODE_NAME]: { param1: 'value1', param2: 'value2' } });
});
it('returns empty object for non-existent workflow/node', () => {
const store = useAgentRequestStore();
const overrides = store.getAgentRequests('non-existent', NODE_ID_1);
expect(overrides).toEqual({});
});
it('gets a specific parameter override', () => {
const store = useAgentRequestStore();
store.setAgentRequestForNode('workflow-1', NODE_ID_1, {
query: { [NODE_NAME]: { param1: 'value1', param2: 'value2' } },
});
const override = store.getQueryValue('workflow-1', NODE_ID_1, NODE_NAME, 'param1');
expect(override).toBe('value1');
});
it('returns undefined for non-existent parameter', () => {
const store = useAgentRequestStore();
store.setAgentRequestForNode('workflow-1', NODE_ID_1, {
query: { [NODE_NAME]: { param1: 'value1' } },
});
const override = store.getQueryValue('workflow-1', NODE_ID_1, NODE_NAME, 'non-existent');
expect(override).toBeUndefined();
});
});
describe('Actions', () => {
it('sets parameter overrides for a node', () => {
const store = useAgentRequestStore();
store.setAgentRequestForNode('workflow-1', NODE_ID_1, {
query: { [NODE_NAME]: { param1: 'value1', param2: 'value2' } },
});
expect(
(store.agentRequests.value['workflow-1'] as unknown as { [key: string]: IAgentRequest })[
NODE_ID_1
].query,
).toEqual({
[NODE_NAME]: { param1: 'value1', param2: 'value2' },
});
});
it('clears parameter overrides for a node', () => {
const store = useAgentRequestStore();
store.setAgentRequestForNode('workflow-1', NODE_ID_1, {
query: { [NODE_NAME]: { param1: 'value1', param2: 'value2' } },
});
store.setAgentRequestForNode('workflow-1', NODE_ID_2, {
query: { [NODE_NAME]: { param3: 'value3' } },
});
store.clearAgentRequests('workflow-1', NODE_ID_1);
expect(
(store.agentRequests.value['workflow-1'] as unknown as { [key: string]: IAgentRequest })[
NODE_ID_1
].query,
).toEqual({});
expect(
(store.agentRequests.value['workflow-1'] as unknown as { [key: string]: IAgentRequest })[
NODE_ID_2
].query,
).toEqual({
[NODE_NAME]: { param3: 'value3' },
});
});
it('clears all parameter overrides for a workflow', () => {
const store = useAgentRequestStore();
store.setAgentRequestForNode('workflow-1', NODE_ID_1, {
query: { [NODE_NAME]: { param1: 'value1' } },
});
store.setAgentRequestForNode('workflow-1', NODE_ID_2, {
query: { [NODE_NAME]: { param2: 'value2' } },
});
store.setAgentRequestForNode('workflow-2', NODE_ID_3, {
query: { [NODE_NAME]: { param3: 'value3' } },
});
store.clearAllAgentRequests('workflow-1');
expect(store.agentRequests.value['workflow-1']).toEqual({});
expect(store.agentRequests.value['workflow-2']).toEqual({
[NODE_ID_3]: { query: { [NODE_NAME]: { param3: 'value3' } } },
});
});
it('clears all parameter overrides when no workflowId is provided', () => {
const store = useAgentRequestStore();
store.setAgentRequestForNode('workflow-1', NODE_ID_1, {
query: { [NODE_NAME]: { param1: 'value1' } },
});
store.setAgentRequestForNode('workflow-2', NODE_ID_2, {
query: { [NODE_NAME]: { param2: 'value2' } },
});
store.clearAllAgentRequests();
expect(store.agentRequests.value).toEqual({});
});
});
describe('Persistence', () => {
it('saves to localStorage when state changes', async () => {
const store = useAgentRequestStore();
store.setAgentRequestForNode('workflow-1', NODE_ID_1, {
query: { [NODE_NAME]: { param1: 'value1' } },
});
await nextTick();
expect(mockLocalStorageValue).toEqual({
'workflow-1': {
[NODE_ID_1]: { query: { [NODE_NAME]: { param1: 'value1' } } },
},
});
});
});
});
@@ -0,0 +1,92 @@
import { useLocalStorage } from '@vueuse/core';
import type { AgentRequestQuery } from 'n8n-workflow';
import { defineStore } from 'pinia';
const LOCAL_STORAGE_AGENT_REQUESTS = 'N8N_AGENT_REQUESTS';
export interface IAgentRequest {
query: AgentRequestQuery;
toolName?: string;
}
export interface IAgentRequestStoreState {
[workflowId: string]: {
[nodeName: string]: IAgentRequest;
};
}
export const useAgentRequestStore = defineStore('agentRequest', () => {
// State
const agentRequests = useLocalStorage<IAgentRequestStoreState>(LOCAL_STORAGE_AGENT_REQUESTS, {});
// Helper function to ensure workflow and node entries exist
const ensureWorkflowAndNodeExist = (workflowId: string, nodeId: string): void => {
if (!agentRequests.value[workflowId]) {
agentRequests.value[workflowId] = {};
}
if (!agentRequests.value[workflowId][nodeId]) {
agentRequests.value[workflowId][nodeId] = { query: {} };
}
};
// Getters
const getAgentRequests = (workflowId: string, nodeId: string): IAgentRequest['query'] => {
return agentRequests.value[workflowId]?.[nodeId]?.query || {};
};
const getQueryValue = (
workflowId: string,
nodeId: string,
nodeName: string,
paramName?: string,
): unknown => {
const query = agentRequests.value[workflowId]?.[nodeId]?.query?.[nodeName];
if (typeof query === 'string' || !paramName) {
return query;
}
return query?.[paramName];
};
const setAgentRequestForNode = (
workflowId: string,
nodeId: string,
request: IAgentRequest,
): void => {
ensureWorkflowAndNodeExist(workflowId, nodeId);
agentRequests.value[workflowId][nodeId] = {
...request,
query: { ...request.query },
};
};
const clearAgentRequests = (workflowId: string, nodeId: string): void => {
if (agentRequests.value[workflowId]) {
agentRequests.value[workflowId][nodeId] = { query: {} };
}
};
const clearAllAgentRequests = (workflowId?: string): void => {
if (workflowId) {
agentRequests.value[workflowId] = {};
} else {
agentRequests.value = {};
}
};
const getAgentRequest = (workflowId: string, nodeId: string): IAgentRequest | undefined => {
if (agentRequests.value[workflowId]) return agentRequests.value[workflowId]?.[nodeId];
return undefined;
};
return {
agentRequests,
getAgentRequests,
getQueryValue,
setAgentRequestForNode,
clearAgentRequests,
clearAllAgentRequests,
getAgentRequest,
};
});
@@ -0,0 +1,259 @@
import { randomString, setGlobalState } from 'n8n-workflow';
import { defineStore } from 'pinia';
import { computed, ref } from 'vue';
import { STORES } from './constants';
import { getConfigFromMetaTag } from './metaTagConfig';
const { VUE_APP_URL_BASE_API } = import.meta.env;
export type RootStoreState = {
baseUrl: string;
restEndpoint: string;
defaultLocale: string;
endpointForm: string;
endpointFormTest: string;
endpointFormWaiting: string;
endpointMcp: string;
endpointMcpTest: string;
endpointWebhook: string;
endpointWebhookTest: string;
endpointWebhookWaiting: string;
timezone: string;
executionTimeout: number;
maxExecutionTimeout: number;
versionCli: string;
oauthCallbackUrls: object;
n8nMetadata: {
[key: string]: string | number | undefined;
};
pushRef: string;
urlBaseWebhook: string;
urlBaseEditor: string;
instanceId: string;
binaryDataMode: 'default' | 'filesystem' | 's3' | 'database';
};
export const useRootStore = defineStore(STORES.ROOT, () => {
// Generate or retrieve client ID from sessionStorage
const getClientId = (): string => {
const storageKey = 'n8n-client-id';
const existingId = sessionStorage.getItem(storageKey);
if (existingId) {
return existingId;
}
const newId = randomString(10).toLowerCase();
sessionStorage.setItem(storageKey, newId);
return newId;
};
const state = ref<RootStoreState>({
baseUrl: VUE_APP_URL_BASE_API ?? window.BASE_PATH,
restEndpoint: getConfigFromMetaTag('rest-endpoint') ?? 'rest',
defaultLocale: 'en',
endpointForm: 'form',
endpointFormTest: 'form-test',
endpointFormWaiting: 'form-waiting',
endpointMcp: 'mcp',
endpointMcpTest: 'mcp-test',
endpointWebhook: 'webhook',
endpointWebhookTest: 'webhook-test',
endpointWebhookWaiting: 'webhook-waiting',
timezone: 'America/New_York',
executionTimeout: -1,
maxExecutionTimeout: Number.MAX_SAFE_INTEGER,
versionCli: '0.0.0',
oauthCallbackUrls: {},
n8nMetadata: {},
pushRef: getClientId(),
urlBaseWebhook: 'http://localhost:5678/',
urlBaseEditor: 'http://localhost:5678',
instanceId: '',
binaryDataMode: 'default',
});
// ---------------------------------------------------------------------------
// #region Computed
// ---------------------------------------------------------------------------
const baseUrl = computed(() => state.value.baseUrl);
const formUrl = computed(() => `${state.value.urlBaseWebhook}${state.value.endpointForm}`);
const formTestUrl = computed(() => `${state.value.urlBaseEditor}${state.value.endpointFormTest}`);
const formWaitingUrl = computed(
() => `${state.value.urlBaseEditor}${state.value.endpointFormWaiting}`,
);
const webhookUrl = computed(() => `${state.value.urlBaseWebhook}${state.value.endpointWebhook}`);
const webhookTestUrl = computed(
() => `${state.value.urlBaseEditor}${state.value.endpointWebhookTest}`,
);
const webhookWaitingUrl = computed(
() => `${state.value.urlBaseEditor}${state.value.endpointWebhookWaiting}`,
);
const mcpUrl = computed(() => `${state.value.urlBaseWebhook}${state.value.endpointMcp}`);
const mcpTestUrl = computed(() => `${state.value.urlBaseEditor}${state.value.endpointMcpTest}`);
const pushRef = computed(() => state.value.pushRef);
const binaryDataMode = computed(() => state.value.binaryDataMode);
const defaultLocale = computed(() => state.value.defaultLocale);
const urlBaseEditor = computed(() => state.value.urlBaseEditor);
const instanceId = computed(() => state.value.instanceId);
const versionCli = computed(() => state.value.versionCli);
const OAuthCallbackUrls = computed(() => state.value.oauthCallbackUrls);
const restUrl = computed(() => `${state.value.baseUrl}${state.value.restEndpoint}`);
const executionTimeout = computed(() => state.value.executionTimeout);
const maxExecutionTimeout = computed(() => state.value.maxExecutionTimeout);
const timezone = computed(() => state.value.timezone);
const restApiContext = computed(() => ({
baseUrl: restUrl.value,
pushRef: state.value.pushRef,
}));
// #endregion
// ---------------------------------------------------------------------------
// #region Methods
// ---------------------------------------------------------------------------
const setUrlBaseWebhook = (value: string) => {
const url = value.endsWith('/') ? value : `${value}/`;
state.value.urlBaseWebhook = url;
};
const setUrlBaseEditor = (value: string) => {
const url = value.endsWith('/') ? value : `${value}/`;
state.value.urlBaseEditor = url;
};
const setEndpointForm = (value: string) => {
state.value.endpointForm = value;
};
const setEndpointFormTest = (value: string) => {
state.value.endpointFormTest = value;
};
const setEndpointFormWaiting = (value: string) => {
state.value.endpointFormWaiting = value;
};
const setEndpointWebhook = (value: string) => {
state.value.endpointWebhook = value;
};
const setEndpointWebhookTest = (value: string) => {
state.value.endpointWebhookTest = value;
};
const setEndpointWebhookWaiting = (value: string) => {
state.value.endpointWebhookWaiting = value;
};
const setEndpointMcp = (value: string) => {
state.value.endpointMcp = value;
};
const setEndpointMcpTest = (value: string) => {
state.value.endpointMcpTest = value;
};
const setTimezone = (value: string) => {
state.value.timezone = value;
setGlobalState({ defaultTimezone: value });
};
const setExecutionTimeout = (value: number) => {
state.value.executionTimeout = value;
};
const setMaxExecutionTimeout = (value: number) => {
state.value.maxExecutionTimeout = value;
};
const setVersionCli = (value: string) => {
state.value.versionCli = value;
};
const setInstanceId = (value: string) => {
state.value.instanceId = value;
};
const setOauthCallbackUrls = (value: RootStoreState['oauthCallbackUrls']) => {
state.value.oauthCallbackUrls = value;
};
const setN8nMetadata = (value: RootStoreState['n8nMetadata']) => {
state.value.n8nMetadata = value;
};
const setDefaultLocale = (value: string) => {
state.value.defaultLocale = value;
};
const setBinaryDataMode = (value: RootStoreState['binaryDataMode']) => {
state.value.binaryDataMode = value;
};
// #endregion
return {
baseUrl,
formUrl,
formTestUrl,
formWaitingUrl,
mcpUrl,
mcpTestUrl,
webhookUrl,
webhookTestUrl,
webhookWaitingUrl,
restUrl,
restApiContext,
urlBaseEditor,
versionCli,
instanceId,
pushRef,
defaultLocale,
binaryDataMode,
OAuthCallbackUrls,
executionTimeout,
maxExecutionTimeout,
timezone,
setUrlBaseWebhook,
setUrlBaseEditor,
setEndpointForm,
setEndpointFormTest,
setEndpointFormWaiting,
setEndpointWebhook,
setEndpointWebhookTest,
setEndpointWebhookWaiting,
setEndpointMcp,
setEndpointMcpTest,
setTimezone,
setExecutionTimeout,
setMaxExecutionTimeout,
setVersionCli,
setInstanceId,
setOauthCallbackUrls,
setN8nMetadata,
setDefaultLocale,
setBinaryDataMode,
};
});