The codemirror-plugins directory contains multiple n8n-specific dependencies that are NOT abstractly designed. These are leftover dependencies from the original n8n codebase that have been partially stubbed out but should be removed or properly abstracted for a standalone library.
Files and Count:
- Total: 2 unique import patterns from
n8n-workflow
Imports:
import type { DocMetadata } from 'n8n-workflow';
import type { IConnections, IWorkflowDataProxyAdditionalKeys, Workflow } from 'n8n-workflow';Locations:
src/types/expressions.ts:3- 2 types (IConnections, IWorkflowDataProxyAdditionalKeys, Workflow)src/lib/codemirror-plugins/completions/utils.ts:15- 1 type (DocMetadata)
Status: These are type-only imports that have been partially replaced with local definitions but still reference external package.
Files and Count:
- Total: 4 unique import patterns
Imports:
import type { Basic } from '@/Interface';
import type { Schema } from '@/Interface';
import type { TargetItem, TargetNodeParameterContext } from '@/Interface';
import type { TargetNodeParameterContext } from '@/Interface';Locations:
src/types/expressions.ts:1- importsBasicsrc/lib/codemirror-plugins/completions/constants.ts:6- importsTargetNodeParameterContextsrc/lib/codemirror-plugins/typescript/types.ts:1- importsSchemasrc/lib/codemirror-plugins/typescript/worker/dynamicTypes.ts:1- importsSchemasrc/lib/codemirror-plugins/typescript/client/useTypescript.ts:24- importsTargetNodeParameterContext
Status: These are actually aliased to src/ via tsconfig (not from external package). The types are defined in:
src/types/workflow.ts- definesBasicinterface- Types are currently missing proper definitions for
SchemaandTargetNodeParameterContext
Store Functions Used:
-
useNDVStore() - NDV (Node Details View) Store
- Files: 5 files in codemirror-plugins
- Functions used:
activeNode- currently editing nodeisInputParentOfActiveNode- input node checkndvInputNodeName,ndvInputRunIndex,ndvInputBranchIndex- input contextexpressionTargetItem- target data for expressionsisDraggableDragging- drag statedraggableType- drag type
- Locations:
src/lib/codemirror-plugins/completions/utils.ts(6 usages)src/lib/codemirror-plugins/dragAndDrop.ts(1 class usage)src/lib/codemirror-plugins/typescript/client/useTypescript.ts(2 usages)- Tests:
dragAndDrop.test.ts,completions/utils.test.ts
-
useWorkflowsStore() - Workflow Data Store
- Files: 5 files in codemirror-plugins
- Functions used:
getNodeByName()- lookup node by nameworkflow.nodes- all workflow nodesworkflowObject.getChildNodes()- get child nodesworkflowObject.getParentNodesByDepth()- get parent nodes
- Locations:
src/lib/codemirror-plugins/completions/utils.ts(5 usages)- Tests:
completions/utils.test.ts
-
useExternalSecretsStore() - Secrets Store
- Files: 2 files in codemirror-plugins
- Functions used:
isEnterpriseExternalSecretsEnabled- feature flag
- Locations:
src/lib/codemirror-plugins/completions/dollar.completions.ts:97(1 usage)- Tests:
completions/completions.test.ts
Summary Table:
| Store | Purpose | Usage Count | Plugin Files |
|---|---|---|---|
| useNDVStore | Node editing context | 7+ | 3 files + tests |
| useWorkflowsStore | Workflow structure | 5+ | 2 files + tests |
| useExternalSecretsStore | Secrets feature flag | 1+ | 1 file + tests |
Package: @/lib/i18n (local stub)
Implementation: Simple key-based stub that just returns the key as-is:
export const i18n = {
baseText: (key: string) => key,
};Usage Locations: 21 files in codemirror-plugins
completions/dollar.completions.ts- 7 usages for variable/secret descriptionscompletions/constants.ts- 50+ usages for UI labels and help textcompletions/nonDollar.completions.ts- 3 usagescompletions/infoBoxRenderer.ts- 5 usagescompletions/nativesAutocompleteDocs/*.ts- 100+ usagescompletions/utils.test.ts- 0 usages
Status: All i18n keys are hardcoded strings referencing n8n's locale system (e.g., 'codeNodeEditor.completer.$pageCount')
Purpose: Provides context about the currently active node being edited
Why it's needed in completions:
- Context awareness: Know which node's parameter is being edited
- Input data resolution: Get data from input nodes to the currently active node
- Pagination detection: Know if in HTTP node pagination context
- Active node tracking: Determine if a node is active/selected
Code Example from completions/utils.ts:
export function resolveAutocompleteExpression(expression: string, contextNodeName?: string) {
const ndvStore = useNDVStore();
const inputData =
contextNodeName === undefined && ndvStore.isInputParentOfActiveNode
? {
targetItem: ndvStore.expressionTargetItem ?? undefined,
inputNodeName: ndvStore.ndvInputNodeName,
inputRunIndex: ndvStore.ndvInputRunIndex,
inputBranchIndex: ndvStore.ndvInputBranchIndex,
}
: {};
return resolveParameter(expression, {
...inputData,
contextNodeName,
});
}Purpose: Provides workflow structure and node relationships
Why it's needed in completions:
- Node lookup: Find nodes by name to check if they exist
- Node relationships: Determine parent/child nodes for expression scoping
- Batch processing: Check for "Split in Batches" node to control $itemIndex availability
- Node navigation: Build list of previous nodes available for
$()expressions
Code Example from completions/utils.ts:
export function autocompletableNodeNames(targetNodeParameterContext?: TargetNodeParameterContext) {
const activeNode = useWorkflowsStore().getNodeByName(targetNodeParameterContext?.nodeName);
const workflowObject = useWorkflowsStore().workflowObject;
const nonMainChildren = workflowObject.getChildNodes(activeNodeName, 'ALL_NON_MAIN');
return getPreviousNodes(activeNodeName);
}Purpose: Provides feature flag for enterprise secrets
Why it's needed:
- Conditional completions: Only show
$secretsand$varscompletions if enterprise secrets are enabled - Feature detection: Know when to render enterprise-only variables
Code Example from completions/dollar.completions.ts:97:
return useExternalSecretsStore().isEnterpriseExternalSecretsEnabled
? [
{ label: '$vars', ... },
{ label: '$secrets', ... },
]
: [];Purpose: Localize UI text in autocompletion
Coverage:
- 50+ completion item labels - Section names, function names, descriptions
- 100+ doc metadata strings - Luxon date-time library documentation
- Help text - Parameter descriptions, examples
Example Keys:
'codeNodeEditor.completer.$pageCount' // "Page count"
'codeNodeEditor.completer.section.fields' // "Fields"
'codeNodeEditor.completer.luxon.instanceMethods.year' // "Year"
'codeNodeEditor.completer.$if.args.condition' // "Condition"
Answer: PARTIALLY, with poor abstraction
The library was extracted from n8n's codebase but:
- Stores are stubbed out but still referenced throughout
- Type definitions are still n8n-specific
- I18N keys are hardcoded to n8n's locale system
- No clear abstraction layer exists
Direct Coupling Points:
| Dependency | Coupling Level | Abstraction? | Impact |
|---|---|---|---|
| useNDVStore | TIGHT | ❌ No | Cannot run completions without node context |
| useWorkflowsStore | TIGHT | ❌ No | Cannot determine available previous nodes |
| useExternalSecretsStore | LOOSE | Only affects conditional feature flag | |
| i18n.baseText() | MEDIUM | Hardcoded keys; stub returns keys as-is | |
| Type imports | TIGHT | Types imported but mostly stubbed |
Problem Summary:
- 80% of completion logic is tightly coupled to n8n stores
- No dependency injection pattern exists
- No configuration layer to swap implementations
- Circular dependencies on n8n-workflow types
This codebase was extracted directly from n8n without proper refactoring for standalone use. The extraction process:
- Copied source files as-is
- Created stub implementations for stores
- Did not remove or abstract n8n-specific logic
- Left type imports unresolved
From MIGRATION_SUMMARY.md:
## 🔧 Remaining Work
### Critical Issues to Fix
1. **TypeScript Dependencies** (⚠️ HIGH PRIORITY)
- Many CodeMirror plugins depend on n8n-specific types from `@/types/n8n-workflow`
- Need to either:
- Copy necessary type definitions into the package
- Make these plugins optional/simplified
- Create stub types for missing dependencies
2. **Dependency Resolution** (⚠️ HIGH PRIORITY)
- Files importing from `@/Interface`, `@/app/composables`, etc. need refactoringN8N Dependencies:
i18n.baseText()- 7 usages (lines 70, 80, 90, 105, 114, 137)useExternalSecretsStore()- 1 usage (line 97)
Functionality:
- Provides
$completion items for expressions - Conditionally includes
$varsand$secretsbased on enterprise flag - Uses i18n for all display labels
Why N8N-Specific:
- Features like
$pageCount,$response,$requestare HTTP node-specific - Enterprise secrets are n8n feature
- I18N keys are all n8n-specific
N8N Dependencies:
useWorkflowsStore()- 5 usages (lines 212, 213, 216, 222, 228, 240)useNDVStore()- 3 usages (lines 173, 175-181, 202-204, 213, 221-222)- Type import
DocMetadatafrom n8n-workflow (line 15)
Key Functions:
resolveAutocompleteExpression() // Uses NDV store
autocompletableNodeNames() // Uses workflows store
hasActiveNode() // Uses both storesWhy N8N-Specific:
- Needs to resolve expressions using n8n's expression resolver
- Needs to know workflow structure to determine available nodes
- HTTP node pagination detection is n8n-specific
N8N Dependencies:
i18n.baseText()- 50+ usages throughout file- Type import
TargetNodeParameterContextfrom @/Interface
Content:
- Global completion definitions for all special variables and functions
- Section headers (Fields, Recommended, Methods, etc.)
- Root dollar completions ($json, $binary, $now, etc.)
- All completion metadata with i18n descriptions
Scope of I18N:
- Every completion item has an i18n description
- Every section has an i18n name
- Every function parameter has i18n documentation
N8N Dependencies:
i18n.baseText()- 5 usages (lines 99, 129, 149, 183, 223)- Type imports:
DocMetadata,DocMetadataArgument,DocMetadataExamplefrom @/types/n8n-workflow
Functionality:
- Renders HTML info boxes for completion items
- Shows function signatures, arguments, examples, defaults
- All text is localized via i18n
N8N Dependencies:
useNDVStore()- 2 usages (line 1, lines 44 and setup in constructor)
Functionality:
- Handles drag-drop of node outputs into editor
- Uses NDV store to track drag state and type
Why N8N-Specific:
- Needs to know what was being dragged from n8n's UI
- Needs to format insertion based on n8n node structure
N8N Dependencies:
i18n.baseText()- 100+ usages- Type import
NativeDocfrom @/types/n8n-workflow
Content:
- Metadata for all Luxon date-time library methods
- Each method has i18n description
- Examples and argument documentation
Scale:
- 400+ lines of i18n keys in
luxon.static.docs.ts - 300+ lines of i18n keys in
luxon.instance.docs.ts
Defined locally:
src/types/workflow.ts- MinimalBasicinterfacesrc/types/n8n-workflow.ts- Partial types (DocMetadata, CodeExecutionMode, etc.)
Missing/Incomplete:
TargetNodeParameterContext- Referenced but not definedSchema- Referenced but not definedTargetItem- Referenced in expressions.ts but not defined- Many n8n workflow types left undefin
Option A: Fully Abstract (Recommended)
-
Create abstraction layer for stores:
export interface IExpressionContext { activeNodeName?: string; workflowNodes?: Node[]; hasExternalSecrets?: boolean; inputData?: any; }
-
Replace store access with dependency injection:
export function dollarCompletions( context: CompletionContext, exprContext?: IExpressionContext ): CompletionResult | null { ... }
-
Make i18n pluggable:
export interface I18nProvider { getText(key: string): string; }
Benefits:
- Works standalone without n8n
- Can be used in other projects
- Clear contract for what's needed
Option B: Complete Stubbing
- Fill in all stub implementations in
src/lib/stores.ts - Define all missing types properly
- Document that this is an n8n library
Current status: Partially done - stubs exist but are incomplete
Critical:
- Define
TargetNodeParameterContexttype properly - Define
Schematype properly - Complete store stubs with full method signatures
- Resolve all type import paths
High Priority:
- Add locale context to i18n or remove i18n dependency
- Document which files are n8n-specific vs. generic
- Extract generic CodeMirror plugins to separate module
Medium Priority:
- Create abstraction layer for workflow context
- Make store dependencies injectable
- Add configuration for feature flags
| File | Category | Dependency | Usage Count | Criticality | Removable? |
|---|---|---|---|---|---|
| dollar.completions.ts | Store | useExternalSecretsStore | 1 | Medium | Yes* |
| dollar.completions.ts | I18N | i18n.baseText | 7 | High | No |
| utils.ts | Store | useWorkflowsStore | 5 | High | No |
| utils.ts | Store | useNDVStore | 3 | High | No |
| dragAndDrop.ts | Store | useNDVStore | 2 | Medium | Yes* |
| constants.ts | I18N | i18n.baseText | 50+ | High | No |
| infoBoxRenderer.ts | I18N | i18n.baseText | 5 | High | No |
| luxon.*.docs.ts | I18N | i18n.baseText | 100+ | Medium | Yes** |
Legend:
- *Yes: Can be stubbed/mocked
- **Yes: Can be replaced with simpler docs
- No: Core to functionality
This library is CURRENTLY n8n-specific with poor abstraction. The n8n dependencies are:
- Direct: n8n-workflow package imports (2 locations)
- Indirect: @/Interface and local stub stores (3 store functions, 10+ files)
- Localization: i18n system hardcoded to n8n keys (175+ usages)
- Structural: Completion logic assumes n8n workflow context (stores)
These are NOT leftover dependencies—they are CORE to the functionality. The library cannot function as standalone without:
- Providing node/workflow context
- Implementing workflow structure queries
- Localizing 175+ UI strings
Recommendation: Either fully abstract the dependencies (6-8 hour refactor) or accept that this is an n8n-specific library.