In this article, we review useEditorContext in n8n codebase. You will learn:
Composables in Vue
useEditorContext as composable in n8n.
Composables in Vue
In the context of Vue applications, a "composable" is a function that leverages Vue's Composition API to encapsulate and reuse stateful logic.
When building frontend applications, we often need to reuse logic for common tasks. For example, we may need to format dates in many places, so we extract a reusable function for that. This formatter function encapsulates stateless logic: it takes some input and immediately returns expected output. There are many libraries out there for reusing stateless logic - for example lodash and date-fns, which you may have heard of.
By contrast, stateful logic involves managing state that changes over time. A simple example would be tracking the current position of the mouse on a page. In real-world scenarios, it could also be more complex logic such as touch gestures or connection status to a database.
This is just like React Hooks.
Learn more about Composables.
useEditorContext as composable in n8n.
Now that we understand what a composable is in Vue.js, btw, n8n editor-ui is written in Vue, let's understand how useEditorContext is used.
Below is a comment I picked from useEditorContext.ts file.
/**
* Per-editor host overrides for the current editor context.
*
* Editor hosts (e.g. the Instance AI artifact preview) scope their embedded
* editor by providing `EditorEnabledFeaturesKey` - the capabilities the host
* supersedes. AI features can only be restricted: an explicit `false` turns one
* off, while omitted (or `true`) features fall back to their store values.
* `readOnly` is a direct flag - `true` forces the canvas read-only. When no host
* provides the key, AI features fall back to their store values and the canvas
* is editable (`readOnly` is `false`).
* `executionSuccessToasts` / `executionErrorToasts` are direct flags too - each
* `true` (the default) shows that class of execution result toast; an explicit
* `false` from the host suppresses it.
*/
export function useEditorContext() {
This comment explains what it does - Per-editor host overrides for the current editor context.
Below is the entire useEditorContext definition:
export function useEditorContext() {
const settings = useSettingsStore();
const enabledFeatures = inject(EditorEnabledFeaturesKey, null);
// A host can only restrict: an explicit `false` supersedes the feature;
// omitted (or `true`) falls back to the store gating below.
const isEnabledByHost = (feature: EditorFeature): boolean =>
enabledFeatures?.value?.[feature] !== false;
const enabledInStore = (feature: EditorFeature): boolean => {
switch (feature) {
case 'aiAssistant':
return settings.isAiAssistantEnabled === true;
case 'aiBuilder':
return settings.isAiBuilderEnabled === true;
case 'askAi':
return settings.isAskAiEnabled === true;
case 'instanceAi':
// Mirrors useInstanceAiAvailable() (the feature-layer gate) with
// app-layer primitives so this base composable imports no feature:
// the module is active, enabled, ready (or admin-fixable), and the
// user may message Instance AI.
return (
settings.isModuleActive('instance-ai') &&
settings.moduleSettings['instance-ai']?.enabled !== false &&
(settings.moduleSettings['instance-ai']?.setupCompleted === true ||
hasPermission(['rbac'], { rbac: { scope: 'instanceAi:manage' } })) &&
hasPermission(['rbac'], { rbac: { scope: 'instanceAi:message' } })
);
}
};
const featureEnabled = (feature: EditorFeature) =>
computed(() => enabledInStore(feature) && isEnabledByHost(feature));
return {
aiAssistant: featureEnabled('aiAssistant'),
aiBuilder: featureEnabled('aiBuilder'),
askAi: featureEnabled('askAi'),
instanceAi: featureEnabled('instanceAi'),
readOnly: computed(() => enabledFeatures?.value?.readOnly === true),
expandGroups: computed(() => enabledFeatures?.value?.expandGroups),
executionButtonType: computed(() => enabledFeatures?.value?.executionButtonType ?? 'primary'),
executionSuccessToasts: computed(
() => enabledFeatures?.value?.executionSuccessToasts !== false,
),
executionErrorToasts: computed(() => enabledFeatures?.value?.executionErrorToasts !== false),
};
}
This uses settings from useSettingsStore - Here Pinia is used. Pinia is a state management library.
I think this returns what features are enabled in the editor context, because this just returns an object containing features as keys and values being boolean depending on "feature enabled".
About me:
Hey, my name is Ramu Narasinga. Email: ramu.narasinga@gmail.com
I spent 3+ years studying OSS codebases and wrote 400+ articles on what makes the production-grade. Now I'm putting that into practice differently - instead of writing every fix myself, I run coding agents that do it.
How it works? Register your machine as a Runtime, point it at your repo. Agents pick up issues. write the fix, open the PR. You just review, they execute.
Build your coding agents and get more work done in less time at thinkthroo.com

Top comments (0)