Repository: n8n-io/n8n
File: packages/frontend/editor-ui/src/features/integrations/quickConnect/composables/useQuickConnect.ts (TypeScript)

Code before:
import { QUICK_CONNECT_EXPERIMENT } from '@/app/constants';
import { usePostHog } from '@/app/stores/posthog.store';
import { useSettingsStore } from '@/app/stores/settings.store';
import { computed, type Ref, toRef } from 'vue';

type UseQuickConnectParams =
	| {
			packageName: string | Ref<string | undefined>;
			credentialType?: never;
			credentialTypes?: never;
	  }
	| {
			packageName?: never;
			credentialType: string | Ref<string | undefined>;
			credentialTypes?: never;
	  }
	| {
			packageName?: never;
			credentialType?: never;
			credentialTypes: string[] | Ref<string[] | undefined>;
	  };

export function useQuickConnect({
	credentialType,
	credentialTypes,
	packageName,
}: UseQuickConnectParams) {
	const settingsStore = useSettingsStore();
	const posthogStore = usePostHog();
	const quickConnectEnabled = posthogStore.isVariantEnabled(
		QUICK_CONNECT_EXPERIMENT.name,
		QUICK_CONNECT_EXPERIMENT.variant,
	);

	return computed(() => {
		if (quickConnectEnabled && settingsStore.moduleSettings['quick-connect']?.options.length) {
			const options = settingsStore.moduleSettings['quick-connect']?.options;

			if (credentialType) {
				return options.find((option) => option.credentialType === toRef(credentialType).value);
			}

			if (credentialTypes) {
				const types = toRef(credentialTypes).value ?? [];
				return options.find((option) => types.includes(option.credentialType));

Review comment (security):
Instead of adding a new parameter we can use `credentialType` and say that you could either pass a single string or an array of credential types. Or we could also define that it must always be an array to have less conditions inside `useQuickConnect` (then `credentialTypes` would be a better name than `credentialType`). What do you think?

PS: coming from React considering reactive values adds quite an overhead in my brain. With a single value for credential type my intention of the hook was that it can work with
1. static values (for example credential type was passed from parent component and is already "final" when `useQuickConnect()` is called), like `useQuickConnect({ credentialType: "ok" })`
2. reactive values (for example where credential type is loaded inside component and therefore can also be undefined), similar [to node info view](https://github.com/n8n-io/n8n/blob/master/packages/frontend/editor-ui/src/features/settings/communityNodes/components/nodeCreator/CommunityNodeInfo.vue#L29)

If we say that you must always provide an array as credentialTypes, then we should probably consider `Ref<string[]>` and `Ref<string>[]`/`Array<Ref<string>>` as possible types? My preference would be to allow either a single value or an array, tho

Code after:
import { QUICK_CONNECT_EXPERIMENT } from '@/app/constants';
import { usePostHog } from '@/app/stores/posthog.store';
import { useSettingsStore } from '@/app/stores/settings.store';
import { computed, type Ref, toRef } from 'vue';

type UseQuickConnectParams =
	| {
			packageName: string | Ref<string | undefined>;
			credentialTypes?: never;
	  }
	| {
			packageName?: never;
			credentialTypes: string[] | Ref<string[]>;
	  };

export function useQuickConnect({ credentialTypes, packageName }: UseQuickConnectParams) {
	const settingsStore = useSettingsStore();
	const posthogStore = usePostHog();
	const quickConnectEnabled = posthogStore.isVariantEnabled(
		QUICK_CONNECT_EXPERIMENT.name,
		QUICK_CONNECT_EXPERIMENT.variant,
	);

	return computed(() => {
		if (quickConnectEnabled && settingsStore.moduleSettings['quick-connect']?.options.length) {
			const options = settingsStore.moduleSettings['quick-connect']?.options;

			if (credentialTypes) {
				const types = toRef(credentialTypes).value;
				return options.find((option) => types.includes(option.credentialType));
			}

			if (packageName) {
				return options.find((option) => option.packageName === toRef(packageName).value);
			}
		}

		return undefined;
	});
}