mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-11 23:02:56 +01:00
New data query node for Directus backend integration
This commit is contained in:
@@ -601,7 +601,7 @@ inputs: {
|
||||
|
||||
---
|
||||
|
||||
### 🔴 GOTCHA #5: Node Registration Path Matters
|
||||
### 🔴 GOTCHA #5: Node Registration Path Matters (Signals Not Wrapping)
|
||||
|
||||
**THE BUG:**
|
||||
|
||||
@@ -633,6 +633,104 @@ module.exports = NodeDefinition.defineNode(MyNode);
|
||||
|
||||
---
|
||||
|
||||
### 🔴 GOTCHA #6: Signal in Static `inputs` + Dynamic Ports = Duplicate Ports (Dec 2025)
|
||||
|
||||
**THE BUG:**
|
||||
|
||||
```javascript
|
||||
// Signal defined in static inputs with handler
|
||||
inputs: {
|
||||
fetch: {
|
||||
type: 'signal',
|
||||
valueChangedToTrue: function() { this.scheduleFetch(); }
|
||||
}
|
||||
}
|
||||
|
||||
// updatePorts() ALSO adds fetch - CAUSES DUPLICATE!
|
||||
function updatePorts(nodeId, parameters, editorConnection) {
|
||||
const ports = [];
|
||||
// ... other ports ...
|
||||
ports.push({ name: 'fetch', type: 'signal', plug: 'input' }); // ❌ Duplicate!
|
||||
editorConnection.sendDynamicPorts(nodeId, ports);
|
||||
}
|
||||
```
|
||||
|
||||
**SYMPTOM:** When trying to connect to the node, TWO "Fetch" signals appear in the connection popup.
|
||||
|
||||
**WHY IT BREAKS:**
|
||||
|
||||
- GOTCHA #2 says "include static ports in dynamic ports" which is true for MOST ports
|
||||
- But signals with `valueChangedToTrue` handlers ALREADY have a runtime registration
|
||||
- Adding them again in `updatePorts()` creates a duplicate visual port
|
||||
- The handler still works, but UX is confusing
|
||||
|
||||
**THE FIX:**
|
||||
|
||||
```javascript
|
||||
// ✅ CORRECT - Only define signal in static inputs, NOT in updatePorts()
|
||||
inputs: {
|
||||
fetch: {
|
||||
type: 'signal',
|
||||
valueChangedToTrue: function() { this.scheduleFetch(); }
|
||||
}
|
||||
}
|
||||
|
||||
function updatePorts(nodeId, parameters, editorConnection) {
|
||||
const ports = [];
|
||||
// ... dynamic ports ...
|
||||
|
||||
// NOTE: 'fetch' signal is defined in static inputs (with valueChangedToTrue handler)
|
||||
// DO NOT add it here again or it will appear twice in the connection popup
|
||||
|
||||
// ... other ports ...
|
||||
editorConnection.sendDynamicPorts(nodeId, ports);
|
||||
}
|
||||
```
|
||||
|
||||
**RULE:** Signals with `valueChangedToTrue` handlers → ONLY in static `inputs`. All other ports (value inputs, outputs) → in `updatePorts()` dynamic ports.
|
||||
|
||||
---
|
||||
|
||||
### 🔴 GOTCHA #7: Require Path Depth for noodl-runtime (Dec 2025)
|
||||
|
||||
**THE BUG:**
|
||||
|
||||
```javascript
|
||||
// File: src/nodes/std-library/data/mynode.js
|
||||
// Trying to require noodl-runtime.js at package root
|
||||
|
||||
const NoodlRuntime = require('../../../noodl-runtime'); // ❌ WRONG - only 3 levels
|
||||
// This breaks the entire runtime with "Cannot find module" error
|
||||
```
|
||||
|
||||
**WHY IT MATTERS:**
|
||||
|
||||
- From `src/nodes/std-library/data/` you need to go UP 4 levels to reach the package root
|
||||
- Path: data → std-library → nodes → src → (package root)
|
||||
- One wrong `../` and the entire app fails to load
|
||||
|
||||
**THE FIX:**
|
||||
|
||||
```javascript
|
||||
// ✅ CORRECT - Count the directories carefully
|
||||
// From src/nodes/std-library/data/mynode.js:
|
||||
const NoodlRuntime = require('../../../../noodl-runtime'); // 4 levels
|
||||
|
||||
// Reference: cloudstore.js at src/api/ uses 2 levels:
|
||||
const NoodlRuntime = require('../../noodl-runtime'); // 2 levels from src/api/
|
||||
```
|
||||
|
||||
**Quick Reference:**
|
||||
|
||||
| File Location | Levels to Package Root | Require Path |
|
||||
| ----------------------------- | ---------------------- | --------------------------- |
|
||||
| `src/api/` | 2 | `../../noodl-runtime` |
|
||||
| `src/nodes/` | 2 | `../../noodl-runtime` |
|
||||
| `src/nodes/std-library/` | 3 | `../../../noodl-runtime` |
|
||||
| `src/nodes/std-library/data/` | 4 | `../../../../noodl-runtime` |
|
||||
|
||||
---
|
||||
|
||||
## Complete Working Pattern (HTTP Node Reference)
|
||||
|
||||
Here's the proven pattern from the HTTP node that handles all gotchas:
|
||||
|
||||
@@ -1071,3 +1071,125 @@ PopupLayer.prototype.dragCompleted = function () {
|
||||
**Keywords**: PopupLayer, dragCompleted, endDrag, TypeError, drag-and-drop, method name, API
|
||||
|
||||
---
|
||||
|
||||
## NoodlRuntime.instance.getMetaData() Pattern for Project Data (Dec 2025)
|
||||
|
||||
### How Runtime Nodes Access Project Metadata
|
||||
|
||||
**Context**: BYOB Query Data node needed to access backend services configuration (URLs, tokens, schema) from runtime code.
|
||||
|
||||
**The Pattern**: Use `NoodlRuntime.instance.getMetaData(key)` to access project metadata stored in graphModel.
|
||||
|
||||
**Working Example** (from byob-query-data.js):
|
||||
|
||||
```javascript
|
||||
const NoodlRuntime = require('../../../../noodl-runtime');
|
||||
|
||||
resolveBackend: function() {
|
||||
// Get metadata - same pattern as cloudstore.js uses for cloudservices
|
||||
const backendServices = NoodlRuntime.instance.getMetaData('backendServices');
|
||||
|
||||
if (!backendServices || !backendServices.backends) {
|
||||
console.log('[BYOB Query Data] No backend services metadata found');
|
||||
console.log('[BYOB Query Data] Available metadata keys:',
|
||||
Object.keys(NoodlRuntime.instance.metadata || {}));
|
||||
return null;
|
||||
}
|
||||
|
||||
// Access the data
|
||||
const backends = backendServices.backends || [];
|
||||
const activeBackendId = backendServices.activeBackendId;
|
||||
|
||||
// Find and use the backend config...
|
||||
}
|
||||
```
|
||||
|
||||
**Reference Implementation** (from `src/api/cloudstore.js`):
|
||||
|
||||
```javascript
|
||||
const NoodlRuntime = require('../../noodl-runtime');
|
||||
|
||||
// Access cloud services config
|
||||
const cloudServices = NoodlRuntime.instance.getMetaData('cloudservices');
|
||||
```
|
||||
|
||||
**How It Works**:
|
||||
|
||||
- `NoodlRuntime.prototype.getMetaData(key)` delegates to `this.graphModel.getMetaData(key)`
|
||||
- Metadata is stored in the project file and loaded into graphModel
|
||||
- Editor components set metadata via `graphModel.setMetaData(key, value)`
|
||||
|
||||
**Available Metadata Keys** (varies by project):
|
||||
|
||||
- `cloudservices` - Parse/Firebase cloud settings
|
||||
- `backendServices` - BYOB backend configurations
|
||||
- Project-specific settings
|
||||
|
||||
**Location**:
|
||||
|
||||
- NoodlRuntime API: `packages/noodl-runtime/noodl-runtime.js` (line 299)
|
||||
- Pattern reference: `packages/noodl-runtime/src/api/cloudstore.js`
|
||||
- BYOB usage: `packages/noodl-runtime/src/nodes/std-library/data/byob-query-data.js`
|
||||
|
||||
**Keywords**: NoodlRuntime, getMetaData, project metadata, runtime, backend config, cloudservices
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Runtime Nodes Must Be in coreNodes Index (Dec 2025)
|
||||
|
||||
### Problem: Node Module Loads But Doesn't Appear in Node Picker
|
||||
|
||||
**Context**: TASK-002 BYOB Data Nodes - Created `byob-query-data.js`, registered in `register-nodes.js`, console showed "Module loaded" but node never appeared in Node Picker.
|
||||
|
||||
**Root Cause**: Runtime nodes need to be registered in THREE places:
|
||||
|
||||
1. ✅ Node file created (`noodl-runtime/src/nodes/std-library/data/byob-query-data.js`)
|
||||
2. ✅ Registered in `register-nodes.js` via `require()`
|
||||
3. ❌ **MISSING** - Added to `coreNodes` index in `nodelibraryexport.js`
|
||||
|
||||
**The Hidden Requirement**:
|
||||
|
||||
```javascript
|
||||
// In nodelibraryexport.js, the coreNodes array determines Node Picker organization
|
||||
const coreNodes = [
|
||||
{
|
||||
name: 'Read & Write Data',
|
||||
subCategories: [
|
||||
{
|
||||
name: 'External Data',
|
||||
items: ['net.noodl.HTTP', 'REST2'] // HTTP appears because it's HERE
|
||||
}
|
||||
// Node not in this array = not in Node Picker!
|
||||
]
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
**The Fix**:
|
||||
|
||||
```javascript
|
||||
// Add node to appropriate category in coreNodes
|
||||
{
|
||||
name: 'BYOB Data',
|
||||
items: ['noodl.byob.QueryData'] // Now appears in Node Picker!
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Is Easy to Miss**:
|
||||
|
||||
- Module loads fine (console log appears)
|
||||
- No errors anywhere
|
||||
- Node IS registered in `nodeRegister._constructors`
|
||||
- Node IS in `nodetypes` array exported to editor
|
||||
- But Node Picker uses `coreNodes` index for organization
|
||||
|
||||
**Critical Rule**: After creating a node, ALWAYS add it to `nodelibraryexport.js` coreNodes array.
|
||||
|
||||
**Location**:
|
||||
|
||||
- `packages/noodl-runtime/src/nodelibraryexport.js` (coreNodes array)
|
||||
- Documented in: `dev-docs/reference/LEARNINGS-NODE-CREATION.md` (Step 3)
|
||||
|
||||
**Keywords**: node picker, coreNodes, nodelibraryexport, runtime node, silent failure, node not appearing
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user