neutronium 2.5.3 → 2.8.0

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/index.d.ts ADDED
@@ -0,0 +1,117 @@
1
+ // @types/netronium/index.d.ts
2
+
3
+ type StateUpdater<T> = (newValue: T) => void;
4
+ type Component<T = any> = (props?: T) => HTMLElement | DocumentFragment;
5
+
6
+ let globalState: any[] = [];
7
+ let stateIndex = 0;
8
+
9
+ // Reset index before each render
10
+ export function resetStateIndex(): void {
11
+ stateIndex = 0;
12
+ }
13
+
14
+ // Custom useState
15
+ export function useState<T>(initialValue: T): [T, StateUpdater<T>] {
16
+ const currentIndex = stateIndex;
17
+
18
+ if (globalState[currentIndex] === undefined) {
19
+ globalState[currentIndex] = initialValue;
20
+ }
21
+
22
+ function setState(newValue: T): void {
23
+ globalState[currentIndex] = newValue;
24
+
25
+ // Re-render
26
+ const root = window.__NEUTRONIUM_ROOT__ as HTMLElement | null;
27
+ const renderFn = window.__NEUTRONIUM_RENDER_FN__ as (() => Node) | null;
28
+
29
+ if (root && typeof renderFn === 'function') {
30
+ root.innerHTML = '';
31
+ resetStateIndex();
32
+ const newVNode = renderFn();
33
+ root.appendChild(newVNode);
34
+ }
35
+ }
36
+
37
+ stateIndex++;
38
+ return [globalState[currentIndex], setState];
39
+ }
40
+
41
+ // JSX-compatible hyperscript function
42
+ export function h(
43
+ type: string | Component,
44
+ props: { [key: string]: any } = {},
45
+ ...children: any[]
46
+ ): HTMLElement | DocumentFragment {
47
+ if (typeof type === 'function') {
48
+ props = props || {};
49
+ props.children = children.flat();
50
+ return type(props);
51
+ }
52
+
53
+ const el = document.createElement(type);
54
+
55
+ for (const [key, value] of Object.entries(props)) {
56
+ if (key.startsWith('on') && typeof value === 'function') {
57
+ el.addEventListener(key.slice(2).toLowerCase(), value);
58
+ } else if (key === 'ref' && typeof value === 'function') {
59
+ value(el);
60
+ } else {
61
+ el.setAttribute(key, value);
62
+ }
63
+ }
64
+
65
+ children.flat().forEach(child => {
66
+ if (typeof child === 'string' || typeof child === 'number') {
67
+ el.appendChild(document.createTextNode(child));
68
+ } else if (child instanceof Node) {
69
+ el.appendChild(child);
70
+ }
71
+ });
72
+
73
+ return el;
74
+ }
75
+
76
+ // Mount app to DOM
77
+ export function createApp(component: () => Node) {
78
+ return {
79
+ mount(selector: string | HTMLElement): Node | null {
80
+ const root =
81
+ typeof selector === 'string'
82
+ ? document.querySelector(selector)
83
+ : selector;
84
+
85
+ if (!root) {
86
+ console.error(`❌ Root element '${selector}' not found`);
87
+ return null;
88
+ }
89
+
90
+ window.__NEUTRONIUM_ROOT__ = root;
91
+ window.__NEUTRONIUM_RENDER_FN__ = component;
92
+
93
+ resetStateIndex();
94
+ const vnode = component();
95
+ root.innerHTML = '';
96
+ root.appendChild(vnode);
97
+
98
+ return vnode;
99
+ }
100
+ };
101
+ }
102
+
103
+ // Fragment support
104
+ export function Fragment(props: { children?: any[] }): DocumentFragment {
105
+ const frag = document.createDocumentFragment();
106
+ const children = props.children ?? [];
107
+
108
+ (Array.isArray(children) ? children : [children]).forEach(child => {
109
+ if (typeof child === 'string' || typeof child === 'number') {
110
+ frag.appendChild(document.createTextNode(child));
111
+ } else if (child instanceof Node) {
112
+ frag.appendChild(child);
113
+ }
114
+ });
115
+
116
+ return frag;
117
+ }
package/package.json CHANGED
@@ -1,41 +1,14 @@
1
1
  {
2
2
  "name": "neutronium",
3
- "version": "2.5.3",
4
- "description": "A dense, efficient JavaScript framework for building modern web applications",
5
- "main": "src/index.js",
6
- "type": "commonjs",
3
+ "version": "2.8.0",
4
+ "description": "",
5
+ "main": "index.ts",
7
6
  "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
8
  },
