neutronium 2.5.3 → 2.8.5

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/cli/index.js CHANGED
@@ -26,20 +26,29 @@ const babelRc = `{
26
26
  ]
27
27
  `;
28
28
 
29
+ const AppTs = `
30
+ import { createApp } from 'neutronium';
31
+
32
+ function App() {
33
+ return (
34
+ <h1>Hello World</h1>
35
+ );
36
+ }
37
+
38
+ createApp(App).mount('body');
39
+ `
40
+
29
41
  // --- Default App.js Starter Template ---
30
42
  const AppJs = `
31
- import { h, createApp } from 'neutronium';
43
+ import { createApp } from 'neutronium';
32
44
 
33
45
  function App() {
34
46
  return (
35
- <div class="container">
36
- <h1>Hello from Neutronium!</h1>
37
- <p>Start building your app in JSX!</p>
38
- </div>
47
+ <h1>Hello World</h1>
39
48
  );
40
49
  }
41
50
 
42
- createApp(App).mount('#app');
51
+ createApp(App).mount('body');
43
52
  `;
44
53
 
45
54
  // --- Basic HTML Template Function ---
@@ -51,7 +60,6 @@ const htmlTemplate = (title, jsCode) => `
51
60
  <title>${title}</title>
52
61
  </head>
53
62
  <body>
54
- <div id="app"></div>
55
63
  <script type="module">
56
64
  ${jsCode}
57
65
  </script>
@@ -101,13 +109,24 @@ async function init() {
101
109
  fs.writeFileSync(path.join(targetPath, '.babelrc'), babelRc);
102
110
 
103
111
  // 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', {
112
+ await execSync('npm init -y', { cwd: targetPath, stdio: 'inherit' });
113
+ await execSync('npm install neutronium', { cwd: targetPath, stdio: 'inherit' });
114
+ await execSync('npm install --save-dev @babel/core @babel/cli @babel/plugin-transform-react-jsx', {
107
115
  cwd: targetPath,
108
116
  stdio: 'inherit'
109
117
  });
110
118
 
119
+ // Read and parse package.json
120
+ const packageJson = await JSON.parse(fs.readFileSync('package.json', 'utf-8'));
121
+
122
+ // Modify the "start" script
123
+ packageJson.scripts = packageJson.scripts || {};
124
+ packageJson.scripts.start = "neu-cli start --watch"; // example: "node index.js"
125
+ packageJson.scripts.compile = "neu-cli start"
126
+ packageJson.scripts.update = "npm i neutronium@latest -g && npm i netronium@latest"
127
+
128
+ // Write back to package.json
129
+ await fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2));
111
130
  // Transpile App.js (in-memory) for preview HTML
112
131
  const jsxWithImport = `import * as _neutronium from 'neutronium';\n\n${AppJs}`;
113
132
  const result = transformSync(jsxWithImport, {
@@ -137,7 +156,8 @@ async function init() {
137
156
  // Print instructions to user
138
157
  const folderCmd = createdFolder ? `cd ${path.basename(targetPath)}` : '';
139
158
  console.log('\n✅ Neutronium app is ready!');
140
- console.log(`➡️ Run the following to get started:\n\n ${folderCmd}\n npx serve dist\n`);
159
+ console.log(`➡️ Run the following to get started:\n\n ${folderCmd}\n npm start\n`);
160
+
141
161
  }
142
162
 
143
163
  // --- CLI Command Routing ---
@@ -159,7 +179,55 @@ switch (command) {
159
179
  compileProject();
160
180
  }
161
181
  break;
182
+ case '--lang':
183
+ const lang = args[0];
184
+
185
+ if (lang === "ts") {
186
+ fs.unlinkSync('App.js');
187
+ fs.writeFileSync('App.ts', AppTs);
188
+ fs.writeFileSync('tsconfig.json', `
189
+ {
190
+ "compilerOptions": {
191
+ "outDir": "build",
192
+ "rootDir": ".",
193
+ "target": "ES2020",
194
+ "module": "ESNext",
195
+ "lib": ["DOM", "ES2020"],
196
+ "jsx": "react",
197
+ "jsxFactory": "h",
198
+ "jsxFragmentFactory": "Fragment",
199
+ "moduleResolution": "Node",
200
+ "strict": true,
201
+ "allowJs": true,
202
+ "checkJs": false,
203
+ "noEmit": true,
204
+ "esModuleInterop": true,
205
+ "skipLibCheck": true,
206
+ "forceConsistentCasingInFileNames": true
207
+ },
208
+ "include": ["**/*"],
209
+ "exclude": ["dist", "node_modules"]
210
+ }
211
+ `);
212
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
213
+ packageJson.scripts = packageJson.scripts || {};
214
+ packageJson.scripts.start = 'tsc && ' + packageJson.scripts.start;
215
+ fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2));
216
+ }
162
217
 
218
+ if (lang === "js") {
219
+ fs.unlinkSync('App.ts');
220
+ fs.writeFileSync('App.js', AppJs); // assuming `AppJs` is defined
221
+ if (fs.existsSync('tsconfig.json')) {
222
+ fs.unlinkSync('tsconfig.json');
223
+ }
224
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
225
+ if (packageJson.scripts && packageJson.scripts.start?.startsWith('tsc &&')) {
226
+ packageJson.scripts.start = packageJson.scripts.start.replace(/^tsc &&\s*/, '');
227
+ }
228
+ fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2));
229
+ }
230
+ break;
163
231
  default:
164
232
  // Help text
165
233
  console.log('❌ Unknown command.');
@@ -1,131 +1,262 @@
1
- const babel = require('@babel/core');
2
- const path = require('path');
1
+ #!/usr/bin/env node
2
+
3
+ const { default: inquirer } = require('inquirer');
3
4
  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';
5
+ const path = require('path');
6
+ const { execSync } = require('child_process');
7
+ const { transformSync } = require('@babel/core');
8
+ const { compileProject, compileProjectWatch } = require('../compiler/compiler');
18
9
 
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
- ''
10
+ const [, , command, ...args] = process.argv;
11
+
12
+ const babelRc = `{
13
+ "plugins": [
14
+ ["@babel/plugin-transform-react-jsx", {
15
+ "pragma": "_neutronium.h",
16
+ "pragmaFrag": "_neutronium.Fragment",
17
+ "runtime": "classic",
18
+ "useBuiltIns": false,
19
+ "sourceMaps": true,
20
+ "comments": false,
21
+ "minified": true
22
+ }]
23
+ ]
24
+ }`;
25
+
26
+ const AppTs = `
27
+ import { createApp } from 'neutronium';
28
+
29
+ function App() {
30
+ return (
31
+ <h1>Hello World (TypeScript)</h1>
46
32
  );
47
- transpiled = transpiled.replace("from 'neutronium';", "from '../node_modules/neutronium/src/index.js';")
33
+ }
48
34
 
