Repository: n8n-io/n8n
File: packages/frontend/editor-ui/src/features/settings/communityNodes/composables/useInstallNode.ts (TypeScript)

Code before:

export function useInstallNode() {
	const communityNodesStore = useCommunityNodesStore();
	const nodeTypesStore = useNodeTypesStore();
	const credentialsStore = useCredentialsStore();
	const workflowsStore = useWorkflowsStore();
	const userStore = useUsersStore();
	const canInstallNodes = computed(() => userStore.isAdmin || userStore.isInstanceOwner);
	const loading = ref(false);
	const toast = useToast();
	const canvasOperations = useCanvasOperations();
	const telemetry = useTelemetry();

	const getNpmVersion = async (key: string) => {
		const communityNodeAttributes = await nodeTypesStore.getCommunityNodeAttributes(key);

		if (communityNodeAttributes) {
			return communityNodeAttributes.npmVersion;
		}

		return undefined;
	};

	const installNode = async (props: InstallNodeProps): Promise<InstallNodeResult> => {
		if (!canInstallNodes.value) {
			const error = new Error('User is not an owner');
			toast.showError(error, i18n.baseText('settings.communityNodes.messages.install.error'));
			return { success: false, error };
		}

		if (props.telemetry) {
			telemetry.track('user started cnr package install', {
				input_string: props.packageName,
				has_quick_connect: props.telemetry.hasQuickConnect,
				source: props.telemetry.source,
			});
		}

		try {
			loading.value = true;
			if (props.type === 'verified') {
				await communityNodesStore.installPackage(
					props.packageName,
					true,
					await getNpmVersion(props.nodeType),
				);
			} else {
				await communityNodesStore.installPackage(props.packageName);
			}

			// refresh store information about installed nodes

Review comment (suggestion):
I think we should update the error message to be in line with new behavior:
```suggestion
			const error = new Error('User is not an owner or an admin');
```

Code after:

export function useInstallNode() {
	const communityNodesStore = useCommunityNodesStore();
	const nodeTypesStore = useNodeTypesStore();
	const credentialsStore = useCredentialsStore();
	const workflowsStore = useWorkflowsStore();
	const userStore = useUsersStore();
	const loading = ref(false);
	const toast = useToast();
	const canvasOperations = useCanvasOperations();
	const telemetry = useTelemetry();

	const getNpmVersion = async (key: string) => {
		const communityNodeAttributes = await nodeTypesStore.getCommunityNodeAttributes(key);

		if (communityNodeAttributes) {
			return communityNodeAttributes.npmVersion;
		}

		return undefined;
	};

	const installNode = async (props: InstallNodeProps): Promise<InstallNodeResult> => {
		if (!userStore.isAdminOrOwner) {
			const error = new Error('User is not an owner or admin');
			toast.showError(error, i18n.baseText('settings.communityNodes.messages.install.error'));
			return { success: false, error };
		}

		if (props.telemetry) {
			telemetry.track('user started cnr package install', {
				input_string: props.packageName,
				has_quick_connect: props.telemetry.hasQuickConnect,
				source: props.telemetry.source,
			});
		}

		try {
			loading.value = true;
			if (props.type === 'verified') {
				await communityNodesStore.installPackage(
					props.packageName,
					true,
					await getNpmVersion(props.nodeType),
				);
			} else {
				await communityNodesStore.installPackage(props.packageName);
			}

			// refresh store information about installed nodes
			await Promise.all([