perf: Make frontend linting faster (no-changelog) (#7717)

Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
Csaba Tuncsik 2023-11-22 15:01:22 +01:00 committed by GitHub
parent e01617ad64
commit 50f568560f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 430 additions and 492 deletions

View file

@ -36,12 +36,16 @@ module.exports = {
'vue/v-slot-style': 'error', 'vue/v-slot-style': 'error',
'vue/no-unused-components': 'error', 'vue/no-unused-components': 'error',
'vue/multi-word-component-names': 'off', 'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-explicit-any': 'error',
// TODO: fix these // TODO: fix these
'@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off', '@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/restrict-template-expressions': 'off', '@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/unbound-method': 'off', '@typescript-eslint/unbound-method': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
// TODO: remove these // TODO: remove these
'vue/no-mutating-props': 'warn', 'vue/no-mutating-props': 'warn',

View file

@ -3,21 +3,21 @@
"private": true, "private": true,
"version": "0.0.1", "version": "0.0.1",
"devDependencies": { "devDependencies": {
"@types/eslint": "^8.44.1", "@types/eslint": "8.44.7",
"@typescript-eslint/eslint-plugin": "^6.2.0", "@typescript-eslint/eslint-plugin": "6.2.0",
"@typescript-eslint/parser": "^6.2.0", "@typescript-eslint/parser": "6.2.0",
"@vue/eslint-config-typescript": "^11.0.3", "@vue/eslint-config-typescript": "12.0.0",
"eslint": "^8.45.0", "eslint": "8.54.0",
"eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-airbnb-typescript": "17.1.0",
"eslint-config-prettier": "^8.9.0", "eslint-config-prettier": "9.0.0",
"eslint-import-resolver-typescript": "^3.5.5", "eslint-import-resolver-typescript": "3.5.5",
"eslint-plugin-import": "^2.28.0", "eslint-plugin-import": "2.28.0",
"eslint-plugin-n8n-local-rules": "^1.0.0", "eslint-plugin-n8n-local-rules": "1.0.0",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "5.0.1",
"eslint-plugin-unicorn": "^48.0.1", "eslint-plugin-unicorn": "49.0.0",
"eslint-plugin-unused-imports": "^3.0.0", "eslint-plugin-unused-imports": "3.0.0",
"eslint-plugin-vue": "^9.15.1", "eslint-plugin-vue": "9.18.1",
"vue-eslint-parser": "^9.3.1" "vue-eslint-parser": "9.3.2"
}, },
"scripts": { "scripts": {
"clean": "rimraf .turbo", "clean": "rimraf .turbo",

View file

@ -30,11 +30,6 @@ module.exports = {
'@typescript-eslint/no-this-alias': 'warn', '@typescript-eslint/no-this-alias': 'warn',
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn', '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn',
'@typescript-eslint/no-unnecessary-type-assertion': 'warn', '@typescript-eslint/no-unnecessary-type-assertion': 'warn',
'@typescript-eslint/no-unsafe-argument': 'warn',
'@typescript-eslint/no-unsafe-assignment': 'warn',
'@typescript-eslint/no-unsafe-call': 'warn',
'@typescript-eslint/no-unsafe-member-access': 'warn',
'@typescript-eslint/no-unsafe-return': 'warn',
'@typescript-eslint/no-unused-expressions': 'warn', '@typescript-eslint/no-unused-expressions': 'warn',
'@typescript-eslint/no-unused-vars': 'warn', '@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/no-use-before-define': 'warn', '@typescript-eslint/no-use-before-define': 'warn',
@ -42,12 +37,9 @@ module.exports = {
'@typescript-eslint/prefer-nullish-coalescing': 'warn', '@typescript-eslint/prefer-nullish-coalescing': 'warn',
'@typescript-eslint/prefer-optional-chain': 'warn', '@typescript-eslint/prefer-optional-chain': 'warn',
'@typescript-eslint/restrict-plus-operands': 'warn', '@typescript-eslint/restrict-plus-operands': 'warn',
'@typescript-eslint/restrict-template-expressions': 'warn',
'@typescript-eslint/unbound-method': 'warn',
'@typescript-eslint/ban-ts-comment': ['warn', { 'ts-ignore': true }], '@typescript-eslint/ban-ts-comment': ['warn', { 'ts-ignore': true }],
'@typescript-eslint/no-redundant-type-constituents': 'warn', '@typescript-eslint/no-redundant-type-constituents': 'warn',
'@typescript-eslint/no-base-to-string': 'warn', '@typescript-eslint/no-base-to-string': 'warn',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unsafe-enum-comparison': 'warn', '@typescript-eslint/no-unsafe-enum-comparison': 'warn',
}, },
}; };

View file

@ -1,7 +1,10 @@
import type { ISettingsState } from '@/Interface'; import type { ISettingsState } from '@/Interface';
import { UserManagementAuthenticationMethod } from '@/Interface'; import { UserManagementAuthenticationMethod } from '@/Interface';
export const retry = async (assertion: () => any, { interval = 20, timeout = 1000 } = {}) => { export const retry = async (
assertion: () => ReturnType<typeof expect>,
{ interval = 20, timeout = 1000 } = {},
) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const startTime = Date.now(); const startTime = Date.now();

View file

@ -70,7 +70,7 @@ export default defineComponent({
return 'SM'; return 'SM';
}, },
value(): any | undefined { value(): number | undefined {
if (this.valueXS !== undefined && this.width < BREAKPOINT_SM) { if (this.valueXS !== undefined && this.width < BREAKPOINT_SM) {
return this.valueXS; return this.valueXS;
} }

View file

@ -686,7 +686,7 @@ export default defineComponent({
this.hasUnsavedChanges = true; this.hasUnsavedChanges = true;
}, },
onDataChange({ name, value }: { name: string; value: any }) { onDataChange({ name, value }: { name: string; value: CredentialInformation }) {
// skip update if new value matches the current // skip update if new value matches the current
if (this.credentialData[name] === value) return; if (this.credentialData[name] === value) return;

View file

@ -147,7 +147,11 @@ export default defineComponent({
}, },
itemSelected(eventData: IVariableItemSelected) { itemSelected(eventData: IVariableItemSelected) {
(this.$refs.inputFieldExpression as any).itemSelected(eventData); (
this.$refs.inputFieldExpression as {
itemSelected: (variable: IVariableItemSelected) => void;
}
).itemSelected(eventData);
void this.$externalHooks().run('expressionEdit.itemSelected', { void this.$externalHooks().run('expressionEdit.itemSelected', {
parameter: this.parameter, parameter: this.parameter,
value: this.modelValue, value: this.modelValue,
@ -224,8 +228,11 @@ export default defineComponent({
this.latestValue = this.modelValue; this.latestValue = this.modelValue;
const resolvedExpressionValue = const resolvedExpressionValue =
(this.$refs.expressionResult && (this.$refs.expressionResult as any).getValue()) || (
undefined; this.$refs.expressionResult as {
getValue: () => string;
}
)?.getValue() || '';
void this.$externalHooks().run('expressionEdit.dialogVisibleChanged', { void this.$externalHooks().run('expressionEdit.dialogVisibleChanged', {
dialogVisible: newValue, dialogVisible: newValue,
parameter: this.parameter, parameter: this.parameter,

View file

@ -78,7 +78,7 @@ export default defineComponent({
segment.kind === 'plaintext' segment.kind === 'plaintext'
? segment.plaintext.length ? segment.plaintext.length
: segment.resolved : segment.resolved
? (segment.resolved as any).toString().length ? segment.resolved.toString().length
: 0; : 0;
segment.to = cursor; segment.to = cursor;

View file

@ -119,7 +119,7 @@ export default defineComponent({
segment.kind === 'plaintext' segment.kind === 'plaintext'
? segment.plaintext.length ? segment.plaintext.length
: segment.resolved : segment.resolved
? (segment.resolved as any).toString().length ? segment.resolved.toString().length
: 0; : 0;
segment.to = cursor; segment.to = cursor;
return segment; return segment;

View file

@ -114,7 +114,7 @@ const draggableStyle = computed<{ top: string; left: string }>(() => ({
const isCommunityNode = computed<boolean>(() => isCommunityPackageName(props.nodeType.name)); const isCommunityNode = computed<boolean>(() => isCommunityPackageName(props.nodeType.name));
const displayName = computed<any>(() => { const displayName = computed<string>(() => {
const displayName = props.nodeType.displayName.trimEnd(); const displayName = props.nodeType.displayName.trimEnd();
return i18n.headerText({ return i18n.headerText({

View file

@ -346,10 +346,13 @@ export default defineComponent({
let options: CredentialDropdownOption[] = []; let options: CredentialDropdownOption[] = [];
types.forEach((type) => { types.forEach((type) => {
options = options.concat( options = options.concat(
this.credentialsStore.allUsableCredentialsByType[type].map((option: any) => ({ this.credentialsStore.allUsableCredentialsByType[type].map(
...option, (option: ICredentialsResponse) =>
typeDisplayName: this.credentialsStore.getCredentialTypeByName(type)?.displayName, ({
})), ...option,
typeDisplayName: this.credentialsStore.getCredentialTypeByName(type)?.displayName,
}) as CredentialDropdownOption,
),
); );
}); });
return options; return options;

View file

@ -399,7 +399,7 @@ export default defineComponent({
try { try {
parameters = JSON.parse(parameters) as { parameters = JSON.parse(parameters) as {
[key: string]: any; [key: string]: unknown;
}; };
//@ts-ignore //@ts-ignore

View file

@ -421,6 +421,8 @@ import { useI18n } from '@/composables';
import type { N8nInput } from 'n8n-design-system'; import type { N8nInput } from 'n8n-design-system';
import { isCredentialOnlyNodeType } from '@/utils/credentialOnlyNodes'; import { isCredentialOnlyNodeType } from '@/utils/credentialOnlyNodes';
type Picker = { $emit: (arg0: string, arg1: Date) => void };
export default defineComponent({ export default defineComponent({
name: 'parameter-input', name: 'parameter-input',
mixins: [externalHooks, nodeHelpers, workflowHelpers, debounceHelper], mixins: [externalHooks, nodeHelpers, workflowHelpers, debounceHelper],
@ -525,14 +527,14 @@ export default defineComponent({
{ {
text: 'Today', // TODO text: 'Today', // TODO
onClick(picker: any) { onClick(picker: Picker) {
picker.$emit('pick', new Date()); picker.$emit('pick', new Date());
}, },
}, },
{ {
text: 'Yesterday', // TODO text: 'Yesterday', // TODO
onClick(picker: any) { onClick(picker: Picker) {
const date = new Date(); const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24); date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', date); picker.$emit('pick', date);
@ -541,7 +543,7 @@ export default defineComponent({
{ {
text: 'A week ago', // TODO text: 'A week ago', // TODO
onClick(picker: any) { onClick(picker: Picker) {
const date = new Date(); const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', date); picker.$emit('pick', date);

View file

@ -4,25 +4,27 @@ import { defineComponent } from 'vue';
export const debounceHelper = defineComponent({ export const debounceHelper = defineComponent({
data() { data() {
return { return {
debouncedFunctions: [] as any[], debouncedFunctions: {} as Record<string, (...args: unknown[]) => Promise<void> | void>,
}; };
}, },
methods: { methods: {
async callDebounced(...inputParameters: any[]): Promise<void> { async callDebounced(
const functionName = inputParameters.shift() as string; functionName: string,
const { trailing, debounceTime } = inputParameters.shift(); options: { debounceTime: number; trailing?: boolean },
...inputParameters: unknown[]
// @ts-ignore ): Promise<void> {
const { trailing, debounceTime } = options;
if (this.debouncedFunctions[functionName] === undefined) { if (this.debouncedFunctions[functionName] === undefined) {
// @ts-ignore
this.debouncedFunctions[functionName] = debounce( this.debouncedFunctions[functionName] = debounce(
this[functionName], async (...args: unknown[]) => {
// @ts-ignore
await this[functionName](...args);
},
debounceTime, debounceTime,
trailing ? { trailing } : { leading: true }, trailing ? { trailing } : { leading: true },
); );
} }
// @ts-ignore await this.debouncedFunctions[functionName](...inputParameters);
await this.debouncedFunctions[functionName].apply(this, inputParameters);
}, },
}, },
}); });

View file

@ -13,7 +13,7 @@ export const genericHelpers = defineComponent({
}, },
data() { data() {
return { return {
loadingService: null as any | null, loadingService: null as null | { close: () => void; text: string },
}; };
}, },
computed: { computed: {
@ -75,7 +75,9 @@ export const genericHelpers = defineComponent({
}); });
}, },
setLoadingText(text: string) { setLoadingText(text: string) {
this.loadingService.text = text; if (this.loadingService !== null) {
this.loadingService.text = text;
}
}, },
stopLoading() { stopLoading() {
if (this.loadingService !== null) { if (this.loadingService !== null) {

View file

@ -37,17 +37,18 @@ export const useExternalSecretsStore = defineStore('externalSecrets', () => {
secretAcc[secret] = '*********'; secretAcc[secret] = '*********';
return secretAcc; return secretAcc;
} }
const obj = (secretAcc[splitSecret[0]] ?? {}) as object; const obj = secretAcc[splitSecret[0]] ?? {};
let acc: any = obj; let acc = obj;
for (let i = 1; i < splitSecret.length; i++) { for (let i = 1; i < splitSecret.length; i++) {
const key = splitSecret[i]; const key = splitSecret[i] as keyof typeof acc;
// Actual value key // Actual value key
if (i === splitSecret.length - 1) { if (i === splitSecret.length - 1) {
acc[key] = '*********'; const key = splitSecret[i] as keyof typeof acc;
acc[key] = '*********' as (typeof acc)[typeof key];
continue; continue;
} }
if (!(key in acc)) { if (Object.keys(acc) && !acc[key]) {
acc[key] = {}; acc[key] = {} as (typeof acc)[typeof key];
} }
acc = acc[key]; acc = acc[key];
} }

View file

@ -750,16 +750,14 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
} }
// Check if the same connection exists already // Check if the same connection exists already
const checkProperties = ['index', 'node', 'type']; const checkProperties = ['index', 'node', 'type'] as Array<keyof IConnection>;
let propertyName: string; let propertyName: keyof IConnection;
let connectionExists = false; let connectionExists = false;
connectionLoop: for (const existingConnection of this.workflow.connections[sourceData.node][ connectionLoop: for (const existingConnection of this.workflow.connections[sourceData.node][
sourceData.type sourceData.type
][sourceData.index]) { ][sourceData.index]) {
for (propertyName of checkProperties) { for (propertyName of checkProperties) {
if ( if (existingConnection[propertyName] !== destinationData[propertyName]) {
(existingConnection as any)[propertyName] !== (destinationData as any)[propertyName]
) {
continue connectionLoop; continue connectionLoop;
} }
} }

View file

@ -102,7 +102,7 @@ export async function makeRestApiRequest<T>(
context: IRestApiContext, context: IRestApiContext,
method: Method, method: Method,
endpoint: string, endpoint: string,
data?: any, data?: IDataObject,
) { ) {
const response = await request({ const response = await request({
method, method,

View file

@ -203,10 +203,11 @@ function getValue<T extends object>(obj: T, prop: string): unknown {
const segments = prop.split('.'); const segments = prop.split('.');
let result: any = obj; let result = obj;
let i = 0; let i = 0;
while (result && i < segments.length) { while (result && i < segments.length) {
result = result[segments[i]]; const key = segments[i] as keyof T;
result = result[key] as T;
i++; i++;
} }
return result; return result;

View file

@ -305,6 +305,7 @@ import type {
INodeUpdatePropertiesInformation, INodeUpdatePropertiesInformation,
NodeCreatorOpenSource, NodeCreatorOpenSource,
AddedNodesAndConnections, AddedNodesAndConnections,
ToggleNodeCreatorOptions,
} from '@/Interface'; } from '@/Interface';
import { debounceHelper } from '@/mixins/debounce'; import { debounceHelper } from '@/mixins/debounce';

View file

@ -682,7 +682,7 @@ export default defineComponent({
this.showError(error, this.$locale.baseText('settings.ldap.configurationError')); this.showError(error, this.$locale.baseText('settings.ldap.configurationError'));
} }
}, },
async getLdapSynchronizations(state: any) { async getLdapSynchronizations(state: { loaded: () => void; complete: () => void }) {
try { try {
this.loadingTable = true; this.loadingTable = true;
const data = await this.settingsStore.getLdapSynchronizations({ const data = await this.settingsStore.getLdapSynchronizations({

File diff suppressed because it is too large Load diff