49
- const finalJsCode = `
50
- import * as _neutronium from '${neutroniumPath}';
35
+ createApp(App).mount("body");
36
+ `;
51
37
 
52
- "use strict";
38
+ const AppJs = `
39
+ import { createApp } from 'neutronium';
53
40
 
54
- ${transpiled}
41
+ function App() {
42
+ return (
43
+ <h1>Hello World</h1>
44
+ );
45
+ }
55
46
 
56
- _neutronium.createApp(App).mount('#app');
47
+ createApp(App).mount("body");
48
+ `;
49
+
50
+ const htmlTemplate = (title, jsCode) => `
51
+ <!DOCTYPE html>
52
+ <html>
53
+ <head>
54
+ <meta charset="UTF-8" />
55
+ <title>${title}</title>
56
+ </head>
57
+ <body>
58
+ <script type="module">
59
+ ${jsCode}
60
+ </script>
61
+ </body>
62
+ </html>
57
63
  `.trim();
58
64
 
59
- ensureDir(distDir);
60
- writeFile(outJsPath, finalJsCode);
65
+ async function init() {
66
+ let targetPath = process.cwd();
67
+ let createdFolder = false;
61
68
 
62
- log('🛠️ Generating index.html...');
63
- const finalHtml = baseHtml(`<div id="app"></div>`, 'App.compiled.js');
64
- writeFile(outHtmlPath, finalHtml);
69
+ const { confirmInit } = await inquirer.prompt([
70
+ {
71
+ type: 'confirm',
72
+ name: 'confirmInit',
73
+ message: 'Initialize a Neutronium app in this folder?',
74
+ default: true
75
+ }
76
+ ]);
65
77
 
66
- log('✅ Compilation complete!');
67
- log(`➡️ Output: ${outHtmlPath}`);
68
- } catch (e) {
69
- console.error('❌ Compilation failed:', e.message);
78
+ let appName = 'neutronium-app';
79
+
80
+ if (!confirmInit) {
81
+ const { projectName } = await inquirer.prompt([
82
+ {
83
+ type: 'input',
84
+ name: 'projectName',
85
+ message: '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);
70
93
  }
71
- }
72
94
 
73
- function compileProjectWatch(projectDir = process.cwd(), port = 3000) {
74
- const appJsPath = path.join(projectDir, 'App.js');
95
+ // Ask language preference
96
+ const { language } = await inquirer.prompt([
97
+ {
98
+ type: 'list',
99
+ name: 'language',
100
+ message: 'Choose your language:',
101
+ choices: ['JavaScript', 'TypeScript']
102
+ }
103
+ ]);
104
+
105
+ const appFileName = language === 'TypeScript' ? 'App.ts' : 'App.js';
106
+ fs.writeFileSync(path.join(targetPath, appFileName), (language === 'TypeScript' ? AppTs : AppJs).trim());
75
107
 
76
- const server = serveProject(projectDir, port);
77
- compileProject(projectDir);
108
+ fs.writeFileSync(path.join(targetPath, '.babelrc'), babelRc);
78
109
 
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
- }
110
+ execSync('npm init -y', { cwd: targetPath, stdio: 'inherit' });
111
+ execSync('npm install neutronium', { cwd: targetPath, stdio: 'inherit' });
112
+ execSync('npm install --save-dev @babel/core @babel/cli @babel/plugin-transform-react-jsx', {
113
+ cwd: targetPath, stdio: 'inherit'
87
114
  });
115
+
116
+ if (language === 'TypeScript') {
117
+ execSync('npm install --save-dev typescript', { cwd: targetPath, stdio: 'inherit' });
118
+ fs.writeFileSync(path.join(targetPath, 'tsconfig.json'), `
119
+ {
120
+ "compilerOptions": {
121
+ "outDir": "build",
122
+ "rootDir": ".",
123
+ "target": "ES2020",
124
+ "module": "ESNext",
125
+ "lib": ["DOM", "ES2020"],
126
+ "jsx": "react",
127
+ "jsxFactory": "h",
128
+ "jsxFragmentFactory": "Fragment",
129
+ "moduleResolution": "Node",
130
+ "strict": true,
131
+ "allowJs": true,
132
+ "checkJs": false,
133
+ "noEmit": true,
134
+ "esModuleInterop": true,
135
+ "skipLibCheck": true,
136
+ "forceConsistentCasingInFileNames": true
137
+ },
138
+ "include": ["**/*"],
139
+ "exclude": ["dist", "node_modules"]
88
140
  }
141
+ `.trim());
142
+ }
89
143
 
90
- function serveProject(projectDir = process.cwd(), port = 3000) {
91
- const distDir = path.join(projectDir, 'dist');
144
+ const packageJsonPath = path.join(targetPath, 'package.json');
145
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
92
146
 
93
- const server = http.createServer((req, res) => {
94
- let reqPath = req.url;
147
+ packageJson.scripts = packageJson.scripts || {};
148
+ packageJson.scripts.start = language === 'TypeScript'
149
+ ? 'tsc && neu-cli start --watch'
150
+ : 'neu-cli start --watch';
95
151
 
96
- // Redirect "/" to "dist/index.html"
97
- if (reqPath === '/' || reqPath === '/index.html') {
98
- reqPath = '/dist/index.html';
99
- }
152
+ packageJson.scripts.compile = 'neu-cli start';
153
+ packageJson.scripts.update = 'npm i neutronium@latest -g && npm i neutronium@latest';
100
154
 
101
- const filePath = path.join(projectDir, reqPath);
155
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
102
156
 
103
- if (!fs.existsSync(filePath)) {
104
- res.writeHead(404);
105
- return res.end('404 Not Found');
106
- }
157
+ // Create preview HTML
158
+ const jsxWithImport = `import * as _neutronium from 'neutronium';\n\n${AppJs}`;
159
+ let compiledCode = '';
160
+ try {
161
+ compiledCode = transformSync(jsxWithImport, {
162
+ filename: 'App.js',
163
+ babelrc: false,
164
+ configFile: false,
165
+ presets: [],
166
+ plugins: [[
167
+ '@babel/plugin-transform-react-jsx',
168
+ {
169
+ pragma: '_neutronium.h',
170
+ pragmaFrag: '_neutronium.Fragment',
171
+ runtime: 'classic'
172
+ }
173
+ ]]
174
+ }).code;
175
+ } catch (e) {
176
+ console.warn('⚠️ Babel preview transform failed:', e.message);
177
+ }
107
178
 
108
- const content = fs.readFileSync(filePath);
109
- res.writeHead(200, { 'Content-Type': Mime.getType(filePath) });
110
- res.end(content);
111
- });
179
+ const distPath = path.join(targetPath, 'dist');
180
+ if (!fs.existsSync(distPath)) fs.mkdirSync(distPath);
181
+ fs.writeFileSync(path.join(distPath, 'index.html'), htmlTemplate(appName, compiledCode));
112
182
 
113
- const wss = new WebSocket.Server({ server });
183
+ const folderCmd = createdFolder ? `cd ${path.basename(targetPath)}` : '';
184
+ console.log('\n✅ Neutronium app is ready!');
185
+ console.log(`➡️ Run the following to get started:\n\n ${folderCmd}\n npm start\n`);
186
+ }
114
187
 
115
- server.broadcastReload = () => {
116
- wss.clients.forEach(client => {
117
- if (client.readyState === WebSocket.OPEN) {
118
- client.send('reload');
119
- }
120
- });
121
- };
188
+ // --- CLI Command Routing ---
189
+ switch (command) {
190
+ case 'init':
191
+ case 'create-app':
192
+ case 'create-neutronium-app':
193
+ init();
194
+ break;
122
195
 
123
- server.listen(port, () => {
124
- log(`🚀 Server running at http://localhost:${port}`);
125
- open(`http://localhost:${port}/dist/index.html`);
126
- });
196
+ case 'start':
197
+ if (args[0] === '--watch') compileProjectWatch();
198
+ else compileProject();
199
+ break;
200
+
201
+ case '--lang':
202
+ const lang = args[0];
203
+ const pkgPath = path.join(process.cwd(), 'package.json');
204
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
127
205
 
128
- return server;
206
+ if (lang === 'ts') {
207
+ fs.unlinkSync('App.js');
208
+ fs.writeFileSync('App.ts', AppTs);
209
+ fs.writeFileSync('tsconfig.json', `
210
+ {
211
+ "compilerOptions": {
212
+ "outDir": "build",
213
+ "rootDir": ".",
214
+ "target": "ES2020",
215
+ "module": "ESNext",
216
+ "lib": ["DOM", "ES2020"],
217
+ "jsx": "react",
218
+ "jsxFactory": "h",
219
+ "jsxFragmentFactory": "Fragment",
220
+ "moduleResolution": "Node",
221
+ "strict": true,
222
+ "allowJs": true,
223
+ "checkJs": false,
224
+ "noEmit": true,
225
+ "esModuleInterop": true,
226
+ "skipLibCheck": true,
227
+ "forceConsistentCasingInFileNames": true
228
+ },
229
+ "include": ["**/*"],
230
+ "exclude": ["dist", "node_modules"]
129
231
  }
232
+ `.trim());
233
+ pkg.scripts.start = 'tsc && neu-cli start --watch';
234
+ }
235
+
236
+ if (lang === 'js') {
237
+ fs.unlinkSync('App.ts');
238
+ fs.writeFileSync('App.js', AppJs);
239
+ if (fs.existsSync('tsconfig.json')) fs.unlinkSync('tsconfig.json');
240
+ pkg.scripts.start = pkg.scripts.start.replace(/^tsc &&\s*/, '');
241
+ }
242
+
243
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
244
+ break;
245
+
246
+ default:
247
+ console.log('❌ Unknown command.');
248
+ console.log(`
249
+ Available Commands:
250
+ init | create-app | create-neutronium-app
251
+ 👉 Initialize a new Neutronium project
252
+
253
+ start
254
+ 👉 Compiles your app once
255
+
256
+ start --watch
257
+ 👉 Start dev server and rebuild on changes
130
258
 
131
- module.exports = { compileProject, compileProjectWatch };
259
+ --lang js | ts
260
+ 👉 Switch between JS and TS
261
+ `);
262
+ }
package/package.json CHANGED
@@ -1,21 +1,20 @@
1
1
  {
2
2
  "name": "neutronium",
3
- "version": "2.5.3",
3
+ "version": "2.8.5",
4
4
  "description": "A dense, efficient JavaScript framework for building modern web applications",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
7
+ "types": "./@types/neutronium/index.d.ts",
7
8
  "scripts": {
8
- },
9
- "export": {
10
- ".": "src/index.js"
11
- },
12
- "bin": {
13
- "neu-cli": "./cli/index.js",
14
- "neu": "src/index.js"
9
+ "build": "node build.js",
10
+ "start": "npx serve dist"
15
11
  },
16
12
  "exports": {
17
13
  ".": "./src/index.js"
18
14
  },
15
+ "bin": {
16
+ "neu-cli": "./cli/index.js"
17
+ },
19
18
  "keywords": [
20
19
  "framework",
21
20
  "javascript",
@@ -26,16 +25,23 @@
26
25
  "author": "PFMCODES",
27
26
  "license": "MIT",
28
27
  "dependencies": {
28
+ "@babel/cli": "^7.28.0",
29
+ "@babel/core": "^7.28.0",
30
+ "@babel/plugin-transform-react-jsx": "^7.27.1",
31
+ "@babel/preset-env": "^7.28.0",
32
+ "@babel/preset-react": "^7.27.1",
29
33
  "chokidar": "^4.0.3",
30
34
  "inquirer": "^12.7.0",
31
35
  "jsdom": "^26.1.0",
32
36
  "mime": "^4.0.7",
33
37
  "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"
38
+ "ws": "^8.18.3"
39
+ },
40
+ "devDependencies": {
41
+ "@rollup/plugin-babel": "^6.0.4",
42
+ "@rollup/plugin-node-resolve": "^16.0.1",
43
+ "esbuild": "^0.25.6",
44
+ "rollup": "^2.79.2",
45
+ "rollup-plugin-terser": "^7.0.2"
40
46
  }
41
47
  }