@aaqu/fromcubes-portal-react 0.1.0-alpha.4 → 0.1.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -11
- package/nodes/portal-react.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,23 +5,26 @@ React portal node for Node-RED. Server-side JSX transpilation via esbuild. Tailw
|
|
|
5
5
|
## How it works
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
┌─ Deploy time (Node-RED server)
|
|
8
|
+
┌─ Deploy time (Node-RED server) ──────────────────────────┐
|
|
9
9
|
│ │
|
|
10
|
-
│ JSX (editor) ──► esbuild transpile ──► cached JS
|
|
10
|
+
│ JSX (editor) ──► esbuild transpile ──► cached JS │
|
|
11
11
|
│ (hash-keyed cache) │
|
|
12
12
|
│ │
|
|
13
|
+
│ Tailwind classes ──► server-side compile ──► CSS file │
|
|
14
|
+
│ (hash-keyed cache) │
|
|
15
|
+
│ │
|
|
13
16
|
│ Unchanged code on redeploy = cache hit, 0ms │
|
|
14
17
|
│ Changed code = retranspile, ~5ms │
|
|
15
18
|
└──────────────────────────────────────────────────────────┘
|
|
16
19
|
|
|
17
|
-
┌─ Runtime (browser)
|
|
20
|
+
┌─ Runtime (browser) ──────────────────────────────────────┐
|
|
18
21
|
│ │
|
|
19
22
|
│ GET /endpoint ──► HTML + pre-compiled JS │
|
|
20
23
|
│ react-19.production.min.js │
|
|
21
|
-
│ Tailwind CSS (
|
|
24
|
+
│ Tailwind CSS (server-compiled) │
|
|
22
25
|
│ NO Babel, NO Sucrase, NO compiler │
|
|
23
26
|
│ │
|
|
24
|
-
│ WebSocket /endpoint/_ws ◄──► Node-RED msg I/O
|
|
27
|
+
│ WebSocket /endpoint/_ws ◄──► Node-RED msg I/O │
|
|
25
28
|
└──────────────────────────────────────────────────────────┘
|
|
26
29
|
```
|
|
27
30
|
|
|
@@ -49,9 +52,8 @@ Dependencies install automatically. No build step needed.
|
|
|
49
52
|
| Field | Purpose |
|
|
50
53
|
|---|---|
|
|
51
54
|
| Endpoint | HTTP path, e.g. `/dashboard` |
|
|
52
|
-
| Title | Browser tab title |
|
|
53
|
-
|
|
|
54
|
-
| Output Schema | JSON — documents emitted `msg.payload` shape |
|
|
55
|
+
| Page Title | Browser tab title |
|
|
56
|
+
| Portal Auth | Enable portal user header extraction |
|
|
55
57
|
| Head HTML | Extra `<head>` tags (CDN, fonts, CSS) |
|
|
56
58
|
| Code Editor | Monaco with JSX — must define `<App />` |
|
|
57
59
|
|
|
@@ -72,13 +74,30 @@ Components are auto-injected into every portal-react page at transpile time.
|
|
|
72
74
|
|
|
73
75
|
```jsx
|
|
74
76
|
function App() {
|
|
75
|
-
const { data, send } = useNodeRed();
|
|
77
|
+
const { data, send, user } = useNodeRed();
|
|
76
78
|
// data = last msg.payload from input wire (reactive)
|
|
77
79
|
// send(payload, topic?) = emit msg on output wire
|
|
80
|
+
// user = portal user object (when Portal Auth enabled), or null
|
|
78
81
|
return <div className="p-4 text-lg">{JSON.stringify(data)}</div>;
|
|
79
82
|
}
|
|
80
83
|
```
|
|
81
84
|
|
|
85
|
+
## Portal Authentication
|
|
86
|
+
|
|
87
|
+
When **Portal Auth** is checked, the node extracts user identity from incoming request headers:
|
|
88
|
+
|
|
89
|
+
| Header | Field |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `x-portal-user-id` | `userId` |
|
|
92
|
+
| `x-portal-user-name` | `userName` |
|
|
93
|
+
| `x-portal-user-username` | `username` |
|
|
94
|
+
| `x-portal-user-email` | `email` |
|
|
95
|
+
| `x-portal-user-role` | `role` |
|
|
96
|
+
| `x-portal-user-groups` | `groups` (JSON array) |
|
|
97
|
+
|
|
98
|
+
- In the browser, `useNodeRed().user` returns the extracted user object (or `null` if auth is disabled or no headers present).
|
|
99
|
+
- On outgoing messages, user info is attached as `msg._client` so downstream nodes can identify the sender.
|
|
100
|
+
|
|
82
101
|
## Deploy lifecycle
|
|
83
102
|
|
|
84
103
|
What happens on each deploy:
|
|
@@ -92,7 +111,7 @@ What happens on each deploy:
|
|
|
92
111
|
- Cache hit → reuse (0ms)
|
|
93
112
|
- Cache miss → esbuild transpile (~5ms)
|
|
94
113
|
6. New HTTP route and WS handler registered
|
|
95
|
-
7. Reconnecting clients
|
|
114
|
+
7. Reconnecting clients soft-reconnect (no page reload) and receive current `lastPayload`
|
|
96
115
|
|
|
97
116
|
Rapid deploys (user clicking deploy repeatedly) are safe:
|
|
98
117
|
- `isClosing` flag prevents accepting new WS connections during teardown
|
|
@@ -110,7 +129,7 @@ Transpile errors:
|
|
|
110
129
|
|---|---|
|
|
111
130
|
| react-19.production.min.js | ~45 KB |
|
|
112
131
|
| Your transpiled JS | ~1-5 KB |
|
|
113
|
-
| Tailwind CSS (
|
|
132
|
+
| Tailwind CSS (server-compiled) | cached per content hash |
|
|
114
133
|
| WebSocket bridge | <1 KB |
|
|
115
134
|
|
|
116
135
|
No Babel, no Sucrase client, no Vue, no Vuetify, no Socket.IO.
|
package/nodes/portal-react.js
CHANGED
|
@@ -597,7 +597,7 @@ window.__NR={
|
|
|
597
597
|
this._ws=ws;
|
|
598
598
|
const s=document.getElementById('__cs');
|
|
599
599
|
ws.onopen=()=>{
|
|
600
|
-
if(this._wasConnected){
|
|
600
|
+
if(this._wasConnected){s.textContent='connected';s.className='ok';this._retries=0;return;}
|
|
601
601
|
s.textContent='connected';s.className='ok';this._retries=0;this._wasConnected=true;
|
|
602
602
|
};
|
|
603
603
|
ws.onmessage=(e)=>{
|