This is an automated email from the ASF dual-hosted git repository.

yuluo-yx pushed a commit to branch 2.0.0
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git


The following commit(s) were added to refs/heads/2.0.0 by this push:
     new 258fefd64f feat: fix 2.0 web frontend
258fefd64f is described below

commit 258fefd64fe0ff1126694670c76baa912220de1b
Author: yuluo-yx <[email protected]>
AuthorDate: Sat Jul 11 00:00:36 2026 +0800

    feat: fix 2.0 web frontend
    
    Signed-off-by: yuluo-yx <[email protected]>
---
 web-next/.eslintrc.json                            |  3 --
 .../components/pages/login-form.submit.test.tsx    |  2 +-
 web-next/components/pages/login-form.test.tsx      |  1 -
 .../components/shell/app-frame.chrome.test.tsx     |  2 +-
 web-next/eslint.config.mjs                         | 12 ++++++++
 web-next/package-lock.json                         |  1 +
 web-next/package.json                              |  3 +-
 web-next/scripts/parity/seed-state-lib.test.ts     | 27 +++++++++---------
 web-next/scripts/release-shell-smoke.test.ts       | 22 +++++++++++++++
 web-next/scripts/release-shell.mjs                 | 33 ++++++++++++++++++----
 web-next/scripts/standalone-server.mjs             |  3 +-
 11 files changed, 81 insertions(+), 28 deletions(-)

