Merged Axel changes. Added dev docs for Cline

This commit is contained in:
Richard Osborne
2025-12-06 22:37:54 +01:00
parent da40209322
commit 9a5952ec13
15 changed files with 3927 additions and 0 deletions

153
.clineignore Normal file
View File

@@ -0,0 +1,153 @@
# =============================================================================
# OpenNoodl .clineignore
# =============================================================================
# This file tells Cline which folders/files to ignore when indexing the codebase.
# Place this file at the root of the OpenNoodl repository.
# =============================================================================
# -----------------------------------------------------------------------------
# Specific heavy file locations that Cline doesn't need
# -----------------------------------------------------------------------------
packages/noodl-editor/src/assets/
packages/noodl-core-ui/src/assets/
packages/noodl-editor/build/icons/
packages/noodl-editor/src/editor/parse-dashboard-public/
packages/noodl-editor/src/assets/
packages/noodl-editor/tests/testfs/
packages/noodl-editor/tests/recordings/
# -----------------------------------------------------------------------------
# Dependencies (MASSIVE - always ignore)
# -----------------------------------------------------------------------------
node_modules/
**/node_modules/
# -----------------------------------------------------------------------------
# Build & Distribution Output
# -----------------------------------------------------------------------------
build/
dist/
**/build/
**/dist/
publish/
**/publish/
bundles/
**/bundles/
# -----------------------------------------------------------------------------
# External Dependencies (Parse Dashboard, etc.)
# -----------------------------------------------------------------------------
deps/
# -----------------------------------------------------------------------------
# Git
# -----------------------------------------------------------------------------
.git/
# -----------------------------------------------------------------------------
# Compiled/Bundled JavaScript (not source code)
# -----------------------------------------------------------------------------
*.bundle.js
*.min.js
*.min.css
**/*.bundle.js
**/*.min.js
# Specific bundled/minified files
packages/noodl-viewer-react/static/
packages/noodl-editor/src/editor/parse-dashboard-public/
# -----------------------------------------------------------------------------
# Static Assets (images, fonts, etc.)
# -----------------------------------------------------------------------------
**/assets/fonts/
**/assets/images/
**/public/fonts/
**/public/images/
**/*.png
**/*.jpg
**/*.jpeg
**/*.gif
**/*.ico
**/*.woff
**/*.woff2
**/*.ttf
**/*.eot
**/*.svg
!packages/noodl-core-ui/src/**/*.svg
# -----------------------------------------------------------------------------
# Test Artifacts
# -----------------------------------------------------------------------------
coverage/
**/coverage/
**/__snapshots__/
*.snap
# -----------------------------------------------------------------------------
# IDE & Editor Configs (not needed for code understanding)
# -----------------------------------------------------------------------------
.idea/
.vscode/
*.code-workspace
# -----------------------------------------------------------------------------
# OS Generated Files
# -----------------------------------------------------------------------------
.DS_Store
Thumbs.db
*.log
# -----------------------------------------------------------------------------
# Temporary & Cache Files
# -----------------------------------------------------------------------------
.cache/
**/.cache/
*.tmp
*.temp
.eslintcache
.prettiercache
# -----------------------------------------------------------------------------
# Environment & Secrets
# -----------------------------------------------------------------------------
.env
.env.*
*.pem
*.key
# -----------------------------------------------------------------------------
# Electron Build Artifacts
# -----------------------------------------------------------------------------
packages/noodl-editor/release/
packages/noodl-editor/out/
# -----------------------------------------------------------------------------
# Storybook Build Output
# -----------------------------------------------------------------------------
storybook-static/
**/storybook-static/
# -----------------------------------------------------------------------------
# Generated Type Declarations (if separate from source)
# -----------------------------------------------------------------------------
**/*.d.ts.map
# -----------------------------------------------------------------------------
# Lock Files (package structure is in package.json)
# -----------------------------------------------------------------------------
package-lock.json
yarn.lock
pnpm-lock.yaml
# -----------------------------------------------------------------------------
# Miscellaneous Large/Unneeded Files
# -----------------------------------------------------------------------------
*.dmg
*.exe
*.AppImage
*.deb
*.rpm
*.zip
*.tar.gz

601
dev-docs/.clinerules Normal file
View File

@@ -0,0 +1,601 @@
# Cline Development Guidelines for OpenNoodl
## Overview
This document provides guidelines for AI-assisted development on the OpenNoodl codebase using Cline in VSCode. Follow these guidelines to ensure consistent, well-documented, and testable contributions.
---
## 1. Before Starting Any Task
### 1.1 Understand the Context
```bash
# Always check which branch you're on
git branch
# Check for uncommitted changes
git status
# Review recent commits
git log --oneline -10
```
### 1.2 Read Relevant Documentation
Before modifying any file, understand its purpose:
1. Check for README files in the package
2. Read JSDoc comments on functions
3. Look for related test files
4. Search for usage patterns: `grep -r "functionName" packages/`
### 1.3 Identify Dependencies
```bash
# Check what imports a file
grep -r "from.*filename" packages/
# Check what the file imports
head -50 path/to/file.ts | grep "import"
```
---
## 2. Code Style Requirements
### 2.1 TypeScript Standards
```typescript
// ✅ GOOD: Explicit types
interface NodeProps {
id: string;
type: NodeType;
connections: Connection[];
}
function processNode(node: NodeProps): ProcessedNode {
// ...
}
// ❌ BAD: Implicit any
function processNode(node) {
// ...
}
// ❌ BAD: Using TSFixme
function processNode(node: TSFixme): TSFixme {
// ...
}
```
### 2.2 React Component Standards
```tsx
// ✅ GOOD: Functional component with types
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
export function Button({ label, onClick, disabled = false }: ButtonProps) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}
// ❌ BAD: Class component (unless necessary for lifecycle)
class Button extends React.Component {
// ...
}
```
### 2.3 Import Organization
```typescript
// 1. External packages (alphabetical)
import classNames from 'classnames';
import React, { useCallback, useState } from 'react';
// 2. Internal packages (alphabetical by alias)
import { IconName } from '@noodl-core-ui/components/common/Icon';
import { NodeGraphModel } from '@noodl-models/nodegraphmodel';
import { KeyCode } from '@noodl-utils/keyboard/KeyCode';
// 3. Relative imports (by depth, then alphabetical)
import { localHelper } from './helpers';
import css from './Component.module.scss';
```
### 2.4 Naming Conventions
| Type | Convention | Example |
|------|------------|---------|
| Components | PascalCase | `NodeEditor.tsx` |
| Hooks | camelCase, use prefix | `useNodeSelection.ts` |
| Utils | camelCase | `formatNodeName.ts` |
| Constants | UPPER_SNAKE | `MAX_CONNECTIONS` |
| CSS Modules | kebab-case | `node-editor.module.scss` |
| Test files | Same + .test | `NodeEditor.test.tsx` |
---
## 3. Documentation Requirements
### 3.1 File Headers
Every new file should have a header comment:
```typescript
/**
* NodeProcessor
*
* Handles the processing of node graph updates and manages
* the execution order of connected nodes.
*
* @module noodl-runtime
* @since 1.2.0
*/
```
### 3.2 Function Documentation
```typescript
/**
* Processes a node and propagates changes to connected nodes.
*
* @param node - The node to process
* @param context - The execution context
* @param options - Processing options
* @param options.force - Force re-evaluation even if inputs unchanged
* @returns The processed output values
* @throws {NodeProcessingError} If the node definition is invalid
*
* @example
* ```typescript
* const output = processNode(myNode, context, { force: true });
* console.log(output.value);
* ```
*/
function processNode(
node: NodeInstance,
context: ExecutionContext,
options: ProcessOptions = {}
): NodeOutput {
// ...
}
```
### 3.3 Complex Logic Comments
```typescript
// Calculate the topological sort order for node evaluation.
// This ensures nodes are processed after their dependencies.
// Uses Kahn's algorithm for O(V+E) complexity.
const sortedNodes = topologicalSort(nodes, connections);
```
---
## 4. Testing Requirements
### 4.1 Test File Location
Tests should be co-located or in a parallel `tests/` directory:
```
// Option A: Co-located
components/
├── Button/
│ ├── Button.tsx
│ ├── Button.test.tsx
│ └── Button.module.scss
// Option B: Parallel (current pattern in noodl-editor)
packages/noodl-editor/
├── src/
│ └── components/Button.tsx
└── tests/
└── components/Button.test.ts
```
### 4.2 Test Structure
```typescript
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
import { renderHook, act } from '@testing-library/react-hooks';
describe('useNodeSelection', () => {
// Setup
let mockContext: NodeGraphContext;
beforeEach(() => {
mockContext = createMockContext();
});
// Group related tests
describe('when selecting a single node', () => {
it('should update selection state', () => {
const { result } = renderHook(() => useNodeSelection(mockContext));
act(() => {
result.current.selectNode('node-1');
});
expect(result.current.selectedNodes).toContain('node-1');
});
it('should clear previous selection by default', () => {
// ...
});
});
describe('when multi-selecting nodes', () => {
// ...
});
});
```
### 4.3 What to Test
| Priority | What to Test |
|----------|--------------|
| High | Utility functions |
| High | Data transformations |
| High | State management logic |
| Medium | React hooks |
| Medium | Component behavior |
| Low | Pure UI rendering |
---
## 5. Git Workflow
### 5.1 Branch Naming
```bash
# Features
git checkout -b feature/add-vercel-deployment
# Bug fixes
git checkout -b fix/page-router-scroll
# Refactoring
git checkout -b refactor/remove-tsfixme-panels
# Documentation
git checkout -b docs/update-node-api
```
### 5.2 Commit Messages
Follow conventional commits:
```bash
# Format: type(scope): description
# Features
git commit -m "feat(editor): add breakpoint support for node connections"
# Bug fixes
git commit -m "fix(viewer): resolve scroll position reset in nested Page Router"
# Refactoring
git commit -m "refactor(runtime): replace TSFixme with proper types in node processor"
# Documentation
git commit -m "docs(api): add JSDoc to all public node methods"
# Tests
git commit -m "test(editor): add unit tests for node selection hook"
# Chores
git commit -m "chore(deps): update react to 19.0.0"
```
### 5.3 Commit Frequency
- Commit after each logical change
- Don't combine unrelated changes
- Commit working states (tests should pass)
---
## 6. Codebase Navigation
### 6.1 Key Directories
```
packages/
├── noodl-editor/
│ ├── src/
│ │ ├── editor/src/
│ │ │ ├── models/ # Data models (ProjectModel, NodeGraph, etc.)
│ │ │ ├── views/ # UI components and views
│ │ │ ├── utils/ # Helper utilities
│ │ │ ├── store/ # State stores (AI Assistant, etc.)
│ │ │ └── pages/ # Page-level components
│ │ ├── main/ # Electron main process
│ │ └── shared/ # Shared utilities
│ └── tests/ # Test files
├── noodl-runtime/
│ └── src/
│ ├── nodes/ # Runtime node definitions
│ └── nodecontext.js # Execution context
├── noodl-viewer-react/
│ └── src/
│ └── nodes/ # React-based visual nodes
└── noodl-core-ui/
└── src/
└── components/ # Shared UI components
```
### 6.2 Finding Things
```bash
# Find a component
find packages/ -name "*NodeEditor*" -type f
# Find where something is imported
grep -r "import.*from.*NodeEditor" packages/
# Find where a function is called
grep -r "processNode(" packages/ --include="*.ts" --include="*.tsx"
# Find all TODO comments
grep -rn "TODO\|FIXME" packages/noodl-editor/src
# Find test files
find packages/ -name "*.test.ts" -o -name "*.spec.ts"
```
### 6.3 Understanding Data Flow
1. **User Action** → `views/` components capture events
2. **State Update** → `models/` handle business logic
3. **Runtime Sync** → `ViewerConnection` sends to preview
4. **Persistence** → `ProjectModel` saves to disk
---
## 7. Common Patterns
### 7.1 Event Handling Pattern
```typescript
// Models use EventDispatcher for pub/sub
import { EventDispatcher } from '../../../shared/utils/EventDispatcher';
class MyModel extends EventDispatcher {
doSomething() {
// ... logic
this.notifyListeners('updated', { data: result });
}
}
// Usage
const model = new MyModel();
model.on('updated', (data) => {
console.log('Model updated:', data);
});
```
### 7.2 React Hook Pattern
```typescript
// Custom hook for model subscription
function useModel<T>(model: EventDispatcher, event: string): T {
const [state, setState] = useState<T>(model.getState());
useEffect(() => {
const handler = (newState: T) => setState(newState);
model.on(event, handler);
return () => model.off(event, handler);
}, [model, event]);
return state;
}
```
### 7.3 Node Definition Pattern
```javascript
// In noodl-runtime/src/nodes/
const MyNode = {
name: 'My.Custom.Node',
displayName: 'My Custom Node',
category: 'Custom',
inputs: {
inputValue: {
type: 'string',
displayName: 'Input Value',
default: ''
}
},
outputs: {
outputValue: {
type: 'string',
displayName: 'Output Value'
}
},
methods: {
setInputValue(value) {
this._internal.inputValue = value;
this.flagOutputDirty('outputValue');
}
},
getOutputValue(name) {
if (name === 'outputValue') {
return this._internal.inputValue.toUpperCase();
}
}
};
```
---
## 8. Error Handling
### 8.1 User-Facing Errors
```typescript
import { ToastLayer } from '../views/ToastLayer/ToastLayer';
try {
await riskyOperation();
} catch (error) {
// Log for debugging
console.error('Operation failed:', error);
// Show user-friendly message
ToastLayer.showError('Unable to complete operation. Please try again.');
}
```
### 8.2 Developer Errors
```typescript
// Use assertions for developer errors
function processNode(node: NodeInstance) {
if (!node.id) {
throw new Error(`processNode: node.id is required`);
}
if (!node.definition) {
throw new Error(`processNode: node "${node.id}" has no definition`);
}
}
```
### 8.3 Graceful Degradation
```typescript
function getNodeIcon(node: NodeInstance): string {
try {
return node.definition.icon || 'default-icon';
} catch {
console.warn(`Could not get icon for node ${node.id}`);
return 'default-icon';
}
}
```
---
## 9. Performance Considerations
### 9.1 Avoid Unnecessary Re-renders
```tsx
// ✅ GOOD: Memoized callback
const handleClick = useCallback(() => {
onNodeSelect(node.id);
}, [node.id, onNodeSelect]);
// ✅ GOOD: Memoized expensive computation
const sortedNodes = useMemo(() => {
return topologicalSort(nodes);
}, [nodes]);
// ❌ BAD: New function on every render
<Button onClick={() => onNodeSelect(node.id)} />
```
### 9.2 Lazy Loading
```tsx
// Lazy load heavy components
const CodeEditor = React.lazy(() => import('./CodeEditor'));
function EditorPanel() {
return (
<Suspense fallback={<LoadingSpinner />}>
<CodeEditor />
</Suspense>
);
}
```
### 9.3 Batch Updates
```typescript
// Batch multiple state updates
import { unstable_batchedUpdates } from 'react-dom';
unstable_batchedUpdates(() => {
setSelection(newSelection);
setHighlight(newHighlight);
setZoom(newZoom);
});
```
---
## 10. Checklist Before Submitting
### Code Quality
- [ ] No `TSFixme` types added
- [ ] All new functions have JSDoc comments
- [ ] Complex logic has inline comments
- [ ] No console.log statements (except errors/warnings)
- [ ] No unused imports or variables
### Testing
- [ ] Unit tests for new utility functions
- [ ] Integration tests for new features
- [ ] Existing tests still pass
- [ ] Manual testing completed
### Documentation
- [ ] README updated if needed
- [ ] JSDoc added to public APIs
- [ ] Comments explain "why", not "what"
### Git
- [ ] Meaningful commit messages
- [ ] No unrelated changes in commits
- [ ] Branch named correctly
- [ ] Based on latest main branch
### Performance
- [ ] No obvious performance regressions
- [ ] Large lists use virtualization
- [ ] Expensive computations are memoized
---
## Quick Reference Commands
```bash
# Development
npm run dev # Start editor with hot reload
npm run test:editor # Run tests
npm run build:editor # Production build
# Code Quality
npx eslint packages/noodl-editor/src --fix
npx prettier --write "packages/**/*.{ts,tsx}"
npx tsc --noEmit # Type check
# Debugging
DEBUG=* npm run dev # Verbose logging
npm run test:editor -- --verbose
# Finding Issues
grep -r "TSFixme" packages/ # Find type escapes
grep -r "any" packages/ --include="*.ts" | head -20
```
---
*Last Updated: December 2024*

View File

@@ -0,0 +1,185 @@
# Cline Custom Instructions for OpenNoodl
Copy this entire file into your Cline Custom Instructions (VSCode → Cline extension settings → Custom Instructions).
---
## Identity
You are an expert TypeScript/React developer working on OpenNoodl, a visual low-code application builder. You write clean, well-documented, tested code that follows established patterns.
## Core Behaviors
### Before ANY Code Changes
1. **Read the task documentation first**
- Check `dev-docs/tasks/` for the current task
- Understand the full scope before writing code
- Follow the checklist step-by-step
2. **Understand the codebase location**
- Check `dev-docs/reference/CODEBASE-MAP.md`
- Use `grep -r "pattern" packages/` to find related code
- Look at similar existing implementations
3. **Verify your understanding**
- State your confidence level (1-10) before major changes
- List assumptions that need validation
- Ask clarifying questions rather than guessing
### Code Quality Standards
```typescript
// ✅ ALWAYS: Explicit types
function processNode(node: NodeInstance): ProcessedResult {
// Implementation
}
// ❌ NEVER: Any types or TSFixme
function processNode(node: any): any {
// Implementation
}
// ✅ ALWAYS: JSDoc for public functions
/**
* Processes a node and returns the result.
* @param node - The node instance to process
* @returns The processed result with output values
*/
function processNode(node: NodeInstance): ProcessedResult {
// Implementation
}
// ✅ ALWAYS: Explain "why" in comments
// We batch updates here to prevent cascading re-renders
// when multiple inputs change in the same frame
this.scheduleAfterInputsHaveUpdated(() => {
// ...
});
```
### React Patterns
```typescript
// ✅ PREFER: Functional components with hooks
export function MyComponent({ value, onChange }: MyComponentProps) {
const [state, setState] = useState(value);
const handleChange = useCallback((newValue: string) => {
setState(newValue);
onChange?.(newValue);
}, [onChange]);
return <input value={state} onChange={e => handleChange(e.target.value)} />;
}
// ❌ AVOID: Class components (unless lifecycle methods required)
class MyComponent extends React.Component {
// ...
}
```
### Import Organization
```typescript
// 1. External packages
import React, { useState, useCallback } from 'react';
import classNames from 'classnames';
// 2. Internal packages (alphabetical by alias)
import { IconName } from '@noodl-core-ui/components/common/Icon';
import { NodeGraphModel } from '@noodl-models/nodegraphmodel';
import { guid } from '@noodl-utils/utils';
// 3. Relative imports
import { localHelper } from './helpers';
import { MyComponentProps } from './types';
// 4. Styles last
import css from './MyComponent.module.scss';
```
## Task Execution Protocol
### Starting Work
1. Read the full task README.md
2. Check off prerequisites in CHECKLIST.md
3. Create your branch: `git checkout -b task/XXX-name`
4. State: "Starting TASK-XXX. Confidence: X/10. Assumptions: [list]"
### During Work
1. Make incremental changes
2. Test frequently: `npm run build:editor`
3. Document changes in CHANGELOG.md as you go
4. Commit logical chunks with descriptive messages
### Before Completing
1. Run full test suite: `npm run test:editor`
2. Run type check: `npx tsc --noEmit`
3. Review all changes against the checklist
4. Update CHANGELOG.md with final summary
## Confidence Checks
Rate your confidence (1-10) at these points:
- Before starting a task
- Before making significant changes
- After completing each checklist item
- Before marking task complete
If confidence < 7:
- List what's uncertain
- Ask for clarification
- Research existing patterns in codebase
## Error Recovery
When something goes wrong:
1. **Don't panic** - state what happened clearly
2. **Check the error** - read the full message
3. **Search codebase** - look for similar patterns
4. **Check common issues** - `dev-docs/reference/COMMON-ISSUES.md`
5. **Ask for help** - provide context and what you've tried
## Prohibited Actions
- ❌ Modifying `node_modules/`, `build/`, `dist/`
- ❌ Adding `any` or `TSFixme` types
- ❌ Committing without running tests
- ❌ Making changes outside task scope without asking
- ❌ Deleting code without understanding why it exists
- ❌ Guessing when uncertain (ask instead)
## Helpful Prompts
Use these phrases to maintain quality:
- "Before I continue, let me verify my understanding..."
- "Confidence level: X/10 because..."
- "I notice [pattern] in the existing code, I'll follow that..."
- "This change might affect [X], should I check?"
- "I'm uncertain about [X], can you clarify?"
## Project-Specific Knowledge
### Key Models
- `ProjectModel` - Project state, components, settings
- `NodeGraphModel` - Graph structure, connections
- `ComponentModel` - Individual component definition
- `NodeLibrary` - Available node types
### Key Patterns
- Event system: `model.on('event', handler)` / `model.off(handler)`
- Dirty flagging: `this.flagOutputDirty('outputName')`
- Scheduled updates: `this.scheduleAfterInputsHaveUpdated(() => {})`
### Key Directories
- Editor UI: `packages/noodl-editor/src/editor/src/views/`
- Models: `packages/noodl-editor/src/editor/src/models/`
- Runtime nodes: `packages/noodl-runtime/src/nodes/`
- Visual nodes: `packages/noodl-viewer-react/src/nodes/`
- UI components: `packages/noodl-core-ui/src/components/`

122
dev-docs/README.md Normal file
View File

@@ -0,0 +1,122 @@
# OpenNoodl Development Documentation
Welcome to the OpenNoodl development docs. This folder contains everything needed for AI-assisted development with Cline and human contributors alike.
## 📁 Structure
```
dev-docs/
├── .clinerules # Project rules (copy to repo root)
├── README.md # This file
├── CLINE-INSTRUCTIONS.md # Custom instructions for Cline
├── TASK-TEMPLATE.md # Template for creating new tasks
├── guidelines/ # Development standards
│ ├── CODING-STANDARDS.md # Code style and patterns
│ ├── TESTING-GUIDE.md # How to write tests
│ └── GIT-WORKFLOW.md # Branch and commit conventions
├── reference/ # Quick reference materials
│ ├── CODEBASE-MAP.md # Navigate the codebase
│ ├── NODE-PATTERNS.md # How to create nodes
│ └── COMMON-ISSUES.md # Troubleshooting guide
└── tasks/ # Task documentation
├── phase-1/ # Foundation tasks
│ ├── TASK-001-dependency-updates/
│ ├── TASK-002-typescript-cleanup/
│ └── ...
├── phase-2/ # Navigation & data tasks
└── phase-3/ # UX & integration tasks
```
## 🚀 Getting Started
### For Cline Users
1. **Copy `.clinerules` to repo root**
```bash
cp dev-docs/.clinerules .clinerules
```
2. **Add custom instructions to Cline**
- Open VSCode → Cline extension settings
- Paste contents of `CLINE-INSTRUCTIONS.md` into Custom Instructions
3. **Pick a task**
- Browse `tasks/` folders
- Each task has its own folder with detailed instructions
- Start with Phase 1 tasks (they're prerequisites for later phases)
### For Human Contributors
1. Read `guidelines/CODING-STANDARDS.md`
2. Check `reference/CODEBASE-MAP.md` to understand the project
3. Pick a task from `tasks/` and follow its documentation
## 📋 Task Workflow
### Starting a Task
1. **Read the task documentation completely**
```
tasks/phase-X/TASK-XXX-name/
├── README.md # Full task description
├── CHECKLIST.md # Step-by-step checklist
├── CHANGELOG.md # Track your changes here
└── NOTES.md # Your working notes
```
2. **Create a branch**
```bash
git checkout -b task/XXX-short-name
```
3. **Follow the checklist**, checking off items as you go
4. **Document everything** in CHANGELOG.md
### Completing a Task
1. Ensure all checklist items are complete
2. Run tests: `npm run test:editor`
3. Run type check: `npx tsc --noEmit`
4. Update CHANGELOG.md with final summary
5. Create pull request with task ID in title
## 🎯 Current Priorities
### Phase 1: Foundation (Do First)
- [ ] TASK-001: Dependency Updates & Build Modernization
- [ ] TASK-002: TypeScript Cleanup & Type Safety
### Phase 2: Core Systems
- [ ] TASK-003: Navigation System Overhaul
- [ ] TASK-004: Data Nodes Modernization
### Phase 3: UX Polish
- [ ] TASK-005: Property Panel Overhaul
- [ ] TASK-006: Import/Export Redesign
- [ ] TASK-007: REST API Improvements
## 📚 Key Resources
| Resource | Description |
|----------|-------------|
| [Codebase Map](reference/CODEBASE-MAP.md) | Navigate the monorepo |
| [Coding Standards](guidelines/CODING-STANDARDS.md) | Style and patterns |
| [Node Patterns](reference/NODE-PATTERNS.md) | Creating new nodes |
| [Common Issues](reference/COMMON-ISSUES.md) | Troubleshooting |
## 🤝 Contributing
1. Pick an unassigned task or create a new one using `TASK-TEMPLATE.md`
2. Follow the task documentation precisely
3. Document all changes in the task's CHANGELOG.md
4. Submit PR with comprehensive description
## ❓ Questions?
- Check `reference/COMMON-ISSUES.md` first
- Search existing task documentation
- Open an issue on GitHub with the `question` label

View File

@@ -0,0 +1,101 @@
# OpenNoodl Dev Docs - Setup Instructions
## What's Included
This folder contains everything needed to set up AI-assisted development with Cline for the OpenNoodl project.
## Files to Add to Repository
Copy these to the **root** of your OpenNoodl repository:
```
OpenNoodl/
├── .clinerules ← Copy from dev-docs/.clinerules
├── .clineignore ← Copy from .clineignore (separate file)
└── dev-docs/ ← Copy entire folder
├── README.md
├── CLINE-INSTRUCTIONS.md
├── TASK-TEMPLATE.md
├── guidelines/
│ ├── CODING-STANDARDS.md
│ └── GIT-WORKFLOW.md
├── reference/
│ ├── CODEBASE-MAP.md
│ ├── NODE-PATTERNS.md
│ └── COMMON-ISSUES.md
└── tasks/
└── phase-1/
└── TASK-001-dependency-updates/
├── README.md
├── CHECKLIST.md
├── CHANGELOG.md
└── NOTES.md
```
## Setup Steps
### 1. Create Branch
```bash
git checkout -b setup/dev-docs
```
### 2. Copy Files
```bash
# Copy .clinerules to repo root
cp path/to/downloads/.clinerules .
# Copy .clineignore to repo root
cp path/to/downloads/.clineignore .
# Copy dev-docs folder to repo root
cp -r path/to/downloads/dev-docs .
```
### 3. Configure Cline
1. Open VSCode with the OpenNoodl project
2. Click Cline extension settings (gear icon)
3. Find "Custom Instructions" field
4. Copy contents of `dev-docs/CLINE-INSTRUCTIONS.md` and paste
### 4. Commit
```bash
git add .clinerules .clineignore dev-docs/
git commit -m "docs: add AI-assisted development documentation"
git push -u origin setup/dev-docs
```
### 5. Start Working
1. Open a task: `dev-docs/tasks/phase-1/TASK-001-dependency-updates/`
2. Read the README.md
3. Follow the CHECKLIST.md
4. Track changes in CHANGELOG.md
5. Keep notes in NOTES.md
## File Purposes
| File | Purpose |
|------|---------|
| `.clinerules` | Project-specific rules Cline follows automatically |
| `.clineignore` | Files/folders Cline should ignore (like .gitignore) |
| `CLINE-INSTRUCTIONS.md` | Custom instructions to paste into Cline settings |
| `TASK-TEMPLATE.md` | Template for creating new task documentation |
| `guidelines/` | Development standards (coding, git workflow) |
| `reference/` | Quick references (codebase map, patterns, troubleshooting) |
| `tasks/` | Task documentation organized by phase |
## Creating New Tasks
1. Copy `TASK-TEMPLATE.md` sections to new folder
2. Follow naming: `TASK-XXX-short-name/`
3. Fill in all sections of README.md
4. Create the checklist specific to the task
5. Initialize empty CHANGELOG.md and NOTES.md
## Questions?
See `dev-docs/reference/COMMON-ISSUES.md` for troubleshooting.

273
dev-docs/TASK-TEMPLATE.md Normal file
View File

@@ -0,0 +1,273 @@
# Task Template
Use this template to create new task documentation. Copy the entire `TASK-XXX-template/` folder and rename it.
## Folder Structure
```
tasks/phase-N/TASK-XXX-short-name/
├── README.md # Full task description (this template)
├── CHECKLIST.md # Step-by-step checklist
├── CHANGELOG.md # Track changes made
└── NOTES.md # Working notes and discoveries
```
---
# README.md Template
```markdown
# TASK-XXX: [Task Title]
## Metadata
| Field | Value |
|-------|-------|
| **ID** | TASK-XXX |
| **Phase** | Phase N |
| **Priority** | 🔴 Critical / 🟠 High / 🟡 Medium / 🟢 Low |
| **Difficulty** | 🔴 Hard / 🟡 Medium / 🟢 Easy |
| **Estimated Time** | X hours/days |
| **Prerequisites** | TASK-YYY, TASK-ZZZ |
| **Branch** | `task/XXX-short-name` |
## Objective
[One clear sentence describing what this task accomplishes]
## Background
[2-3 paragraphs explaining:
- Why this task is needed
- What problems it solves
- How it fits into the bigger picture]
## Current State
[Describe what exists today:
- Current behavior
- Known issues/bugs
- User pain points
- Technical debt]
## Desired State
[Describe the end goal:
- Expected behavior after completion
- User experience improvements
- Technical improvements]
## Scope
### In Scope
- [ ] Item 1
- [ ] Item 2
- [ ] Item 3
### Out of Scope
- Item A (reason)
- Item B (reason)
## Technical Approach
### Key Files to Modify
| File | Changes |
|------|---------|
| `path/to/file1.ts` | [What changes] |
| `path/to/file2.tsx` | [What changes] |
### New Files to Create
| File | Purpose |
|------|---------|
| `path/to/newfile.ts` | [Purpose] |
### Dependencies
- [ ] Requires TASK-XXX to be completed first
- [ ] New npm package: `package-name@version`
## Implementation Steps
### Step 1: [Name]
[Detailed description of what to do]
### Step 2: [Name]
[Detailed description of what to do]
### Step 3: [Name]
[Detailed description of what to do]
## Testing Plan
### Unit Tests
- [ ] Test: [Description]
- [ ] Test: [Description]
### Integration Tests
- [ ] Test: [Description]
### Manual Testing
- [ ] Scenario: [Description]
- [ ] Scenario: [Description]
## Success Criteria
- [ ] Criterion 1
- [ ] Criterion 2
- [ ] All tests pass
- [ ] No TypeScript errors
- [ ] Documentation updated
## Risks & Mitigations
| Risk | Mitigation |
|------|------------|
| [Risk 1] | [How to mitigate] |
| [Risk 2] | [How to mitigate] |
## Rollback Plan
[How to revert if something goes wrong]
## References
- [Link to relevant docs]
- [Link to related issues]
- [Link to design specs]
```
---
# CHECKLIST.md Template
```markdown
# TASK-XXX Checklist
## Prerequisites
- [ ] Read README.md completely
- [ ] Understand the scope and success criteria
- [ ] Create branch: `git checkout -b task/XXX-short-name`
- [ ] Verify build works: `npm run build:editor`
## Phase 1: Research & Planning
- [ ] Identify all files that need changes
- [ ] Review existing patterns in codebase
- [ ] List assumptions and validate them
- [ ] Update NOTES.md with findings
## Phase 2: Implementation
- [ ] Step 1: [Description]
- [ ] Sub-step A
- [ ] Sub-step B
- [ ] Document in CHANGELOG.md
- [ ] Step 2: [Description]
- [ ] Sub-step A
- [ ] Sub-step B
- [ ] Document in CHANGELOG.md
- [ ] Step 3: [Description]
- [ ] Sub-step A
- [ ] Sub-step B
- [ ] Document in CHANGELOG.md
## Phase 3: Testing
- [ ] Write unit tests
- [ ] Write integration tests
- [ ] Run full test suite: `npm run test:editor`
- [ ] Run type check: `npx tsc --noEmit`
- [ ] Manual testing scenarios
## Phase 4: Documentation
- [ ] Add JSDoc to new public functions
- [ ] Update README if behavior changed
- [ ] Complete CHANGELOG.md with summary
- [ ] Update dev-docs if needed
## Phase 5: Completion
- [ ] Self-review all changes
- [ ] Verify all success criteria met
- [ ] Clean up any debug code
- [ ] Create pull request
- [ ] Mark task as complete
```
---
# CHANGELOG.md Template
```markdown
# TASK-XXX Changelog
## [Date] - [Your Name/Handle]
### Summary
[Brief summary of what was accomplished]
### Files Modified
- `path/to/file.ts` - [What changed and why]
- `path/to/file2.tsx` - [What changed and why]
### Files Created
- `path/to/newfile.ts` - [Purpose]
### Files Deleted
- `path/to/oldfile.ts` - [Why removed]
### Breaking Changes
- [Any breaking changes and migration path]
### Testing Notes
- [What was tested]
- [Any edge cases discovered]
### Known Issues
- [Any remaining issues or follow-up needed]
### Notes
- [Any other relevant information]
```
---
# NOTES.md Template
```markdown
# TASK-XXX Working Notes
## Research
### Existing Patterns Found
- [Pattern 1]: Found in `path/to/file.ts`
- [Pattern 2]: Found in `path/to/file2.ts`
### Questions to Resolve
- [ ] Question 1?
- [ ] Question 2?
### Assumptions
- Assumption 1: [Description] - ✅ Validated / ❓ Pending
- Assumption 2: [Description] - ✅ Validated / ❓ Pending
## Implementation Notes
### Approach Decisions
- Decided to [approach] because [reason]
- Rejected [alternative] because [reason]
### Gotchas / Surprises
- [Something unexpected discovered]
### Useful Commands
```bash
# Commands that were helpful
grep -r "pattern" packages/
```
## Debug Log
### [Date/Time]
- Trying: [what you're attempting]
- Result: [what happened]
- Next: [what to try next]
```

View File

@@ -0,0 +1,474 @@
# OpenNoodl Coding Standards
This document defines the coding style and patterns for OpenNoodl development.
## TypeScript Standards
### Type Safety
```typescript
// ✅ DO: Explicit types
function processNode(node: NodeGraphNode): ProcessResult {
return { success: true, data: node.data };
}
// ❌ DON'T: Any types
function processNode(node: any): any {
return { success: true, data: node.data };
}
// ❌ DON'T: TSFixme
function processNode(node: TSFixme): TSFixme {
return { success: true, data: node.data };
}
```
### When Type is Truly Unknown
```typescript
// ✅ DO: Use unknown and narrow
function handleData(data: unknown): string {
if (typeof data === 'string') {
return data;
}
if (typeof data === 'object' && data !== null && 'message' in data) {
return String((data as { message: unknown }).message);
}
return String(data);
}
// ✅ DO: Document why if using any (rare)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// Any required here because external library doesn't export types
function handleExternalLib(input: any): void {
externalLib.process(input);
}
```
### Interface Definitions
```typescript
// ✅ DO: Define interfaces for data structures
interface NodeConfig {
name: string;
displayName: string;
category: string;
inputs: Record<string, InputDefinition>;
outputs: Record<string, OutputDefinition>;
}
// ✅ DO: Use type for unions/aliases
type NodeColor = 'data' | 'logic' | 'visual' | 'component';
// ✅ DO: Export types from dedicated files
// types.ts
export interface MyComponentProps {
value: string;
onChange: (value: string) => void;
}
```
## React Standards
### Functional Components
```typescript
// ✅ DO: Functional components with typed props
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
export function Button({ label, onClick, disabled = false }: ButtonProps) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}
// ❌ DON'T: Class components (unless lifecycle methods required)
class Button extends React.Component<ButtonProps> {
render() {
return <button>{this.props.label}</button>;
}
}
```
### Hooks Usage
```typescript
// ✅ DO: Proper hook dependencies
const handleChange = useCallback((value: string) => {
onChange(value);
onValidate?.(value);
}, [onChange, onValidate]);
// ✅ DO: Cleanup in effects
useEffect(() => {
const handler = (e: Event) => { /* ... */ };
window.addEventListener('resize', handler);
return () => window.removeEventListener('resize', handler);
}, []);
// ❌ DON'T: Missing dependencies
const handleChange = useCallback((value: string) => {
onChange(value); // onChange not in deps!
}, []);
```
### Component Organization
```typescript
// Component file structure
import React, { useState, useCallback, useEffect } from 'react';
// External imports
import classNames from 'classnames';
// Internal imports
import { Icon, IconName } from '@noodl-core-ui/components/common/Icon';
import { useModel } from '@noodl-utils/hooks';
// Relative imports
import { ButtonProps } from './types';
import { validateInput } from './utils';
// Styles last
import css from './Button.module.scss';
// Types (if not in separate file)
interface LocalState {
isHovered: boolean;
}
// Component
export function Button({ label, onClick, variant = 'primary' }: ButtonProps) {
// Hooks first
const [state, setState] = useState<LocalState>({ isHovered: false });
const model = useModel(SomeModel.instance);
// Callbacks
const handleClick = useCallback(() => {
onClick();
}, [onClick]);
// Effects
useEffect(() => {
// Setup
return () => {
// Cleanup
};
}, []);
// Render helpers
const buttonClass = classNames(css.Button, css[variant]);
// Render
return (
<button className={buttonClass} onClick={handleClick}>
{label}
</button>
);
}
```
## File Organization
### Directory Structure
```
feature/
├── index.ts # Public exports only
├── FeatureName.tsx # Main component
├── FeatureName.module.scss
├── FeatureName.test.ts
├── types.ts # Type definitions
├── utils.ts # Helper functions
└── hooks.ts # Custom hooks (if any)
```
### Index Files (Barrel Exports)
```typescript
// index.ts - Export only public API
export { FeatureName } from './FeatureName';
export type { FeatureNameProps } from './types';
// DON'T export internal utilities
```
### Import Order
```typescript
// 1. React
import React, { useState, useEffect } from 'react';
// 2. External packages (alphabetical)
import classNames from 'classnames';
import { motion } from 'framer-motion';
// 3. Internal packages (alphabetical by alias)
import { Icon } from '@noodl-core-ui/components/common/Icon';
import { NodeGraphModel } from '@noodl-models/nodegraphmodel';
import { guid } from '@noodl-utils/utils';
// 4. Relative imports (parent first, then siblings)
import { ParentComponent } from '../ParentComponent';
import { SiblingComponent } from './SiblingComponent';
import { localHelper } from './utils';
// 5. Types (if separate import needed)
import type { MyComponentProps } from './types';
// 6. Styles
import css from './MyComponent.module.scss';
```
## Documentation Standards
### JSDoc for Public APIs
```typescript
/**
* Processes a node and returns the computed result.
*
* @param node - The node to process
* @param options - Processing options
* @returns The computed result with output values
*
* @example
* ```typescript
* const result = processNode(myNode, { validate: true });
* console.log(result.outputs);
* ```
*/
export function processNode(
node: NodeGraphNode,
options: ProcessOptions = {}
): ProcessResult {
// Implementation
}
```
### File Headers
```typescript
/**
* NodeGraphModel - Manages the structure of a node graph.
*
* This model handles:
* - Node creation and deletion
* - Connection management
* - Graph traversal
*
* @module models/NodeGraphModel
*/
```
### Inline Comments
```typescript
// ✅ DO: Explain "why", not "what"
// We batch updates here to prevent cascading re-renders
// when multiple inputs change in the same frame
this.scheduleAfterInputsHaveUpdated(() => {
this.processAllInputs();
});
// ❌ DON'T: State the obvious
// Loop through items
for (const item of items) {
// Process item
process(item);
}
```
## Naming Conventions
### Files
| Type | Convention | Example |
|------|------------|---------|
| React Component | PascalCase | `NodePicker.tsx` |
| Utility | camelCase | `formatUtils.ts` |
| Types | camelCase or PascalCase | `types.ts` or `NodeTypes.ts` |
| Test | Match source + `.test` | `NodePicker.test.ts` |
| Styles | Match component + `.module` | `NodePicker.module.scss` |
### Code
```typescript
// Constants: UPPER_SNAKE_CASE
const MAX_RETRY_COUNT = 3;
const DEFAULT_TIMEOUT_MS = 5000;
// Functions/Methods: camelCase
function processNodeGraph() {}
function calculateOffset() {}
// Classes/Interfaces/Types: PascalCase
class NodeGraphModel {}
interface ProcessOptions {}
type NodeColor = 'data' | 'logic';
// Private members: underscore prefix
class MyClass {
private _internalState: State;
private _processInternal(): void {}
}
// Boolean variables: is/has/should prefix
const isEnabled = true;
const hasChildren = node.children.length > 0;
const shouldUpdate = isDirty && isVisible;
```
## Error Handling
```typescript
// ✅ DO: Specific error types
class NodeNotFoundError extends Error {
constructor(nodeId: string) {
super(`Node not found: ${nodeId}`);
this.name = 'NodeNotFoundError';
}
}
// ✅ DO: Handle errors gracefully
async function fetchData(): Promise<Result> {
try {
const response = await api.fetch();
return { success: true, data: response };
} catch (error) {
console.error('Failed to fetch data:', error);
return { success: false, error: getErrorMessage(error) };
}
}
// ✅ DO: Type-safe error messages
function getErrorMessage(error: unknown): string {
if (error instanceof Error) return error.message;
return String(error);
}
```
## Testing Standards
### Test File Structure
```typescript
import { render, screen, fireEvent } from '@testing-library/react';
import { MyComponent } from './MyComponent';
describe('MyComponent', () => {
// Group related tests
describe('rendering', () => {
it('should render with default props', () => {
render(<MyComponent />);
expect(screen.getByRole('button')).toBeInTheDocument();
});
});
describe('interactions', () => {
it('should call onClick when clicked', () => {
const onClick = jest.fn();
render(<MyComponent onClick={onClick} />);
fireEvent.click(screen.getByRole('button'));
expect(onClick).toHaveBeenCalledTimes(1);
});
});
});
```
### Test Naming
```typescript
// ✅ DO: Descriptive test names
it('should display error message when validation fails', () => {});
it('should disable submit button while loading', () => {});
// ❌ DON'T: Vague names
it('works', () => {});
it('test 1', () => {});
```
## Git Commit Messages
### Format
```
type(scope): description
[optional body]
[optional footer]
```
### Types
- `feat`: New feature
- `fix`: Bug fix
- `refactor`: Code change that neither fixes bug nor adds feature
- `docs`: Documentation only
- `test`: Adding or updating tests
- `chore`: Build process or auxiliary tool changes
### Examples
```
feat(editor): add breakpoint support to connections
fix(runtime): resolve memory leak in collection listener
refactor(property-panel): convert to functional component
docs(readme): update installation instructions
test(nodes): add unit tests for REST node
```
## Performance Guidelines
### React Performance
```typescript
// ✅ DO: Memoize expensive computations
const sortedItems = useMemo(() => {
return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);
// ✅ DO: Memoize callbacks passed to children
const handleChange = useCallback((value: string) => {
onChange(value);
}, [onChange]);
// ✅ DO: Use React.memo for pure components
export const ListItem = React.memo(function ListItem({ item }: Props) {
return <div>{item.name}</div>;
});
```
### General Performance
```typescript
// ✅ DO: Batch DOM operations
function updateNodes(nodes: Node[]) {
// Collect all changes first
const changes = nodes.map(calculateChange);
// Apply in single batch
requestAnimationFrame(() => {
changes.forEach(applyChange);
});
}
// ✅ DO: Debounce frequent events
const debouncedSearch = useMemo(
() => debounce((query: string) => performSearch(query), 300),
[]
);
```

View File

@@ -0,0 +1,332 @@
# Git Workflow Guide
How to manage branches, commits, and pull requests for OpenNoodl development.
## Branch Naming
### Format
```
type/id-short-description
```
### Types
| Type | Use For | Example |
|------|---------|---------|
| `task` | Task documentation work | `task/001-dependency-updates` |
| `feature` | New features | `feature/vercel-deployment` |
| `fix` | Bug fixes | `fix/page-router-scroll` |
| `refactor` | Code improvements | `refactor/property-panel-hooks` |
| `docs` | Documentation only | `docs/api-reference` |
| `test` | Test additions | `test/rest-node-coverage` |
### Examples
```bash
# Task branches (from dev-docs)
git checkout -b task/001-dependency-updates
git checkout -b task/002-typescript-cleanup
# Feature branches
git checkout -b feature/add-oauth-support
git checkout -b feature/multi-project-windows
# Fix branches
git checkout -b fix/nested-router-scroll
git checkout -b fix/array-change-tracking
# Refactor branches
git checkout -b refactor/remove-class-components
git checkout -b refactor/data-node-architecture
```
## Commit Messages
### Format
```
type(scope): short description
[optional longer description]
[optional footer with references]
```
### Types
- `feat` - New feature
- `fix` - Bug fix
- `refactor` - Code restructuring (no behavior change)
- `docs` - Documentation changes
- `test` - Test additions/changes
- `chore` - Build/tooling changes
- `style` - Formatting (no code change)
- `perf` - Performance improvement
### Scopes
Use the affected area:
- `editor` - Main editor code
- `runtime` - Runtime engine
- `viewer` - Viewer/preview
- `ui` - Core UI components
- `build` - Build system
- `deps` - Dependencies
### Examples
```bash
# Features
git commit -m "feat(editor): add connection breakpoints"
git commit -m "feat(runtime): implement retry logic for REST node"
# Fixes
git commit -m "fix(viewer): resolve scroll jumping in nested routers"
git commit -m "fix(editor): prevent crash when deleting connected node"
# Refactoring
git commit -m "refactor(ui): convert PropertyPanel to functional component"
git commit -m "refactor(runtime): simplify collection change tracking"
# Docs
git commit -m "docs(readme): update installation instructions"
git commit -m "docs(api): add JSDoc to public methods"
# Tests
git commit -m "test(runtime): add unit tests for REST node"
git commit -m "test(editor): add integration tests for import flow"
# Chores
git commit -m "chore(deps): update webpack to 5.101.3"
git commit -m "chore(build): enable source maps in development"
```
### Multi-line Commits
For complex changes:
```bash
git commit -m "feat(editor): add AI-powered node suggestions
- Integrate with OpenAI API for code analysis
- Add suggestion UI in node picker
- Cache suggestions for performance
Closes #123"
```
## Workflow
### Starting Work
```bash
# 1. Ensure main is up to date
git checkout main
git pull origin main
# 2. Create your branch
git checkout -b task/001-dependency-updates
# 3. Make your changes...
# 4. Stage and commit frequently
git add -A
git commit -m "feat(deps): update React to v19"
```
### During Development
```bash
# Check status often
git status
# View your changes
git diff
# Stage specific files
git add packages/noodl-editor/package.json
# Commit logical chunks
git commit -m "fix(deps): resolve peer dependency conflicts"
# Push to remote (first time)
git push -u origin task/001-dependency-updates
# Push subsequent commits
git push
```
### Keeping Up to Date
```bash
# If main has changed, rebase your work
git fetch origin
git rebase origin/main
# Resolve any conflicts, then continue
git add .
git rebase --continue
# Force push after rebase (your branch only!)
git push --force-with-lease
```
### Creating Pull Request
1. Push your branch to remote
2. Go to GitHub repository
3. Click "New Pull Request"
4. Select your branch
5. Fill in the template:
```markdown
## Summary
Brief description of changes
## Task Reference
TASK-001: Dependency Updates
## Changes Made
- Updated React to v19
- Fixed peer dependency conflicts
- Migrated to createRoot API
## Testing
- [ ] All existing tests pass
- [ ] Manual testing completed
- [ ] New tests added (if applicable)
## Checklist
- [ ] Code follows style guidelines
- [ ] Documentation updated
- [ ] CHANGELOG.md updated
- [ ] No console.log statements
```
### After PR Merged
```bash
# Switch to main
git checkout main
# Pull the merged changes
git pull origin main
# Delete your local branch
git branch -d task/001-dependency-updates
# Delete remote branch (if not auto-deleted)
git push origin --delete task/001-dependency-updates
```
## Common Scenarios
### Oops, Wrong Branch
```bash
# Stash your changes
git stash
# Switch to correct branch
git checkout correct-branch
# Apply your changes
git stash pop
```
### Need to Undo Last Commit
```bash
# Undo commit but keep changes
git reset --soft HEAD~1
# Undo commit and discard changes
git reset --hard HEAD~1
```
### Need to Update Commit Message
```bash
# Most recent commit
git commit --amend -m "new message"
# Older commit (interactive rebase)
git rebase -i HEAD~3
# Change 'pick' to 'reword' for the commit
```
### Accidentally Committed to Main
```bash
# Create a branch with your commits
git branch my-feature
# Reset main to origin
git reset --hard origin/main
# Switch to your feature branch
git checkout my-feature
```
### Merge Conflicts
```bash
# During rebase or merge, if conflicts occur:
# 1. Open conflicted files and resolve
# Look for <<<<<<< ======= >>>>>>> markers
# 2. Stage resolved files
git add resolved-file.ts
# 3. Continue the rebase/merge
git rebase --continue
# or
git merge --continue
```
## Branch Protection
The `main` branch has these protections:
- Requires pull request
- Requires passing CI checks
- Requires up-to-date branch
- No force pushes allowed
## Tips
### Useful Aliases
Add to your `~/.gitconfig`:
```ini
[alias]
st = status
co = checkout
br = branch
ci = commit
lg = log --oneline --graph --all
unstage = reset HEAD --
last = log -1 HEAD
branches = branch -a
```
### Before Every PR
1. Run tests: `npm run test:editor`
2. Run type check: `npx tsc --noEmit`
3. Run linter: `npx eslint packages/ --fix`
4. Review your diff: `git diff main`
5. Check commit history: `git log --oneline main..HEAD`
### Good Commit Hygiene
- Commit early and often
- Each commit should be atomic (one logical change)
- Commits should compile and pass tests
- Write meaningful commit messages
- Don't commit generated files
- Don't commit debug code

View File

@@ -0,0 +1,378 @@
# OpenNoodl Codebase Quick Navigation
## 🗺️ Package Map
```
┌─────────────────────────────────────────────────────────────────────────┐
│ MONOREPO ROOT │
├─────────────────────────────────────────────────────────────────────────┤
│ package.json → Workspace config, global scripts │
│ lerna.json → Monorepo management │
│ scripts/ → Build and CI scripts │
└─────────────────────────────────────────────────────────────────────────┘
┌───────────────────────────┼───────────────────────────┐
▼ ▼ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ EDITOR (GPL) │ │ RUNTIME (MIT) │ │ UI LIBRARY │
│ noodl-editor │ │ noodl-runtime │ │ noodl-core-ui │
│ │ │ │ │ │
│ • Electron app │ │ • Node engine │ │ • React components│
│ • React UI │ │ • Data flow │ │ • Storybook │
│ • Property panels │ │ • Event system │ │ • Styling │
└───────────────────┘ └───────────────────┘ └───────────────────┘
│ │
│ ▼
│ ┌───────────────────┐
│ │ VIEWER (MIT) │
│ │ noodl-viewer-react│
│ │ │
│ │ • React runtime │
│ │ • Visual nodes │
│ │ • DOM handling │
│ └───────────────────┘
┌───────────────────────────────────────────────────────────────────────┐
│ PLATFORM LAYER │
├───────────────────┬───────────────────┬───────────────────────────────┤
│ noodl-platform │ platform-electron │ platform-node │
│ (abstraction) │ (desktop impl) │ (server impl) │
└───────────────────┴───────────────────┴───────────────────────────────┘
```
---
## 📁 Key Directories
### noodl-editor (Main Application)
```
packages/noodl-editor/src/
├── editor/src/
│ ├── models/ # 🎯 Business logic & data
│ │ ├── projectmodel.ts → Project state
│ │ ├── nodegraphmodel.ts → Graph structure
│ │ ├── componentmodel.ts → Components
│ │ ├── nodelibrary/ → Node type registry
│ │ ├── AiAssistant/ → AI features
│ │ └── sidebar/ → Sidebar state
│ │
│ ├── views/ # 🖥️ UI components
│ │ ├── nodegrapheditor.ts → Canvas/graph editor
│ │ ├── panels/ → Property panels
│ │ ├── NodePicker/ → Node creation UI
│ │ ├── documents/ → Document views
│ │ └── popups/ → Modal dialogs
│ │
│ ├── utils/ # 🔧 Utilities
│ │ ├── CodeEditor/ → Monaco integration
│ │ ├── filesystem.ts → File operations
│ │ └── projectimporter.js → Import/export
│ │
│ ├── store/ # 💾 Persistent state
│ │ └── AiAssistantStore.ts → AI settings
│ │
│ └── pages/ # 📄 Page components
│ └── EditorPage/ → Main editor page
├── main/ # ⚡ Electron main process
│ └── main.js → App entry point
└── shared/ # 🔗 Shared utilities
└── utils/
└── EventDispatcher.ts → Pub/sub system
```
### noodl-runtime (Execution Engine)
```
packages/noodl-runtime/
├── src/
│ ├── nodes/ # 📦 Node implementations
│ │ └── std-library/
│ │ ├── data/ → Data nodes (REST, DB, etc.)
│ │ ├── logic/ → Logic nodes
│ │ └── events/ → Event nodes
│ │
│ ├── node.js # Base node class
│ ├── nodedefinition.js # Node definition API
│ ├── noderegister.js # Node registry
│ ├── nodescope.js # Component scope
│ └── nodecontext.js # Runtime context
└── noodl-runtime.js # Main runtime entry
```
### noodl-viewer-react (React Runtime)
```
packages/noodl-viewer-react/src/
├── nodes/ # 🎨 Visual nodes
│ ├── basic/ → Group, Text, Image
│ ├── controls/ → Button, Input, Checkbox
│ ├── navigation/ → PageRouter, Page
│ └── std-library/ → Standard library nodes
└── react-component-node.js # React node wrapper
```
### noodl-core-ui (Component Library)
```
packages/noodl-core-ui/src/
├── components/
│ ├── common/ # 🧩 Basic components
│ │ ├── Icon/
│ │ └── ActivityIndicator/
│ │
│ ├── inputs/ # 📝 Form controls
│ │ ├── TextInput/
│ │ ├── PrimaryButton/
│ │ └── Checkbox/
│ │
│ ├── layout/ # 📐 Layout components
│ │ ├── Box/
│ │ ├── Container/
│ │ └── Tabs/
│ │
│ ├── popups/ # 💬 Dialogs & menus
│ │ ├── MenuDialog/
│ │ └── PopupToolbar/
│ │
│ └── ai/ # 🤖 AI UI components
│ ├── AiChatBox/
│ └── AiChatMessage/
└── styles/ # 🎨 Global styles
```
---
## 🔍 Finding Things
### Search Patterns
```bash
# Find a file by name
find packages/ -name "*NodeGraph*" -type f
# Find where a function is defined
grep -rn "function processNode" packages/
# Find where something is imported/used
grep -r "import.*from.*nodegraphmodel" packages/
# Find all usages of a component
grep -r "<NodeEditor" packages/ --include="*.tsx"
# Find TODO/FIXME comments
grep -rn "TODO\|FIXME" packages/noodl-editor/src
```
### Common Search Targets
| Looking for... | Search pattern |
|----------------|----------------|
| Node definitions | `packages/noodl-runtime/src/nodes/` |
| React visual nodes | `packages/noodl-viewer-react/src/nodes/` |
| UI components | `packages/noodl-core-ui/src/components/` |
| Models/state | `packages/noodl-editor/src/editor/src/models/` |
| Property panels | `packages/noodl-editor/src/editor/src/views/panels/` |
| Tests | `packages/noodl-editor/tests/` |
---
## 🚀 Quick Commands
### Development
```bash
# Start everything
npm run dev
# Start just the editor (faster)
npm run start:editor
# Start Storybook (UI components)
npm run start:storybook
# Start viewer dev server
npm run start:viewer
```
### Building
```bash
# Build editor
npm run build:editor
# Create distributable package
npm run build:editor:pack
# Build cloud runtime
npm run build:cloud-runtime
```
### Testing
```bash
# Run all editor tests
npm run test:editor
# Run platform tests
npm run test:platform
```
### Code Quality
```bash
# Type check
npx tsc --noEmit
# Lint
npx eslint packages/noodl-editor/src
# Format
npx prettier --write "packages/**/*.{ts,tsx}"
```
---
## 🔗 Key Files Reference
### Configuration
| File | Purpose |
|------|---------|
| `package.json` | Root workspace config |
| `lerna.json` | Monorepo settings |
| `tsconfig.json` | TypeScript config |
| `.eslintrc.js` | Linting rules |
| `.prettierrc` | Code formatting |
### Entry Points
| File | Purpose |
|------|---------|
| `noodl-editor/src/main/main.js` | Electron main process |
| `noodl-editor/src/editor/src/index.js` | Renderer entry |
| `noodl-runtime/noodl-runtime.js` | Runtime engine |
| `noodl-viewer-react/index.js` | React runtime |
### Core Models
| File | Purpose |
|------|---------|
| `projectmodel.ts` | Project state management |
| `nodegraphmodel.ts` | Graph data structure |
| `componentmodel.ts` | Component definitions |
| `nodelibrary.ts` | Node type registry |
### Important Views
| File | Purpose |
|------|---------|
| `nodegrapheditor.ts` | Main canvas editor |
| `EditorPage.tsx` | Main page layout |
| `NodePicker.tsx` | Node creation panel |
| `PropertyEditor/` | Property panels |
---
## 🏷️ Type System
### Key Types (global.d.ts)
```typescript
// TSFixme - Type escape hatch (TO BE REMOVED)
type TSFixme = any;
// Node colors
type NodeColor = 'data' | 'visual' | 'logic' | 'component' | 'javascript';
// CSS modules
declare module '*.scss' {
const styles: { readonly [key: string]: string };
export default styles;
}
```
### Common Interfaces
```typescript
// Node graph structures (nodegraphmodel.ts)
interface NodeGraphNode {
id: string;
type: string;
x: number;
y: number;
parameters: Record<string, any>;
}
interface Connection {
fromId: string;
fromPort: string;
toId: string;
toPort: string;
}
// Component structure (componentmodel.ts)
interface ComponentModel {
name: string;
graph: NodeGraphModel;
metadata: Record<string, any>;
}
```
---
## 📝 Path Aliases
```typescript
// Configured in tsconfig.json
@noodl-models/ packages/noodl-editor/src/editor/src/models/
@noodl-utils/ packages/noodl-editor/src/editor/src/utils/
@noodl-contexts/ packages/noodl-editor/src/editor/src/contexts/
@noodl-hooks/ packages/noodl-editor/src/editor/src/hooks/
@noodl-constants/ packages/noodl-editor/src/editor/src/constants/
@noodl-core-ui/ packages/noodl-core-ui/src/
@noodl/platform packages/noodl-platform/src/
```
---
## 🚨 Common Issues
### Build Problems
```bash
# Clear caches
rm -rf node_modules/.cache
rm -rf packages/*/node_modules/.cache
# Reinstall dependencies
rm -rf node_modules
npm install
```
### TypeScript Errors
```bash
# Check for circular dependencies
npx madge --circular packages/noodl-editor/src
```
### Electron Issues
```bash
# Clear app data (macOS)
rm -rf ~/Library/Application\ Support/OpenNoodl/
# Rebuild native modules
npm run rebuild
```
---
*Quick reference card for OpenNoodl development. Print or pin to your IDE!*

View File

@@ -0,0 +1,253 @@
# Common Issues & Troubleshooting
Solutions to frequently encountered problems when developing OpenNoodl.
## Build Issues
### "Module not found" Errors
**Symptom**: Build fails with `Cannot find module '@noodl-xxx/...'`
**Solutions**:
1. Run `npm install` from root directory
2. Check if package exists in `packages/`
3. Verify tsconfig paths are correct
4. Try: `rm -rf node_modules && npm install`
### "Peer dependency" Warnings
**Symptom**: npm install shows peer dependency warnings
**Solutions**:
1. Check if versions are compatible
2. Update the conflicting package
3. Last resort: `npm install --legacy-peer-deps`
4. Document why in CHANGELOG.md
### TypeScript Errors After Update
**Symptom**: Types that worked before now fail
**Solutions**:
1. Run `npx tsc --noEmit` to see all errors
2. Check if `@types/*` packages need updating
3. Look for breaking changes in updated packages
4. Check `tsconfig.json` for configuration issues
### Webpack Build Hangs
**Symptom**: Build starts but never completes
**Solutions**:
1. Check for circular imports: `npx madge --circular packages/`
2. Increase Node memory: `NODE_OPTIONS=--max_old_space_size=4096`
3. Check for infinite loops in build scripts
4. Try building individual packages
## Runtime Issues
### Hot Reload Not Working
**Symptom**: Changes don't appear without full restart
**Solutions**:
1. Check webpack dev server is running
2. Verify file is being watched (check webpack config)
3. Clear browser cache
4. Check for syntax errors preventing reload
5. Restart dev server: `npm run dev`
### Node Not Appearing in Picker
**Symptom**: Created a node but it doesn't show up
**Solutions**:
1. Verify node is exported in `nodelibraryexport.js`
2. Check `category` is valid
3. Verify no JavaScript errors in node definition
4. Restart the editor
### "Cannot read property of undefined"
**Symptom**: Runtime error accessing object properties
**Solutions**:
1. Add null checks: `obj?.property`
2. Verify data is loaded before access
3. Check async timing issues
4. Add defensive initialization
### State Not Updating
**Symptom**: Changed input but output doesn't update
**Solutions**:
1. Verify `flagOutputDirty()` is called
2. Check if batching is interfering
3. Verify connection exists in graph
4. Check for conditional logic preventing update
## Editor Issues
### Preview Not Loading
**Symptom**: Preview panel is blank or shows error
**Solutions**:
1. Check browser console for errors
2. Verify viewer runtime is built
3. Check for JavaScript errors in project
4. Try creating a new empty project
### Property Panel Empty
**Symptom**: Selected node but no properties shown
**Solutions**:
1. Verify node has `inputs` defined
2. Check `group` values are set
3. Look for errors in property panel code
4. Verify node type is registered
### Canvas Performance Issues
**Symptom**: Node graph is slow/laggy
**Solutions**:
1. Reduce number of visible nodes
2. Check for expensive render operations
3. Verify no infinite update loops
4. Profile with Chrome DevTools
## Git Issues
### Merge Conflicts in package-lock.json
**Symptom**: Complex conflicts in lock file
**Solutions**:
1. Accept either version
2. Run `npm install` to regenerate
3. Commit the regenerated lock file
### Large File Warnings
**Symptom**: Git warns about large files
**Solutions**:
1. Check `.gitignore` includes build outputs
2. Verify `node_modules` not committed
3. Use Git LFS for large assets if needed
## Testing Issues
### Tests Timeout
**Symptom**: Tests hang or timeout
**Solutions**:
1. Check for unresolved promises
2. Verify mocks are set up correctly
3. Increase timeout if legitimately slow
4. Check for infinite loops
### Snapshot Tests Failing
**Symptom**: Snapshot doesn't match
**Solutions**:
1. Review the diff carefully
2. If change is intentional: `npm test -- -u`
3. If unexpected, investigate component changes
## Debugging Tips
### Enable Verbose Logging
```javascript
// Add to see more info
console.log('[DEBUG]', variable);
// For node execution
this.context.debugLog('Message', data);
```
### Use Chrome DevTools
1. Open editor
2. Press `Cmd+Option+I` (Mac) or `Ctrl+Shift+I` (Windows)
3. Check Console for errors
4. Use Sources for breakpoints
5. Use Network for API issues
### Inspect Node State
```javascript
// In browser console
const node = NoodlRuntime.instance.getNodeById('node-id');
console.log(node._internal);
```
### Check Event Flow
```javascript
// Add listener to see all events
model.on('*', (event, data) => {
console.log('Event:', event, data);
});
```
## Error Messages
### "Maximum call stack size exceeded"
**Cause**: Infinite recursion or circular dependency
**Fix**:
1. Check for circular imports
2. Add base case to recursive functions
3. Break dependency cycles
### "Cannot access before initialization"
**Cause**: Temporal dead zone with `let`/`const`
**Fix**:
1. Check import order
2. Move declaration before usage
3. Check for circular imports
### "Unexpected token"
**Cause**: Syntax error or wrong file type
**Fix**:
1. Check file extension matches content
2. Verify JSON is valid
3. Check for missing brackets/quotes
### "ENOENT: no such file or directory"
**Cause**: Missing file or wrong path
**Fix**:
1. Verify file exists
2. Check path is correct (case-sensitive)
3. Ensure build step completed
## Getting Help
1. Search this document first
2. Check existing task documentation
3. Search codebase for similar patterns
4. Check GitHub issues
5. Ask in community channels
## Contributing Solutions
Found a solution not listed here? Add it!
1. Edit this file
2. Follow the format: Symptom → Solutions
3. Include specific commands when helpful
4. Submit PR with your addition

View File

@@ -0,0 +1,446 @@
# Node Patterns Reference
How to create and modify nodes in OpenNoodl.
## Node Types
There are two main types of nodes:
1. **Runtime Nodes** (`noodl-runtime`) - Logic, data, utilities
2. **Visual Nodes** (`noodl-viewer-react`) - React components for UI
## Basic Node Structure
### Runtime Node (JavaScript)
Location: `packages/noodl-runtime/src/nodes/`
```javascript
'use strict';
const MyNode = {
// === METADATA ===
name: 'My.Custom.Node', // Unique identifier
displayName: 'My Custom Node', // Shown in UI
category: 'Custom', // Node picker category
color: 'data', // Node color theme
docs: 'https://docs.example.com', // Documentation link
// === INITIALIZATION ===
initialize() {
// Called when node is created
this._internal.myValue = '';
this._internal.callbacks = [];
},
// === INPUTS ===
inputs: {
// Simple input
textInput: {
type: 'string',
displayName: 'Text Input',
group: 'General',
default: '',
set(value) {
this._internal.textInput = value;
this.flagOutputDirty('result');
}
},
// Number with validation
numberInput: {
type: 'number',
displayName: 'Number',
group: 'General',
default: 0,
set(value) {
if (typeof value !== 'number') return;
this._internal.numberInput = value;
this.flagOutputDirty('result');
}
},
// Signal input (trigger)
doAction: {
type: 'signal',
displayName: 'Do Action',
group: 'Actions',
valueChangedToTrue() {
// Called when signal received
this.performAction();
}
},
// Boolean toggle
enabled: {
type: 'boolean',
displayName: 'Enabled',
group: 'General',
default: true,
set(value) {
this._internal.enabled = value;
}
},
// Dropdown/enum
mode: {
type: {
name: 'enum',
enums: [
{ value: 'mode1', label: 'Mode 1' },
{ value: 'mode2', label: 'Mode 2' }
]
},
displayName: 'Mode',
group: 'General',
default: 'mode1',
set(value) {
this._internal.mode = value;
}
}
},
// === OUTPUTS ===
outputs: {
// Value output
result: {
type: 'string',
displayName: 'Result',
group: 'General',
getter() {
return this._internal.result;
}
},
// Signal output
completed: {
type: 'signal',
displayName: 'Completed',
group: 'Events'
},
// Error output
error: {
type: 'string',
displayName: 'Error',
group: 'Error',
getter() {
return this._internal.error;
}
}
},
// === METHODS ===
methods: {
performAction() {
if (!this._internal.enabled) return;
try {
// Do something
this._internal.result = 'Success';
this.flagOutputDirty('result');
this.sendSignalOnOutput('completed');
} catch (e) {
this._internal.error = e.message;
this.flagOutputDirty('error');
}
},
// Called when node is deleted
_onNodeDeleted() {
// Cleanup
this._internal.callbacks = [];
}
},
// === INSPECTOR (Debug Panel) ===
getInspectInfo() {
return {
type: 'text',
value: `Current: ${this._internal.result}`
};
}
};
module.exports = {
node: MyNode
};
```
### Visual Node (React)
Location: `packages/noodl-viewer-react/src/nodes/`
```javascript
'use strict';
const { Node } = require('@noodl/noodl-runtime');
const MyVisualNode = {
name: 'My.Visual.Node',
displayName: 'My Visual Node',
category: 'UI Elements',
// Visual nodes need these
allowChildren: true, // Can have child nodes
allowChildrenWithCategory: ['UI Elements'], // Restrict child types
getReactComponent() {
return MyReactComponent;
},
// Frame updates for animations
frame: {
// Called every frame if registered
update(context) {
// Animation logic
}
},
inputs: {
// Standard style inputs
backgroundColor: {
type: 'color',
displayName: 'Background Color',
group: 'Style',
default: 'transparent',
set(value) {
this.props.style.backgroundColor = value;
this.forceUpdate();
}
},
// Dimension with units
width: {
type: {
name: 'number',
units: ['px', '%', 'vw'],
defaultUnit: 'px'
},
displayName: 'Width',
group: 'Dimensions',
set(value) {
this.props.style.width = value.value + value.unit;
this.forceUpdate();
}
}
},
outputs: {
// DOM event outputs
onClick: {
type: 'signal',
displayName: 'Click',
group: 'Events'
}
},
methods: {
// Called when mounted
didMount() {
// Setup
},
// Called when unmounted
willUnmount() {
// Cleanup
}
}
};
// React component
function MyReactComponent(props) {
const handleClick = () => {
props.noodlNode.sendSignalOnOutput('onClick');
};
return (
<div style={props.style} onClick={handleClick}>
{props.children}
</div>
);
}
module.exports = {
node: MyVisualNode
};
```
## Common Patterns
### Scheduled Updates
Batch multiple input changes before processing:
```javascript
inputs: {
value1: {
set(value) {
this._internal.value1 = value;
this.scheduleProcess();
}
},
value2: {
set(value) {
this._internal.value2 = value;
this.scheduleProcess();
}
}
},
methods: {
scheduleProcess() {
if (this._internal.scheduled) return;
this._internal.scheduled = true;
this.scheduleAfterInputsHaveUpdated(() => {
this._internal.scheduled = false;
this.processValues();
});
},
processValues() {
// Process both values together
}
}
```
### Async Operations
Handle promises and async work:
```javascript
inputs: {
fetch: {
type: 'signal',
valueChangedToTrue() {
this.doFetch();
}
}
},
methods: {
async doFetch() {
try {
const response = await fetch(this._internal.url);
const data = await response.json();
this._internal.result = data;
this.flagOutputDirty('result');
this.sendSignalOnOutput('success');
} catch (error) {
this._internal.error = error.message;
this.flagOutputDirty('error');
this.sendSignalOnOutput('failure');
}
}
}
```
### Collection/Model Binding
Work with Noodl's data system:
```javascript
const Collection = require('../../../collection');
const Model = require('../../../model');
inputs: {
items: {
type: 'array',
set(value) {
this.bindCollection(value);
}
}
},
methods: {
bindCollection(collection) {
// Unbind previous
if (this._internal.collection) {
this._internal.collection.off('change', this._internal.onChange);
}
this._internal.collection = collection;
if (collection) {
this._internal.onChange = () => {
this.flagOutputDirty('count');
};
collection.on('change', this._internal.onChange);
}
}
}
```
### Dynamic Ports
Add ports based on configuration:
```javascript
inputs: {
properties: {
type: { name: 'stringlist', allowEditOnly: true },
displayName: 'Properties',
set(value) {
// Register dynamic inputs/outputs based on list
value.forEach(prop => {
if (!this.hasInput('prop-' + prop)) {
this.registerInput('prop-' + prop, {
set(val) {
this._internal.values[prop] = val;
}
});
}
});
}
}
}
```
## Input Types Reference
| Type | Description | Example |
|------|-------------|---------|
| `string` | Text input | `type: 'string'` |
| `number` | Numeric input | `type: 'number'` |
| `boolean` | Toggle | `type: 'boolean'` |
| `color` | Color picker | `type: 'color'` |
| `signal` | Trigger/event | `type: 'signal'` |
| `array` | Array/collection | `type: 'array'` |
| `object` | Object/model | `type: 'object'` |
| `component` | Component reference | `type: 'component'` |
| `enum` | Dropdown selection | `type: { name: 'enum', enums: [...] }` |
| `stringlist` | Editable list | `type: { name: 'stringlist' }` |
| `number` with units | Dimension | `type: { name: 'number', units: [...] }` |
## Node Colors
Available color themes for nodes:
- `data` - Blue (data operations)
- `logic` - Purple (logic/control)
- `visual` - Green (UI elements)
- `component` - Orange (component utilities)
- `default` - Gray
## Registering Nodes
Add to the node library export:
```javascript
// In packages/noodl-runtime/src/nodelibraryexport.js
const MyNode = require('./nodes/my-node');
// Add to appropriate category in coreNodes array
```
## Testing Nodes
```javascript
// Example test structure
describe('MyNode', () => {
it('should process input correctly', () => {
const node = createNode('My.Custom.Node');
node.setInput('textInput', 'hello');
expect(node.getOutput('result')).toBe('HELLO');
});
});
```

View File

@@ -0,0 +1,140 @@
# TASK-001 Changelog
Track all changes made during this task. Update this file as you work.
---
## [Date] - [Your Name/Handle]
### Summary
[To be filled in as work progresses]
### Starting Point
- Based on branch: `12-upgrade-dependencies`
- Previous work by: [previous developer]
- Previous commits include:
- Package.json dependency updates
- "Update rendering to use non-deprecated react-dom calls"
---
## Dependency Fixes
### Package: [package-name]
- **Issue**: [What was wrong]
- **Fix**: [What was changed]
- **File**: `path/to/package.json`
---
## React 19 Migration
### File: [filename]
- **Before**: `ReactDOM.render(<App />, element)`
- **After**: `createRoot(element).render(<App />)`
- **Notes**: [Any relevant context]
---
## react-instantsearch Migration
### File: HelpCenter.tsx
- **Before**: `import { ... } from 'react-instantsearch-hooks-web'`
- **After**: `import { ... } from 'react-instantsearch'`
- **API Changes**: [List any API differences encountered]
---
## Build Fixes
### Error: [Error message]
- **Cause**: [Why it happened]
- **Fix**: [What was changed]
- **File**: `path/to/file`
---
## Build Optimizations
### Optimization: [Name]
- **Before**: Build time X seconds
- **After**: Build time Y seconds
- **Change**: [What was optimized]
---
## Files Modified
<!-- Update this list as you make changes -->
- [ ] `package.json` (root)
- [ ] `packages/noodl-editor/package.json`
- [ ] `packages/noodl-core-ui/package.json`
- [ ] `packages/noodl-viewer-react/package.json`
- [ ] `packages/noodl-editor/src/editor/src/views/HelpCenter/HelpCenter.tsx`
- [ ] [Add more as needed]
---
## Files Created
<!-- List any new files created -->
- None expected for this task
---
## Files Deleted
<!-- List any files removed -->
- None expected for this task
---
## Breaking Changes
- React 19 requires Node.js 18+ (documented in root package.json engines)
- [Add any other breaking changes discovered]
---
## Testing Notes
### Automated Tests
- `npm run test:editor`: [PASS/FAIL] - [Notes]
- `npm run test:platform`: [PASS/FAIL] - [Notes]
- `npx tsc --noEmit`: [PASS/FAIL] - [Notes]
### Manual Tests
- Dev server start: [PASS/FAIL]
- Create project: [PASS/FAIL]
- Node operations: [PASS/FAIL]
- Preview: [PASS/FAIL]
- Help Center search: [PASS/FAIL]
- Hot reload: [PASS/FAIL]
---
## Known Issues
<!-- Document any issues discovered that aren't fixed in this task -->
1. [Issue description] - [Will be addressed in TASK-XXX]
---
## Follow-up Tasks
<!-- Note any work that should be done in future tasks -->
1. [Follow-up item] - Suggested for TASK-XXX
---
## Final Summary
[To be completed when task is done]
**Total files modified**: X
**Total lines changed**: +X / -Y
**Build time**: Before X sec → After Y sec
**Tests**: All passing / X failures
**Confidence**: X/10

View File

@@ -0,0 +1,123 @@
# TASK-001 Checklist
## Prerequisites
- [ ] Read README.md completely
- [ ] Understand React 19 breaking changes
- [ ] Have Node.js 18+ installed
- [ ] Clone the repository fresh (or ensure clean state)
## Phase 1: Setup
- [ ] Checkout existing work: `git checkout 12-upgrade-dependencies`
- [ ] Create task branch: `git checkout -b task/001-dependency-updates`
- [ ] Delete node_modules: `rm -rf node_modules packages/*/node_modules`
- [ ] Clean install: `npm install`
- [ ] Document any install errors in NOTES.md
- [ ] Note: confidence level for this phase: __/10
## Phase 2: Dependency Conflicts
- [ ] List all peer dependency warnings
- [ ] Research each warning
- [ ] Fix conflicts in root package.json
- [ ] Fix conflicts in packages/noodl-editor/package.json
- [ ] Fix conflicts in packages/noodl-core-ui/package.json
- [ ] Fix conflicts in packages/noodl-viewer-react/package.json
- [ ] Fix conflicts in other packages as needed
- [ ] Verify clean `npm install`
- [ ] Document fixes in CHANGELOG.md
- [ ] Note: confidence level for this phase: __/10
## Phase 3: Build Errors
- [ ] Run `npm run build:editor`
- [ ] List all build errors
- [ ] Fix error 1: _______________
- [ ] Fix error 2: _______________
- [ ] Fix error 3: _______________
- [ ] (add more as needed)
- [ ] Verify clean build
- [ ] Document fixes in CHANGELOG.md
- [ ] Note: confidence level for this phase: __/10
## Phase 4: React 19 Migration
- [ ] Search for ReactDOM.render usage:
```bash
grep -rn "ReactDOM.render" packages/ --include="*.ts" --include="*.tsx" --include="*.js"
```
- [ ] List all files found: _______________
- [ ] Update file 1: _______________
- [ ] Update file 2: _______________
- [ ] (add more as needed)
- [ ] Search for ReactDOM.hydrate usage
- [ ] Search for ReactDOM.unmountComponentAtNode usage
- [ ] Update any found
- [ ] Verify no legacy ReactDOM usage remains
- [ ] Document changes in CHANGELOG.md
- [ ] Note: confidence level for this phase: __/10
## Phase 5: react-instantsearch Migration
- [ ] Open `packages/noodl-editor/src/editor/src/views/HelpCenter/HelpCenter.tsx`
- [ ] Update import from `react-instantsearch-hooks-web` to `react-instantsearch`
- [ ] Check all hooks used are still available
- [ ] Search for other files using old package:
```bash
grep -rn "react-instantsearch-hooks-web" packages/
```
- [ ] Update any other files found
- [ ] Test search functionality works
- [ ] Document changes in CHANGELOG.md
- [ ] Note: confidence level for this phase: __/10
## Phase 6: Build Optimization (Optional but Recommended)
- [ ] Measure current build time: ___ seconds
- [ ] Check webpack config for cache settings
- [ ] Enable persistent caching if not enabled
- [ ] Check for unnecessary rebuilds
- [ ] Measure new build time: ___ seconds
- [ ] Document optimizations in CHANGELOG.md
## Phase 7: Testing - Automated
- [ ] Run `npm run test:editor`
- [ ] All tests pass
- [ ] Note any failures: _______________
- [ ] Run `npm run test:platform`
- [ ] All tests pass
- [ ] Note any failures: _______________
- [ ] Run `npx tsc --noEmit`
- [ ] No TypeScript errors
- [ ] Note any errors: _______________
## Phase 8: Testing - Manual
- [ ] Start dev server: `npm run dev`
- [ ] Starts without errors
- [ ] No console warnings about deprecated APIs
- [ ] Create new project
- [ ] Add Group node to canvas
- [ ] Add Text node as child
- [ ] Connect nodes
- [ ] Open preview
- [ ] Edit text content, verify preview updates
- [ ] Save and reopen project
- [ ] Open Help Center, test search (react-instantsearch)
- [ ] Edit Function node code
- [ ] Change a file, verify hot reload works
- [ ] Build production: `npm run build:editor`
## Phase 9: Cleanup & Documentation
- [ ] Remove any debug console.logs added
- [ ] Review all changes for code quality
- [ ] Complete CHANGELOG.md with summary
- [ ] Update NOTES.md with learnings
- [ ] Self-review: confidence level __/10
## Phase 10: Completion
- [ ] All success criteria met (see README.md)
- [ ] Create pull request
- [ ] PR title: "TASK-001: Dependency Updates & Build Modernization"
- [ ] PR description includes:
- [ ] Summary of changes
- [ ] Testing performed
- [ ] Any known issues or follow-ups
- [ ] Mark task complete
## Final Confidence Check
- Overall confidence this task is complete and correct: __/10
- Remaining concerns: _______________

View File

@@ -0,0 +1,128 @@
# TASK-001 Working Notes
## Research
### Previous Developer's Work
**Branch**: `12-upgrade-dependencies`
**Commits found**:
1. Package.json updates across all packages
2. "Update rendering to use non-deprecated react-dom calls"
**What they changed**:
- React 17.0.2 → 19.0.0
- react-instantsearch-hooks-web → react-instantsearch
- Removed deprecated react-json-view, added @microlink/react-json-view
- Updated webpack 5.74.0 → 5.101.3
- Removed Node.js upper version cap (was <=18, now 16+)
- Removed Storybook 6.x packages
### React 19 Breaking Changes to Watch For
1. **Automatic Batching** - State updates are now automatically batched
2. **Concurrent Features** - May affect node graph rendering timing
3. **Strict Mode** - Double-renders effects for cleanup detection
4. **Removed APIs**:
- `ReactDOM.render()``createRoot()`
- `ReactDOM.hydrate()``hydrateRoot()`
- `ReactDOM.unmountComponentAtNode()``root.unmount()`
### react-instantsearch Changes
The package was renamed from `react-instantsearch-hooks-web` to `react-instantsearch`.
Most APIs are compatible, but verify:
- `useHits`
- `useSearchBox`
- `InstantSearch` component props
### Files to Search
```bash
# Find ReactDOM.render usage
grep -rn "ReactDOM.render" packages/ --include="*.ts" --include="*.tsx" --include="*.js"
# Find old instantsearch imports
grep -rn "react-instantsearch-hooks-web" packages/
# Find any remaining TSFixme (for awareness, not this task)
grep -rn "TSFixme" packages/ --include="*.ts" --include="*.tsx"
```
---
## Assumptions
- [ ] Previous dev's changes are on `12-upgrade-dependencies` branch - **VERIFY**
- [ ] Build was working before their changes - **VERIFY by checking main**
- [ ] No other branches need to be merged first - **VERIFY**
---
## Implementation Notes
### Approach Decisions
[To be filled in during work]
### Gotchas / Surprises
[To be filled in during work]
---
## Debug Log
### [Date/Time]
- **Trying**: [what you're attempting]
- **Result**: [what happened]
- **Next**: [what to try next]
---
## Useful Commands
```bash
# Clean install
rm -rf node_modules packages/*/node_modules
npm install
# Build editor
npm run build:editor
# Run tests
npm run test:editor
# Type check
npx tsc --noEmit
# Start dev server
npm run dev
# Find files with pattern
grep -rn "pattern" packages/ --include="*.ts" --include="*.tsx"
# Check git status
git status
git diff --stat
# Compare with main
git diff main..HEAD --stat
```
---
## Questions to Resolve
- [ ] Are there any other branches that should be merged first?
- [ ] Did the previous dev test the build?
- [ ] Are there any known issues documented anywhere?
---
## Links & Resources
- [React 19 Blog Post](https://react.dev/blog/2024/04/25/react-19)
- [React 19 Upgrade Guide](https://react.dev/blog/2024/04/25/react-19-upgrade-guide)
- [react-instantsearch Migration](https://www.algolia.com/doc/guides/building-search-ui/upgrade-guides/react/)

View File

@@ -0,0 +1,218 @@
# TASK-001: Dependency Updates & Build Modernization
## Metadata
| Field | Value |
|-------|-------|
| **ID** | TASK-001 |
| **Phase** | Phase 1 - Foundation |
| **Priority** | 🔴 Critical |
| **Difficulty** | 🟡 Medium |
| **Estimated Time** | 2-3 days |
| **Prerequisites** | None (this is the first task) |
| **Branch** | `task/001-dependency-updates` |
| **Related Branches** | `12-upgrade-dependencies` (previous dev work) |
## Objective
Complete and validate all dependency updates, fully migrate to React 19, and modernize the build pipeline for reliable, fast development.
## Background
A previous developer started this work on the `12-upgrade-dependencies` branch. They updated package.json files across the monorepo, including:
- React 17 → 19
- Various webpack, typescript, and tooling updates
- Removed Node.js version upper cap
They also made a commit "Update rendering to use non-deprecated react-dom calls" which addressed some React 19 breaking changes.
This task completes that work, validates everything works, and improves the overall build experience.
## Current State
### What Exists
- Branch `12-upgrade-dependencies` with package.json updates
- Some React 19 migration work done
- Build may have errors or warnings
### Known Issues
- `react-instantsearch-hooks-web` renamed to `react-instantsearch` (breaking API change)
- `ReactDOM.render()` deprecated in React 18+
- Potential peer dependency conflicts
- Hot reload may be unreliable
- Build times are slow
### Key Package Changes (from previous dev)
| Package | Old | New | Breaking Changes |
|---------|-----|-----|------------------|
| react | 17.0.2 | 19.0.0 | Yes - see below |
| react-dom | 17.0.0 | 19.0.0 | Yes - render API |
| react-instantsearch-hooks-web | 6.38.0 | react-instantsearch 7.16.2 | Yes - renamed |
| webpack | 5.74.0 | 5.101.3 | Minor |
| typescript | 4.8.3 | 4.9.5 | Minor |
## Desired State
After this task:
- All packages build without errors
- No deprecation warnings in console
- React 19 fully adopted (no legacy patterns)
- Hot reload works reliably
- Build completes in <60 seconds
- All existing tests pass
## Scope
### In Scope
- [x] Validate and fix dependency updates
- [x] Complete React 19 migration
- [x] Fix all build errors and warnings
- [x] Update react-instantsearch usage
- [x] Improve build performance
- [x] Fix hot reload issues
### Out of Scope
- Major refactoring (that's later tasks)
- New features
- TSFixme cleanup (TASK-002)
- Storybook 9 migration (can be separate task)
## Technical Approach
### Key Files to Modify
| File | Changes |
|------|---------|
| `package.json` (root) | Verify dependencies, fix conflicts |
| `packages/*/package.json` | Verify peer deps, fix conflicts |
| `packages/noodl-editor/src/editor/src/views/HelpCenter/HelpCenter.tsx` | Update react-instantsearch imports |
| Any file with `ReactDOM.render` | Migrate to createRoot |
| `packages/noodl-viewer-react/` | React 19 compatibility |
### React 19 Migration Points
```typescript
// OLD (React 17)
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));
// NEW (React 19)
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
```
Search for these patterns:
```bash
grep -r "ReactDOM.render" packages/ --include="*.ts" --include="*.tsx" --include="*.js"
grep -r "ReactDOM.hydrate" packages/ --include="*.ts" --include="*.tsx" --include="*.js"
grep -r "ReactDOM.unmountComponentAtNode" packages/ --include="*.ts" --include="*.tsx" --include="*.js"
```
### react-instantsearch Migration
```typescript
// OLD
import { InstantSearch, Hits } from 'react-instantsearch-hooks-web';
// NEW
import { InstantSearch, Hits } from 'react-instantsearch';
```
The API is mostly compatible, but verify all hooks used still exist.
## Implementation Steps
### Step 1: Setup and Initial Validation
1. Checkout the existing branch: `git checkout 12-upgrade-dependencies`
2. Create our task branch: `git checkout -b task/001-dependency-updates`
3. Clean install: `rm -rf node_modules && npm install`
4. Document any install errors in NOTES.md
### Step 2: Fix Dependency Conflicts
1. Run `npm install` and note all peer dependency warnings
2. For each warning, determine the correct resolution
3. Update package.json files as needed
4. Repeat until `npm install` runs cleanly
### Step 3: Fix Build Errors
1. Run `npm run build:editor`
2. Fix each error one at a time
3. Document each fix in CHANGELOG.md
4. Repeat until build succeeds
### Step 4: React 19 Migration
1. Search for deprecated ReactDOM calls
2. Update each to use createRoot pattern
3. Check for class component lifecycle issues
4. Test each changed component
### Step 5: react-instantsearch Update
1. Update imports in HelpCenter.tsx
2. Verify all hooks/components still available
3. Test search functionality
### Step 6: Build Optimization
1. Analyze current build time
2. Check webpack configs for optimization opportunities
3. Enable caching if not already
4. Measure improvement
### Step 7: Validation
1. Run full test suite
2. Manual testing of key workflows
3. Verify hot reload works
4. Check for console warnings
## Testing Plan
### Automated Tests
- [ ] Run `npm run test:editor` - all pass
- [ ] Run `npm run test:platform` - all pass
- [ ] Run `npx tsc --noEmit` - no type errors
### Manual Testing Scenarios
- [ ] Start dev server: `npm run dev` - starts without errors
- [ ] Create new project - works
- [ ] Add nodes to canvas - works
- [ ] Connect nodes - works
- [ ] Preview project - works
- [ ] Edit code in Function node - works
- [ ] Hot reload when editing - works
- [ ] Search in Help Center - works (react-instantsearch)
- [ ] Build for production - works
## Success Criteria
- [ ] `npm install` completes with no errors
- [ ] `npm run build:editor` completes with no errors
- [ ] `npm run test:editor` all tests pass
- [ ] `npx tsc --noEmit` no TypeScript errors
- [ ] No deprecation warnings in browser console
- [ ] Hot reload works reliably
- [ ] All manual test scenarios pass
## Risks & Mitigations
| Risk | Mitigation |
|------|------------|
| React 19 breaks something subtle | Extensive manual testing, rollback plan ready |
| react-instantsearch API changes | Read migration guide, test search thoroughly |
| Build time regression | Measure before/after, optimize if needed |
| Peer dependency hell | Use `--legacy-peer-deps` as last resort, document why |
## Rollback Plan
If major issues discovered:
1. Checkout main branch
2. Cherry-pick any non-breaking fixes
3. Document issues for future attempt
4. Consider incremental approach (React 18 first, then 19)
## References
- [React 19 Release Notes](https://react.dev/blog/2024/04/25/react-19)
- [react-instantsearch v7 Migration](https://www.algolia.com/doc/guides/building-search-ui/upgrade-guides/react/)
- Previous dev branch: `12-upgrade-dependencies`
- Previous dev commit: "Update rendering to use non-deprecated react-dom calls"