@nitronjs/framework 0.2.10 → 0.2.12

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.
@@ -1,10 +1,31 @@
1
+ /**
2
+ * Custom JSX Runtime for NitronJS
3
+ *
4
+ * Handles React 19's strict key prop requirements and provides
5
+ * island architecture support for client components.
6
+ */
1
7
  const JSX_RUNTIME = `
2
8
  import * as React from 'react';
3
9
  import * as OriginalJsx from '__react_jsx_original__';
4
10
 
5
11
  const CTX = Symbol.for('__nitron_view_context__');
6
12
  const MARK = Symbol.for('__nitron_client_component__');
7
- const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
13
+ const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype', 'key', 'ref']);
14
+
15
+ // Filter React 19 key warnings from third-party libraries
16
+ if (typeof console !== 'undefined' && console.error) {
17
+ const originalError = console.error;
18
+ console.error = function(...args) {
19
+ const msg = args[0];
20
+ if (typeof msg === 'string' && (
21
+ msg.includes('A props object containing a "key" prop is being spread into JSX') ||
22
+ msg.includes('\`key\` is not a prop')
23
+ )) {
24
+ return;
25
+ }
26
+ return originalError.apply(console, args);
27
+ };
28
+ }
8
29
 
9
30
  function getContext() {
10
31
  return globalThis[CTX]?.getStore?.();
@@ -20,6 +41,7 @@ globalThis.request = () => {
20
41
  const DepthContext = React.createContext(false);
21
42
  const componentCache = new WeakMap();
22
43
 
44
+ // Sanitizes props for client-side hydration (removes functions, symbols, circular refs)
23
45
  function sanitizeProps(obj, seen = new WeakSet()) {
24
46
  if (obj == null) return obj;
25
47
 
@@ -62,6 +84,7 @@ function wrapWithDepth(children) {
62
84
  return OriginalJsx.jsx(DepthContext.Provider, { value: true, children });
63
85
  }
64
86
 
87
+ // Creates an island wrapper for client components (hydrated independently)
65
88
  function createIsland(Component, name) {
66
89
  function IslandBoundary(props) {
67
90
  if (React.useContext(DepthContext)) {
@@ -96,12 +119,23 @@ function getWrappedComponent(Component) {
96
119
  return componentCache.get(Component);
97
120
  }
98
121
 
122
+ // Extracts key from props without triggering React 19's getter warning
99
123
  function extractKey(props, key) {
100
- if (props == null || !('key' in props)) {
101
- return [props, key];
124
+ if (props == null) return [props, key];
125
+ if (!Object.prototype.hasOwnProperty.call(props, 'key')) return [props, key];
126
+
127
+ const cleanProps = {};
128
+ let extractedKey = key;
129
+
130
+ for (const k of Object.keys(props)) {
131
+ if (k === 'key') {
132
+ if (extractedKey == null) extractedKey = props[k];
133
+ } else {
134
+ cleanProps[k] = props[k];
135
+ }
102
136
  }
103
- const { key: propKey, ...rest } = props;
104
- return [rest, key ?? propKey];
137
+
138
+ return [cleanProps, extractedKey];
105
139
  }
106
140
 
107
141
  export function jsx(type, props, key) {
@@ -1,14 +1,63 @@
1
1
  import * as React from 'react';
2
2
  import * as ReactDOM from 'react-dom';
3
3
  import * as ReactDOMClient from 'react-dom/client';
4
- import * as ReactJSXRuntime from 'react/jsx-runtime';
4
+ import * as OriginalJsx from 'react/jsx-runtime';
5
5
  import RefreshRuntime from 'react-refresh/runtime';
6
6
 
7
+ // Filter React 19 key warnings from third-party libraries
8
+ const originalError = console.error;
9
+ console.error = function(...args: any[]) {
10
+ const msg = args[0];
11
+ if (typeof msg === 'string' && (
12
+ msg.includes('A props object containing a "key" prop is being spread into JSX') ||
13
+ msg.includes('`key` is not a prop')
14
+ )) {
15
+ return;
16
+ }
17
+ return originalError.apply(console, args);
18
+ };
19
+
20
+ // Extracts key from props without triggering React 19's getter warning
21
+ function extractKey(props: any, key: any): [any, any] {
22
+ if (props == null) return [props, key];
23
+ if (!Object.prototype.hasOwnProperty.call(props, 'key')) return [props, key];
24
+
25
+ const cleanProps: any = {};
26
+ let extractedKey = key;
27
+
28
+ for (const k of Object.keys(props)) {
29
+ if (k === 'key') {
30
+ if (extractedKey == null) extractedKey = props[k];
31
+ }
32
+ else {
33
+ cleanProps[k] = props[k];
34
+ }
35
+ }
36
+
37
+ return [cleanProps, extractedKey];
38
+ }
39
+
40
+ function jsx(type: any, props: any, key?: any) {
41
+ const [cleanProps, finalKey] = extractKey(props, key);
42
+ return OriginalJsx.jsx(type, cleanProps, finalKey);
43
+ }
44
+
45
+ function jsxs(type: any, props: any, key?: any) {
46
+ const [cleanProps, finalKey] = extractKey(props, key);
47
+ return OriginalJsx.jsxs(type, cleanProps, finalKey);
48
+ }
49
+
50
+ const NitronJSXRuntime = {
51
+ jsx,
52
+ jsxs,
53
+ Fragment: OriginalJsx.Fragment
54
+ };
55
+
7
56
  Object.assign(window, {
8
57
  __NITRON_REACT__: React,
9
58
  __NITRON_REACT_DOM__: ReactDOM,
10
59
  __NITRON_REACT_DOM_CLIENT__: ReactDOMClient,
11
- __NITRON_JSX_RUNTIME__: ReactJSXRuntime
60
+ __NITRON_JSX_RUNTIME__: NitronJSXRuntime
12
61
  });
13
62
 
14
63
  RefreshRuntime.injectIntoGlobalHook(window);
@@ -1,11 +1,46 @@
1
1
  import * as React from 'react';
2
2
  import * as ReactDOM from 'react-dom';
3
3
  import * as ReactDOMClient from 'react-dom/client';
4
- import * as ReactJSXRuntime from 'react/jsx-runtime';
4
+ import * as OriginalJsx from 'react/jsx-runtime';
5
+
6
+ // Extracts key from props without triggering React 19's getter warning
7
+ function extractKey(props: any, key: any): [any, any] {
8
+ if (props == null) return [props, key];
9
+ if (!Object.prototype.hasOwnProperty.call(props, 'key')) return [props, key];
10
+
11
+ const cleanProps: any = {};
12
+ let extractedKey = key;
13
+
14
+ for (const k of Object.keys(props)) {
15
+ if (k === 'key') {
16
+ if (extractedKey == null) extractedKey = props[k];
17
+ } else {
18
+ cleanProps[k] = props[k];
19
+ }
20
+ }
21
+
22
+ return [cleanProps, extractedKey];
23
+ }
24
+
25
+ function jsx(type: any, props: any, key?: any) {
26
+ const [cleanProps, finalKey] = extractKey(props, key);
27
+ return OriginalJsx.jsx(type, cleanProps, finalKey);
28
+ }
29
+
30
+ function jsxs(type: any, props: any, key?: any) {
31
+ const [cleanProps, finalKey] = extractKey(props, key);
32
+ return OriginalJsx.jsxs(type, cleanProps, finalKey);
33
+ }
34
+
35
+ const NitronJSXRuntime = {
36
+ jsx,
37
+ jsxs,
38
+ Fragment: OriginalJsx.Fragment
39
+ };
5
40
 
6
41
  Object.assign(window, {
7
42
  __NITRON_REACT__: React,
8
43
  __NITRON_REACT_DOM__: ReactDOM,
9
44
  __NITRON_REACT_DOM_CLIENT__: ReactDOMClient,
10
- __NITRON_JSX_RUNTIME__: ReactJSXRuntime
45
+ __NITRON_JSX_RUNTIME__: NitronJSXRuntime
11
46
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitronjs/framework",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "NitronJS is a modern and extensible Node.js MVC framework built on Fastify. It focuses on clean architecture, modular structure, and developer productivity, offering built-in routing, middleware, configuration management, CLI tooling, and native React integration for scalable full-stack applications.",
5
5
  "bin": {
6
6
  "njs": "./cli/njs.js"