diff --git a/web-next/.eslintrc.json b/web-next/.eslintrc.json
deleted file mode 100644
index 957cd1545e..0000000000
--- a/web-next/.eslintrc.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "extends": ["next/core-web-vitals"]
-}
diff --git a/web-next/components/pages/login-form.submit.test.tsx 
b/web-next/components/pages/login-form.submit.test.tsx
index 28f21a60cd..c6fa650a22 100644
--- a/web-next/components/pages/login-form.submit.test.tsx
+++ b/web-next/components/pages/login-form.submit.test.tsx
@@ -26,7 +26,7 @@ vi.mock('next/navigation', () => ({
 }));
 
 vi.mock('next/image', () => ({
-  default: ({ alt, src, priority: _priority, ...props }: any) => <img 
alt={alt} src={src} {...props} />
+  default: ({ alt, src, priority: _priority, ...props }: any) => 
React.createElement('img', { alt, src, ...props })
 }));
 
 vi.mock('../providers/i18n-provider', () => ({
diff --git a/web-next/components/pages/login-form.test.tsx 
b/web-next/components/pages/login-form.test.tsx
index 25449884fa..110738b608 100644
--- a/web-next/components/pages/login-form.test.tsx
+++ b/web-next/components/pages/login-form.test.tsx
@@ -1,5 +1,4 @@
 import { createTranslatorMock } from '../../test/i18n-test-helper';
-/* eslint-disable @next/next/no-img-element */
 import React from 'react';
 import { readFileSync } from 'node:fs';
 import { resolve } from 'node:path';
diff --git a/web-next/components/shell/app-frame.chrome.test.tsx 
b/web-next/components/shell/app-frame.chrome.test.tsx
index b7b7607744..9a5cb5d93e 100644
--- a/web-next/components/shell/app-frame.chrome.test.tsx
+++ b/web-next/components/shell/app-frame.chrome.test.tsx
@@ -7,7 +7,7 @@ import { createTranslatorMock } from 
'../../test/i18n-test-helper';
 
 vi.mock('next/image', () => ({
   default: ({ alt, priority: _priority, ...props }: 
React.ComponentProps<'img'> & { priority?: boolean }) => (
-    <img alt={alt} {...props} />
+    React.createElement('img', { alt, ...props })
   )
 }));
 
diff --git a/web-next/eslint.config.mjs b/web-next/eslint.config.mjs
new file mode 100644
index 0000000000..722ed58a4a
--- /dev/null
+++ b/web-next/eslint.config.mjs
@@ -0,0 +1,12 @@
+import { FlatCompat } from '@eslint/eslintrc';
+
+const compat = new FlatCompat({ baseDirectory: import.meta.dirname });
+
+const eslintConfig = [
+  {
+    ignores: ['.next/**', '.next-*/**', 'next-env.d.ts']
+  },
+  ...compat.extends('next/core-web-vitals')
+];
+
+export default eslintConfig;
diff --git a/web-next/package-lock.json b/web-next/package-lock.json
index 6866386618..61b44b6223 100644
--- a/web-next/package-lock.json
+++ b/web-next/package-lock.json
@@ -33,6 +33,7 @@
         "tailwind-merge": "3.3.0"
       },
       "devDependencies": {
+        "@eslint/eslintrc": "3.3.5",
         "@types/node": "22.15.21",
         "@types/react": "19.1.2",
         "@types/react-dom": "19.1.2",
diff --git a/web-next/package.json b/web-next/package.json
index f06fd24767..4923fdf280 100644
--- a/web-next/package.json
+++ b/web-next/package.json
@@ -6,7 +6,7 @@
     "dev": "next dev --turbopack -p 4200",
     "build": "next build && node ./scripts/standalone-server.mjs prepare",
     "start": "node ./scripts/standalone-server.mjs start",
-    "lint": "ESLINT_USE_FLAT_CONFIG=false eslint . --ext .js,.jsx,.ts,.tsx",
+    "lint": "eslint .",
     "test": "vitest run",
     "parity:runtime": "node ./scripts/parity/runtime.mjs",
     "parity:smoke": "node ./scripts/parity/harness.mjs",
@@ -47,6 +47,7 @@
     "tailwind-merge": "3.3.0"
   },
   "devDependencies": {
+    "@eslint/eslintrc": "3.3.5",
     "@types/node": "22.15.21",
     "@types/react": "19.1.2",
     "@types/react-dom": "19.1.2",
diff --git a/web-next/scripts/parity/seed-state-lib.test.ts 
b/web-next/scripts/parity/seed-state-lib.test.ts
index 44fc403934..173207c45b 100644
--- a/web-next/scripts/parity/seed-state-lib.test.ts
+++ b/web-next/scripts/parity/seed-state-lib.test.ts
@@ -1,4 +1,5 @@
 import { describe, expect, it, vi } from 'vitest';
+import { fileURLToPath } from 'node:url';
 import {
   applySeedContextToRoutePair,
   resolveSeedContext,
@@ -222,18 +223,18 @@ describe('parity seed-state helpers', () => {
       execFileSyncImpl
     });
 
-    expect(execFileSyncImpl).toHaveBeenCalledWith(
-      'bash',
-      [expect.stringContaining('seed-trace-rich-demo.sh')],
-      expect.objectContaining({
-        cwd: 
expect.stringContaining('/Users/zhaoqingran/IdeaProjects/hertzbeat'),
-        encoding: 'utf8',
-        stdio: 'pipe',
-        env: expect.objectContaining({
-          TRACE_WINDOW_END_MS: '1776751800000',
-          GREPTIME_HTTP: 'http://127.0.0.1:14000'
-        })
-      })
-    );
+    const [command, args, options] = execFileSyncImpl.mock.lastCall as unknown 
as [
+      string,
+      string[],
+      { cwd: string; encoding: string; stdio: string; env: NodeJS.ProcessEnv }
+    ];
+
+    expect(command).toBe('bash');
+    expect(args).toEqual([fileURLToPath(new 
URL('../../../script/dev/seed-trace-rich-demo.sh', import.meta.url))]);
+    expect(options.cwd).toBe(fileURLToPath(new URL('../../../', 
import.meta.url)));
+    expect(options.encoding).toBe('utf8');
+    expect(options.stdio).toBe('pipe');
+    expect(options.env.TRACE_WINDOW_END_MS).toBe('1776751800000');
+    expect(options.env.GREPTIME_HTTP).toBe('http://127.0.0.1:14000');
   });
 });
diff --git a/web-next/scripts/release-shell-smoke.test.ts 
b/web-next/scripts/release-shell-smoke.test.ts
index 707bd0c37e..a04e6a186a 100644
--- a/web-next/scripts/release-shell-smoke.test.ts
+++ b/web-next/scripts/release-shell-smoke.test.ts
@@ -1,11 +1,14 @@
 import { describe, expect, it } from 'vitest';
 import { readFileSync } from 'node:fs';
+import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
+import os from 'node:os';
 import { resolve } from 'node:path';
 import {
   buildExpectedQueryEntries,
   findMismatchedQueryEntries,
   resolveNextRedirectDigestUrl
 } from './release-shell-smoke.mjs';
