Skip to content

Commit

Permalink
feat: Rewrite Front End cloud and posthog hooks using TypeScript (no-…
Browse files Browse the repository at this point in the history
…changelog) (n8n-io#5491)
  • Loading branch information
alexgrozav authored Nov 13, 2023
1 parent 3dfabc3 commit a262c45
Show file tree
Hide file tree
Showing 41 changed files with 1,439 additions and 131 deletions.
2 changes: 1 addition & 1 deletion packages/editor-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"scripts": {
"clean": "rimraf dist .turbo",
"build": "cross-env VUE_APP_PUBLIC_PATH=\"/{{BASE_PATH}}/\" NODE_OPTIONS=\"--max-old-space-size=8192\" vite build",
"typecheck": "vue-tsc --emitDeclarationOnly",
"typecheck": "vue-tsc",
"dev": "pnpm serve",
"lint": "eslint src --ext .js,.ts,.vue --quiet",
"lintfix": "eslint src --ext .js,.ts,.vue --fix",
Expand Down
25 changes: 23 additions & 2 deletions packages/editor-ui/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
<script lang="ts">
import { defineComponent } from 'vue';
import { mapStores } from 'pinia';
import { extendExternalHooks } from '@/mixins/externalHooks';
import { newVersions } from '@/mixins/newVersions';
import BannerStack from '@/components/banners/BannerStack.vue';
import Modals from '@/components/Modals.vue';
Expand All @@ -57,8 +59,10 @@ import {
useUsageStore,
} from '@/stores';
import { useHistoryHelper } from '@/composables/useHistoryHelper';
import { newVersions } from '@/mixins/newVersions';
import { useRoute } from 'vue-router';
import type { ExternalHooks } from '@/types';
import type { PartialDeep } from 'type-fest';
import { runExternalHook } from '@/utils';
export default defineComponent({
name: 'App',
Expand Down Expand Up @@ -131,6 +135,21 @@ export default defineComponent({
await this.nodeTypesStore.getNodeTranslationHeaders();
}
},
async initializeHooks(): Promise<void> {
const hooksImports = [];
if (this.settingsStore.isCloudDeployment) {
hooksImports.push(
import('./hooks/cloud').then(
({ n8nCloudHooks }: { n8nCloudHooks: PartialDeep<ExternalHooks> }) => {
extendExternalHooks(n8nCloudHooks);
},
),
);
}
await Promise.allSettled(hooksImports);
},
async onAfterAuthenticate() {
if (this.onAfterAuthenticateInitialized) {
return;
Expand All @@ -153,10 +172,12 @@ export default defineComponent({
async mounted() {
this.logHiringBanner();
await this.initializeHooks();
void this.checkForNewVersions();
void this.onAfterAuthenticate();
void this.externalHooks.run('app.mount');
void runExternalHook('app.mount');
this.loading = false;
},
watch: {
Expand Down
8 changes: 5 additions & 3 deletions packages/editor-ui/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type {
REGULAR_NODE_CREATOR_VIEW,
AI_OTHERS_NODE_CREATOR_VIEW,
} from './constants';

import type { IMenuItem } from 'n8n-design-system';
import type {
GenericValue,
Expand Down Expand Up @@ -50,6 +49,7 @@ import type {
import type { BulkCommand, Undoable } from '@/models/history';
import type { PartialBy, TupleToUnion } from '@/utils/typeHelpers';
import type { Component } from 'vue';
import type { runExternalHook } from '@/utils';

export * from 'n8n-design-system/types';

Expand Down Expand Up @@ -92,7 +92,9 @@ declare global {
debug?(): void;
};
analytics?: {
track(event: string, proeprties?: ITelemetryTrackProperties): void;
identify(userId: string): void;
track(event: string, properties?: ITelemetryTrackProperties): void;
page(category: string, name: string, properties?: ITelemetryTrackProperties): void;
};
featureFlags?: {
getAll: () => FeatureFlags;
Expand Down Expand Up @@ -158,7 +160,7 @@ export interface INodeTypesMaxCount {
}

export interface IExternalHooks {
run(eventName: string, metadata?: IDataObject): Promise<void>;
run: typeof runExternalHook;
}

export interface INodeTranslationHeaders {
Expand Down
10 changes: 5 additions & 5 deletions packages/editor-ui/src/components/MainSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,8 @@ export default defineComponent({
for (const item of injectedItems) {
items.push({
id: item.id,
// @ts-ignore
icon: item.properties ? item.properties.icon : '',
// @ts-ignore
label: item.properties ? item.properties.title : '',
icon: item.icon || '',
label: item.label || '',
position: item.position,
type: item.properties?.href ? 'link' : 'regular',
properties: item.properties,
Expand Down Expand Up @@ -353,7 +351,9 @@ export default defineComponent({
mounted() {
this.basePath = this.rootStore.baseUrl;
if (this.$refs.user) {
void this.$externalHooks().run('mainSidebar.mounted', { userRef: this.$refs.user });
void this.$externalHooks().run('mainSidebar.mounted', {
userRef: this.$refs.user as Element,
});
}
void this.$nextTick(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
} from '@/constants';
import { useUsersStore } from '@/stores/users.store';
import { useWebhooksStore } from '@/stores/webhooks.store';
import { runExternalHook } from '@/utils';
import { useActions } from '../composables/useActions';
Expand Down Expand Up @@ -171,7 +170,7 @@ function trackActionsView() {
trigger_action_count,
};
void runExternalHook('nodeCreateList.onViewActions', useWebhooksStore(), trackingPayload);
void runExternalHook('nodeCreateList.onViewActions', trackingPayload);
telemetry?.trackNodesPanel('nodeCreateList.onViewActions', trackingPayload);
}
Expand All @@ -192,7 +191,7 @@ function addHttpNode() {
if (telemetry) setAddedNodeActionParameters(updateData);
const app_identifier = actions.value[0].key;
void runExternalHook('nodeCreateList.onActionsCustmAPIClicked', useWebhooksStore(), {
void runExternalHook('nodeCreateList.onActionsCustmAPIClicked', {
app_identifier,
});
telemetry?.trackNodesPanel('nodeCreateList.onActionsCustmAPIClicked', { app_identifier });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@

<script setup lang="ts">
import { onMounted, reactive, toRefs, onBeforeUnmount } from 'vue';
import { useWebhooksStore } from '@/stores/webhooks.store';
import { runExternalHook } from '@/utils';
import { useExternalHooks } from '@/composables';
export interface Props {
placeholder: string;
Expand All @@ -46,6 +45,8 @@ const state = reactive({
inputRef: null as HTMLInputElement | null,
});
const externalHooks = useExternalHooks();
function focus() {
state.inputRef?.focus();
}
Expand All @@ -60,9 +61,7 @@ function clear() {
}
onMounted(() => {
void runExternalHook('nodeCreator_searchBar.mount', useWebhooksStore(), {
inputRef: state.inputRef,
});
void externalHooks.run('nodeCreatorSearchBar.mount', { inputRef: state.inputRef });
setTimeout(focus, 0);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { useNodeCreatorStore } from '@/stores/nodeCreator.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { runExternalHook } from '@/utils';
import { useWebhooksStore } from '@/stores/webhooks.store';

import { sortNodeCreateElements, transformNodeType } from '../utils';

Expand Down Expand Up @@ -256,7 +255,7 @@ export const useActions = () => {
source_mode: rootView.toLowerCase(),
resource: (action.value as INodeParameters).resource || '',
};
void runExternalHook('nodeCreateList.addAction', useWebhooksStore(), payload);
void runExternalHook('nodeCreateList.addAction', payload);
telemetry?.trackNodesPanel('nodeCreateList.addAction', payload);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/editor-ui/src/components/ParameterInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,7 @@ export default defineComponent({
void this.$externalHooks().run('parameterInput.mount', {
parameter: this.parameter,
inputFieldRef: this.$refs.inputField,
inputFieldRef: this.$refs.inputField as InstanceType<typeof N8nInput>,
});
},
beforeUnmount() {
Expand Down
5 changes: 4 additions & 1 deletion packages/editor-ui/src/components/PersonalizationModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,10 @@ export default defineComponent({
personalization_survey_n8n_version: this.rootStore.versionCli,
};
await this.$externalHooks().run('personalizationModal.onSubmit', survey);
await this.$externalHooks().run(
'personalizationModal.onSubmit',
survey as IPersonalizationLatestVersion,
);
await this.usersStore.submitPersonalizationSurvey(survey as IPersonalizationLatestVersion);
Expand Down
4 changes: 1 addition & 3 deletions packages/editor-ui/src/components/RunDataSchema.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { INodeUi } from '@/Interface';
import RunDataSchemaItem from '@/components/RunDataSchemaItem.vue';
import Draggable from '@/components/Draggable.vue';
import { useNDVStore } from '@/stores/ndv.store';
import { useWebhooksStore } from '@/stores/webhooks.store';
import { telemetry } from '@/plugins/telemetry';
import type { IDataObject } from 'n8n-workflow';
import { isEmpty, runExternalHook } from '@/utils';
Expand All @@ -27,7 +26,6 @@ const props = withDefaults(defineProps<Props>(), {
const draggingPath = ref<string>('');
const ndvStore = useNDVStore();
const webhooksStore = useWebhooksStore();
const { getSchemaForExecutionData } = useDataSchema();
const schema = computed(() => getSchemaForExecutionData(props.data));
Expand Down Expand Up @@ -59,7 +57,7 @@ const onDragEnd = (el: HTMLElement) => {
...mappingTelemetry,
};
void runExternalHook('runDataJson.onDragEnd', webhooksStore, telemetryPayload);
void runExternalHook('runDataJson.onDragEnd', telemetryPayload);
telemetry.track('User dragged data for mapping', telemetryPayload);
}, 1000); // ensure dest data gets set if drop
Expand Down
3 changes: 2 additions & 1 deletion packages/editor-ui/src/components/VariablesRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { computed, nextTick, onMounted, ref, watch } from 'vue';
import type { EnvironmentVariable, Rule, RuleGroup } from '@/Interface';
import { useI18n, useToast, useCopyToClipboard } from '@/composables';
import { EnterpriseEditionFeature } from '@/constants';
import { useSettingsStore, useUsersStore } from '@/stores';
import { useSettingsStore } from '@/stores/settings.store';
import { useUsersStore } from '@/stores/users.store';
import { getVariablesPermissions } from '@/permissions';
const i18n = useI18n();
Expand Down
10 changes: 4 additions & 6 deletions packages/editor-ui/src/components/__tests__/BannersStack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import { STORES } from '@/constants';

import { createTestingPinia } from '@pinia/testing';
import BannerStack from '@/components/banners/BannerStack.vue';
import { useUIStore } from '@/stores/ui.store';
import { useUsersStore } from '@/stores/users.store';
import type { RenderOptions } from '@/__tests__/render';
import { createComponentRenderer } from '@/__tests__/render';
import { waitFor } from '@testing-library/vue';
import { useUIStore } from '@/stores/ui.store';
import { useUsersStore } from '@/stores/users.store';

let uiStore: ReturnType<typeof useUIStore>;
let usersStore: ReturnType<typeof useUsersStore>;

const initialState = {
[STORES.SETTINGS]: {
Expand Down Expand Up @@ -55,7 +54,6 @@ const renderComponent = createComponentRenderer(BannerStack, defaultRenderOption
describe('BannerStack', () => {
beforeEach(() => {
uiStore = useUIStore();
usersStore = useUsersStore();
});

afterEach(() => {
Expand All @@ -75,7 +73,7 @@ describe('BannerStack', () => {
it('should dismiss banner on click', async () => {
const { getByTestId } = renderComponent();
const dismissBannerSpy = vi
.spyOn(useUIStore(), 'dismissBanner')
.spyOn(uiStore, 'dismissBanner')
.mockImplementation(async (banner, mode) => {});
expect(getByTestId('banners-V1')).toBeInTheDocument();
const closeTrialBannerButton = getByTestId('banner-V1-close');
Expand All @@ -87,7 +85,7 @@ describe('BannerStack', () => {
it('should permanently dismiss banner on click', async () => {
const { getByTestId } = renderComponent();
const dismissBannerSpy = vi
.spyOn(useUIStore(), 'dismissBanner')
.spyOn(uiStore, 'dismissBanner')
.mockImplementation(async (banner, mode) => {});

const permanentlyDismissBannerLink = getByTestId('banner-confirm-v1');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import type { EnvironmentVariable } from '@/Interface';
import { fireEvent } from '@testing-library/vue';
import { setupServer } from '@/__tests__/server';
import { afterAll, beforeAll } from 'vitest';
import { useSettingsStore, useUsersStore } from '@/stores';
import { useSettingsStore } from '@/stores/settings.store';
import { useUsersStore } from '@/stores/users.store';
import { createComponentRenderer } from '@/__tests__/render';
import { createTestingPinia } from '@pinia/testing';
import { STORES } from '@/constants';
Expand Down
2 changes: 1 addition & 1 deletion packages/editor-ui/src/components/banners/TrialBanner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import BaseBanner from '@/components/banners/BaseBanner.vue';
import { i18n as locale } from '@/plugins/i18n';
import { useCloudPlanStore } from '@/stores/cloudPlan.store';
import { computed } from 'vue';
import { useUIStore } from '@/stores';
import { useUIStore } from '@/stores/ui.store';
const trialDaysLeft = computed(() => {
const { trialDaysLeft } = useCloudPlanStore();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts" setup>
import BaseBanner from '@/components/banners/BaseBanner.vue';
import { i18n as locale } from '@/plugins/i18n';
import { useUIStore } from '@/stores';
import { useUIStore } from '@/stores/ui.store';
function onUpdatePlanClick() {
void useUIStore().goToUpgrade('canvas-nav', 'upgrade-canvas-nav', 'redirect');
Expand Down
2 changes: 1 addition & 1 deletion packages/editor-ui/src/components/banners/V1Banner.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts" setup>
import BaseBanner from '@/components/banners/BaseBanner.vue';
import { i18n as locale } from '@/plugins/i18n';
import { useUsersStore } from '@/stores';
import { useUsersStore } from '@/stores/users.store';
import { useUIStore } from '@/stores/ui.store';
const uiStore = useUIStore();
Expand Down
6 changes: 1 addition & 5 deletions packages/editor-ui/src/composables/useExternalHooks.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import type { IExternalHooks } from '@/Interface';
import type { IDataObject } from 'n8n-workflow';
import { useWebhooksStore } from '@/stores/webhooks.store';
import { runExternalHook } from '@/utils';

export function useExternalHooks(): IExternalHooks {
return {
async run(eventName: string, metadata?: IDataObject): Promise<void> {
return runExternalHook(eventName, useWebhooksStore(), metadata);
},
run: runExternalHook,
};
}
Loading

0 comments on commit a262c45

Please sign in to comment.