nukejs 0.0.15 → 0.0.16

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/dist/app.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import http from "http";
2
2
  import path from "path";
3
3
  import { existsSync, watch } from "fs";
4
- import { ansi, c, log, setDebugLevel, getDebugLevel } from "./logger.js";
4
+ import { c, log, setDebugLevel, getDebugLevel } from "./logger.js";
5
5
  import { loadConfig } from "./config.js";
6
6
  import { discoverApiPrefixes, matchApiPrefix, createApiHandler } from "./http-server.js";
7
7
  import { loadMiddleware, runMiddleware } from "./middleware-loader.js";
@@ -9,6 +9,7 @@ import { serveReactBundle, serveNukeBundle, serveClientComponentBundle } from ".
9
9
  import { serverSideRender } from "./ssr.js";
10
10
  import { watchDir, broadcastRestart } from "./hmr.js";
11
11
  const isDev = process.env.ENVIRONMENT !== "production";
12
+ const _startMs = Date.now();
12
13
  if (isDev) {
13
14
  const React = await import("react");
14
15
  global.React = React;
@@ -84,30 +85,28 @@ function tryListen(port) {
84
85
  server.listen(port, () => resolve(port));
85
86
  });
86
87
  }
87
- function printStartupBanner(port, isDev2) {
88
+ function printStartupBanner(port, configuredPort, startMs) {
88
89
  const url = `http://localhost:${port}`;
89
90
  const level = getDebugLevel();
90
- const debugStr = String(level);
91
- const innerWidth = 42;
92
- const line = "\u2500".repeat(innerWidth);
93
- const pad = (text, width) => {
94
- const visibleLen = text.replace(/\x1b\[[0-9;]*m/g, "").length;
95
- return text + " ".repeat(Math.max(0, width - visibleLen));
91
+ const elapsed = Date.now() - startMs;
92
+ const keyW = 5;
93
+ const visible = (s) => s.replace(/\x1b\[[\d;]*m/g, "").length;
94
+ const row = (key, val) => {
95
+ const pad = " ".repeat(Math.max(0, keyW - visible(key)));
96
+ console.log(` ${c("gray", key)}${pad} ${val}`);
96
97
  };
97
- const row = (content, w = 2) => `${ansi.gray}\u2502${ansi.reset} ${pad(content, innerWidth - w)} ${ansi.gray}\u2502${ansi.reset}`;
98
- const label = (key, val) => row(`${c("gray", key)} ${val}`);
99
98
  console.log("");
100
- console.log(`${ansi.gray}\u250C${line}\u2510${ansi.reset}`);
101
- console.log(row(` ${c("red", "\u2622\uFE0F nukejs ", true)}`, 1));
102
- console.log(`${ansi.gray}\u251C${line}\u2524${ansi.reset}`);
103
- console.log(label(" Local ", c("cyan", url, true)));
104
- console.log(`${ansi.gray}\u251C${line}\u2524${ansi.reset}`);
105
- console.log(label(" Pages ", c("white", path.relative(process.cwd(), PAGES_DIR))));
106
- console.log(label(" Server ", c("white", path.relative(process.cwd(), SERVER_DIR))));
107
- console.log(label(" Dev ", isDev2 ? c("green", "yes") : c("gray", "no")));
108
- console.log(label(" Debug ", level === false ? c("gray", "off") : level === true ? c("green", "verbose") : c("yellow", debugStr)));
109
- console.log(`${ansi.gray}\u2514${line}\u2518${ansi.reset}`);
99
+ console.log(` ${c("orange", "NukeJS", true)} ${c("gray", `ready in ${elapsed}ms`)}`);
100
+ console.log("");
101
+ row(
102
+ "Local",
103
+ port !== configuredPort ? `${c("cyan", url, true)} ${c("yellow", `(${configuredPort} was in use)`)}` : c("cyan", url, true)
104
+ );
105
+ row(
106
+ "Debug",
107
+ level === false ? c("gray", "off") : level === true ? c("green", "verbose") : c("yellow", String(level))
108
+ );
110
109
  console.log("");
111
110
  }
112
111
  const actualPort = await tryListen(PORT);
113
- printStartupBanner(actualPort, isDev);
112
+ printStartupBanner(actualPort, PORT, _startMs);
@@ -618,7 +618,7 @@ export default async function handler(req: IncomingMessage, res: ServerResponse)
618
618
 
619
619
  <script id="__n_data" type="application/json">\${runtimeData}</script>
620
620
 
621
- <script type="importmap">
621
+ \${hydrated.size > 0 ? \`<script type="importmap">
622
622
  {
623
623
  "imports": {
624
624
  "react": "/__n.js",
@@ -633,7 +633,7 @@ export default async function handler(req: IncomingMessage, res: ServerResponse)
633
633
  const { initRuntime } = await import('nukejs');
634
634
  const data = JSON.parse(document.getElementById('__n_data').textContent);
635
635
  await initRuntime(data);
636
- </script>
636
+ </script>\` : ''}
637
637
  \${bodyScriptsHtml}</body>
638
638
  </html>\`;
639
639
 
@@ -800,16 +800,19 @@ async function buildCombinedBundle(staticDir) {
800
800
  stdin: {
801
801
  contents: `
802
802
  import React, {
803
+ createElement, cloneElement, createRef, isValidElement, Children,
803
804
  useState, useEffect, useContext, useReducer, useCallback, useMemo,
804
805
  useRef, useImperativeHandle, useLayoutEffect, useDebugValue,
805
806
  useDeferredValue, useTransition, useId, useSyncExternalStore,
806
807
  useInsertionEffect, createContext, forwardRef, memo, lazy,
807
- Suspense, Fragment, StrictMode, Component, PureComponent
808
+ Suspense, Fragment, StrictMode, Component, PureComponent,
809
+ createPortal
808
810
  } from 'react';
809
811
  import { jsx, jsxs } from 'react/jsx-runtime';
810
812
  import { hydrateRoot, createRoot } from 'react-dom/client';
811
813
  export { initRuntime, setupLocationChangeMonitor } from "./${bundleFile}.js";
812
814
  export {
815
+ createElement, cloneElement, createRef, isValidElement, Children,
813
816
  useState, useEffect, useContext, useReducer, useCallback, useMemo,
814
817
  useRef, useImperativeHandle, useLayoutEffect, useDebugValue,
815
818
  useDeferredValue, useTransition, useId, useSyncExternalStore,
package/dist/bundler.js CHANGED
@@ -37,16 +37,19 @@ async function serveReactBundle(res) {
37
37
  stdin: {
38
38
  contents: `
39
39
  import React, {
40
+ createElement, cloneElement, createRef, isValidElement, Children,
40
41
  useState, useEffect, useContext, useReducer, useCallback, useMemo,
41
42
  useRef, useImperativeHandle, useLayoutEffect, useDebugValue,
42
43
  useDeferredValue, useTransition, useId, useSyncExternalStore,
43
44
  useInsertionEffect, createContext, forwardRef, memo, lazy,
44
- Suspense, Fragment, StrictMode, Component, PureComponent
45
+ Suspense, Fragment, StrictMode, Component, PureComponent,
46
+ createPortal
45
47
  } from 'react';
46
48
  import { jsx, jsxs } from 'react/jsx-runtime';
47
49
  import { hydrateRoot, createRoot } from 'react-dom/client';
48
50
 
49
51
  export {
52
+ createElement, cloneElement, createRef, isValidElement, Children,
50
53
  useState, useEffect, useContext, useReducer, useCallback, useMemo,
51
54
  useRef, useImperativeHandle, useLayoutEffect, useDebugValue,
52
55
  useDeferredValue, useTransition, useId, useSyncExternalStore,
@@ -75,7 +78,7 @@ async function serveReactBundle(res) {
75
78
  res.end(await reactBundlePromise);
76
79
  }
77
80
  async function serveNukeBundle(res) {
78
- log.verbose("Bundling nuke runtime");
81
+ log.verbose("Bundling NukeJS runtime");
79
82
  if (!nukeBundlePromise) {
80
83
  const dir = path.dirname(fileURLToPath(import.meta.url));
81
84
  const entry = path.join(dir, `bundle.${dir.endsWith("dist") ? "js" : "ts"}`);
package/dist/logger.d.ts CHANGED
@@ -26,6 +26,7 @@ export declare const ansi: {
26
26
  readonly cyan: "\u001B[36m";
27
27
  readonly white: "\u001B[37m";
28
28
  readonly gray: "\u001B[90m";
29
+ readonly orange: "\u001B[38;5;208m";
29
30
  readonly bgBlue: "\u001B[44m";
30
31
  readonly bgGreen: "\u001B[42m";
31
32
  readonly bgMagenta: "\u001B[45m";
package/dist/logger.js CHANGED
@@ -11,6 +11,7 @@ const ansi = {
11
11
  cyan: "\x1B[36m",
12
12
  white: "\x1B[37m",
13
13
  gray: "\x1B[90m",
14
+ orange: "\x1B[38;5;208m",
14
15
  bgBlue: "\x1B[44m",
15
16
  bgGreen: "\x1B[42m",
16
17
  bgMagenta: "\x1B[45m"
@@ -11,7 +11,7 @@ async function loadMiddlewareFromPath(middlewarePath) {
11
11
  try {
12
12
  const mod = await import(pathToFileURL(middlewarePath).href);
13
13
  if (typeof mod.default === "function") {
14
- middlewares.push(mod.default);
14
+ middlewares.push({ fn: mod.default, src: middlewarePath });
15
15
  log.info(`Middleware loaded from ${middlewarePath}`);
16
16
  } else {
17
17
  log.warn(`${middlewarePath} does not export a default function`);
@@ -34,10 +34,14 @@ async function loadMiddleware() {
34
34
  }
35
35
  async function runMiddleware(req, res) {
36
36
  if (middlewares.length === 0) return false;
37
- for (const middleware of middlewares) {
38
- await middleware(req, res);
37
+ for (const { fn, src } of middlewares) {
38
+ await fn(req, res);
39
39
  if (res.writableEnded || res.headersSent) {
40
- log.verbose("Middleware handled request, skipping further processing");
40
+ const method = (req.method ?? "GET").toUpperCase();
41
+ const url = req.url ?? "/";
42
+ const status = res.statusCode;
43
+ const srcName = path.basename(src);
44
+ log.verbose(`middleware ${method} ${url} ${status} (${srcName})`);
41
45
  return true;
42
46
  }
43
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nukejs",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "A minimal, opinionated full-stack React framework on Node.js that server-renders everything and hydrates only interactive parts.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",