+import { resolveLocalReleaseLaunch } from './release-shell.mjs';
 
 describe('release-shell smoke helpers', () => {
   it('normalizes expected query entries into string pairs', () => {
@@ -36,6 +39,25 @@ describe('release-shell smoke helpers', () => {
     expect(resolveNextRedirectDigestUrl('<html><body>no redirect 
digest</body></html>', 'http://127.0.0.1:4200')).toBeNull();
   });
 
+  it('runs release checks through the standalone server when a production 
build exists', async () => {
+    const rootDir = await mkdtemp(resolve(os.tmpdir(), 
'hertzbeat-release-shell-'));
+    try {
+      const appDir = resolve(rootDir, '.next', 'standalone', 'web-next');
+      const serverFile = resolve(appDir, 'server.js');
+      await mkdir(appDir, { recursive: true });
+      await writeFile(resolve(rootDir, '.next', 'BUILD_ID'), 'build-id');
+      await writeFile(serverFile, 'server');
+
+      expect(resolveLocalReleaseLaunch({ port: 4300, rootDir })).toEqual({
+        args: [serverFile],
+        cwd: appDir,
+        env: { PORT: '4300', HOSTNAME: '127.0.0.1' }
+      });
+    } finally {
+      await rm(rootDir, { recursive: true, force: true });
+    }
+  });
+
   it('keeps the release route browser smoke on the required route and console 
contracts', () => {
     const source = readFileSync(resolve(process.cwd(), 
'scripts/release-route-browser-smoke.spec.ts'), 'utf8');
 
diff --git a/web-next/scripts/release-shell.mjs 
b/web-next/scripts/release-shell.mjs
index dd78792c44..c3ff3b525b 100644
--- a/web-next/scripts/release-shell.mjs
+++ b/web-next/scripts/release-shell.mjs
@@ -2,6 +2,7 @@ import { spawn } from 'node:child_process';
 import { existsSync } from 'node:fs';
 import path from 'node:path';
 import process from 'node:process';
+import { resolveStandalonePaths } from './standalone-server.mjs';
 
 export function sleep(ms) {
   return new Promise(resolve => {
@@ -30,17 +31,37 @@ export async function waitForServer(baseUrl, readyPath = 
'/overview') {
   );
 }
 
+export function resolveLocalReleaseLaunch({
+  port,
+  distDir = process.env.NEXT_DIST_DIR || '.next',
+  rootDir = process.cwd()
+}) {
+  const buildIdPath = path.join(rootDir, distDir, 'BUILD_ID');
+  if (existsSync(buildIdPath)) {
+    const { appDir, serverFile } = resolveStandalonePaths(rootDir, distDir);
+    return {
+      args: [serverFile],
+      cwd: appDir,
+      env: { PORT: String(port), HOSTNAME: '127.0.0.1' }
+    };
+  }
+
+  return {
+    args: [path.join(rootDir, 'node_modules', 'next', 'dist', 'bin', 'next'), 
'dev', '--hostname', '127.0.0.1', '--port', String(port)],
+    cwd: rootDir,
+    env: { PORT: String(port) }
+  };
+}
+
 export async function startLocalReleaseServer({
   port,
   readyPath = '/overview',
   distDir = process.env.NEXT_DIST_DIR || '.next'
 }) {
-  const buildIdPath = path.join(process.cwd(), distDir, 'BUILD_ID');
-  const nextBinPath = path.join(process.cwd(), 'node_modules', 'next', 'dist', 
'bin', 'next');
-  const command = existsSync(buildIdPath) ? 'start' : 'dev';
-  const child = spawn(process.execPath, [nextBinPath, command, '--hostname', 
'127.0.0.1', '--port', String(port)], {
-    cwd: process.cwd(),
-    env: { ...process.env, PORT: String(port) },
+  const launch = resolveLocalReleaseLaunch({ port, distDir });
+  const child = spawn(process.execPath, launch.args, {
+    cwd: launch.cwd,
+    env: { ...process.env, ...launch.env },
     stdio: ['ignore', 'pipe', 'pipe']
   });
 
diff --git a/web-next/scripts/standalone-server.mjs 
b/web-next/scripts/standalone-server.mjs
index 9c26740890..e67feb0f96 100644
--- a/web-next/scripts/standalone-server.mjs
+++ b/web-next/scripts/standalone-server.mjs
@@ -41,8 +41,7 @@ export function parseStartArgs(args, env = process.env) {
   return parsed;
 }
 
-export function resolveStandalonePaths(rootDir = process.cwd()) {
-  const distDir = process.env.NEXT_DIST_DIR || '.next';
+export function resolveStandalonePaths(rootDir = process.cwd(), distDir = 
process.env.NEXT_DIST_DIR || '.next') {
   const standaloneRoot = path.join(rootDir, distDir, 'standalone');
   const candidates = [path.join(standaloneRoot, 'web-next'), standaloneRoot];
   const appDir = candidates.find((candidate) => 
existsSync(path.join(candidate, 'server.js')));


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to