Skip to content

Commit

Permalink
feat(cli): Enable community nodes based on npm availability (#3871)
Browse files Browse the repository at this point in the history
* ⚡ Detect npm availability

* 📘 Expand interfaces

* ⚡ Adjust store

* 🎨 Replace button with warning
  • Loading branch information
ivov authored Aug 11, 2022
1 parent 620525e commit 936264b
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 10 deletions.
1 change: 1 addition & 0 deletions packages/cli/src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ export interface IN8nUISettings {
missingPackages?: boolean;
executionMode: 'regular' | 'queue';
communityNodesEnabled: boolean;
isNpmAvailable: boolean;
}

export interface IPersonalizationSurveyAnswers {
Expand Down
9 changes: 9 additions & 0 deletions packages/cli/src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import express from 'express';
import { readFileSync, promises } from 'fs';
import { readFile } from 'fs/promises';
import { exec as callbackExec } from 'child_process';
import _, { cloneDeep } from 'lodash';
import { dirname as pathDirname, join as pathJoin, resolve as pathResolve } from 'path';
import {
Expand Down Expand Up @@ -86,6 +87,7 @@ import jwks from 'jwks-rsa';
import timezones from 'google-timezones-json';
import parseUrl from 'parseurl';
import promClient, { Registry } from 'prom-client';
import { promisify } from 'util';
import * as Queue from './Queue';
import {
ActiveExecutions,
Expand Down Expand Up @@ -167,6 +169,8 @@ import { loadPublicApiVersions } from './PublicApi';

require('body-parser-xml')(bodyParser);

const exec = promisify(callbackExec);

export const externalHooks: IExternalHooksClass = ExternalHooks();

class App {
Expand Down Expand Up @@ -330,6 +334,7 @@ class App {
onboardingCallPromptEnabled: config.getEnv('onboardingCallPrompt.enabled'),
executionMode: config.getEnv('executions.mode'),
communityNodesEnabled: config.getEnv('nodes.communityPackages.enabled'),
isNpmAvailable: false,
};
}

Expand Down Expand Up @@ -374,6 +379,10 @@ class App {
promClient.collectDefaultMetrics({ register });
}

this.frontendSettings.isNpmAvailable = await exec('npm --version')
.then(() => true)
.catch(() => false);

this.versions = await GenericHelpers.getVersions();
this.frontendSettings.versionCli = this.versions.cli;

Expand Down
2 changes: 2 additions & 0 deletions packages/editor-ui/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ export interface IN8nUISettings {
};
executionMode: string;
communityNodesEnabled: boolean;
isNpmAvailable: boolean;
publicApi: {
enabled: boolean;
latestVersion: number;
Expand Down Expand Up @@ -881,6 +882,7 @@ export interface IRootState {
sidebarMenuItems: IMenuItem[];
instanceId: string;
nodeMetadata: {[nodeName: string]: INodeMetadata};
isNpmAvailable: boolean;
}

export interface ICommunityPackageMap {
Expand Down
1 change: 1 addition & 0 deletions packages/editor-ui/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const NPM_PACKAGE_DOCS_BASE_URL = `https://www.npmjs.com/package/`;
export const NPM_KEYWORD_SEARCH_URL = `https://www.npmjs.com/search?q=keywords%3An8n-community-node-package`;
export const N8N_QUEUE_MODE_DOCS_URL = `https://docs.n8n.io/hosting/scaling/queue-mode/`;
export const COMMUNITY_NODES_INSTALLATION_DOCS_URL = `https://docs.n8n.io/integrations/community-nodes/installation/`;
export const COMMUNITY_NODES_NPM_INSTALLATION_URL = 'https://docs.npmjs.com/downloading-and-installing-node-js-and-npm';
export const COMMUNITY_NODES_RISKS_DOCS_URL = `https://docs.n8n.io/integrations/community-nodes/risks/`;
export const COMMUNITY_NODES_BLOCKLIST_DOCS_URL = `https://docs.n8n.io/integrations/community-nodes/blocklist/`;
export const CUSTOM_NODES_DOCS_URL = `https://docs.n8n.io/integrations/creating-nodes/code/create-n8n-nodes-module/`;
Expand Down
4 changes: 4 additions & 0 deletions packages/editor-ui/src/modules/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ const module: Module<ISettingsState, IRootState> = {
isCommunityNodesFeatureEnabled: (state): boolean => {
return state.settings.communityNodesEnabled;
},
isNpmAvailable: (state): boolean => {
return state.settings.isNpmAvailable;
},
isQueueModeEnabled: (state): boolean => {
return state.settings.executionMode === 'queue';
},
Expand Down Expand Up @@ -138,6 +141,7 @@ const module: Module<ISettingsState, IRootState> = {
context.commit('setOauthCallbackUrls', settings.oauthCallbackUrls, {root: true});
context.commit('setN8nMetadata', settings.n8nMetadata || {}, {root: true});
context.commit('setDefaultLocale', settings.defaultLocale, {root: true});
context.commit('setIsNpmAvailable', settings.isNpmAvailable, {root: true});
context.commit('versions/setVersionNotificationSettings', settings.versionNotifications, {root: true});
context.commit('setCommunityNodesFeatureEnabled', settings.communityNodesEnabled === true);
},
Expand Down
1 change: 1 addition & 0 deletions packages/editor-ui/src/plugins/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,7 @@
"settings.communityNodes.empty.description.no-packages": "Install node packages contributed by our community. <br /><a href=\"{docURL}\" target=\"_blank\" title=\"Read the n8n docs\">More info</a>",
"settings.communityNodes.empty.installPackageLabel": "Install a community node",
"settings.communityNodes.queueMode.warning": "You need to install community nodes manually because your instance is running in queue mode. <a href=\"{docURL}\" target=\"_blank\" title=\"Read the n8n docs\">More info</a>",
"settings.communityNodes.npmUnavailable.warning": "To use this feature, please <a href=\"{npmUrl}\" target=\"_blank\" title=\"How to install npm\">install npm</a> and restart n8n.",
"settings.communityNodes.packageNodes.label": "{count} node | {count} nodes",
"settings.communityNodes.updateAvailable.tooltip": "A newer version is available",
"settings.communityNodes.viewDocsAction.label": "Documentation",
Expand Down
4 changes: 4 additions & 0 deletions packages/editor-ui/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ const state: IRootState = {
selectedNodes: [],
sessionId: Math.random().toString(36).substring(2, 15),
urlBaseWebhook: 'http://localhost:5678/',
isNpmAvailable: false,
workflow: {
id: PLACEHOLDER_EMPTY_WORKFLOW_ID,
name: '',
Expand Down Expand Up @@ -600,6 +601,9 @@ export const store = new Vuex.Store({
setDefaultLocale(state, locale: string) {
Vue.set(state, 'defaultLocale', locale);
},
setIsNpmAvailable(state, isNpmAvailable: boolean) {
Vue.set(state, 'isNpmAvailable', isNpmAvailable);
},
setActiveNode(state, nodeName: string) {
state.activeNode = nodeName;
},
Expand Down
44 changes: 34 additions & 10 deletions packages/editor-ui/src/views/SettingsCommunityNodesView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
<n8n-action-box
:heading="$locale.baseText('settings.communityNodes.empty.title')"
:description="getEmptyStateDescription"
:buttonText="$locale.baseText('settings.communityNodes.empty.installPackageLabel')"
:buttonText="
isNpmAvailable
? $locale.baseText('settings.communityNodes.empty.installPackageLabel')
: ''
"
:calloutText="actionBoxConfig.calloutText"
:calloutTheme="actionBoxConfig.calloutTheme"
@click="openInstallModal"
Expand All @@ -63,7 +67,11 @@ import SettingsView from './SettingsView.vue';
import CommunityPackageCard from '../components/CommunityPackageCard.vue';
import { showMessage } from '@/components/mixins/showMessage';
import mixins from 'vue-typed-mixins';
import { COMMUNITY_PACKAGE_INSTALL_MODAL_KEY, COMMUNITY_NODES_INSTALLATION_DOCS_URL } from '../constants';
import {
COMMUNITY_PACKAGE_INSTALL_MODAL_KEY,
COMMUNITY_NODES_INSTALLATION_DOCS_URL,
COMMUNITY_NODES_NPM_INSTALLATION_URL,
} from '../constants';
import { PublicInstalledPackage } from 'n8n-workflow';
const PACKAGE_COUNT_THRESHOLD = 31;
Expand Down Expand Up @@ -123,7 +131,7 @@ export default mixins(
}
},
computed: {
...mapGetters('settings', ['isQueueModeEnabled']),
...mapGetters('settings', ['isNpmAvailable', 'isQueueModeEnabled']),
...mapGetters('communityNodes', ['getInstalledPackages']),
getEmptyStateDescription() {
const packageCount = this.$store.getters['communityNodes/availablePackageCount'];
Expand All @@ -141,13 +149,29 @@ export default mixins(
});
},
actionBoxConfig() {
return this.isQueueModeEnabled ? {
calloutText: this.$locale.baseText('settings.communityNodes.queueMode.warning', {
interpolate: { docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL },
}),
calloutTheme: 'warning',
hideButton: true,
} : {
if (!this.isNpmAvailable) {
return {
calloutText: this.$locale.baseText(
'settings.communityNodes.npmUnavailable.warning',
{ interpolate: { npmUrl: COMMUNITY_NODES_NPM_INSTALLATION_URL } },
),
calloutTheme: 'warning',
hideButton: true,
};
}
if (this.isQueueModeEnabled) {
return {
calloutText: this.$locale.baseText(
'settings.communityNodes.queueMode.warning',
{ interpolate: { docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL } },
),
calloutTheme: 'warning',
hideButton: true,
};
}
return {
calloutText: '',
calloutTheme: '',
hideButton: false,
Expand Down

0 comments on commit 936264b

Please sign in to comment.