react-client 1.0.11 → 1.0.13

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 CHANGED
@@ -35,7 +35,7 @@ npm install
35
35
  npm run dev
36
36
  ```
37
37
 
38
- This launches the **custom dev server** — not Vite — built on **Connect + WebSocket + esbuild**, featuring:
38
+ This launches the **custom dev server** — built on **Connect + WebSocket + esbuild**, featuring:
39
39
  - Instant rebuilds
40
40
  - React Fast Refresh (HMR)
41
41
  - Auto port detection & confirmation prompt
@@ -85,9 +85,9 @@ Each template is pre-configured for esbuild, HMR, and fast bootstrapping.
85
85
 
86
86
  ## 💎 Core Features
87
87
 
88
- - ⚡ **Custom Dev Server (no Vite)** — Connect + WebSocket + esbuild
88
+ - ⚡ **Custom Dev Server** — Connect + WebSocket + esbuild
89
89
  - 🔁 **React Fast Refresh (HMR)** — State-preserving reloads
90
- - 💥 **Vite-style Overlay** — Syntax-highlighted stack frames, clickable file links (`vscode://file`)
90
+ - 💥 **Overlay** — Syntax-highlighted stack frames, clickable file links (`vscode://file`)
91
91
  - 🔍 **Source Map Stack Mapping** — Maps runtime errors to original TS/JS source lines
92
92
  - 💬 **Auto Port Detection** — Prompts when default port 5173 is occupied
93
93
  - 🧠 **Smart Config Loader** — Detects project root, compiles `.ts` configs dynamically
@@ -19,7 +19,7 @@ const child_process_1 = require("child_process");
19
19
  const chalk_1 = __importDefault(require("chalk"));
