diff --git a/packages/frontend/@n8n/stores/.eslintrc.cjs b/packages/frontend/@n8n/stores/.eslintrc.cjs
new file mode 100644
index 0000000000..3f9a316c08
--- /dev/null
+++ b/packages/frontend/@n8n/stores/.eslintrc.cjs
@@ -0,0 +1,10 @@
+const sharedOptions = require('@n8n/eslint-config/shared');
+
+/**
+ * @type {import('@types/eslint').ESLint.ConfigData}
+ */
+module.exports = {
+ extends: ['@n8n/eslint-config/frontend'],
+
+ ...sharedOptions(__dirname, 'frontend'),
+};
diff --git a/packages/frontend/@n8n/stores/.gitignore b/packages/frontend/@n8n/stores/.gitignore
new file mode 100644
index 0000000000..a547bf36d8
--- /dev/null
+++ b/packages/frontend/@n8n/stores/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/packages/frontend/@n8n/stores/README.md b/packages/frontend/@n8n/stores/README.md
new file mode 100644
index 0000000000..cb3e742e4d
--- /dev/null
+++ b/packages/frontend/@n8n/stores/README.md
@@ -0,0 +1,24 @@
+# @n8n/stores
+
+A collection of Pinia stores that provide common data-related functionality across n8n's Front-End packages.
+
+## Table of Contents
+
+- [Features](#features)
+- [Contributing](#contributing)
+- [License](#license)
+
+## Features
+
+- **Composable State Management**: Share and reuse stateful logic across multiple Vue components using Pinia stores.
+- **Consistent Patterns**: Promote uniform state handling and best practices throughout the front-end codebase.
+- **Easy Extensibility**: Add or modify stores as project requirements evolve, supporting scalable development.
+- **Composition API Support**: Designed to work seamlessly with Vue's Composition API for modern, maintainable code.
+
+## Contributing
+
+For more details, please read our [CONTRIBUTING.md](CONTRIBUTING.md).
+
+## License
+
+For more details, please read our [LICENSE.md](LICENSE.md).
diff --git a/packages/frontend/@n8n/stores/biome.jsonc b/packages/frontend/@n8n/stores/biome.jsonc
new file mode 100644
index 0000000000..f882da95a5
--- /dev/null
+++ b/packages/frontend/@n8n/stores/biome.jsonc
@@ -0,0 +1,4 @@
+{
+ "$schema": "../../../../node_modules/@biomejs/biome/configuration_schema.json",
+ "extends": ["../../../../biome.jsonc"]
+}
diff --git a/packages/frontend/@n8n/stores/package.json b/packages/frontend/@n8n/stores/package.json
new file mode 100644
index 0000000000..700ba8dc22
--- /dev/null
+++ b/packages/frontend/@n8n/stores/package.json
@@ -0,0 +1,60 @@
+{
+ "name": "@n8n/stores",
+ "type": "module",
+ "version": "1.0.0",
+ "files": [
+ "dist"
+ ],
+ "main": "dist/index.cjs",
+ "module": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js",
+ "require": "./dist/index.cjs"
+ },
+ "./*": {
+ "types": "./dist/*.d.ts",
+ "import": "./dist/*.js",
+ "require": "./dist/*.cjs"
+ }
+ },
+ "scripts": {
+ "dev": "vite",
+ "build": "pnpm run typecheck && tsup",
+ "preview": "vite preview",
+ "typecheck": "vue-tsc --noEmit",
+ "test": "vitest run",
+ "test:dev": "vitest --silent=false",
+ "lint": "eslint src --ext .js,.ts,.vue --quiet",
+ "lintfix": "eslint src --ext .js,.ts,.vue --fix",
+ "format": "biome format --write . && prettier --write . --ignore-path ../../../../.prettierignore",
+ "format:check": "biome ci . && prettier --check . --ignore-path ../../../../.prettierignore"
+ },
+ "dependencies": {
+ "n8n-workflow": "workspace:*"
+ },
+ "devDependencies": {
+ "@n8n/eslint-config": "workspace:*",
+ "@n8n/typescript-config": "workspace:*",
+ "@n8n/vitest-config": "workspace:*",
+ "@testing-library/jest-dom": "catalog:frontend",
+ "@testing-library/user-event": "catalog:frontend",
+ "@testing-library/vue": "catalog:frontend",
+ "@vitejs/plugin-vue": "catalog:frontend",
+ "@vue/tsconfig": "catalog:frontend",
+ "@vueuse/core": "catalog:frontend",
+ "vue": "catalog:frontend",
+ "tsup": "catalog:",
+ "typescript": "catalog:frontend",
+ "vite": "catalog:frontend",
+ "vitest": "catalog:frontend",
+ "vue-tsc": "catalog:frontend"
+ },
+ "peerDependencies": {
+ "@vueuse/core": "catalog:frontend",
+ "vue": "catalog:frontend"
+ },
+ "license": "See LICENSE.md file in the root of the repository"
+}
diff --git a/packages/frontend/@n8n/stores/src/constants.ts b/packages/frontend/@n8n/stores/src/constants.ts
new file mode 100644
index 0000000000..1de5b0ff8d
--- /dev/null
+++ b/packages/frontend/@n8n/stores/src/constants.ts
@@ -0,0 +1,33 @@
+export const STORES = {
+ COMMUNITY_NODES: 'communityNodes',
+ ROOT: 'root',
+ SETTINGS: 'settings',
+ UI: 'ui',
+ USERS: 'users',
+ WORKFLOWS: 'workflows',
+ WORKFLOWS_V2: 'workflowsV2',
+ WORKFLOWS_EE: 'workflowsEE',
+ 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',
+ BECOME_TEMPLATE_CREATOR: 'becomeTemplateCreator',
+ PROJECTS: 'projects',
+ API_KEYS: 'apiKeys',
+ TEST_DEFINITION: 'testDefinition',
+ FOLDERS: 'folders',
+ MODULES: 'modules',
+} as const;
diff --git a/packages/frontend/@n8n/stores/src/index.ts b/packages/frontend/@n8n/stores/src/index.ts
new file mode 100644
index 0000000000..c94f80f843
--- /dev/null
+++ b/packages/frontend/@n8n/stores/src/index.ts
@@ -0,0 +1 @@
+export * from './constants';
diff --git a/packages/frontend/@n8n/stores/src/shims.d.ts b/packages/frontend/@n8n/stores/src/shims.d.ts
new file mode 100644
index 0000000000..e7c555b100
--- /dev/null
+++ b/packages/frontend/@n8n/stores/src/shims.d.ts
@@ -0,0 +1,19 @@
+///
+
+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;
+ }
+}
diff --git a/packages/frontend/editor-ui/src/stores/root.store.ts b/packages/frontend/@n8n/stores/src/useRootStore.ts
similarity index 63%
rename from packages/frontend/editor-ui/src/stores/root.store.ts
rename to packages/frontend/@n8n/stores/src/useRootStore.ts
index 2546ff4907..b3742aae38 100644
--- a/packages/frontend/editor-ui/src/stores/root.store.ts
+++ b/packages/frontend/@n8n/stores/src/useRootStore.ts
@@ -1,13 +1,40 @@
-import { CLOUD_BASE_URL_PRODUCTION, CLOUD_BASE_URL_STAGING, STORES } from '@/constants';
-import type { RootState } from '@/Interface';
import { randomString, setGlobalState } from 'n8n-workflow';
import { defineStore } from 'pinia';
import { computed, ref } from 'vue';
+import { STORES } from './constants';
+
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';
+};
+
export const useRootStore = defineStore(STORES.ROOT, () => {
- const state = ref({
+ const state = ref({
baseUrl: VUE_APP_URL_BASE_API ?? window.BASE_PATH,
restEndpoint:
!window.REST_ENDPOINT || window.REST_ENDPOINT === '{{REST_ENDPOINT}}'
@@ -85,13 +112,6 @@ export const useRootStore = defineStore(STORES.ROOT, () => {
const timezone = computed(() => state.value.timezone);
- const restCloudApiContext = computed(() => ({
- baseUrl: window.location.host.includes('stage-app.n8n.cloud')
- ? CLOUD_BASE_URL_STAGING
- : CLOUD_BASE_URL_PRODUCTION,
- pushRef: '',
- }));
-
const restApiContext = computed(() => ({
baseUrl: restUrl.value,
pushRef: state.value.pushRef,
@@ -103,75 +123,75 @@ export const useRootStore = defineStore(STORES.ROOT, () => {
// #region Methods
// ---------------------------------------------------------------------------
- const setUrlBaseWebhook = (urlBaseWebhook: string) => {
- const url = urlBaseWebhook.endsWith('/') ? urlBaseWebhook : `${urlBaseWebhook}/`;
+ const setUrlBaseWebhook = (value: string) => {
+ const url = value.endsWith('/') ? value : `${value}/`;
state.value.urlBaseWebhook = url;
};
- const setUrlBaseEditor = (urlBaseEditor: string) => {
- const url = urlBaseEditor.endsWith('/') ? urlBaseEditor : `${urlBaseEditor}/`;
+ const setUrlBaseEditor = (value: string) => {
+ const url = value.endsWith('/') ? value : `${value}/`;
state.value.urlBaseEditor = url;
};
- const setEndpointForm = (endpointForm: string) => {
- state.value.endpointForm = endpointForm;
+ const setEndpointForm = (value: string) => {
+ state.value.endpointForm = value;
};
- const setEndpointFormTest = (endpointFormTest: string) => {
- state.value.endpointFormTest = endpointFormTest;
+ const setEndpointFormTest = (value: string) => {
+ state.value.endpointFormTest = value;
};
- const setEndpointFormWaiting = (endpointFormWaiting: string) => {
- state.value.endpointFormWaiting = endpointFormWaiting;
+ const setEndpointFormWaiting = (value: string) => {
+ state.value.endpointFormWaiting = value;
};
- const setEndpointWebhook = (endpointWebhook: string) => {
- state.value.endpointWebhook = endpointWebhook;
+ const setEndpointWebhook = (value: string) => {
+ state.value.endpointWebhook = value;
};
- const setEndpointWebhookTest = (endpointWebhookTest: string) => {
- state.value.endpointWebhookTest = endpointWebhookTest;
+ const setEndpointWebhookTest = (value: string) => {
+ state.value.endpointWebhookTest = value;
};
- const setEndpointWebhookWaiting = (endpointWebhookWaiting: string) => {
- state.value.endpointWebhookWaiting = endpointWebhookWaiting;
+ const setEndpointWebhookWaiting = (value: string) => {
+ state.value.endpointWebhookWaiting = value;
};
- const setTimezone = (timezone: string) => {
- state.value.timezone = timezone;
- setGlobalState({ defaultTimezone: timezone });
+ const setTimezone = (value: string) => {
+ state.value.timezone = value;
+ setGlobalState({ defaultTimezone: value });
};
- const setExecutionTimeout = (executionTimeout: number) => {
- state.value.executionTimeout = executionTimeout;
+ const setExecutionTimeout = (value: number) => {
+ state.value.executionTimeout = value;
};
- const setMaxExecutionTimeout = (maxExecutionTimeout: number) => {
- state.value.maxExecutionTimeout = maxExecutionTimeout;
+ const setMaxExecutionTimeout = (value: number) => {
+ state.value.maxExecutionTimeout = value;
};
- const setVersionCli = (version: string) => {
- state.value.versionCli = version;
+ const setVersionCli = (value: string) => {
+ state.value.versionCli = value;
};
- const setInstanceId = (instanceId: string) => {
- state.value.instanceId = instanceId;
+ const setInstanceId = (value: string) => {
+ state.value.instanceId = value;
};
- const setOauthCallbackUrls = (urls: RootState['oauthCallbackUrls']) => {
- state.value.oauthCallbackUrls = urls;
+ const setOauthCallbackUrls = (value: RootStoreState['oauthCallbackUrls']) => {
+ state.value.oauthCallbackUrls = value;
};
- const setN8nMetadata = (metadata: RootState['n8nMetadata']) => {
- state.value.n8nMetadata = metadata;
+ const setN8nMetadata = (value: RootStoreState['n8nMetadata']) => {
+ state.value.n8nMetadata = value;
};
- const setDefaultLocale = (locale: string) => {
- state.value.defaultLocale = locale;
+ const setDefaultLocale = (value: string) => {
+ state.value.defaultLocale = value;
};
- const setBinaryDataMode = (binaryDataMode: RootState['binaryDataMode']) => {
- state.value.binaryDataMode = binaryDataMode;
+ const setBinaryDataMode = (value: RootStoreState['binaryDataMode']) => {
+ state.value.binaryDataMode = value;
};
// #endregion
@@ -187,7 +207,6 @@ export const useRootStore = defineStore(STORES.ROOT, () => {
webhookTestUrl,
webhookWaitingUrl,
restUrl,
- restCloudApiContext,
restApiContext,
urlBaseEditor,
versionCli,
diff --git a/packages/frontend/@n8n/stores/tsconfig.json b/packages/frontend/@n8n/stores/tsconfig.json
new file mode 100644
index 0000000000..10f9ee1b73
--- /dev/null
+++ b/packages/frontend/@n8n/stores/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "@n8n/typescript-config/tsconfig.frontend.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "rootDir": ".",
+ "outDir": "dist",
+ "types": ["vite/client", "vitest/globals"],
+ "isolatedModules": true
+ },
+ "include": ["src/**/*.ts", "src/**/*.vue", "vite.config.ts", "tsup.config.ts"]
+}
diff --git a/packages/frontend/@n8n/stores/tsup.config.ts b/packages/frontend/@n8n/stores/tsup.config.ts
new file mode 100644
index 0000000000..0d555b1ab0
--- /dev/null
+++ b/packages/frontend/@n8n/stores/tsup.config.ts
@@ -0,0 +1,11 @@
+import { defineConfig } from 'tsup';
+
+export default defineConfig({
+ entry: ['src/**/*.ts', '!src/**/*.test.ts', '!src/**/*.d.ts', '!src/__tests__**/*'],
+ format: ['cjs', 'esm'],
+ clean: true,
+ dts: true,
+ cjsInterop: true,
+ splitting: true,
+ sourcemap: true,
+});
diff --git a/packages/frontend/@n8n/stores/vite.config.ts b/packages/frontend/@n8n/stores/vite.config.ts
new file mode 100644
index 0000000000..784f3fb497
--- /dev/null
+++ b/packages/frontend/@n8n/stores/vite.config.ts
@@ -0,0 +1,4 @@
+import { defineConfig, mergeConfig } from 'vite';
+import { vitestConfig } from '@n8n/vitest-config/frontend';
+
+export default mergeConfig(defineConfig({}), vitestConfig);
diff --git a/packages/frontend/editor-ui/package.json b/packages/frontend/editor-ui/package.json
index cbcb15df7c..905409066e 100644
--- a/packages/frontend/editor-ui/package.json
+++ b/packages/frontend/editor-ui/package.json
@@ -38,6 +38,7 @@
"@n8n/composables": "workspace:*",
"@n8n/design-system": "workspace:*",
"@n8n/permissions": "workspace:*",
+ "@n8n/stores": "workspace:*",
"@n8n/utils": "workspace:*",
"@replit/codemirror-indentation-markers": "^6.5.3",
"@sentry/vue": "catalog:frontend",
diff --git a/packages/frontend/editor-ui/src/App.vue b/packages/frontend/editor-ui/src/App.vue
index 6da74dfae0..ebd33d65ec 100644
--- a/packages/frontend/editor-ui/src/App.vue
+++ b/packages/frontend/editor-ui/src/App.vue
@@ -11,7 +11,7 @@ import AskAssistantFloatingButton from '@/components/AskAssistant/Chat/AskAssist
import AssistantsHub from '@/components/AskAssistant/AssistantsHub.vue';
import { loadLanguage } from '@/plugins/i18n';
import { APP_MODALS_ELEMENT_ID, HIRING_BANNER, VIEWS } from '@/constants';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { useAssistantStore } from '@/stores/assistant.store';
import { useBuilderStore } from '@/stores/builder.store';
import { useUIStore } from '@/stores/ui.store';
diff --git a/packages/frontend/editor-ui/src/Interface.ts b/packages/frontend/editor-ui/src/Interface.ts
index 4db4536384..a5a273c23e 100644
--- a/packages/frontend/editor-ui/src/Interface.ts
+++ b/packages/frontend/editor-ui/src/Interface.ts
@@ -970,33 +970,6 @@ export interface WorkflowsState {
isInDebugMode?: boolean;
}
-export interface RootState {
- 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';
-}
-
export interface NodeMetadataMap {
[nodeName: string]: INodeMetadata;
}
diff --git a/packages/frontend/editor-ui/src/components/AboutModal.vue b/packages/frontend/editor-ui/src/components/AboutModal.vue
index 0a9d88ce50..c6082f3bba 100644
--- a/packages/frontend/editor-ui/src/components/AboutModal.vue
+++ b/packages/frontend/editor-ui/src/components/AboutModal.vue
@@ -2,7 +2,7 @@
import { createEventBus } from '@n8n/utils/event-bus';
import Modal from './Modal.vue';
import { ABOUT_MODAL_KEY } from '../constants';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { useToast } from '@/composables/useToast';
import { useClipboard } from '@/composables/useClipboard';
import { useDebugInfo } from '@/composables/useDebugInfo';
diff --git a/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.test.ts b/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.test.ts
index 3b4658178b..3088cf2b54 100644
--- a/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.test.ts
+++ b/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.test.ts
@@ -1,6 +1,7 @@
import { createComponentRenderer } from '@/__tests__/render';
import { createTestingPinia } from '@pinia/testing';
-import { API_KEY_CREATE_OR_EDIT_MODAL_KEY, STORES } from '@/constants';
+import { API_KEY_CREATE_OR_EDIT_MODAL_KEY } from '@/constants';
+import { STORES } from '@n8n/stores';
import { cleanupAppModals, createAppModals, mockedStore, retry } from '@/__tests__/utils';
import ApiKeyEditModal from './ApiKeyCreateOrEditModal.vue';
import { fireEvent } from '@testing-library/vue';
diff --git a/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.vue b/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.vue
index b9d674c462..fc1a8d142d 100644
--- a/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.vue
+++ b/packages/frontend/editor-ui/src/components/ApiKeyCreateOrEditModal.vue
@@ -5,7 +5,7 @@ import { computed, onMounted, ref } from 'vue';
import { useUIStore } from '@/stores/ui.store';
import { createEventBus } from '@n8n/utils/event-bus';
import { useI18n } from '@/composables/useI18n';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { useDocumentTitle } from '@/composables/useDocumentTitle';
import { useApiKeysStore } from '@/stores/apiKeys.store';
import { useToast } from '@/composables/useToast';
diff --git a/packages/frontend/editor-ui/src/components/AskAssistant/Agent/AskAssistantBuild.test.ts b/packages/frontend/editor-ui/src/components/AskAssistant/Agent/AskAssistantBuild.test.ts
index e6824e8342..6e92e572a3 100644
--- a/packages/frontend/editor-ui/src/components/AskAssistant/Agent/AskAssistantBuild.test.ts
+++ b/packages/frontend/editor-ui/src/components/AskAssistant/Agent/AskAssistantBuild.test.ts
@@ -10,7 +10,7 @@ import { faker } from '@faker-js/faker';
import AskAssistantBuild from './AskAssistantBuild.vue';
import { useBuilderStore } from '@/stores/builder.store';
import { mockedStore } from '@/__tests__/utils';
-import { STORES } from '@/constants';
+import { STORES } from '@n8n/stores';
vi.mock('@/event-bus', () => ({
nodeViewEventBus: {
diff --git a/packages/frontend/editor-ui/src/components/AssignmentCollection/Assignment.test.ts b/packages/frontend/editor-ui/src/components/AssignmentCollection/Assignment.test.ts
index e16a01ae08..5ebe92d8fb 100644
--- a/packages/frontend/editor-ui/src/components/AssignmentCollection/Assignment.test.ts
+++ b/packages/frontend/editor-ui/src/components/AssignmentCollection/Assignment.test.ts
@@ -3,7 +3,7 @@ import { createTestingPinia } from '@pinia/testing';
import userEvent from '@testing-library/user-event';
import Assignment from './Assignment.vue';
import { defaultSettings } from '@/__tests__/defaults';
-import { STORES } from '@/constants';
+import { STORES } from '@n8n/stores';
import { merge } from 'lodash-es';
import { cleanupAppModals, createAppModals } from '@/__tests__/utils';
diff --git a/packages/frontend/editor-ui/src/components/AssignmentCollection/AssignmentCollection.test.ts b/packages/frontend/editor-ui/src/components/AssignmentCollection/AssignmentCollection.test.ts
index 43c31c1e0f..226045d6b7 100644
--- a/packages/frontend/editor-ui/src/components/AssignmentCollection/AssignmentCollection.test.ts
+++ b/packages/frontend/editor-ui/src/components/AssignmentCollection/AssignmentCollection.test.ts
@@ -5,7 +5,7 @@ import userEvent from '@testing-library/user-event';
import { fireEvent, within } from '@testing-library/vue';
import * as workflowHelpers from '@/composables/useWorkflowHelpers';
import AssignmentCollection from './AssignmentCollection.vue';
-import { STORES } from '@/constants';
+import { STORES } from '@n8n/stores';
import { cleanupAppModals, createAppModals, SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils';
const DEFAULT_SETUP = {
diff --git a/packages/frontend/editor-ui/src/components/BannersStack.test.ts b/packages/frontend/editor-ui/src/components/BannersStack.test.ts
index 468a20232d..0de42f5dcc 100644
--- a/packages/frontend/editor-ui/src/components/BannersStack.test.ts
+++ b/packages/frontend/editor-ui/src/components/BannersStack.test.ts
@@ -2,7 +2,8 @@ import { merge } from 'lodash-es';
import userEvent from '@testing-library/user-event';
import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils';
-import { ROLE, STORES } from '@/constants';
+import { ROLE } from '@/constants';
+import { STORES } from '@n8n/stores';
import { createTestingPinia } from '@pinia/testing';
import BannerStack from '@/components/banners/BannerStack.vue';
diff --git a/packages/frontend/editor-ui/src/components/BecomeTemplateCreatorCta/becomeTemplateCreatorStore.ts b/packages/frontend/editor-ui/src/components/BecomeTemplateCreatorCta/becomeTemplateCreatorStore.ts
index faf2ad8e0c..e122259f44 100644
--- a/packages/frontend/editor-ui/src/components/BecomeTemplateCreatorCta/becomeTemplateCreatorStore.ts
+++ b/packages/frontend/editor-ui/src/components/BecomeTemplateCreatorCta/becomeTemplateCreatorStore.ts
@@ -1,10 +1,10 @@
import { DateTime } from 'luxon';
import { defineStore } from 'pinia';
import { computed, ref } from 'vue';
-import { STORES } from '@/constants';
+import { STORES } from '@n8n/stores';
import { useCloudPlanStore } from '@/stores/cloudPlan.store';
import { useStorage } from '@/composables/useStorage';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { getBecomeCreatorCta } from '@/api/ctas';
const LOCAL_STORAGE_KEY = 'N8N_BECOME_TEMPLATE_CREATOR_CTA_DISMISSED_AT';
diff --git a/packages/frontend/editor-ui/src/components/ButtonParameter/ButtonParameter.test.ts b/packages/frontend/editor-ui/src/components/ButtonParameter/ButtonParameter.test.ts
index 5264821232..fdca835457 100644
--- a/packages/frontend/editor-ui/src/components/ButtonParameter/ButtonParameter.test.ts
+++ b/packages/frontend/editor-ui/src/components/ButtonParameter/ButtonParameter.test.ts
@@ -6,7 +6,7 @@ import ButtonParameter, { type Props } from '@/components/ButtonParameter/Button
import { useNDVStore } from '@/stores/ndv.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { usePostHog } from '@/stores/posthog.store';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { useI18n } from '@/composables/useI18n';
import { useToast } from '@/composables/useToast';
import type { INodeProperties } from 'n8n-workflow';
@@ -14,7 +14,7 @@ import type { INodeProperties } from 'n8n-workflow';
vi.mock('@/stores/ndv.store');
vi.mock('@/stores/workflows.store');
vi.mock('@/stores/posthog.store');
-vi.mock('@/stores/root.store');
+vi.mock('@n8n/stores/useRootStore');
vi.mock('@/api/ai');
vi.mock('@/composables/useI18n');
vi.mock('@/composables/useToast');
diff --git a/packages/frontend/editor-ui/src/components/ButtonParameter/utils.test.ts b/packages/frontend/editor-ui/src/components/ButtonParameter/utils.test.ts
index 7453d41fb5..e49d2bb73a 100644
--- a/packages/frontend/editor-ui/src/components/ButtonParameter/utils.test.ts
+++ b/packages/frontend/editor-ui/src/components/ButtonParameter/utils.test.ts
@@ -17,7 +17,7 @@ vi.mock('./utils', async () => {
};
});
-vi.mock('@/stores/root.store', () => ({
+vi.mock('@n8n/stores/useRootStore', () => ({
useRootStore: () => ({
pushRef: 'mockRootPushRef',
restApiContext: {},
diff --git a/packages/frontend/editor-ui/src/components/ButtonParameter/utils.ts b/packages/frontend/editor-ui/src/components/ButtonParameter/utils.ts
index 47a4081963..c10624e499 100644
--- a/packages/frontend/editor-ui/src/components/ButtonParameter/utils.ts
+++ b/packages/frontend/editor-ui/src/components/ButtonParameter/utils.ts
@@ -5,7 +5,7 @@ import { useNDVStore } from '@/stores/ndv.store';
import { useDataSchema } from '@/composables/useDataSchema';
import { executionDataToJson } from '@/utils/nodeTypesUtils';
import { generateCodeForPrompt } from '@/api/ai';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { type AskAiRequest } from '@/types/assistant.types';
import { useSettingsStore } from '@/stores/settings.store';
import { format } from 'prettier';
diff --git a/packages/frontend/editor-ui/src/components/CanvasChat/CanvasChat.test.ts b/packages/frontend/editor-ui/src/components/CanvasChat/CanvasChat.test.ts
index 8b11376484..fc2e37f8f0 100644
--- a/packages/frontend/editor-ui/src/components/CanvasChat/CanvasChat.test.ts
+++ b/packages/frontend/editor-ui/src/components/CanvasChat/CanvasChat.test.ts
@@ -11,7 +11,7 @@ import CanvasChat from './CanvasChat.vue';
import { createComponentRenderer } from '@/__tests__/render';
import { createTestWorkflowObject } from '@/__tests__/mocks';
import { mockedStore } from '@/__tests__/utils';
-import { STORES } from '@/constants';
+import { STORES } from '@n8n/stores';
import { ChatOptionsSymbol, ChatSymbol } from '@n8n/chat/constants';
import { chatEventBus } from '@n8n/chat/event-buses';
diff --git a/packages/frontend/editor-ui/src/components/ChatEmbedModal.test.ts b/packages/frontend/editor-ui/src/components/ChatEmbedModal.test.ts
index eb6afdd122..5af65c7d05 100644
--- a/packages/frontend/editor-ui/src/components/ChatEmbedModal.test.ts
+++ b/packages/frontend/editor-ui/src/components/ChatEmbedModal.test.ts
@@ -1,6 +1,7 @@
import ChatEmbedModal from '@/components/ChatEmbedModal.vue';
import { createTestingPinia } from '@pinia/testing';
-import { CHAT_EMBED_MODAL_KEY, STORES, WEBHOOK_NODE_TYPE } from '@/constants';
+import { CHAT_EMBED_MODAL_KEY, WEBHOOK_NODE_TYPE } from '@/constants';
+import { STORES } from '@n8n/stores';
import { createComponentRenderer } from '@/__tests__/render';
import { waitFor } from '@testing-library/vue';
import { cleanupAppModals, createAppModals } from '@/__tests__/utils';
diff --git a/packages/frontend/editor-ui/src/components/ChatEmbedModal.vue b/packages/frontend/editor-ui/src/components/ChatEmbedModal.vue
index 2f24141297..3b0bb00771 100644
--- a/packages/frontend/editor-ui/src/components/ChatEmbedModal.vue
+++ b/packages/frontend/editor-ui/src/components/ChatEmbedModal.vue
@@ -4,7 +4,7 @@ import type { EventBus } from '@n8n/utils/event-bus';
import { createEventBus } from '@n8n/utils/event-bus';
import Modal from './Modal.vue';
import { CHAT_EMBED_MODAL_KEY, CHAT_TRIGGER_NODE_TYPE, WEBHOOK_NODE_TYPE } from '../constants';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { useWorkflowsStore } from '@/stores/workflows.store';
import HtmlEditor from '@/components/HtmlEditor/HtmlEditor.vue';
import JsEditor from '@/components/JsEditor/JsEditor.vue';
diff --git a/packages/frontend/editor-ui/src/components/CodeNodeEditor/AskAI/AskAI.vue b/packages/frontend/editor-ui/src/components/CodeNodeEditor/AskAI/AskAI.vue
index 1b65ffc182..4c6116adc4 100644
--- a/packages/frontend/editor-ui/src/components/CodeNodeEditor/AskAI/AskAI.vue
+++ b/packages/frontend/editor-ui/src/components/CodeNodeEditor/AskAI/AskAI.vue
@@ -16,7 +16,7 @@ import { useI18n } from '@/composables/useI18n';
import { useMessage } from '@/composables/useMessage';
import { useToast } from '@/composables/useToast';
import { useNDVStore } from '@/stores/ndv.store';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { executionDataToJson } from '@/utils/nodeTypesUtils';
import {
diff --git a/packages/frontend/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue b/packages/frontend/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue
index 74bbddacc3..5f2738cfc0 100644
--- a/packages/frontend/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue
+++ b/packages/frontend/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue
@@ -8,7 +8,7 @@ import { computed, onBeforeUnmount, onMounted, ref, toRaw, watch } from 'vue';
import { CODE_NODE_TYPE } from '@/constants';
import { codeNodeEditorEventBus } from '@/event-bus';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { useCodeEditor } from '@/composables/useCodeEditor';
import { useI18n } from '@/composables/useI18n';
diff --git a/packages/frontend/editor-ui/src/components/CollaborationPane.test.ts b/packages/frontend/editor-ui/src/components/CollaborationPane.test.ts
index 6405d10821..c194fe546b 100644
--- a/packages/frontend/editor-ui/src/components/CollaborationPane.test.ts
+++ b/packages/frontend/editor-ui/src/components/CollaborationPane.test.ts
@@ -1,7 +1,7 @@
import { createTestingPinia } from '@pinia/testing';
import { mock } from 'vitest-mock-extended';
-import { STORES } from '@/constants';
+import { STORES } from '@n8n/stores';
import CollaborationPane from '@/components/MainHeader/CollaborationPane.vue';
import type { IUser } from '@/Interface';
diff --git a/packages/frontend/editor-ui/src/components/CommunityPackageInstallModal.test.ts b/packages/frontend/editor-ui/src/components/CommunityPackageInstallModal.test.ts
index bbf2701068..d3cc8ec2a5 100644
--- a/packages/frontend/editor-ui/src/components/CommunityPackageInstallModal.test.ts
+++ b/packages/frontend/editor-ui/src/components/CommunityPackageInstallModal.test.ts
@@ -1,7 +1,8 @@
import { createComponentRenderer } from '@/__tests__/render';
import CommunityPackageInstallModal from './CommunityPackageInstallModal.vue';
import { createTestingPinia } from '@pinia/testing';
-import { COMMUNITY_PACKAGE_INSTALL_MODAL_KEY, STORES } from '@/constants';
+import { COMMUNITY_PACKAGE_INSTALL_MODAL_KEY } from '@/constants';
+import { STORES } from '@n8n/stores';
import userEvent from '@testing-library/user-event';
import { cleanupAppModals, createAppModals, retry } from '@/__tests__/utils';
diff --git a/packages/frontend/editor-ui/src/components/ContactPromptModal.vue b/packages/frontend/editor-ui/src/components/ContactPromptModal.vue
index c0757e53cd..5ce17f8388 100644
--- a/packages/frontend/editor-ui/src/components/ContactPromptModal.vue
+++ b/packages/frontend/editor-ui/src/components/ContactPromptModal.vue
@@ -4,7 +4,7 @@ import type { IN8nPromptResponse, ModalKey } from '@/Interface';
import { VALID_EMAIL_REGEX } from '@/constants';
import Modal from '@/components/Modal.vue';
import { useSettingsStore } from '@/stores/settings.store';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { createEventBus } from '@n8n/utils/event-bus';
import { useToast } from '@/composables/useToast';
import { useNpsSurveyStore } from '@/stores/npsSurvey.store';
diff --git a/packages/frontend/editor-ui/src/components/CopyInput.test.ts b/packages/frontend/editor-ui/src/components/CopyInput.test.ts
index 8857ab8b3e..a26e478156 100644
--- a/packages/frontend/editor-ui/src/components/CopyInput.test.ts
+++ b/packages/frontend/editor-ui/src/components/CopyInput.test.ts
@@ -1,7 +1,7 @@
import { merge } from 'lodash-es';
import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils';
-import { STORES } from '@/constants';
+import { STORES } from '@n8n/stores';
import { createTestingPinia } from '@pinia/testing';
import CopyInput from '@/components/CopyInput.vue';
diff --git a/packages/frontend/editor-ui/src/components/CredentialConfig.test.ts b/packages/frontend/editor-ui/src/components/CredentialConfig.test.ts
index b84fcb3eae..0e8d8fcf91 100644
--- a/packages/frontend/editor-ui/src/components/CredentialConfig.test.ts
+++ b/packages/frontend/editor-ui/src/components/CredentialConfig.test.ts
@@ -4,7 +4,7 @@ import type { ICredentialDataDecryptedObject, ICredentialType } from 'n8n-workfl
import { createTestingPinia } from '@pinia/testing';
import type { RenderOptions } from '@/__tests__/render';
import { createComponentRenderer } from '@/__tests__/render';
-import { STORES } from '@/constants';
+import { STORES } from '@n8n/stores';
const defaultRenderOptions: RenderOptions = {
pinia: createTestingPinia({
diff --git a/packages/frontend/editor-ui/src/components/CredentialEdit/CredentialConfig.vue b/packages/frontend/editor-ui/src/components/CredentialEdit/CredentialConfig.vue
index a104c6cc01..38c61b8ae2 100644
--- a/packages/frontend/editor-ui/src/components/CredentialEdit/CredentialConfig.vue
+++ b/packages/frontend/editor-ui/src/components/CredentialEdit/CredentialConfig.vue
@@ -23,7 +23,7 @@ import type { PermissionsRecord } from '@/permissions';
import { addCredentialTranslation } from '@/plugins/i18n';
import { useCredentialsStore } from '@/stores/credentials.store';
import { useNDVStore } from '@/stores/ndv.store';
-import { useRootStore } from '@/stores/root.store';
+import { useRootStore } from '@n8n/stores/useRootStore';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import Banner from '../Banner.vue';
diff --git a/packages/frontend/editor-ui/src/components/CredentialEdit/GoogleAuthButton.vue b/packages/frontend/editor-ui/src/components/CredentialEdit/GoogleAuthButton.vue
index b0e7b6a4d1..bb9c607817 100644
--- a/packages/frontend/editor-ui/src/components/CredentialEdit/GoogleAuthButton.vue
+++ b/packages/frontend/editor-ui/src/components/CredentialEdit/GoogleAuthButton.vue
@@ -1,6 +1,6 @@