9
- "export": {
10
- ".": "src/index.js"
11
- },
12
- "bin": {
13
- "neu-cli": "./cli/index.js",
14
- "neu": "src/index.js"
15
- },
16
- "exports": {
17
- ".": "./src/index.js"
18
- },
19
- "keywords": [
20
- "framework",
21
- "javascript",
22
- "frontend",
23
- "ui",
24
- "components"
25
- ],
26
- "author": "PFMCODES",
27
- "license": "MIT",
28
- "dependencies": {
29
- "chokidar": "^4.0.3",
30
- "inquirer": "^12.7.0",
31
- "jsdom": "^26.1.0",
32
- "mime": "^4.0.7",
33
- "open": "^10.1.2",
34
- "ws": "^8.18.3",
35
- "@babel/cli": "^7.28.0",
36
- "@babel/core": "^7.28.0",
37
- "@babel/plugin-transform-react-jsx": "^7.27.1",
38
- "@babel/preset-env": "^7.28.0",
39
- "@babel/preset-react": "^7.27.1"
40
- }
9
+ "keywords": [],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "type": "module",
13
+ "types": "./index.d.ts"
41
14
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 PFMCODES
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,52 +0,0 @@
1
- # ⚛️ Neutronium
2
-
3
- **Ultra-dense JavaScript framework – maximum performance, minimal overhead**
4
-
5
- [![NPM Downloads](https://img.shields.io/npm/dw/neutronium?style=flat-square)](https://www.npmjs.com/package/neutronium)
6
- [![License: MIT](https://img.shields.io/npm/l/neutronium?style=flat-square)](https://opensource.org/licenses/MIT)
7
- [![Version](https://img.shields.io/npm/v/neutronium?style=flat-square)](https://www.npmjs.com/package/neutronium)
8
-
9
- ---
10
-
11
- ## 🚀 About
12
-
13
- **Neutronium** is a lightweight, efficient JavaScript framework designed for building modern web applications with **React-like simplicity** but **minimal overhead**.
14
-
15
- > Ultra-fast ⚡️. Tiny footprint 📦. No build tools 🛠️. Pure JavaScript ✨.
16
-
17
- ---
18
-
19
- ## ✨ Features
20
-
21
- - ⚡️ **Blazing fast rendering**
22
- - 🧠 **Simple component logic**
23
- - 🔌 **No dependencies or virtual DOM**
24
- - 📦 **Small size (~139kB unpacked)**
25
- - 🛠️ **Works out of the box**
26
- - 🔁 **Easy JSX-style structure**
27
-
28
- ---
29
-
30
- ## 📦 Installation
31
-
32
- ```bash
33
- npm i neutronium
34
- ```
35
-
36
- ## Usage Example
37
- ```jsx
38
- // App.js
39
- function Greeting(props) {
40
- return <h2>Hello, {props.name}!</h2>;
41
- }
42
-
43
- export default function App() {
44
- return (
45
- <>
46
- <h1>Welcome to Neutronium</h1>
47
- {Greeting({ name: "Krushna" })}
48
- </>
49
- );
50
- }
51
- ```
52
-
package/cli/index.js DELETED
@@ -1,178 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // --- Module Imports ---
4
- const { default: inquirer } = require('inquirer');
5
- const fs = require('fs');
6
- const path = require('path');
7
- const { execSync } = require('child_process');
8
- const { transformSync } = require('@babel/core');
9
- const { compileProject, compileProjectWatch } = require('../compiler/compiler');
10
-
11
- // --- CLI Arguments ---
12
- const [, , command, ...args] = process.argv;
13
-
14
- // --- Default Babel Config ---
15
- const babelRc = `{
16
- "plugins": [
17
- ["@babel/plugin-transform-react-jsx", {
18
- "pragma": "_neutronium.h",
19
- "pragmaFrag": "_neutronium.Fragment",
20
- "runtime": "classic",
21
- "useBuiltIns": false,
22
- "sourceMaps": true,
23
- "comments": false,
24
- "minified": true,
25
- }]
26
- ]
27
- `;
28
-
29
- // --- Default App.js Starter Template ---
30
- const AppJs = `
31
- import { h, createApp } from 'neutronium';
32
-
33
- function App() {
34
- return (
35
- <div class="container">
36
- <h1>Hello from Neutronium!</h1>
37
- <p>Start building your app in JSX!</p>
38
- </div>
39
- );
40
- }
41
-
42
- createApp(App).mount('#app');
43
- `;
44
-
45
- // --- Basic HTML Template Function ---
46
- const htmlTemplate = (title, jsCode) => `
47
- <!DOCTYPE html>
48
- <html>
49
- <head>
50
- <meta charset="UTF-8" />
51
- <title>${title}</title>
52
- </head>
53
- <body>
54
- <div id="app"></div>
55
- <script type="module">
56
- ${jsCode}
57
- </script>
58
- </body>
59
- </html>
60
- `.trim();
61
-
62
- // --- Project Initializer Function ---
63
- async function init() {
64
- let targetPath = process.cwd(); // default to current folder
65
- let createdFolder = false;
66
-
67
- // Prompt user for init location
68
- const { confirmInit } = await inquirer.prompt([
69
- {
70
- type: 'confirm',
71
- name: 'confirmInit',
72
- message: 'Initialize a Neutronium app in this folder?',
73
- default: true
74
- }
75
- ]);
76
-
77
- let appName = 'neutronium-app';
78
-
79
- // If no, ask for folder name and create it
80
- if (!confirmInit) {
81
- const { projectName } = await inquirer.prompt([
82
- {
83
- type: 'input',
84
- name: 'projectName',
85
- message: 'Please enter your project name:',
86
- default: 'neutronium-app'
87
- }
88
- ]);
89
- appName = projectName;
90
- targetPath = path.resolve(process.cwd(), projectName);
91
- createdFolder = true;
92
- if (!fs.existsSync(targetPath)) fs.mkdirSync(targetPath);
93
- else console.log('⚠️ Folder already exists. Using it anyway.');
94
- }
95
-
96
- // Write App.js
97
- const appPath = path.join(targetPath, 'App.js');
98
- fs.writeFileSync(appPath, AppJs.trim());
99
-
100
- // Write .babelrc
101
- fs.writeFileSync(path.join(targetPath, '.babelrc'), babelRc);
102
-
103
- // Init NPM and install dependencies
104
- execSync('npm init -y', { cwd: targetPath, stdio: 'inherit' });
105
- execSync('npm install neutronium', { cwd: targetPath, stdio: 'inherit' });
106
- execSync('npm install --save-dev @babel/core @babel/cli @babel/plugin-transform-react-jsx', {
107
- cwd: targetPath,
108
- stdio: 'inherit'
109
- });
110
-
111
- // Transpile App.js (in-memory) for preview HTML
112
- const jsxWithImport = `import * as _neutronium from 'neutronium';\n\n${AppJs}`;
113
- const result = transformSync(jsxWithImport, {
114
- filename: 'App.js',
115
- babelrc: false,
116
- configFile: false,
117
- presets: [],
118
- plugins: [
119
- ['@babel/plugin-transform-react-jsx', {
120
- pragma: '_neutronium.h',
121
- pragmaFrag: '_neutronium.Fragment',
122
- runtime: 'classic',
123
- useBuiltIns: false,
124
- sourceMaps: true,
125
- comments: false,
126
- minified: true,
127
- }]
128
- ]
129
- });
130
-
131
- // Write dist/index.html with inlined JS
132
- const finalHtml = htmlTemplate(appName, result.code);
133
- const distPath = path.join(targetPath, 'dist');
134
- if (!fs.existsSync(distPath)) fs.mkdirSync(distPath);
135
- fs.writeFileSync(path.join(distPath, 'index.html'), finalHtml);
136
-
137
- // Print instructions to user
138
- const folderCmd = createdFolder ? `cd ${path.basename(targetPath)}` : '';
139
- console.log('\n✅ Neutronium app is ready!');
140
- console.log(`➡️ Run the following to get started:\n\n ${folderCmd}\n npx serve dist\n`);
141
- }
142
-
143
- // --- CLI Command Routing ---
144
- switch (command) {
145
- case 'init':
146
- case 'create-app':
147
- case 'create-neu-app':
148
- case 'create-new-app':
149
- case 'create-neutronium-app':
150
- init();
151
- break;
152
-
153
- case 'start':
154
- // Watch mode for development
155
- if (args[0] === '--watch') {
156
- compileProjectWatch();
157
- } else {
158
- // Build once without watching
159
- compileProject();
160
- }
161
- break;
162
-
163
- default:
164
- // Help text
165
- console.log('❌ Unknown command.');
166
- console.log(`
167
- Available Commands:
168
-
169
- init | create-app | create-neutronium-app
170
- 👉 Initialize a new Neutronium project
171
-
172
- start
173
- 👉 Compiles your app once
174
-
175
- start --watch
176
- 👉 Start dev server and rebuild on changes
177
- `);
178
- }
@@ -1,131 +0,0 @@
1
- const babel = require('@babel/core');
2
- const path = require('path');
3
- const fs = require('fs');
4
- const { baseHtml } = require('./template');
5
- const { log, writeFile, ensureDir } = require('./utils');
6
- const chokidar = require('chokidar');
7
- const http = require('http');
8
- const { default: Mime } = require('mime');
9
- const WebSocket = require('ws');
10
- const { default: open } = require('open');
11
-
12
- function compileProject(projectDir = process.cwd()) {
13
- const appJsPath = path.join(projectDir, 'App.js');
14
- const distDir = path.join(projectDir, 'dist');
15
- const outHtmlPath = path.join(distDir, 'index.html');
16
- const outJsPath = path.join(distDir, 'App.compiled.js');
17
- const neutroniumPath = '../node_modules/neutronium/src/index.js';
18
-
19
- try {
20
- log('📖 Reading App.js...');
21
- const sourceCode = fs.readFileSync(appJsPath, 'utf-8');
22
-
23
- log('⚙️ Compiling JSX with Babel...');
24
- let { code: transpiled } = babel.transformSync(sourceCode, {
25
- filename: 'App.js', // or use path.basename(appJsPath)
26
- babelrc: false,
27
- configFile: false,
28
- presets: [],
29
- plugins: [
30
- ['@babel/plugin-transform-react-jsx', {
31
- pragma: '_neutronium.h',
32
- pragmaFrag: '_neutronium.Fragment',
33
- runtime: 'classic',
34
- useBuiltIns: false, // <- IMPORTANT
35
- sourceMaps: true,
36
- comments: false,
37
- minified: true,
38
- }]
39
- ]
40
- });
41
-
42
- // Remove CommonJS require if present
43
- transpiled = transpiled.replace(
44
- /(const|var|let)\s+_neutronium\s*=\s*require\(["']neutronium["']\);?/g,
45
- ''
46
- );
47
- transpiled = transpiled.replace("from 'neutronium';", "from '../node_modules/neutronium/src/index.js';")
48
-
49
- const finalJsCode = `
50
- import * as _neutronium from '${neutroniumPath}';
51
-
52
- "use strict";
53
-
54
- ${transpiled}
55
-
56
- _neutronium.createApp(App).mount('#app');
57
- `.trim();
58
-
59
- ensureDir(distDir);
60
- writeFile(outJsPath, finalJsCode);
61
-
62
- log('🛠️ Generating index.html...');
63
- const finalHtml = baseHtml(`<div id="app"></div>`, 'App.compiled.js');
64
- writeFile(outHtmlPath, finalHtml);
65
-
66
- log('✅ Compilation complete!');
67
- log(`➡️ Output: ${outHtmlPath}`);
68
- } catch (e) {
69
- console.error('❌ Compilation failed:', e.message);
70
- }
71
- }
72
-
73
- function compileProjectWatch(projectDir = process.cwd(), port = 3000) {
74
- const appJsPath = path.join(projectDir, 'App.js');
75
-
76
- const server = serveProject(projectDir, port);
77
- compileProject(projectDir);
78
-
79
- log('👀 Watching App.js for changes...');
80
- chokidar.watch(appJsPath).on('change', () => {
81
- console.clear();
82
- log('🔁 Detected change in App.js...');
83
- compileProject(projectDir);
84
- if (server.broadcastReload) {
85
- server.broadcastReload();
86
- }
87
- });
88
- }
89
-
90
- function serveProject(projectDir = process.cwd(), port = 3000) {
91
- const distDir = path.join(projectDir, 'dist');
92
-
93
- const server = http.createServer((req, res) => {
94
- let reqPath = req.url;
95
-
96
- // Redirect "/" to "dist/index.html"
97
- if (reqPath === '/' || reqPath === '/index.html') {
98
- reqPath = '/dist/index.html';
99
- }
100
-
101
- const filePath = path.join(projectDir, reqPath);
102
-
103
- if (!fs.existsSync(filePath)) {
104
- res.writeHead(404);
105
- return res.end('404 Not Found');
106
- }
107
-
108
- const content = fs.readFileSync(filePath);
109
- res.writeHead(200, { 'Content-Type': Mime.getType(filePath) });
110
- res.end(content);
111
- });
112
-
113
- const wss = new WebSocket.Server({ server });
114
-
115
- server.broadcastReload = () => {
116
- wss.clients.forEach(client => {
117
- if (client.readyState === WebSocket.OPEN) {
118
- client.send('reload');
119
- }
120
- });
121
- };
122
-
123
- server.listen(port, () => {
124
- log(`🚀 Server running at http://localhost:${port}`);
125
- open(`http://localhost:${port}/dist/index.html`);
126
- });
127
-
128
- return server;
129
- }
130
-
131
- module.exports = { compileProject, compileProjectWatch };
@@ -1,26 +0,0 @@
1
- function baseHtml(appHtml, scriptName) {
2
- return `
3
- <!DOCTYPE html>
4
- <html>
5
- <head>
6
- <meta charset="UTF-8">
7
- <title>Neutronium App</title>
8
- </head>
9
- <body>
10
- ${appHtml}
11
- <script type="module" src="./${scriptName}"></script>
12
- <script>
13
- const ws = new WebSocket('ws://' + location.host);
14
- ws.onmessage = (msg) => {
15
- if (msg.data === 'reload') {
16
- console.log('[Neutronium] Reloading...');
17
- location.reload();
18
- }
19
- };
20
- </script>
21
- </body>
22
- </html>
23
- `.trim();
24
- }
25
-
26
- module.exports = { baseHtml };
package/compiler/utils.js DELETED
@@ -1,22 +0,0 @@
1
- // compiler/utils.js
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
-
6
- function writeFile(filePath, content) {
7
- fs.writeFileSync(filePath, content, 'utf-8');
8
- }
9
-
10
- function readFile(filePath) {
11
- return fs.readFileSync(filePath, 'utf-8');
12
- }
13
-
14
- function ensureDir(dir) {
15
- if (!fs.existsSync(dir)) fs.mkdirSync(dir);
16
- }
17
-
18
- function log(msg) {
19
- console.log(`🔹 ${msg}`);
20
- }
21
-
22
- module.exports = { writeFile, readFile, ensureDir, log };
package/neutronium.png DELETED
Binary file
package/src/index.js DELETED
@@ -1,104 +0,0 @@
1
- // src/index.js
2
-
3
- let globalState = [];
4
- let stateIndex = 0;
5
-
6
- // This will be called before rendering begins
7
- export function resetStateIndex() {
8
- stateIndex = 0;
9
- }
10
-
11
- // Custom useState implementation
12
- function useState(initialValue) {
13
- const current = stateIndex;
14
-
15
- if (globalState[current] === undefined) {
16
- globalState[current] = initialValue;
17
- }
18
-
19
- function setState(newValue) {
20
- globalState[current] = newValue;
21
-
22
- // Re-render the entire app
23
- if (window.__NEUTRONIUM_ROOT__ && typeof window.__NEUTRONIUM_RENDER_FN__ === 'function') {
24
- window.__NEUTRONIUM_ROOT__.innerHTML = '';
25
- resetStateIndex();
26
- const newVNode = window.__NEUTRONIUM_RENDER_FN__();
27
- window.__NEUTRONIUM_ROOT__.appendChild(newVNode);
28
- }
29
- }
30
-
31
- stateIndex++;
32
- return [globalState[current], setState];
33
- }
34
-
35
- function h(type, props = {}, ...children) {
36
- if (typeof type === 'function') {
37
- // 🔧 Add children to props
38
- props = props || {};
39
- props.children = children.flat(); // ✅ critical fix
40
- return type(props);
41
- }
42
-
43
- const el = document.createElement(type);
44
-
45
- for (const [key, value] of Object.entries(props || {})) {
46
- if (key.startsWith('on') && typeof value === 'function') {
47
- el.addEventListener(key.slice(2).toLowerCase(), value);
48
- } else if (key === 'ref' && typeof value === 'function') {
49
- value(el);
50
- } else {
51
- el.setAttribute(key, value);
52
- }
53
- }
54
-
55
- children.flat().forEach(child => {
56
- if (typeof child === 'string' || typeof child === 'number') {
57
- el.appendChild(document.createTextNode(child));
58
- } else if (child instanceof Node) {
59
- el.appendChild(child);
60
- }
61
- });
62
-
63
- return el;
64
- }
65
-
66
- function createApp(component) {
67
- return {
68
- mount(selector) {
69
- const root = typeof selector === 'string' ? document.querySelector(selector) : selector;
70
- if (!root) {
71
- console.error(`❌ Root element '${selector}' not found`);
72
- return null; // return something explicit
73
- }
74
- // Save render function + root globally so useState can use them
75
- window.__NEUTRONIUM_ROOT__ = root;
76
- window.__NEUTRONIUM_RENDER_FN__ = component;
77
-
78
- // Reset before first render
79
- resetStateIndex();
80
- const vnode = component();
81
- root.innerHTML = '';
82
- root.appendChild(vnode);
83
-
84
- return vnode; // ✅ REQUIRED
85
- }
86
- };
87
- }
88
-
89
- function Fragment(props = {}) {
90
- const frag = document.createDocumentFragment();
91
- const children = props.children || [];
92
-
93
- (Array.isArray(children) ? children : [children]).forEach(child => {
94
- if (typeof child === 'string' || typeof child === 'number') {
95
- frag.appendChild(document.createTextNode(child));
96
- } else if (child instanceof Node) {
97
- frag.appendChild(child);
98
- }
99
- });
100
-
101
- return frag;
102
- }
103
-
104
- export { h, createApp, Fragment, useState };