20
20
  async function dev() {
21
21
  const root = process.cwd();
22
- // 🧩 Load config
22
+ // 🧩 Load user config
23
23
  const userConfig = await (0, loadConfig_1.loadReactClientConfig)(root);
24
24
  const appRoot = path_1.default.resolve(root, userConfig.root || '.');
25
25
  const defaultPort = userConfig.server?.port || 5173;
@@ -33,7 +33,7 @@ async function dev() {
33
33
  }
34
34
  const indexHtml = path_1.default.join(appRoot, 'index.html');
35
35
  await fs_extra_1.default.ensureDir(outDir);
36
- // 🧠 Detect open port
36
+ // ⚙️ Detect open port
37
37
  const availablePort = await (0, detect_port_1.default)(defaultPort);
38
38
  const port = availablePort;
39
39
  if (availablePort !== defaultPort) {
@@ -73,7 +73,7 @@ async function dev() {
73
73
  }
74
74
  }
75
75
  const reactRefreshRuntime = safeResolveReactRefresh();
76
- // 🏗️ esbuild context
76
+ // 🏗️ Create esbuild context
77
77
  const ctx = await esbuild_1.default.context({
78
78
  entryPoints: [entry],
79
79
  bundle: true,
@@ -88,7 +88,7 @@ async function dev() {
88
88
  console.log(chalk_1.default.gray('📦 Watching and building dev bundle...'));
89
89
  console.log(chalk_1.default.gray(' Output dir:'), chalk_1.default.blue(outDir));
90
90
  console.log(chalk_1.default.gray(' Entry file:'), chalk_1.default.yellow(entry));
91
- // 🌐 connect server
91
+ // 🌐 Connect server setup
92
92
  const app = (0, connect_1.default)();
93
93
  // 🛡 Security headers
94
94
  app.use((_req, res, next) => {
@@ -96,11 +96,12 @@ async function dev() {
96
96
  res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
97
97
  next();
98
98
  });
99
+ // 🧠 In-memory cache for /@modules
100
+ const moduleCache = new Map();
99
101
  // 1️⃣ Serve react-refresh runtime with safe browser shim
100
102
  app.use('/@react-refresh', async (_req, res) => {
101
103
  const runtime = await fs_extra_1.default.readFile(reactRefreshRuntime, 'utf8');
102
104
  const shim = `
103
- // React Refresh browser shims
104
105
  window.process = window.process || { env: { NODE_ENV: 'development' } };
105
106
  window.module = { exports: {} };
106
107
  window.global = window;
@@ -109,31 +110,43 @@ async function dev() {
109
110
  res.setHeader('Content-Type', 'application/javascript');
110
111
  res.end(shim + '\n' + runtime);
111
112
  });
112
- // 2️⃣ Minimal bare import resolver (/@modules/)
113
+ // 2️⃣ Bare module resolver with memory cache
113
114
  app.use('/@modules/', async (req, res, next) => {
114
- const id = req.url?.replace(/^\/@modules\//, '');
115
+ let id = req.url?.replace(/^\/@modules\//, '');
115
116
  if (!id)
116
117
  return next();
118
+ // 🧩 Normalize: remove leading slashes that may appear (e.g. "/react")
119
+ id = id.replace(/^\/+/, '');
120
+ if (!id)
121
+ return next();
122
+ if (moduleCache.has(id)) {
123
+ res.setHeader('Content-Type', 'application/javascript');
124
+ res.end(moduleCache.get(id));
125
+ return;
126
+ }
117
127
  try {
118
- const entry = require.resolve(id, { paths: [appRoot] });
128
+ const entryPath = require.resolve(id, { paths: [appRoot] });
119
129
  const out = await esbuild_1.default.build({
120
- entryPoints: [entry],
130
+ entryPoints: [entryPath],
121
131
  bundle: true,
122
132
  write: false,
123
133
  platform: 'browser',
124
134
  format: 'esm',
125
135
  target: 'es2020',
126
136
  });
137
+ const code = out.outputFiles[0].text;
138
+ moduleCache.set(id, code); // ✅ cache module
127
139
  res.setHeader('Content-Type', 'application/javascript');
128
- res.end(out.outputFiles[0].text);
140
+ res.end(code);
129
141
  }
130
142
  catch (err) {
131
- console.error('Failed to resolve module', id, err);
143
+ const msg = err instanceof Error ? err.message : String(err);
144
+ console.error(chalk_1.default.red(`Failed to resolve module ${id}: ${msg}`));
132
145
  res.writeHead(500);
133
146
  res.end(`// Could not resolve module ${id}`);
134
147
  }
135
148
  });
136
- // 3️⃣ Serve /src/* files (on-the-fly transform)
149
+ // 3️⃣ Serve /src/* files on-the-fly transform + bare import rewrite
137
150
  app.use(async (req, res, next) => {
138
151
  if (!req.url || !req.url.startsWith('/src/'))
139
152
  return next();
@@ -141,8 +154,11 @@ async function dev() {
141
154
  const filePath = path_1.default.join(appRoot, decodeURIComponent(req.url.split('?')[0]));
142
155
  if (!(await fs_extra_1.default.pathExists(filePath)))
143
156
  return next();
144
- const code = await fs_extra_1.default.readFile(filePath, 'utf8');
157
+ let code = await fs_extra_1.default.readFile(filePath, 'utf8');
145
158
  const ext = path_1.default.extname(filePath).toLowerCase();
159
+ // 🪄 Rewrite bare imports → /@modules/
160
+ // 🧩 Rewrite *only bare imports* like "react", not "./" or "/" or "../"
161
+ code = code.replace(/from\s+['"]((?![\.\/])[a-zA-Z0-9@/_-]+)['"]/g, (_match, dep) => `from "/@modules/${dep}"`);
146
162
  let loader = 'js';
147
163
  if (ext === '.ts')
148
164
  loader = 'ts';
@@ -163,7 +179,7 @@ async function dev() {
163
179
  }
164
180
  catch (err) {
165
181
  const msg = err instanceof Error ? err.message : String(err);
166
- console.error('Error serving src file:', msg);
182
+ console.error('Error serving /src file:', msg);
167
183
  res.writeHead(500);
168
184
  res.end(`// Error: ${msg}`);
169
185
  }
@@ -214,7 +230,7 @@ async function dev() {
214
230
  next();
215
231
  }
216
232
  });
217
- // 🔁 HMR via WebSocket
233
+ // 🔁 HMR WebSocket server
218
234
  const server = http_1.default.createServer(app);
219
235
  const wss = new ws_1.WebSocketServer({ server });
220
236
  const broadcast = (data) => {
@@ -236,6 +252,7 @@ async function dev() {
236
252
  }
237
253
  }
238
254
  });
255
+ // 🟢 Start server
239
256
  server.listen(port, async () => {
240
257
  const url = `http://localhost:${port}`;
241
258
  console.log(chalk_1.default.cyan.bold(`\n🚀 React Client Dev Server`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-client",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "react-client is a lightweight CLI and runtime for building React apps with fast iteration.",
5
5
  "license": "MIT",
6
6
  "author": "Venkatesh Sundaram",