refactor(editor): Fix typescript issues in composables and misc files (no-changelog) (#9583)

This commit is contained in:
Elias Meire 2024-06-03 11:34:51 +02:00 committed by GitHub
parent 7be616e583
commit 6268276746
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 90 additions and 58 deletions

View file

@ -1862,7 +1862,8 @@ export type CloudUpdateLinkSourceType =
| 'workflow-history'
| 'worker-view'
| 'external-secrets'
| 'rbac';
| 'rbac'
| 'debug';
export type UTMCampaign =
| 'upgrade-custom-data-filter'
@ -1883,7 +1884,8 @@ export type UTMCampaign =
| 'upgrade-advanced-permissions'
| 'upgrade-worker-view'
| 'upgrade-external-secrets'
| 'upgrade-rbac';
| 'upgrade-rbac'
| 'upgrade-debug';
export type N8nBanners = {
[key in BannerName]: {

View file

@ -160,6 +160,9 @@ export const defaultSettings: IN8nUISettings = {
ai: {
enabled: false,
provider: '',
features: {
generateCurl: false,
},
},
workflowHistory: {
pruneTime: 0,

View file

@ -1,10 +1,9 @@
import type { Server } from 'miragejs';
import { Response } from 'miragejs';
import type { AppSchema } from '../types';
import { defaultSettings } from '../../defaults';
export function routesForSettings(server: Server) {
server.get('/rest/settings', (schema: AppSchema) => {
server.get('/rest/settings', () => {
return new Response(
200,
{},

View file

@ -17,7 +17,7 @@ export function routesForSourceControl(server: Server) {
keyGeneratorType: 'ed25519',
};
server.get(`${sourceControlApiRoot}/preferences`, (schema: AppSchema, request: Request) => {
server.get(`${sourceControlApiRoot}/preferences`, () => {
return new Response(
200,
{},
@ -27,7 +27,7 @@ export function routesForSourceControl(server: Server) {
);
});
server.post(`${sourceControlApiRoot}/preferences`, (schema: AppSchema, request: Request) => {
server.post(`${sourceControlApiRoot}/preferences`, (_schema: AppSchema, request: Request) => {
const requestBody: Partial<SourceControlPreferences> = jsonParse(request.requestBody);
return new Response(
@ -42,7 +42,7 @@ export function routesForSourceControl(server: Server) {
);
});
server.patch(`${sourceControlApiRoot}/preferences`, (schema: AppSchema, request: Request) => {
server.patch(`${sourceControlApiRoot}/preferences`, (_schema: AppSchema, request: Request) => {
const requestBody: Partial<SourceControlPreferences> = jsonParse(request.requestBody);
return new Response(

View file

@ -17,8 +17,8 @@ export function routesForSSO(server: Server) {
return new Response(200, {}, { data: samlConfig });
});
server.post('/rest/sso/saml/config', (schema: AppSchema, request: Request) => {
const requestBody = jsonParse(request.requestBody);
server.post('/rest/sso/saml/config', (_schema: AppSchema, request: Request) => {
const requestBody = jsonParse<object>(request.requestBody);
samlConfig = {
...samlConfig,

View file

@ -3,8 +3,8 @@ import type { ITag } from '@/Interface';
import { faker } from '@faker-js/faker';
export const tagFactory = Factory.extend<ITag>({
id(i: string) {
return i;
id(i: number) {
return i.toString();
},
name() {
return faker.lorem.word();

View file

@ -3,8 +3,20 @@ import type { IWorkflowDb } from '@/Interface';
import { faker } from '@faker-js/faker';
export const workflowFactory = Factory.extend<IWorkflowDb>({
id(i: string) {
return i;
id(i: number) {
return i.toString();
},
versionId(i: number) {
return i.toString();
},
active() {
return faker.datatype.boolean();
},
nodes() {
return [];
},
connections() {
return {};
},
name() {
return faker.lorem.word();
@ -12,6 +24,9 @@ export const workflowFactory = Factory.extend<IWorkflowDb>({
createdAt() {
return faker.date.recent().toISOString();
},
updatedAt() {
return faker.date.recent().toISOString();
},
tags() {
return faker.lorem.words(2.5).split(' ');
},

View file

@ -35,7 +35,7 @@
active-color="#13ce66"
inactive-color="#8899AA"
data-test-id="workflow-activate-switch"
@update:model-value="onEnabledSwitched($event, destination.id)"
@update:model-value="onEnabledSwitched($event)"
>
</el-switch>
@ -128,17 +128,19 @@ export default defineComponent({
}
},
async onClick(event: Event) {
const cardActions = this.$refs.cardActions as HTMLDivElement | null;
const target = event.target as HTMLDivElement | null;
if (
this.$refs.cardActions === event.target ||
this.$refs.cardActions?.contains(event.target) ||
event.target?.contains(this.$refs.cardActions)
cardActions === target ||
cardActions?.contains(target) ||
target?.contains(cardActions)
) {
return;
}
this.$emit('edit', this.destination.id);
},
onEnabledSwitched(state: boolean, destinationId: string) {
onEnabledSwitched(state: boolean) {
this.nodeParameters.enabled = state;
void this.saveDestination();
},

View file

@ -69,7 +69,7 @@
</template>
<script lang="ts">
import { ElCheckbox as Checkbox } from 'element-plus';
import { ElCheckbox as Checkbox, type CheckboxValueType } from 'element-plus';
import { mapStores } from 'pinia';
import type { BaseTextKey } from '@/plugins/i18n';
import { useLogStreamingStore } from '@/stores/logStreaming.store';
@ -101,12 +101,13 @@ export default {
onInput() {
this.$emit('input');
},
onCheckboxChecked(eventName: string, checked: boolean) {
this.logStreamingStore.setSelectedInGroup(this.destinationId, eventName, checked);
onCheckboxChecked(eventName: string, checked: CheckboxValueType) {
this.logStreamingStore.setSelectedInGroup(this.destinationId, eventName, Boolean(checked));
this.$forceUpdate();
},
anonymizeAuditMessagesChanged(value: boolean) {
this.logStreamingStore.items[this.destinationId].destination.anonymizeAuditMessages = value;
anonymizeAuditMessagesChanged(value: CheckboxValueType) {
this.logStreamingStore.items[this.destinationId].destination.anonymizeAuditMessages =
Boolean(value);
this.$emit('change', { name: 'anonymizeAuditMessages', node: this.destinationId, value });
this.$forceUpdate();
},

View file

@ -431,11 +431,11 @@ export default defineComponent({
: `$('${escapeMappingString(nodeName)}').item.binary`;
const binaryData = [];
let binaryPropertyData = [];
let binaryPropertyData: IVariableSelectorOption[] = [];
for (const dataPropertyName of Object.keys(outputData.binary!)) {
for (const dataPropertyName of Object.keys(outputData.binary ?? {})) {
binaryPropertyData = [];
for (const propertyName in outputData.binary![dataPropertyName]) {
for (const propertyName in outputData.binary?.[dataPropertyName]) {
if (propertyName === 'data') {
continue;
}
@ -448,7 +448,7 @@ export default defineComponent({
binaryPropertyData.push({
name: propertyName,
key: `${binaryPropertyPrefix}.${dataPropertyName}.${propertyName}`,
value: outputData.binary![dataPropertyName][propertyName],
value: outputData.binary?.[dataPropertyName][propertyName]?.toString(),
});
}

View file

@ -144,7 +144,7 @@ function focusFirstInput() {
required
validate-on-blur
:validation-rules="keyValidationRules"
@validate="(value) => onValidate('key', value)"
@validate="(value: boolean) => onValidate('key', value)"
/>
</div>
</td>
@ -161,7 +161,7 @@ function focusFirstInput() {
:placeholder="i18n.baseText('variables.editing.value.placeholder')"
validate-on-blur
:validation-rules="valueValidationRules"
@validate="(value) => onValidate('value', value)"
@validate="(value: boolean) => onValidate('value', value)"
/>
</div>
</td>

View file

@ -228,7 +228,8 @@ export default defineComponent({
setTimeout(() => {
this.scrollToLatestMessage();
this.$refs.inputField?.focus();
const inputField = this.$refs.inputField as HTMLInputElement | null;
inputField?.focus();
}, 0);
},
methods: {
@ -513,10 +514,13 @@ export default defineComponent({
const lastNodeExecuted =
this.workflowsStore.getWorkflowExecution?.data?.resultData.lastNodeExecuted;
const nodeResponseDataArray = get(
this.workflowsStore.getWorkflowExecution?.data?.resultData.runData,
lastNodeExecuted,
) as ITaskData[];
if (!lastNodeExecuted) return;
const nodeResponseDataArray =
get(
this.workflowsStore.getWorkflowExecution?.data?.resultData.runData,
lastNodeExecuted,
) ?? [];
const nodeResponseData = nodeResponseDataArray[nodeResponseDataArray.length - 1];

View file

@ -3,8 +3,8 @@ import { MAIN_HEADER_TABS } from '@/constants';
import { render } from '@testing-library/vue';
import userEvent from '@testing-library/user-event';
import { useHistoryHelper } from '../useHistoryHelper';
import { defineComponent } from 'vue';
import type { Route } from 'vue-router';
import { defineComponent, type PropType } from 'vue';
import type { RouteLocationNormalizedLoaded } from 'vue-router';
const undoMock = vi.fn();
const redoMock = vi.fn();
@ -37,11 +37,12 @@ vi.mock('vue-router', () => ({
const TestComponent = defineComponent({
props: {
route: {
type: Object,
type: Object as PropType<RouteLocationNormalizedLoaded>,
required: true,
},
},
setup(props) {
useHistoryHelper(props.route as Route);
useHistoryHelper(props.route);
return {};
},

View file

@ -58,8 +58,8 @@ describe('useUniqueNodeName', () => {
name: 'S3',
description: '',
version: 1,
inputs: [''],
outputs: [''],
inputs: [],
outputs: [],
group: [''],
properties: [],
defaults: {

View file

@ -8,14 +8,14 @@ import { useUIStore } from '@/stores/ui.store';
import { onMounted, onUnmounted, nextTick } from 'vue';
import { useDeviceSupport } from 'n8n-design-system';
import { getNodeViewTab } from '@/utils/canvasUtils';
import type { Route } from 'vue-router';
import type { RouteLocationNormalizedLoaded } from 'vue-router';
import { useTelemetry } from './useTelemetry';
import { useDebounce } from '@/composables/useDebounce';
const UNDO_REDO_DEBOUNCE_INTERVAL = 100;
const ELEMENT_UI_OVERLAY_SELECTOR = '.el-overlay';
export function useHistoryHelper(activeRoute: Route) {
export function useHistoryHelper(activeRoute: RouteLocationNormalizedLoaded) {
const telemetry = useTelemetry();
const ndvStore = useNDVStore();

View file

@ -77,10 +77,14 @@ export function useNodeHelpers() {
if (!isObject(parameters)) return false;
const { resource, operation } = parameters;
if (!isString(resource) || !isString(operation)) return false;
if ('resource' in parameters && 'operation' in parameters) {
const { resource, operation } = parameters;
if (!isString(resource) || !isString(operation)) return false;
return resource.includes(CUSTOM_API_CALL_KEY) || operation.includes(CUSTOM_API_CALL_KEY);
return resource.includes(CUSTOM_API_CALL_KEY) || operation.includes(CUSTOM_API_CALL_KEY);
}
return false;
}
function getParameterValue(nodeValues: INodeParameters, parameterName: string, path: string) {
@ -520,7 +524,7 @@ export function useNodeHelpers() {
workflowsStore.setNodeIssue({
node: node.name,
type: 'credentials',
value: issues === null ? null : issues.credentials,
value: issues?.credentials ?? null,
});
}
}
@ -712,12 +716,12 @@ export function useNodeHelpers() {
const allNodeConnections = workflowsStore.outgoingConnectionsByNodeName(sourceNode.name);
const connectionType = Object.keys(allNodeConnections)[0];
const connectionType = Object.keys(allNodeConnections)[0] as NodeConnectionType;
const nodeConnections = allNodeConnections[connectionType];
const outputMap = NodeViewUtils.getOutputSummary(
data,
nodeConnections || [],
(connectionType as ConnectionTypes) ?? NodeConnectionType.Main,
connectionType ?? NodeConnectionType.Main,
);
const sourceNodeType = nodeTypesStore.getNodeType(sourceNode.type, sourceNode.typeVersion);
@ -732,7 +736,7 @@ export function useNodeHelpers() {
parseInt(sourceOutputIndex, 10),
targetNode,
parseInt(targetInputIndex, 10),
connectionType as ConnectionTypes,
connectionType,
sourceNodeType,
canvasStore.jsPlumbInstance,
);

View file

@ -8,6 +8,7 @@ import { useUIStore } from '@/stores/ui.store';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { useRouter } from 'vue-router';
import { ExpressionError, type IPinData, type IRunData, type Workflow } from 'n8n-workflow';
import type * as router from 'vue-router';
vi.mock('@/stores/n8nRoot.store', () => ({
useRootStore: vi.fn().mockReturnValue({ pushConnectionActive: true }),
@ -77,7 +78,7 @@ vi.mock('@/composables/useTitleChange', () => ({
}));
vi.mock('vue-router', async (importOriginal) => {
const { RouterLink } = await importOriginal();
const { RouterLink } = await importOriginal<typeof router>();
return {
RouterLink,
useRouter: vi.fn().mockReturnValue({

View file

@ -1,6 +1,6 @@
import type { AxiosRequestConfig, Method, RawAxiosRequestHeaders } from 'axios';
import axios from 'axios';
import type { IDataObject } from 'n8n-workflow';
import type { GenericValue, IDataObject } from 'n8n-workflow';
import type { IExecutionFlattedResponse, IExecutionResponse, IRestApiContext } from '@/Interface';
import { parse } from 'flatted';
@ -56,7 +56,7 @@ const legacyParamSerializer = (params: Record<string, any>) =>
.filter((key) => params[key] !== undefined)
.map((key) => {
if (Array.isArray(params[key])) {
return params[key].map((v) => `${key}[]=${encodeURIComponent(v)}`).join('&');
return params[key].map((v: string) => `${key}[]=${encodeURIComponent(v)}`).join('&');
}
if (typeof params[key] === 'object') {
params[key] = JSON.stringify(params[key]);
@ -70,7 +70,7 @@ export async function request(config: {
baseURL: string;
endpoint: string;
headers?: RawAxiosRequestHeaders;
data?: IDataObject | IDataObject[];
data?: GenericValue | GenericValue[];
withCredentials?: boolean;
}) {
const { method, baseURL, endpoint, headers, data } = config;
@ -129,7 +129,7 @@ export async function makeRestApiRequest<T>(
context: IRestApiContext,
method: Method,
endpoint: string,
data?: IDataObject | IDataObject[],
data?: GenericValue | GenericValue[],
) {
const response = await request({
method,
@ -165,7 +165,7 @@ export async function patch(
baseURL: string,
endpoint: string,
params?: IDataObject,
headers?: IDataObject,
headers?: RawAxiosRequestHeaders,
) {
return await request({ method: 'PATCH', baseURL, endpoint, headers, data: params });
}
@ -177,9 +177,9 @@ export async function patch(
*/
export function unflattenExecutionData(
fullExecutionData: IExecutionFlattedResponse,
): IExecutionResponse {
): Omit<IExecutionResponse, 'status'> {
// Unflatten the data
const returnData: IExecutionResponse = {
const returnData: Omit<IExecutionResponse, 'status'> = {
...fullExecutionData,
workflowData: fullExecutionData.workflowData,
data: parse(fullExecutionData.data),

View file

@ -324,7 +324,7 @@ const WorkflowsView = defineComponent({
this.workflowsStore.fetchActiveWorkflows(),
]);
},
onClickTag(tagId: string, event: PointerEvent) {
onClickTag(tagId: string) {
if (!this.filters.tags.includes(tagId)) {
this.filters.tags.push(tagId);
}