Add more fixes

This commit is contained in:
Charlie Kolb 2024-11-29 13:03:39 +01:00
parent a8f21fd671
commit 005aac7df1
No known key found for this signature in database
12 changed files with 48 additions and 48 deletions

View file

@ -261,12 +261,12 @@ const mapCookies = (cookies: CurlJson['cookies']): { cookie: string } | {} => {
}; };
export const flattenObject = (obj: { [x: string]: any }, prefix = '') => export const flattenObject = (obj: { [x: string]: any }, prefix = '') =>
Object.keys(obj).reduce((acc, k) => { Object.keys(obj).reduce<Record<string, unknown>>((acc, k) => {
const pre = prefix.length ? prefix + '.' : ''; const pre = prefix.length ? prefix + '.' : '';
// @Problem: `typeof null` is `object`, which creates a bug here
if (typeof obj[k] === 'object')
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); Object.assign(acc, flattenObject(obj[k], pre + k));
//@ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
else acc[pre + k] = obj[k]; else acc[pre + k] = obj[k];
return acc; return acc;
}, {}); }, {});
@ -465,12 +465,14 @@ export class CurlService {
} }
if (!Object.keys(httpNodeParameters.options?.redirect.redirect).length) { if (!Object.keys(httpNodeParameters.options?.redirect.redirect).length) {
// @ts-ignore // @Cleanup: Type `options.redirect` as optional and fix type errors
// @ts-expect-error Options is typed as non-optional
delete httpNodeParameters.options.redirect; delete httpNodeParameters.options.redirect;
} }
if (!Object.keys(httpNodeParameters.options.response.response).length) { if (!Object.keys(httpNodeParameters.options.response.response).length) {
// @ts-ignore // @Cleanup: Type `options.response` as optional and fix type errors
// @ts-expect-error Options is typed as non-optional
delete httpNodeParameters.options.response; delete httpNodeParameters.options.response;
} }

View file

@ -21,8 +21,8 @@ describe('bodyParser', () => {
const response = await request(server) const response = await request(server)
.post('/') .post('/')
.set('content-encoding', 'gzip') .set('content-encoding', 'gzip')
// @ts-ignore // Mock for testing
.serialize((d) => gzipSync(JSON.stringify(d))) .serialize((d) => gzipSync(JSON.stringify(d)) as unknown as string)
.send({ hello: 'world' }) .send({ hello: 'world' })
.expect(200); .expect(200);
expect(response.text).toEqual('{"hello":"world"}'); expect(response.text).toEqual('{"hello":"world"}');
@ -32,8 +32,8 @@ describe('bodyParser', () => {
const response = await request(server) const response = await request(server)
.post('/') .post('/')
.set('content-encoding', 'deflate') .set('content-encoding', 'deflate')
// @ts-ignore // Mock for testing
.serialize((d) => deflateSync(JSON.stringify(d))) .serialize((d) => deflateSync(JSON.stringify(d)) as unknown as string)
.send({ hello: 'world' }) .send({ hello: 'world' })
.expect(200); .expect(200);
expect(response.text).toEqual('{"hello":"world"}'); expect(response.text).toEqual('{"hello":"world"}');

View file

@ -1,3 +1,4 @@
import type { ICredentialDataDecryptedObject } from 'n8n-workflow';
import { Container } from 'typedi'; import { Container } from 'typedi';
import { CredentialsEntity } from '@/databases/entities/credentials-entity'; import { CredentialsEntity } from '@/databases/entities/credentials-entity';
@ -17,8 +18,8 @@ export async function encryptCredentialData(
const { createCredentialsFromCredentialsEntity } = await import('@/credentials-helper'); const { createCredentialsFromCredentialsEntity } = await import('@/credentials-helper');
const coreCredential = createCredentialsFromCredentialsEntity(credential, true); const coreCredential = createCredentialsFromCredentialsEntity(credential, true);
// @ts-ignore // data column is actually an object despite the type
coreCredential.setData(credential.data); coreCredential.setData(credential.data as unknown as ICredentialDataDecryptedObject);
return Object.assign(credential, coreCredential.getDataToSave()); return Object.assign(credential, coreCredential.getDataToSave());
} }

View file

@ -1504,17 +1504,11 @@ export class WorkflowExecute {
lineResult.json.$error !== undefined && lineResult.json.$error !== undefined &&
lineResult.json.$json !== undefined lineResult.json.$json !== undefined
) { ) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
lineResult.error = lineResult.json.$error as NodeApiError | NodeOperationError; lineResult.error = lineResult.json.$error as NodeApiError | NodeOperationError;
lineResult.json = { lineResult.json = {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
error: (lineResult.json.$error as NodeApiError | NodeOperationError).message, error: (lineResult.json.$error as NodeApiError | NodeOperationError).message,
}; };
} else if (lineResult.error !== undefined) { } else if (lineResult.error !== undefined) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
lineResult.json = { error: lineResult.error.message }; lineResult.json = { error: lineResult.error.message };
} }
} }

