feat: Replace Vue.extend with defineComponent in editor-ui (no-changelog) (#6033)

* refactor: replace Vue.extend with defineComponent in editor-ui

* fix: change $externalHooks extractions from mixins

* fix: refactor externalHooks mixin
This commit is contained in:
Alex Grozav 2023-04-21 18:51:08 +03:00 committed by GitHub
parent 8a38624cbc
commit 9c94050deb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
90 changed files with 265 additions and 235 deletions

View file

@ -1,4 +1,6 @@
import { ISettingsState, UserManagementAuthenticationMethod } from '@/Interface'; import { ISettingsState, UserManagementAuthenticationMethod } from '@/Interface';
import { render } from '@testing-library/vue';
import { PiniaVuePlugin } from 'pinia';
export const retry = (assertion: () => any, { interval = 20, timeout = 200 } = {}) => { export const retry = (assertion: () => any, { interval = 20, timeout = 200 } = {}) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -18,6 +20,12 @@ export const retry = (assertion: () => any, { interval = 20, timeout = 200 } = {
}); });
}; };
type RenderParams = Parameters<typeof render>;
export const renderComponent = (Component: RenderParams[0], renderOptions: RenderParams[1] = {}) =>
render(Component, renderOptions, (vue) => {
vue.use(PiniaVuePlugin);
});
export const waitAllPromises = () => new Promise((resolve) => setTimeout(resolve)); export const waitAllPromises = () => new Promise((resolve) => setTimeout(resolve));
export const SETTINGS_STORE_DEFAULT_STATE: ISettingsState = { export const SETTINGS_STORE_DEFAULT_STATE: ISettingsState = {

View file

@ -54,7 +54,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import { ABOUT_MODAL_KEY } from '../constants'; import { ABOUT_MODAL_KEY } from '../constants';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
@ -62,7 +62,7 @@ import { useSettingsStore } from '@/stores/settings';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { createEventBus } from '@/event-bus'; import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default defineComponent({
name: 'About', name: 'About',
components: { components: {
Modal, Modal,

View file

@ -35,7 +35,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import Modal from '@/components/Modal.vue'; import Modal from '@/components/Modal.vue';
import { import {
@ -51,7 +51,7 @@ import { useWorkflowsStore } from '@/stores/workflows';
import { useNodeTypesStore } from '@/stores/nodeTypes'; import { useNodeTypesStore } from '@/stores/nodeTypes';
import { createEventBus } from '@/event-bus'; import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default defineComponent({
name: 'ActivationModal', name: 'ActivationModal',
components: { components: {
Modal, Modal,

View file

@ -23,12 +23,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import Modal from './Modal.vue'; import Modal from './Modal.vue';
import { ASK_AI_MODAL_KEY, ASK_AI_WAITLIST_URL } from '../constants'; import { ASK_AI_MODAL_KEY, ASK_AI_WAITLIST_URL } from '../constants';
import { createEventBus } from '@/event-bus'; import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default defineComponent({
name: 'AskAI', name: 'AskAI',
components: { components: {
Modal, Modal,

View file

@ -36,9 +36,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'Banner', name: 'Banner',
data() { data() {
return { return {

View file

@ -68,12 +68,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import TimeAgo from '../TimeAgo.vue'; import TimeAgo from '../TimeAgo.vue';
import { INodeTypeDescription } from 'n8n-workflow'; import { INodeTypeDescription } from 'n8n-workflow';
export default Vue.extend({ export default defineComponent({
name: 'CredentialInfo', name: 'CredentialInfo',
props: ['nodesWithAccess', 'nodeAccess', 'currentCredential', 'credentialPermissions'], props: ['nodesWithAccess', 'nodeAccess', 'currentCredential', 'credentialPermissions'],
components: { components: {

View file

@ -24,12 +24,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { IParameterLabel } from 'n8n-workflow'; import { IParameterLabel } from 'n8n-workflow';
import { IUpdateInformation } from '@/Interface'; import { IUpdateInformation } from '@/Interface';
import ParameterInputExpanded from '../ParameterInputExpanded.vue'; import ParameterInputExpanded from '../ParameterInputExpanded.vue';
export default Vue.extend({ export default defineComponent({
name: 'CredentialsInput', name: 'CredentialsInput',
props: [ props: [
'credentialProperties', 'credentialProperties',

View file

@ -12,9 +12,9 @@ import { useRootStore } from '@/stores/n8nRootStore';
import { useNodeTypesStore } from '@/stores/nodeTypes'; import { useNodeTypesStore } from '@/stores/nodeTypes';
import { ICredentialType, INodeTypeDescription } from 'n8n-workflow'; import { ICredentialType, INodeTypeDescription } from 'n8n-workflow';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
props: { props: {
credentialTypeName: { credentialTypeName: {
type: String, type: String,

View file

@ -56,7 +56,7 @@
<script lang="ts"> <script lang="ts">
import { ICredentialType } from 'n8n-workflow'; import { ICredentialType } from 'n8n-workflow';
import Vue from 'vue'; import Vue, { defineComponent } from 'vue';
import ScopesNotice from '@/components/ScopesNotice.vue'; import ScopesNotice from '@/components/ScopesNotice.vue';
import NodeCredentials from '@/components/NodeCredentials.vue'; import NodeCredentials from '@/components/NodeCredentials.vue';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
@ -65,7 +65,7 @@ import { N8nSelect } from 'n8n-design-system';
type N8nSelectRef = InstanceType<typeof N8nSelect>; type N8nSelectRef = InstanceType<typeof N8nSelect>;
export default Vue.extend({ export default defineComponent({
name: 'CredentialsSelect', name: 'CredentialsSelect',
components: { components: {
ScopesNotice, ScopesNotice,

View file

@ -19,12 +19,12 @@
import { XYPosition } from '@/Interface'; import { XYPosition } from '@/Interface';
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
// @ts-ignore // @ts-ignore
import Teleport from 'vue2-teleport'; import Teleport from 'vue2-teleport';
export default Vue.extend({ export default defineComponent({
name: 'draggable', name: 'draggable',
components: { components: {
Teleport, Teleport,

View file

@ -7,9 +7,10 @@
<script lang="ts"> <script lang="ts">
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import type { PropType } from 'vue';
export default Vue.extend({ export default defineComponent({
props: { props: {
type: { type: {
type: String, type: String,

View file

@ -6,12 +6,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { EnterpriseEditionFeature } from '@/constants'; import { EnterpriseEditionFeature } from '@/constants';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
export default Vue.extend({ export default defineComponent({
name: 'EnterpriseEdition', name: 'EnterpriseEdition',
props: { props: {
features: { features: {

View file

@ -7,13 +7,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import ExecutionsList from '@/components/ExecutionsList.vue'; import ExecutionsList from '@/components/ExecutionsList.vue';
import Modal from '@/components/Modal.vue'; import Modal from '@/components/Modal.vue';
import { EXECUTIONS_MODAL_KEY } from '@/constants'; import { EXECUTIONS_MODAL_KEY } from '@/constants';
import { createEventBus } from '@/event-bus'; import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default defineComponent({
name: 'ExecutionsModal', name: 'ExecutionsModal',
components: { components: {
Modal, Modal,

View file

@ -27,10 +27,10 @@ import { PLACEHOLDER_EMPTY_WORKFLOW_ID, VIEWS } from '@/constants';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
import ExecutionsInfoAccordion from './ExecutionsInfoAccordion.vue'; import ExecutionsInfoAccordion from './ExecutionsInfoAccordion.vue';
export default Vue.extend({ export default defineComponent({
name: 'executions-landing-page', name: 'executions-landing-page',
components: { components: {
ExecutionsInfoAccordion, ExecutionsInfoAccordion,

View file

@ -70,7 +70,7 @@ import ExecutionFilter from '@/components/ExecutionFilter.vue';
import { VIEWS } from '@/constants'; import { VIEWS } from '@/constants';
import type { IExecutionsSummary } from 'n8n-workflow'; import type { IExecutionsSummary } from 'n8n-workflow';
import { Route } from 'vue-router'; import { Route } from 'vue-router';
import Vue from 'vue'; import { defineComponent } from 'vue';
import { PropType } from 'vue'; import { PropType } from 'vue';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
@ -79,7 +79,7 @@ import { ExecutionFilterType } from '@/Interface';
type ExecutionCardRef = InstanceType<typeof ExecutionCard>; type ExecutionCardRef = InstanceType<typeof ExecutionCard>;
export default Vue.extend({ export default defineComponent({
name: 'executions-sidebar', name: 'executions-sidebar',
components: { components: {
ExecutionCard, ExecutionCard,

View file

@ -6,9 +6,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'ExpandableInputBase', name: 'ExpandableInputBase',
props: ['value', 'placeholder', 'staticSize'], props: ['value', 'placeholder', 'staticSize'],
computed: { computed: {

View file

@ -16,11 +16,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import ExpandableInputBase from './ExpandableInputBase.vue'; import ExpandableInputBase from './ExpandableInputBase.vue';
import { EventBus } from '@/event-bus'; import type { PropType } from 'vue';
import type { EventBus } from '@/event-bus';
export default Vue.extend({ export default defineComponent({
components: { ExpandableInputBase }, components: { ExpandableInputBase },
name: 'ExpandableInputEdit', name: 'ExpandableInputEdit',
props: { props: {

View file

@ -12,10 +12,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import ExpandableInputBase from './ExpandableInputBase.vue'; import ExpandableInputBase from './ExpandableInputBase.vue';
export default Vue.extend({ export default defineComponent({
components: { ExpandableInputBase }, components: { ExpandableInputBase },
name: 'ExpandableInputPreview', name: 'ExpandableInputPreview',
props: ['value'], props: ['value'],

View file

@ -3,9 +3,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { PropType } from 'vue';
import { EditorView } from '@codemirror/view'; import { EditorView } from '@codemirror/view';
import { EditorState } from '@codemirror/state'; import { EditorState } from '@codemirror/state';
import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import { highlighter } from '@/plugins/codemirror/resolvableHighlighter'; import { highlighter } from '@/plugins/codemirror/resolvableHighlighter';
import { outputTheme } from './theme'; import { outputTheme } from './theme';
@ -13,7 +14,7 @@ import { outputTheme } from './theme';
import type { Plaintext, Resolved, Segment } from '@/types/expressions'; import type { Plaintext, Resolved, Segment } from '@/types/expressions';
import { forceParse } from '@/utils/forceParse'; import { forceParse } from '@/utils/forceParse';
export default Vue.extend({ export default defineComponent({
name: 'ExpressionEditorModalOutput', name: 'ExpressionEditorModalOutput',
props: { props: {
segments: { segments: {

View file

@ -66,7 +66,7 @@
<script lang="ts"> <script lang="ts">
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
@ -81,7 +81,7 @@ import type { TargetItem } from '@/Interface';
type InlineExpressionEditorInputRef = InstanceType<typeof InlineExpressionEditorInput>; type InlineExpressionEditorInputRef = InstanceType<typeof InlineExpressionEditorInput>;
export default Vue.extend({ export default defineComponent({
name: 'ExpressionParameterInput', name: 'ExpressionParameterInput',
components: { components: {
InlineExpressionEditorInput, InlineExpressionEditorInput,

View file

@ -35,9 +35,9 @@ import { useSettingsStore } from '@/stores/settings';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'FeatureComingSoon', name: 'FeatureComingSoon',
props: { props: {
featureId: { featureId: {

View file

@ -112,21 +112,21 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { Component, PropType } from 'vue'; import { defineComponent } from 'vue';
import { IUpdateInformation } from '@/Interface'; import type { Component, PropType } from 'vue';
import type { IUpdateInformation } from '@/Interface';
import { import { deepCopy, isINodePropertyCollectionList } from 'n8n-workflow';
import type {
INodeParameters, INodeParameters,
INodeProperties, INodeProperties,
INodePropertyCollection, INodePropertyCollection,
NodeParameterValue, NodeParameterValue,
deepCopy,
isINodePropertyCollectionList,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { get } from 'lodash-es'; import { get } from 'lodash-es';
export default Vue.extend({ export default defineComponent({
name: 'FixedCollectionParameter', name: 'FixedCollectionParameter',
props: { props: {
nodeValues: { nodeValues: {

View file

@ -7,9 +7,9 @@
<script lang="ts"> <script lang="ts">
import { VIEWS } from '@/constants'; import { VIEWS } from '@/constants';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'GoBackButton', name: 'GoBackButton',
data() { data() {
return { return {

View file

@ -40,7 +40,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { ITemplatesNode } from '@/Interface'; import { ITemplatesNode } from '@/Interface';
import { INodeTypeDescription } from 'n8n-workflow'; import { INodeTypeDescription } from 'n8n-workflow';
@ -54,7 +54,7 @@ interface NodeIconData {
fileBuffer?: string; fileBuffer?: string;
} }
export default Vue.extend({ export default defineComponent({
name: 'HoverableNodeIcon', name: 'HoverableNodeIcon',
props: { props: {
circle: { circle: {

View file

@ -3,16 +3,18 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { PropType } from 'vue';
import { EditorView } from '@codemirror/view'; import { EditorView } from '@codemirror/view';
import { EditorState } from '@codemirror/state'; import { EditorState } from '@codemirror/state';
import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import { highlighter } from '@/plugins/codemirror/resolvableHighlighter'; import { highlighter } from '@/plugins/codemirror/resolvableHighlighter';
import { outputTheme } from './theme'; import { outputTheme } from './theme';
import type { Plaintext, Resolved, Segment } from '@/types/expressions'; import type { Plaintext, Resolved, Segment } from '@/types/expressions';
export default Vue.extend({ export default defineComponent({
name: 'InlineExpressionEditorOutput', name: 'InlineExpressionEditorOutput',
props: { props: {
segments: { segments: {

View file

@ -21,12 +21,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import ExpandableInputEdit from '@/components/ExpandableInput/ExpandableInputEdit.vue'; import ExpandableInputEdit from '@/components/ExpandableInput/ExpandableInputEdit.vue';
import ExpandableInputPreview from '@/components/ExpandableInput/ExpandableInputPreview.vue'; import ExpandableInputPreview from '@/components/ExpandableInput/ExpandableInputPreview.vue';
import { createEventBus } from '@/event-bus'; import { createEventBus } from '@/event-bus';
export default Vue.extend({ export default defineComponent({
name: 'InlineTextEdit', name: 'InlineTextEdit',
components: { ExpandableInputEdit, ExpandableInputPreview }, components: { ExpandableInputEdit, ExpandableInputPreview },
props: ['isEditEnabled', 'value', 'placeholder', 'maxLength', 'previewValue'], props: ['isEditEnabled', 'value', 'placeholder', 'maxLength', 'previewValue'],

View file

@ -5,9 +5,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'IntersectionObserver', name: 'IntersectionObserver',
props: ['threshold', 'enabled'], props: ['threshold', 'enabled'],
data() { data() {

View file

@ -5,9 +5,9 @@
<script lang="ts"> <script lang="ts">
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
computed: { computed: {
...mapStores(useRootStore), ...mapStores(useRootStore),
basePath(): string { basePath(): string {

View file

@ -12,13 +12,14 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import { ITabBarItem } from '@/Interface'; import type { PropType } from 'vue';
import type { ITabBarItem } from '@/Interface';
import { MAIN_HEADER_TABS } from '@/constants'; import { MAIN_HEADER_TABS } from '@/constants';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
export default Vue.extend({ export default defineComponent({
name: 'tab-bar', name: 'tab-bar',
data() { data() {
return { return {

View file

@ -43,12 +43,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { EventBus } from '@/event-bus'; import type { EventBus } from '@/event-bus';
export default Vue.extend({ export default defineComponent({
name: 'Modal', name: 'Modal',
props: { props: {
name: { name: {

View file

@ -21,10 +21,11 @@
<script lang="ts"> <script lang="ts">
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import { EventBus } from '@/event-bus'; import type { PropType } from 'vue';
import type { EventBus } from '@/event-bus';
export default Vue.extend({ export default defineComponent({
name: 'ModalDrawer', name: 'ModalDrawer',
props: { props: {
name: { name: {

View file

@ -12,11 +12,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
export default Vue.extend({ export default defineComponent({
name: 'ModalRoot', name: 'ModalRoot',
props: { props: {
name: { name: {

View file

@ -119,7 +119,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { import {
ABOUT_MODAL_KEY, ABOUT_MODAL_KEY,
CHANGE_PASSWORD_MODAL_KEY, CHANGE_PASSWORD_MODAL_KEY,
@ -171,7 +171,7 @@ import WorkflowShareModal from './WorkflowShareModal.ee.vue';
import WorkflowSuccessModal from './UserActivationSurveyModal.vue'; import WorkflowSuccessModal from './UserActivationSurveyModal.vue';
import EventDestinationSettingsModal from '@/components/SettingsLogStreaming/EventDestinationSettingsModal.ee.vue'; import EventDestinationSettingsModal from '@/components/SettingsLogStreaming/EventDestinationSettingsModal.ee.vue';
export default Vue.extend({ export default defineComponent({
name: 'Modals', name: 'Modals',
components: { components: {
AboutModal, AboutModal,

View file

@ -84,15 +84,16 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import { IUpdateInformation } from '@/Interface'; import type { PropType } from 'vue';
import type { IUpdateInformation } from '@/Interface';
import { deepCopy, INodeParameters, INodeProperties } from 'n8n-workflow'; import { deepCopy, INodeParameters, INodeProperties } from 'n8n-workflow';
import CollectionParameter from '@/components/CollectionParameter.vue'; import CollectionParameter from '@/components/CollectionParameter.vue';
import ParameterInputFull from '@/components/ParameterInputFull.vue'; import ParameterInputFull from '@/components/ParameterInputFull.vue';
import { get } from 'lodash-es'; import { get } from 'lodash-es';
export default Vue.extend({ export default defineComponent({
name: 'MultipleParameter', name: 'MultipleParameter',
components: { components: {
CollectionParameter, CollectionParameter,

View file

@ -37,7 +37,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { getMidCanvasPosition } from '@/utils/nodeViewUtils'; import { getMidCanvasPosition } from '@/utils/nodeViewUtils';
import { import {
DEFAULT_STICKY_HEIGHT, DEFAULT_STICKY_HEIGHT,
@ -48,7 +48,7 @@ import {
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
export default Vue.extend({ export default defineComponent({
name: 'node-creation', name: 'node-creation',
components: { components: {
NodeCreator: () => import('@/components/Node/NodeCreator/NodeCreator.vue'), NodeCreator: () => import('@/components/Node/NodeCreator/NodeCreator.vue'),

View file

@ -96,7 +96,6 @@ import {
nextTick, nextTick,
} from 'vue'; } from 'vue';
import { camelCase } from 'lodash-es'; import { camelCase } from 'lodash-es';
import { externalHooks } from '@/mixins/externalHooks';
import { INodeTypeDescription } from 'n8n-workflow'; import { INodeTypeDescription } from 'n8n-workflow';
import ItemIterator from './ItemIterator.vue'; import ItemIterator from './ItemIterator.vue';
import SearchBar from './SearchBar.vue'; import SearchBar from './SearchBar.vue';
@ -114,6 +113,7 @@ import { sublimeSearch, matchesNodeType, matchesSelectType } from '@/utils';
import { useWorkflowsStore } from '@/stores/workflows'; import { useWorkflowsStore } from '@/stores/workflows';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { useNodeCreatorStore } from '@/stores/nodeCreator'; import { useNodeCreatorStore } from '@/stores/nodeCreator';
import { useExternalHooks } from '@/composables';
export interface Props { export interface Props {
showSubcategoryIcon?: boolean; showSubcategoryIcon?: boolean;
@ -148,7 +148,7 @@ const emit = defineEmits<{
}>(); }>();
const instance = getCurrentInstance(); const instance = getCurrentInstance();
const { $externalHooks } = new externalHooks(); const externalHooks = useExternalHooks();
const { defaultLocale } = useRootStore(); const { defaultLocale } = useRootStore();
const { workflowId } = useWorkflowsStore(); const { workflowId } = useWorkflowsStore();
@ -549,7 +549,7 @@ onUnmounted(() => {
}); });
watch(filteredNodeTypes, (returnItems) => { watch(filteredNodeTypes, (returnItems) => {
$externalHooks().run('nodeCreateList.filteredNodeTypesComputed', { externalHooks.run('nodeCreateList.filteredNodeTypesComputed', {
nodeFilter: nodeCreatorStore.itemsFilter, nodeFilter: nodeCreatorStore.itemsFilter,
result: returnItems, result: returnItems,
selectedType: nodeCreatorStore.selectedView, selectedType: nodeCreatorStore.selectedView,
@ -569,7 +569,7 @@ watch(
// Reset the index whenver the filter-value changes // Reset the index whenver the filter-value changes
state.activeIndex = 0; state.activeIndex = 0;
state.activeSubcategoryIndex = 0; state.activeSubcategoryIndex = 0;
$externalHooks().run('nodeCreateList.nodeFilterChanged', { externalHooks.run('nodeCreateList.nodeFilterChanged', {
oldValue, oldValue,
newValue, newValue,
selectedType: nodeCreatorStore.selectedView, selectedType: nodeCreatorStore.selectedView,

View file

@ -105,12 +105,12 @@ import {
import CategorizedItems from './CategorizedItems.vue'; import CategorizedItems from './CategorizedItems.vue';
import { useNodeCreatorStore } from '@/stores/nodeCreator'; import { useNodeCreatorStore } from '@/stores/nodeCreator';
import { getCategoriesWithNodes, getCategorizedList } from '@/utils'; import { getCategoriesWithNodes, getCategorizedList } from '@/utils';
import { externalHooks } from '@/mixins/externalHooks';
import { useNodeTypesStore } from '@/stores/nodeTypes'; import { useNodeTypesStore } from '@/stores/nodeTypes';
import { BaseTextKey } from '@/plugins/i18n'; import { BaseTextKey } from '@/plugins/i18n';
import NoResults from './NoResults.vue'; import NoResults from './NoResults.vue';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import useMainPanelView from './useMainPanelView'; import useMainPanelView from './useMainPanelView';
import { useExternalHooks } from '@/composables';
const instance = getCurrentInstance(); const instance = getCurrentInstance();
@ -124,7 +124,8 @@ const state = reactive({
activeNodeActions: null as INodeTypeDescription | null, activeNodeActions: null as INodeTypeDescription | null,
}); });
const { baseUrl } = useRootStore(); const { baseUrl } = useRootStore();
const { $externalHooks } = new externalHooks(); const externalHooks = useExternalHooks();
const { const {
mergedAppNodes, mergedAppNodes,
getActionData, getActionData,
@ -324,7 +325,7 @@ function addHttpNode(isAction: boolean) {
setAddedNodeActionParameters(updateData, telemetry, false); setAddedNodeActionParameters(updateData, telemetry, false);
const app_identifier = state.activeNodeActions?.name; const app_identifier = state.activeNodeActions?.name;
$externalHooks().run('nodeCreateList.onActionsCustmAPIClicked', { app_identifier }); externalHooks.run('nodeCreateList.onActionsCustmAPIClicked', { app_identifier });
telemetry?.trackNodesPanel('nodeCreateList.onActionsCustmAPIClicked', { app_identifier }); telemetry?.trackNodesPanel('nodeCreateList.onActionsCustmAPIClicked', { app_identifier });
} }
} }
@ -362,7 +363,7 @@ function trackActionsView() {
trigger_action_count, trigger_action_count,
}; };
$externalHooks().run('nodeCreateList.onViewActions', trackingPayload); externalHooks.run('nodeCreateList.onViewActions', trackingPayload);
telemetry?.trackNodesPanel('nodeCreateList.onViewActions', trackingPayload); telemetry?.trackNodesPanel('nodeCreateList.onViewActions', trackingPayload);
} }

View file

@ -25,8 +25,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, reactive, toRefs, onBeforeUnmount } from 'vue'; import { onMounted, reactive, toRefs, onBeforeUnmount } from 'vue';
import { externalHooks } from '@/mixins/externalHooks';
import { EventBus } from '@/event-bus'; import { EventBus } from '@/event-bus';
import { useExternalHooks } from '@/composables';
export interface Props { export interface Props {
placeholder: string; placeholder: string;
@ -43,7 +43,7 @@ const emit = defineEmits<{
(event: 'input', value: string): void; (event: 'input', value: string): void;
}>(); }>();
const { $externalHooks } = new externalHooks(); const externalHooks = useExternalHooks();
const state = reactive({ const state = reactive({
inputRef: null as HTMLInputElement | null, inputRef: null as HTMLInputElement | null,
@ -63,7 +63,7 @@ function clear() {
} }
onMounted(() => { onMounted(() => {
$externalHooks().run('nodeCreator_searchBar.mount', { inputRef: state.inputRef }); externalHooks.run('nodeCreator_searchBar.mount', { inputRef: state.inputRef });
setTimeout(focus, 0); setTimeout(focus, 0);
}); });

View file

@ -18,7 +18,7 @@ import { IVersionNode } from '@/Interface';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { INodeTypeDescription } from 'n8n-workflow'; import { INodeTypeDescription } from 'n8n-workflow';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
interface NodeIconSource { interface NodeIconSource {
path?: string; path?: string;
@ -26,7 +26,7 @@ interface NodeIconSource {
icon?: string; icon?: string;
} }
export default Vue.extend({ export default defineComponent({
name: 'NodeIcon', name: 'NodeIcon',
props: { props: {
nodeType: {}, nodeType: {},

View file

@ -40,9 +40,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'NodeTitle', name: 'NodeTitle',
props: { props: {
value: { value: {

View file

@ -9,9 +9,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'PageContentWrapper', name: 'PageContentWrapper',
}); });
</script> </script>

View file

@ -42,10 +42,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import Draggable from './Draggable.vue'; import Draggable from './Draggable.vue';
export default Vue.extend({ export default defineComponent({
components: { components: {
Draggable, Draggable,
}, },

View file

@ -58,7 +58,8 @@
<script lang="ts"> <script lang="ts">
import { IUpdateInformation } from '@/Interface'; import { IUpdateInformation } from '@/Interface';
import ParameterOptions from './ParameterOptions.vue'; import ParameterOptions from './ParameterOptions.vue';
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import ParameterInputWrapper from './ParameterInputWrapper.vue'; import ParameterInputWrapper from './ParameterInputWrapper.vue';
import { isValueExpression } from '@/utils'; import { isValueExpression } from '@/utils';
import { INodeParameterResourceLocator, INodeProperties, IParameterLabel } from 'n8n-workflow'; import { INodeParameterResourceLocator, INodeProperties, IParameterLabel } from 'n8n-workflow';
@ -67,7 +68,7 @@ import { useWorkflowsStore } from '@/stores/workflows';
type ParamRef = InstanceType<typeof ParameterInputWrapper>; type ParamRef = InstanceType<typeof ParameterInputWrapper>;
export default Vue.extend({ export default defineComponent({
name: 'parameter-input-expanded', name: 'parameter-input-expanded',
components: { components: {
ParameterOptions, ParameterOptions,

View file

@ -17,9 +17,9 @@
<script lang="ts"> <script lang="ts">
import { sanitizeHtml } from '@/utils'; import { sanitizeHtml } from '@/utils';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'InputHint', name: 'InputHint',
props: { props: {
hint: { hint: {

View file

@ -10,10 +10,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import TitledList from '@/components/TitledList.vue'; import TitledList from '@/components/TitledList.vue';
export default Vue.extend({ export default defineComponent({
name: 'ParameterIssues', name: 'ParameterIssues',
components: { components: {
TitledList, TitledList,

View file

@ -25,11 +25,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { NodeParameterValueType } from 'n8n-workflow'; import type { NodeParameterValueType } from 'n8n-workflow';
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import { isValueExpression, isResourceLocatorValue } from '@/utils'; import { isValueExpression, isResourceLocatorValue } from '@/utils';
export default Vue.extend({ export default defineComponent({
name: 'parameter-options', name: 'parameter-options',
props: { props: {
parameter: { parameter: {

View file

@ -18,9 +18,9 @@
<script lang="ts"> <script lang="ts">
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'PushConnectionTracker', name: 'PushConnectionTracker',
computed: { computed: {
...mapStores(useRootStore), ...mapStores(useRootStore),

View file

@ -79,12 +79,13 @@
<script lang="ts"> <script lang="ts">
import { IResourceLocatorResultExpanded } from '@/Interface'; import { IResourceLocatorResultExpanded } from '@/Interface';
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import type { PropType } from 'vue';
const SEARCH_BAR_HEIGHT_PX = 40; const SEARCH_BAR_HEIGHT_PX = 40;
const SCROLL_MARGIN_PX = 10; const SCROLL_MARGIN_PX = 10;
export default Vue.extend({ export default defineComponent({
name: 'resource-locator-dropdown', name: 'resource-locator-dropdown',
props: { props: {
value: { value: {

View file

@ -6,10 +6,9 @@ import RunDataSchemaItem from '@/components/RunDataSchemaItem.vue';
import Draggable from '@/components/Draggable.vue'; import Draggable from '@/components/Draggable.vue';
import { useNDVStore } from '@/stores/ndv'; import { useNDVStore } from '@/stores/ndv';
import { useWebhooksStore } from '@/stores/webhooks'; import { useWebhooksStore } from '@/stores/webhooks';
import { runExternalHook } from '@/mixins/externalHooks';
import { telemetry } from '@/plugins/telemetry'; import { telemetry } from '@/plugins/telemetry';
import { IDataObject } from 'n8n-workflow'; import { IDataObject } from 'n8n-workflow';
import { getSchema, isEmpty } from '@/utils'; import { getSchema, isEmpty, runExternalHook } from '@/utils';
import { i18n } from '@/plugins/i18n'; import { i18n } from '@/plugins/i18n';
import MappingPill from './MappingPill.vue'; import MappingPill from './MappingPill.vue';

View file

@ -14,10 +14,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { ITaskData } from 'n8n-workflow'; import type { ITaskData } from 'n8n-workflow';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
props: { props: {
taskData: {}, // ITaskData taskData: {}, // ITaskData
}, },

View file

@ -14,9 +14,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'SaveButton', name: 'SaveButton',
props: { props: {
saved: { saved: {

View file

@ -5,9 +5,9 @@
<script lang="ts"> <script lang="ts">
import { useCredentialsStore } from '@/stores/credentials'; import { useCredentialsStore } from '@/stores/credentials';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'ScopesNotice', name: 'ScopesNotice',
props: ['activeCredentialType', 'scopes'], props: ['activeCredentialType', 'scopes'],
computed: { computed: {

View file

@ -5,13 +5,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { shorten } from '@/utils'; import { shorten } from '@/utils';
const DEFAULT_WORKFLOW_NAME_LIMIT = 25; const DEFAULT_WORKFLOW_NAME_LIMIT = 25;
const WORKFLOW_NAME_END_COUNT_TO_KEEP = 4; const WORKFLOW_NAME_END_COUNT_TO_KEEP = 4;
export default Vue.extend({ export default defineComponent({
name: 'ShortenName', name: 'ShortenName',
props: ['name', 'limit', 'testId'], props: ['name', 'limit', 'testId'],
computed: { computed: {

View file

@ -39,7 +39,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue, { defineComponent } from 'vue';
import { ITag } from '@/Interface'; import { ITag } from '@/Interface';
import IntersectionObserver from './IntersectionObserver.vue'; import IntersectionObserver from './IntersectionObserver.vue';
@ -56,7 +56,7 @@ interface TagEl extends ITag {
isCount?: boolean; isCount?: boolean;
} }
export default Vue.extend({ export default defineComponent({
components: { IntersectionObserver, IntersectionObserved }, components: { IntersectionObserver, IntersectionObserved },
name: 'TagsContainer', name: 'TagsContainer',
props: ['tagIds', 'limit', 'clickable', 'responsive', 'hoverable'], props: ['tagIds', 'limit', 'clickable', 'responsive', 'hoverable'],

View file

@ -16,9 +16,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'NoTagsView', name: 'NoTagsView',
}); });
</script> </script>

View file

@ -110,7 +110,7 @@
import { Table as ElTable } from 'element-ui'; import { Table as ElTable } from 'element-ui';
import { MAX_TAG_NAME_LENGTH } from '@/constants'; import { MAX_TAG_NAME_LENGTH } from '@/constants';
import { ITagRow } from '@/Interface'; import { ITagRow } from '@/Interface';
import Vue from 'vue'; import { defineComponent } from 'vue';
import { N8nInput } from 'n8n-design-system'; import { N8nInput } from 'n8n-design-system';
type TableRef = InstanceType<typeof ElTable>; type TableRef = InstanceType<typeof ElTable>;
@ -119,7 +119,7 @@ type N8nInputRef = InstanceType<typeof N8nInput>;
const INPUT_TRANSITION_TIMEOUT = 350; const INPUT_TRANSITION_TIMEOUT = 350;
const DELETE_TRANSITION_TIMEOUT = 100; const DELETE_TRANSITION_TIMEOUT = 100;
export default Vue.extend({ export default defineComponent({
name: 'TagsTable', name: 'TagsTable',
props: ['rows', 'isLoading', 'newName', 'isSaving'], props: ['rows', 'isLoading', 'newName', 'isSaving'],
data() { data() {

View file

@ -29,9 +29,9 @@
<script lang="ts"> <script lang="ts">
import { MAX_TAG_NAME_LENGTH } from '@/constants'; import { MAX_TAG_NAME_LENGTH } from '@/constants';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
props: { props: {
disabled: { disabled: {
default: false, default: false,

View file

@ -23,9 +23,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { ITag, ITagRow } from '@/Interface'; import type { ITag, ITagRow } from '@/Interface';
import TagsTableHeader from '@/components/TagsManager/TagsView/TagsTableHeader.vue'; import TagsTableHeader from '@/components/TagsManager/TagsView/TagsTableHeader.vue';
import TagsTable from '@/components/TagsManager/TagsView/TagsTable.vue'; import TagsTable from '@/components/TagsManager/TagsView/TagsTable.vue';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
@ -34,7 +34,7 @@ import { useUsersStore } from '@/stores/users';
const matches = (name: string, filter: string) => const matches = (name: string, filter: string) =>
name.toLowerCase().trim().includes(filter.toLowerCase().trim()); name.toLowerCase().trim().includes(filter.toLowerCase().trim());
export default Vue.extend({ export default defineComponent({
components: { TagsTableHeader, TagsTable }, components: { TagsTableHeader, TagsTable },
name: 'TagsView', name: 'TagsView',
props: ['tags', 'isLoading'], props: ['tags', 'isLoading'],

View file

@ -47,14 +47,16 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import TemplateDetailsBlock from '@/components/TemplateDetailsBlock.vue'; import TemplateDetailsBlock from '@/components/TemplateDetailsBlock.vue';
import NodeIcon from '@/components/NodeIcon.vue'; import NodeIcon from '@/components/NodeIcon.vue';
import { abbreviateNumber, filterTemplateNodes } from '@/utils'; import { abbreviateNumber, filterTemplateNodes } from '@/utils';
import { ITemplatesNode, ITemplatesWorkflow, ITemplatesWorkflowFull } from '@/Interface'; import { ITemplatesNode, ITemplatesWorkflow, ITemplatesWorkflowFull } from '@/Interface';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useTemplatesStore } from '@/stores/templates'; import { useTemplatesStore } from '@/stores/templates';
export default Vue.extend({
export default defineComponent({
name: 'TemplateDetails', name: 'TemplateDetails',
props: { props: {
blockTitle: { blockTitle: {

View file

@ -10,9 +10,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'TemplateDetailsBlock', name: 'TemplateDetailsBlock',
props: { props: {
title: { title: {

View file

@ -30,9 +30,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { nextTick, defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'TextEdit', name: 'TextEdit',
props: ['dialogVisible', 'parameter', 'path', 'value', 'isReadOnly'], props: ['dialogVisible', 'parameter', 'path', 'value', 'isReadOnly'],
data() { data() {
@ -65,7 +65,7 @@ export default Vue.extend({
watch: { watch: {
dialogVisible() { dialogVisible() {
if (this.dialogVisible === true) { if (this.dialogVisible === true) {
Vue.nextTick(() => { nextTick(() => {
(this.$refs.inputField as HTMLInputElement).focus(); (this.$refs.inputField as HTMLInputElement).focus();
}); });
} }

View file

@ -7,11 +7,11 @@
<script lang="ts"> <script lang="ts">
import { format, LocaleFunc, register } from 'timeago.js'; import { format, LocaleFunc, register } from 'timeago.js';
import { convertToHumanReadableDate } from '@/utils'; import { convertToHumanReadableDate } from '@/utils';
import Vue from 'vue'; import { defineComponent } from 'vue';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useRootStore } from '@/stores/n8nRootStore'; import { useRootStore } from '@/stores/n8nRootStore';
export default Vue.extend({ export default defineComponent({
name: 'TimeAgo', name: 'TimeAgo',
props: { props: {
date: { date: {

View file

@ -8,9 +8,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'TitledList', name: 'TitledList',
props: { props: {
title: { title: {

View file

@ -43,7 +43,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import ModalDrawer from './ModalDrawer.vue'; import ModalDrawer from './ModalDrawer.vue';
import TimeAgo from './TimeAgo.vue'; import TimeAgo from './TimeAgo.vue';
@ -53,7 +53,7 @@ import { mapStores } from 'pinia';
import { useVersionsStore } from '@/stores/versions'; import { useVersionsStore } from '@/stores/versions';
import { IVersion } from '@/Interface'; import { IVersion } from '@/Interface';
export default Vue.extend({ export default defineComponent({
name: 'UpdatesPanel', name: 'UpdatesPanel',
components: { components: {
ModalDrawer, ModalDrawer,

View file

@ -55,7 +55,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue, { defineComponent } from 'vue';
import NodeIcon from './NodeIcon.vue'; import NodeIcon from './NodeIcon.vue';
import TimeAgo from './TimeAgo.vue'; import TimeAgo from './TimeAgo.vue';
import Badge from './Badge.vue'; import Badge from './Badge.vue';
@ -67,7 +67,7 @@ Vue.component('TimeAgo', TimeAgo);
Vue.component('Badge', Badge); Vue.component('Badge', Badge);
Vue.component('WarningTooltip', WarningTooltip); Vue.component('WarningTooltip', WarningTooltip);
export default Vue.extend({ export default defineComponent({
components: { NodeIcon, TimeAgo, Badge, WarningTooltip }, components: { NodeIcon, TimeAgo, Badge, WarningTooltip },
name: 'VersionCard', name: 'VersionCard',
props: ['version'], props: ['version'],

View file

@ -1,5 +1,5 @@
import { vi, describe, it, expect } from 'vitest'; import { vi, describe, it, expect } from 'vitest';
import Vue from 'vue'; import Vue, { defineComponent } from 'vue';
import { PiniaVuePlugin } from 'pinia'; import { PiniaVuePlugin } from 'pinia';
import { createTestingPinia } from '@pinia/testing'; import { createTestingPinia } from '@pinia/testing';
import { render } from '@testing-library/vue'; import { render } from '@testing-library/vue';
@ -47,7 +47,7 @@ const executionsData = Array.from({ length: 2 }, () => ({
let getPastExecutionsSpy = vi.fn().mockResolvedValue({ count: 0, results: [], estimated: false }); let getPastExecutionsSpy = vi.fn().mockResolvedValue({ count: 0, results: [], estimated: false });
const mockRestApiMixin = Vue.extend({ const mockRestApiMixin = defineComponent({
methods: { methods: {
restApi() { restApi() {
return { return {

View file

@ -1,20 +1,23 @@
import VariablesRow from '../VariablesRow.vue'; import VariablesRow from '../VariablesRow.vue';
import { EnvironmentVariable } from '@/Interface'; import { EnvironmentVariable } from '@/Interface';
import { fireEvent, render } from '@testing-library/vue'; import { fireEvent } from '@testing-library/vue';
import { createPinia, setActivePinia } from 'pinia'; import { createPinia, setActivePinia } from 'pinia';
import { setupServer } from '@/__tests__/server'; import { setupServer } from '@/__tests__/server';
import { afterAll, beforeAll } from 'vitest'; import { afterAll, beforeAll } from 'vitest';
import { useSettingsStore, useUsersStore } from '@/stores'; import { useSettingsStore, useUsersStore } from '@/stores';
import { renderComponent } from '@/__tests__/utils';
describe('VariablesRow', () => { describe('VariablesRow', () => {
let server: ReturnType<typeof setupServer>; let server: ReturnType<typeof setupServer>;
let pinia: ReturnType<typeof createPinia>;
beforeAll(() => { beforeAll(() => {
server = setupServer(); server = setupServer();
}); });
beforeEach(async () => { beforeEach(async () => {
setActivePinia(createPinia()); pinia = createPinia();
setActivePinia(pinia);
await useSettingsStore().getSettings(); await useSettingsStore().getSettings();
await useUsersStore().loginWithCookie(); await useUsersStore().loginWithCookie();
@ -33,11 +36,12 @@ describe('VariablesRow', () => {
}; };
it('should render correctly', () => { it('should render correctly', () => {
const wrapper = render(VariablesRow, { const wrapper = renderComponent(VariablesRow, {
props: { props: {
data: environmentVariable, data: environmentVariable,
}, },
stubs, stubs,
pinia,
}); });
expect(wrapper.html()).toMatchSnapshot(); expect(wrapper.html()).toMatchSnapshot();
@ -45,11 +49,12 @@ describe('VariablesRow', () => {
}); });
it('should show edit and delete buttons on hover', async () => { it('should show edit and delete buttons on hover', async () => {
const wrapper = render(VariablesRow, { const wrapper = renderComponent(VariablesRow, {
props: { props: {
data: environmentVariable, data: environmentVariable,
}, },
stubs, stubs,
pinia,
}); });
await fireEvent.mouseEnter(wrapper.container); await fireEvent.mouseEnter(wrapper.container);
@ -59,12 +64,13 @@ describe('VariablesRow', () => {
}); });
it('should show key and value inputs in edit mode', async () => { it('should show key and value inputs in edit mode', async () => {
const wrapper = render(VariablesRow, { const wrapper = renderComponent(VariablesRow, {
props: { props: {
data: environmentVariable, data: environmentVariable,
editing: true, editing: true,
}, },
stubs, stubs,
pinia,
}); });
await fireEvent.mouseEnter(wrapper.container); await fireEvent.mouseEnter(wrapper.container);
@ -82,12 +88,13 @@ describe('VariablesRow', () => {
}); });
it('should show cancel and save buttons in edit mode', async () => { it('should show cancel and save buttons in edit mode', async () => {
const wrapper = render(VariablesRow, { const wrapper = renderComponent(VariablesRow, {
props: { props: {
data: environmentVariable, data: environmentVariable,
editing: true, editing: true,
}, },
stubs, stubs,
pinia,
}); });
await fireEvent.mouseEnter(wrapper.container); await fireEvent.mouseEnter(wrapper.container);

View file

@ -3,10 +3,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import * as monaco from 'monaco-editor'; import * as monaco from 'monaco-editor';
export default Vue.extend({ export default defineComponent({
props: { props: {
type: { type: {
type: String, type: String,

View file

@ -63,15 +63,16 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue, { PropType } from 'vue'; import { defineComponent } from 'vue';
import { EnterpriseEditionFeature } from '@/constants'; import { EnterpriseEditionFeature } from '@/constants';
import { IUser } from '@/Interface';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import type { PropType } from 'vue';
import type { IUser } from '@/Interface';
export type IResourceFiltersType = Record<string, boolean | string | string[]>; export type IResourceFiltersType = Record<string, boolean | string | string[]>;
export default Vue.extend({ export default defineComponent({
props: { props: {
value: { value: {
type: Object as PropType<IResourceFiltersType>, type: Object as PropType<IResourceFiltersType>,

View file

@ -8,10 +8,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import { IMenuItem } from 'n8n-design-system'; import { IMenuItem } from 'n8n-design-system';
export default Vue.extend({ export default defineComponent({
props: { props: {
value: { value: {
type: Boolean, type: Boolean,

View file

@ -14,9 +14,9 @@
<script lang="ts"> <script lang="ts">
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'PageViewLayout', name: 'PageViewLayout',
data() { data() {
return { return {

View file

@ -5,9 +5,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'SlideTransition', name: 'SlideTransition',
}); });
</script> </script>

View file

@ -1,12 +1,12 @@
import { IExternalHooks } from '@/Interface'; import type { IExternalHooks } from '@/Interface';
import { IDataObject } from 'n8n-workflow'; import type { IDataObject } from 'n8n-workflow';
import { useWebhooksStore } from '@/stores'; import { useWebhooksStore } from '@/stores';
import { runExternalHook } from '@/mixins/externalHooks'; import { runExternalHook } from '@/utils';
export function useExternalHooks(): IExternalHooks { export function useExternalHooks(): IExternalHooks {
return { return {
async run(eventName: string, metadata?: IDataObject): Promise<void> { async run(eventName: string, metadata?: IDataObject): Promise<void> {
return await runExternalHook.call(this, eventName, useWebhooksStore(), metadata); return await runExternalHook(eventName, useWebhooksStore(), metadata);
}, },
}; };
} }

View file

@ -19,16 +19,14 @@ import '@fontsource/open-sans/latin-700.css';
import App from '@/App.vue'; import App from '@/App.vue';
import router from './router'; import router from './router';
import { runExternalHook } from '@/mixins/externalHooks'; import { runExternalHook } from '@/utils';
import { TelemetryPlugin } from './plugins/telemetry'; import { TelemetryPlugin } from './plugins/telemetry';
import { I18nPlugin, i18nInstance } from './plugins/i18n'; import { I18nPlugin, i18nInstance } from './plugins/i18n';
import { createPinia, PiniaVuePlugin } from 'pinia'; import { createPinia, PiniaVuePlugin } from 'pinia';
import { useWebhooksStore } from './stores/webhooks'; import { useWebhooksStore, useUsersStore } from '@/stores';
import { useUsersStore } from './stores/users';
import { VIEWS } from '@/constants'; import { VIEWS } from '@/constants';
import { useUIStore } from './stores/ui';
Vue.config.productionTip = false; Vue.config.productionTip = false;

View file

@ -2,10 +2,10 @@
* Captures any pasted data and sends it to method "receivedCopyPasteData" which has to be * Captures any pasted data and sends it to method "receivedCopyPasteData" which has to be
* defined on the component which uses this mixin * defined on the component which uses this mixin
*/ */
import Vue from 'vue'; import { defineComponent } from 'vue';
import { debounce } from 'lodash-es'; import { debounce } from 'lodash-es';
export const copyPaste = Vue.extend({ export const copyPaste = defineComponent({
data() { data() {
return { return {
copyPasteElementsGotCreated: false, copyPasteElementsGotCreated: false,

View file

@ -1,7 +1,7 @@
import { debounce } from 'lodash-es'; import { debounce } from 'lodash-es';
import Vue from 'vue'; import { defineComponent } from 'vue';
export const debounceHelper = Vue.extend({ export const debounceHelper = defineComponent({
data() { data() {
return { return {
debouncedFunctions: [] as any[], debouncedFunctions: [] as any[],

View file

@ -1,6 +1,6 @@
import Vue from 'vue'; import { defineComponent } from 'vue';
export const deviceSupportHelpers = Vue.extend({ export const deviceSupportHelpers = defineComponent({
data() { data() {
return { return {
// @ts-ignore msMaxTouchPoints is deprecated but must fix tablet bugs before fixing this.. otherwise breaks touchscreen computers // @ts-ignore msMaxTouchPoints is deprecated but must fix tablet bugs before fixing this.. otherwise breaks touchscreen computers

View file

@ -1,35 +1,10 @@
import { IExternalHooks } from '@/Interface'; import type { IExternalHooks } from '@/Interface';
import type { IDataObject } from 'n8n-workflow';
import { useWebhooksStore } from '@/stores/webhooks'; import { useWebhooksStore } from '@/stores/webhooks';
import { IDataObject } from 'n8n-workflow'; import { defineComponent } from 'vue';
import { Store } from 'pinia'; import { runExternalHook } from '@/utils';
import Vue from 'vue';
declare global { export const externalHooks = defineComponent({
interface Window {
n8nExternalHooks?: Record<
string,
Record<string, Array<(store: Store, metadata?: IDataObject) => Promise<void>>>
>;
}
}
export async function runExternalHook(eventName: string, store: Store, metadata?: IDataObject) {
if (!window.n8nExternalHooks) {
return;
}
const [resource, operator] = eventName.split('.');
if (window.n8nExternalHooks[resource]?.[operator]) {
const hookMethods = window.n8nExternalHooks[resource][operator];
for (const hookMethod of hookMethods) {
await hookMethod(store, metadata);
}
}
}
export const externalHooks = Vue.extend({
methods: { methods: {
$externalHooks(): IExternalHooks { $externalHooks(): IExternalHooks {
return { return {

View file

@ -1,4 +1,4 @@
import Vue from 'vue'; import { defineComponent } from 'vue';
import { parse } from 'flatted'; import { parse } from 'flatted';
import { Method } from 'axios'; import { Method } from 'axios';
@ -55,7 +55,7 @@ function unflattenExecutionData(fullExecutionData: IExecutionFlattedResponse): I
return returnData; return returnData;
} }
export const restApi = Vue.extend({ export const restApi = defineComponent({
computed: { computed: {
...mapStores(useRootStore), ...mapStores(useRootStore),
}, },

View file

@ -1,10 +1,10 @@
import { IPermissions, IUser } from '@/Interface'; import type { IPermissions } from '@/Interface';
import { isAuthorized } from '@/utils'; import { isAuthorized } from '@/utils';
import { useUsersStore } from '@/stores/users'; import { useUsersStore } from '@/stores/users';
import Vue from 'vue'; import { defineComponent } from 'vue';
import { Route } from 'vue-router'; import type { Route } from 'vue-router';
export const userHelpers = Vue.extend({ export const userHelpers = defineComponent({
methods: { methods: {
canUserAccessRouteByName(name: string): boolean { canUserAccessRouteByName(name: string): boolean {
const { route } = this.$router.resolve({ name }); const { route } = this.$router.resolve({ name });

View file

@ -1,4 +1,6 @@
import Vue, { VNode } from 'vue'; import Vue, { VNode } from 'vue';
import type { Store } from 'pinia';
import type { IDataObject } from 'n8n-workflow';
declare module 'markdown-it-link-attributes'; declare module 'markdown-it-link-attributes';
declare module 'markdown-it-emoji'; declare module 'markdown-it-emoji';
@ -17,6 +19,10 @@ declare global {
interface Window { interface Window {
BASE_PATH: string; BASE_PATH: string;
REST_ENDPOINT: string; REST_ENDPOINT: string;
n8nExternalHooks?: Record<
string,
Record<string, Array<(store: Store, metadata?: IDataObject) => Promise<void>>>
>;
} }
namespace JSX { namespace JSX {

View file

@ -20,11 +20,12 @@ import {
} from '@/constants'; } from '@/constants';
import { useNodeTypesStore } from '@/stores/nodeTypes'; import { useNodeTypesStore } from '@/stores/nodeTypes';
import { useWorkflowsStore } from './workflows'; import { useWorkflowsStore } from './workflows';
import { CUSTOM_API_CALL_KEY, ALL_NODE_FILTER } from '@/constants'; import { CUSTOM_API_CALL_KEY } from '@/constants';
import { INodeCreatorState, INodeFilterType, IUpdateInformation } from '@/Interface'; import { INodeCreatorState, INodeFilterType, IUpdateInformation } from '@/Interface';
import { BaseTextKey, i18n } from '@/plugins/i18n'; import { i18n } from '@/plugins/i18n';
import { externalHooks } from '@/mixins/externalHooks';
import { Telemetry } from '@/plugins/telemetry'; import { Telemetry } from '@/plugins/telemetry';
import { runExternalHook } from '@/utils';
import { useWebhooksStore } from '@/stores/webhooks';
const PLACEHOLDER_RECOMMENDED_ACTION_KEY = 'placeholder_recommended'; const PLACEHOLDER_RECOMMENDED_ACTION_KEY = 'placeholder_recommended';
@ -286,14 +287,12 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, {
return storeWatcher; return storeWatcher;
}, },
trackActionSelected(action: IUpdateInformation, telemetry?: Telemetry) { trackActionSelected(action: IUpdateInformation, telemetry?: Telemetry) {
const { $externalHooks } = new externalHooks();
const payload = { const payload = {
node_type: action.key, node_type: action.key,
action: action.name, action: action.name,
resource: (action.value as INodeParameters).resource || '', resource: (action.value as INodeParameters).resource || '',
}; };
$externalHooks().run('nodeCreateList.addAction', payload); runExternalHook('nodeCreateList.addAction', useWebhooksStore(), payload);
telemetry?.trackNodesPanel('nodeCreateList.addAction', payload); telemetry?.trackNodesPanel('nodeCreateList.addAction', payload);
}, },
}, },

View file

@ -0,0 +1,18 @@
import type { IDataObject } from 'n8n-workflow';
import type { Store } from 'pinia';
export async function runExternalHook(eventName: string, store: Store, metadata?: IDataObject) {
if (!window.n8nExternalHooks) {
return;
}
const [resource, operator] = eventName.split('.');
if (window.n8nExternalHooks[resource]?.[operator]) {
const hookMethods = window.n8nExternalHooks[resource][operator];
for (const hookMethod of hookMethods) {
await hookMethod(store, metadata);
}
}
}

View file

@ -1,5 +1,6 @@
export * from './apiUtils'; export * from './apiUtils';
export * from './canvasUtils'; export * from './canvasUtils';
export * from './externalHooks';
export * from './htmlUtils'; export * from './htmlUtils';
export * from './nodeTypesUtils'; export * from './nodeTypesUtils';
export * from './sortUtils'; export * from './sortUtils';

View file

@ -22,12 +22,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import Logo from '@/components/Logo.vue'; import Logo from '@/components/Logo.vue';
import SSOLogin from '@/components/SSOLogin.vue'; import SSOLogin from '@/components/SSOLogin.vue';
export default Vue.extend({ export default defineComponent({
name: 'AuthView', name: 'AuthView',
components: { components: {
Logo, Logo,

View file

@ -18,9 +18,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
export default Vue.extend({ export default defineComponent({
name: 'ErrorView', name: 'ErrorView',
props: { props: {
messageKey: { messageKey: {

View file

@ -3,10 +3,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import ExecutionsList from '@/components/ExecutionsList.vue'; import ExecutionsList from '@/components/ExecutionsList.vue';
export default Vue.extend({ export default defineComponent({
name: 'ExecutionsView', name: 'ExecutionsView',
components: { components: {
ExecutionsList, ExecutionsList,

View file

@ -4,12 +4,12 @@
<script lang="ts"> <script lang="ts">
import { IFakeDoor } from '@/Interface'; import { IFakeDoor } from '@/Interface';
import Vue from 'vue'; import { defineComponent } from 'vue';
import FeatureComingSoon from '@/components/FeatureComingSoon.vue'; import FeatureComingSoon from '@/components/FeatureComingSoon.vue';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui'; import { useUIStore } from '@/stores/ui';
export default Vue.extend({ export default defineComponent({
name: 'SettingsFakeDoorView', name: 'SettingsFakeDoorView',
components: { components: {
FeatureComingSoon, FeatureComingSoon,

View file

@ -15,10 +15,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import { defineComponent } from 'vue';
import GoBackButton from '@/components/GoBackButton.vue'; import GoBackButton from '@/components/GoBackButton.vue';
export default Vue.extend({ export default defineComponent({
name: 'TemplatesView', name: 'TemplatesView',
components: { components: {
GoBackButton, GoBackButton,

View file

@ -4,16 +4,19 @@ import { setupServer } from '@/__tests__/server';
import { render } from '@testing-library/vue'; import { render } from '@testing-library/vue';
import VariablesView from '@/views/VariablesView.vue'; import VariablesView from '@/views/VariablesView.vue';
import { useSettingsStore, useUsersStore } from '@/stores'; import { useSettingsStore, useUsersStore } from '@/stores';
import { renderComponent } from '@/__tests__/utils';
describe('store', () => { describe('store', () => {
let server: ReturnType<typeof setupServer>; let server: ReturnType<typeof setupServer>;
let pinia: ReturnType<typeof createPinia>;
beforeAll(() => { beforeAll(() => {
server = setupServer(); server = setupServer();
}); });
beforeEach(async () => { beforeEach(async () => {
setActivePinia(createPinia()); pinia = createPinia();
setActivePinia(pinia);
await useSettingsStore().getSettings(); await useSettingsStore().getSettings();
await useUsersStore().fetchUsers(); await useUsersStore().fetchUsers();
@ -25,13 +28,13 @@ describe('store', () => {
}); });
it('should render loading state', () => { it('should render loading state', () => {
const wrapper = render(VariablesView); const wrapper = renderComponent(VariablesView, { pinia });
expect(wrapper.container.querySelectorAll('.n8n-loading')).toHaveLength(3); expect(wrapper.container.querySelectorAll('.n8n-loading')).toHaveLength(3);
}); });
it('should render empty state', async () => { it('should render empty state', async () => {
const wrapper = render(VariablesView); const wrapper = renderComponent(VariablesView, { pinia });
await wrapper.findByTestId('empty-resources-list'); await wrapper.findByTestId('empty-resources-list');
expect(wrapper.getByTestId('empty-resources-list')).toBeVisible(); expect(wrapper.getByTestId('empty-resources-list')).toBeVisible();
@ -40,7 +43,7 @@ describe('store', () => {
it('should render variable entries', async () => { it('should render variable entries', async () => {
server.createList('variable', 3); server.createList('variable', 3);
const wrapper = render(VariablesView); const wrapper = renderComponent(VariablesView, { pinia });
await wrapper.findByTestId('resources-table'); await wrapper.findByTestId('resources-table');
expect(wrapper.getByTestId('resources-table')).toBeVisible(); expect(wrapper.getByTestId('resources-table')).toBeVisible();