View file

@ -9,7 +9,6 @@ import { ref, onMounted } from 'vue';
import { useUsersStore } from '@/stores/users.store'; import { useUsersStore } from '@/stores/users.store';
import { mfaEventBus } from '@/event-bus'; import { mfaEventBus } from '@/event-bus';
import { useToast } from '@/composables/useToast'; import { useToast } from '@/composables/useToast';
//@ts-ignore
import QrcodeVue from 'qrcode.vue'; import QrcodeVue from 'qrcode.vue';
import { useClipboard } from '@/composables/useClipboard'; import { useClipboard } from '@/composables/useClipboard';
import { useI18n } from '@/composables/useI18n'; import { useI18n } from '@/composables/useI18n';

View file

@ -403,7 +403,8 @@ const valueChanged = (parameterData: IUpdateInformation) => {
if (parameterData.value && typeof parameterData.value === 'object') { if (parameterData.value && typeof parameterData.value === 'object') {
for (const parameterName of Object.keys(parameterData.value)) { for (const parameterName of Object.keys(parameterData.value)) {
//@ts-ignore // @Cleanup: Instead use `Object.entries()` to get both key and value
// @ts-expect-error this breaks the connection of keys and values
newValue = parameterData.value[parameterName]; newValue = parameterData.value[parameterName];
// Remove the 'parameters.' from the beginning to just have the // Remove the 'parameters.' from the beginning to just have the
@ -415,7 +416,8 @@ const valueChanged = (parameterData: IUpdateInformation) => {
const parameterPathArray = parameterPath.match(/(.*)\[(\d+)\]$/); const parameterPathArray = parameterPath.match(/(.*)\[(\d+)\]$/);
// Apply the new value // Apply the new value
//@ts-ignore // @Problem: `parameterData[parameterName]` makes little sense to me, please investigate if this should be `parameterData.value[parameterName]`? But that doesn't really make sense either.
// @ts-expect-error This seems like a bug?
if (parameterData[parameterName] === undefined && parameterPathArray !== null) { if (parameterData[parameterName] === undefined && parameterPathArray !== null) {
// Delete array item // Delete array item
const path = parameterPathArray[1]; const path = parameterPathArray[1];

View file

@ -70,9 +70,8 @@ const vModel = reactive(
return filter[key]; return filter[key];
}, },
set(value) { set(value) {
// TODO: find out what exactly is typechecker complaining about // @Cleanup: Type the `computed<>()` call correctly or swap reduce for an easier to type solution
// @ts-expect-error We lose type info on value because we set this up in a reduce loop
// @ts-ignore
filter[key] = value; filter[key] = value;
emit('filterChanged', filter); emit('filterChanged', filter);
}, },

View file

@ -11,13 +11,14 @@ import type { PermissionsRecord } from '@/permissions';
type Command = 'retrySaved' | 'retryOriginal' | 'delete'; type Command = 'retrySaved' | 'retryOriginal' | 'delete';
const emit = defineEmits<{ const emit = defineEmits<
{
stop: [data: ExecutionSummary]; stop: [data: ExecutionSummary];
select: [data: ExecutionSummary]; select: [data: ExecutionSummary];
retrySaved: [data: ExecutionSummary]; } & {
retryOriginal: [data: ExecutionSummary]; [c in Command]: [data: ExecutionSummary];
delete: [data: ExecutionSummary]; }
}>(); >();
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@ -160,8 +161,9 @@ function onSelect() {
} }
async function handleActionItemClick(commandData: Command) { async function handleActionItemClick(commandData: Command) {
//@ts-ignore todo: fix this type // The `emit` function is not typed very well and does not take type unions of the single event types
emit(commandData, props.execution); // Se we need to hide the type
emit(commandData as never, props.execution);
} }
</script> </script>
<template> <template>

View file

@ -4,7 +4,10 @@ import { render } from '@testing-library/vue';
import userEvent from '@testing-library/user-event'; import userEvent from '@testing-library/user-event';
import { useHistoryHelper } from './useHistoryHelper'; import { useHistoryHelper } from './useHistoryHelper';
import { defineComponent, type PropType } from 'vue'; import { defineComponent, type PropType } from 'vue';
import type { RouteLocationNormalizedLoaded } from 'vue-router'; import type {
RouteLocationNormalizedLoaded,
RouteLocationNormalizedLoadedGeneric,
} from 'vue-router';
import { mock } from 'vitest-mock-extended'; import { mock } from 'vitest-mock-extended';
const undoMock = vi.fn(); const undoMock = vi.fn();
@ -56,7 +59,6 @@ describe('useHistoryHelper', () => {
redoMock.mockClear(); redoMock.mockClear();
}); });
it('should call undo when Ctrl+Z is pressed', async () => { it('should call undo when Ctrl+Z is pressed', async () => {
// @ts-ignore
render(TestComponent, { render(TestComponent, {
props: { props: {
route: mock<RouteLocationNormalizedLoaded>({ route: mock<RouteLocationNormalizedLoaded>({
@ -74,7 +76,6 @@ describe('useHistoryHelper', () => {
expect(undoMock).toHaveBeenCalledTimes(2); expect(undoMock).toHaveBeenCalledTimes(2);
}); });
it('should call redo when Ctrl+Shift+Z is pressed', async () => { it('should call redo when Ctrl+Shift+Z is pressed', async () => {
// @ts-ignore
render(TestComponent, { render(TestComponent, {
props: { props: {
route: mock<RouteLocationNormalizedLoaded>({ route: mock<RouteLocationNormalizedLoaded>({
@ -92,8 +93,7 @@ describe('useHistoryHelper', () => {
expect(redoMock).toHaveBeenCalledTimes(2); expect(redoMock).toHaveBeenCalledTimes(2);
}); });
it('should not call undo when Ctrl+Z if not on NodeView', async () => { it('should not call undo when Ctrl+Z if not on NodeView', async () => {
// @ts-ignore render(TestComponent, { props: { route: {} as RouteLocationNormalizedLoadedGeneric } });
render(TestComponent, { props: { route: {} } });
await userEvent.keyboard('{Control>}z'); await userEvent.keyboard('{Control>}z');
await userEvent.keyboard('{Control>}z'); await userEvent.keyboard('{Control>}z');

View file

@ -518,7 +518,6 @@ export function useWorkflowHelpers(options: { router: ReturnType<typeof useRoute
const nodes: INode[] = []; const nodes: INode[] = [];
for (let nodeIndex = 0; nodeIndex < workflowNodes.length; nodeIndex++) { for (let nodeIndex = 0; nodeIndex < workflowNodes.length; nodeIndex++) {
// @ts-ignore
nodeData = getNodeDataToSave(workflowNodes[nodeIndex]); nodeData = getNodeDataToSave(workflowNodes[nodeIndex]);
nodes.push(nodeData); nodes.push(nodeData);
@ -555,16 +554,17 @@ export function useWorkflowHelpers(options: { router: ReturnType<typeof useRoute
'notes', 'notes',
'parameters', 'parameters',
'status', 'status',
]; ] as const;
// @ts-ignore // @Cleanup: Unify the following lines in a type-safe way, probably with Object.assign() and a filter
const nodeData: INodeUi = { // Cast to INodeUi as we're about to provide all required keys
const nodeData = {
parameters: {}, parameters: {},
}; } as INodeUi;
for (const key in node) { for (const key in node) {
if (key.charAt(0) !== '_' && skipKeys.indexOf(key) === -1) { if (key.charAt(0) !== '_' && skipKeys.indexOf(key as never) === -1) {
// @ts-ignore // @ts-expect-error We can't narrow the type to the same key, should Object.assign instead
nodeData[key] = node[key]; nodeData[key] = node[key];
} }
} }

View file

@ -142,7 +142,8 @@ export const usePushConnectionStore = defineStore(STORES.PUSH, () => {
async function pushMessageReceived(event: Event) { async function pushMessageReceived(event: Event) {
let receivedData: PushMessage; let receivedData: PushMessage;
try { try {
// @ts-ignore // @Cleanup: Check for data explicitly and log telemetry on missing field if appropriate
// @ts-expect-error We're okay to error on missing data attribute here
receivedData = JSON.parse(event.data); receivedData = JSON.parse(event.data);
} catch (error) { } catch (error) {
return; return;

View file

@ -366,7 +366,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
undefined, undefined,
}; };
}, },
} as unknown as INodeTypes; };
return nodeTypes; return nodeTypes;
} }