@qzsy/vinext 0.1.80 → 0.1.81

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/cli.js CHANGED
File without changes
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { normalizePathSeparators, stripJsExtension, stripViteModuleQuery } from
5
5
  import { buildViteResolveExtensions, createValidFileMatcher, findFileWithExts, normalizeViteResolveExtensions } from "./routing/file-matcher.js";
6
6
  import { apiRouter, invalidateRouteCache, matchRoute, pagesRouter } from "./routing/pages-router.js";
7
7
  import { VINEXT_MW_CTX_HEADER } from "./utils/protocol-headers.js";
8
- import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_TIMING_HEADER } from "./server/headers.js";
8
+ import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS } from "./server/headers.js";
9
9
  import { normalizePath as normalizePath$1 } from "./server/normalize-path.js";
10
10
  import { matchesRewriteSource, proxyExternalRequest } from "./config/config-matchers.js";
11
11
  import { isOpenRedirectShaped } from "./server/open-redirect.js";
@@ -16,7 +16,6 @@ import { generateClientEntry } from "./entries/pages-client-entry.js";
16
16
  import { appRouteGraph, appRouter, invalidateAppRouteCache, matchAppRoute } from "./routing/app-router.js";
17
17
  import { findInstrumentationClientFile, findInstrumentationFile, runInstrumentation } from "./server/instrumentation.js";
18
18
  import { isUnknownRecord } from "./utils/record.js";
19
- import { logRequest, now } from "./server/request-log.js";
20
19
  import { resolvePagesI18nRequest } from "./server/pages-i18n.js";
21
20
  import { isNextDataPathname, parseNextDataPathname } from "./server/pages-data-route.js";
22
21
  import { createSSRHandler } from "./server/dev-server.js";
@@ -40,6 +39,7 @@ import { RESOLVED_VIRTUAL_GOOGLE_FONTS, VIRTUAL_GOOGLE_FONTS, createGoogleFontsP
40
39
  import { getDepOptimizeNodeEnvOptions, getViteMajorVersion, serializeViteDefine } from "./utils/vite-version.js";
41
40
  import { createRscCompatibilityId, findNextConfigPath, loadNextConfig, resolveNextConfig, resolveNextConfigInput } from "./config/next-config.js";
42
41
  import { mergeServerExternalPackages } from "./config/server-external-packages.js";
42
+ import { installAppRouterDevRequestLogging } from "./server/dev-response-headers.js";
43
43
  import { precompressAssets } from "./build/precompress.js";
44
44
  import { ensureAssetsIgnore } from "./build/assets-ignore.js";
45
45
  import { emitNextClientRuntimeManifests } from "./build/next-client-runtime-manifests.js";
@@ -1707,56 +1707,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
1707
1707
  if (instrumentationPath && !hasAppDir) runInstrumentation(getPagesRunner(), instrumentationPath).catch((err) => {
1708
1708
  console.error("[vinext] Instrumentation error:", err);
1709
1709
  });
1710
- if (hasAppDir) server.middlewares.use((req, res, next) => {
1711
- const url = req.url ?? "/";
1712
- const [pathname] = url.split("?");
1713
- if (url.startsWith("/@") || url.startsWith("/__vite") || url.startsWith("/node_modules") || url.includes(".") && !pathname.endsWith(".html") && !pathname.endsWith(".rsc")) return next();
1714
- const _reqStart = now();
1715
- let _compileMs;
1716
- let _renderMs;
1717
- function _parseTiming(raw) {
1718
- const [handlerStart, inHandlerCompileMs, renderMs] = String(raw).split(",").map((v) => Number(v));
1719
- if (!Number.isNaN(handlerStart) && !Number.isNaN(inHandlerCompileMs) && inHandlerCompileMs !== -1) _compileMs = Math.max(0, Math.round(handlerStart - _reqStart)) + inHandlerCompileMs;
1720
- if (!Number.isNaN(renderMs) && renderMs !== -1) _renderMs = renderMs;
1721
- }
1722
- const _origSetHeader = res.setHeader.bind(res);
1723
- res.setHeader = function(name, value) {
1724
- if (name.toLowerCase() === "x-vinext-timing") {
1725
- _parseTiming(value);
1726
- return res;
1727
- }
1728
- return _origSetHeader(name, value);
1729
- };
1730
- const _origWriteHead = res.writeHead.bind(res);
1731
- res.writeHead = function(statusCode, ...args) {
1732
- let headers;
1733
- const [reasonOrHeaders, maybeHeaders] = args;
1734
- if (typeof reasonOrHeaders === "string") headers = maybeHeaders;
1735
- else headers = reasonOrHeaders;
1736
- if (headers && typeof headers === "object" && !Array.isArray(headers)) {
1737
- const timingKey = Object.keys(headers).find((k) => k.toLowerCase() === VINEXT_TIMING_HEADER);
1738
- if (timingKey) {
1739
- _parseTiming(headers[timingKey]);
1740
- delete headers[timingKey];
1741
- }
1742
- }
1743
- return _origWriteHead(statusCode, ...args);
1744
- };
1745
- res.on("finish", () => {
1746
- const logUrl = url.replace(/\.rsc(\?|$)/, "$1");
1747
- const totalMs = now() - _reqStart;
1748
- const resolvedRenderMs = _renderMs !== void 0 ? _renderMs : _compileMs !== void 0 ? Math.max(0, Math.round(totalMs - _compileMs)) : void 0;
1749
- logRequest({
1750
- method: req.method ?? "GET",
1751
- url: logUrl,
1752
- status: res.statusCode,
1753
- totalMs,
1754
- compileMs: _compileMs,
1755
- renderMs: resolvedRenderMs
1756
- });
1757
- });
1758
- next();
1759
- });
1710
+ if (hasAppDir) installAppRouterDevRequestLogging(server.middlewares);
1760
1711
  const handlePagesMiddleware = async (req, res, next) => {
1761
1712
  try {
1762
1713
  let url = req.url ?? "/";
@@ -19,11 +19,11 @@ import "./app-page-response.js";
19
19
  import { parseNextHttpErrorDigest } from "./next-error-digest.js";
20
20
  import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
21
21
  import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
22
+ import { flattenErrorCauses } from "../utils/error-cause.js";
22
23
  import { pickRootParams, setRootParams } from "../shims/root-params.js";
23
24
  import { createServerActionNotFoundResponse, getServerActionNotFoundMessage } from "./server-action-not-found.js";
24
25
  import { buildPageCacheTags } from "./implicit-tags.js";
25
26
  import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
26
- import { flattenErrorCauses } from "../utils/error-cause.js";
27
27
  import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
28
28
  import { normalizeRscRequest } from "./app-rsc-request-normalization.js";
29
29
  import { runWithPrerenderWorkUnit } from "./prerender-work-unit-setup.js";
@@ -8,6 +8,7 @@ import { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI } from "./app-rsc-rende
8
8
  import { headersContextFromRequest, isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
9
9
  import { getAndClearActionRevalidationKind } from "../shims/cache-request-state.js";
10
10
  import { setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
11
+ import { applyServerActionLogHeader, createServerActionLogInfo, isDevServerActionLoggingEnabled } from "./server-action-logger.js";
11
12
  import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
12
13
  import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
13
14
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
@@ -575,6 +576,9 @@ async function handleServerActionRscRequest(options) {
575
576
  let actionThrew = false;
576
577
  const actionWasForwarded = Boolean(options.request.headers.get(ACTION_FORWARDED_HEADER));
577
578
  const rootParamsUsage = createRootParamsUsageController();
579
+ const shouldLogAction = isDevServerActionLoggingEnabled();
580
+ const actionLogStart = shouldLogAction ? performance.now() : 0;
581
+ let actionLogInfo = null;
578
582
  const previousHeadersPhase = options.setHeadersAccessPhase("action");
579
583
  try {
580
584
  try {
@@ -609,6 +613,11 @@ async function handleServerActionRscRequest(options) {
609
613
  }
610
614
  }
611
615
  } finally {
616
+ if (shouldLogAction) actionLogInfo = createServerActionLogInfo({
617
+ actionId: options.actionId,
618
+ args,
619
+ durationMs: Math.round(performance.now() - actionLogStart)
620
+ });
612
621
  options.setHeadersAccessPhase(previousHeadersPhase);
613
622
  if (actionThrew && !actionWasForwarded) rootParamsUsage.transitionToRender();
614
623
  }
@@ -630,6 +639,7 @@ async function handleServerActionRscRequest(options) {
630
639
  for (const cookie of actionPendingCookies) redirectHeaders.append("Set-Cookie", cookie);
631
640
  if (actionDraftCookie) redirectHeaders.append("Set-Cookie", actionDraftCookie);
632
641
  setActionRevalidatedHeader(redirectHeaders, actionRevalidationKind);
642
+ applyServerActionLogHeader(redirectHeaders, actionLogInfo);
633
643
  const redirectTarget = resolveInternalActionRedirectTarget(actionRedirectUrl, options.request.url, options.basePath ?? "");
634
644
  if (!redirectTarget) {
635
645
  options.clearRequestContext();
@@ -728,6 +738,7 @@ async function handleServerActionRscRequest(options) {
728
738
  for (const cookie of actionPendingCookies) actionHeaders.append("Set-Cookie", cookie);
729
739
  if (actionDraftCookie) actionHeaders.append("Set-Cookie", actionDraftCookie);
730
740
  setActionRevalidatedHeader(actionHeaders, actionRevalidationKind);
741
+ applyServerActionLogHeader(actionHeaders, actionLogInfo);
731
742
  return createServerActionRscResponse(rscStream, {
732
743
  status: options.middlewareStatus ?? actionStatus,
733
744
  headers: actionHeaders
@@ -804,6 +815,7 @@ async function handleServerActionRscRequest(options) {
804
815
  mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);
805
816
  applyRscCompatibilityIdHeader(actionHeaders);
806
817
  setActionRevalidatedHeader(actionHeaders, actionRevalidationKind);
818
+ applyServerActionLogHeader(actionHeaders, actionLogInfo);
807
819
  const actionResponse = createServerActionRscResponse(rscStream, {
808
820
  status: options.middlewareStatus ?? actionStatus,
809
821
  headers: actionHeaders
@@ -0,0 +1,19 @@
1
+ import { RequestLogOptions } from "./request-log.js";
2
+ import { ServerResponse } from "node:http";
3
+
4
+ //#region src/server/dev-response-headers.d.ts
5
+ type DevResponseMetrics = {
6
+ compileMs?: number;
7
+ renderMs?: number;
8
+ actionLogRaw?: string;
9
+ };
10
+ declare function parseVinextTimingHeader(raw: unknown, reqStart: number): Pick<DevResponseMetrics, "compileMs" | "renderMs">;
11
+ /** Intercept dev-only headers on a Node response and capture their payloads. */
12
+ declare function interceptDevResponseHeaders(res: ServerResponse, reqStart: number, metrics: DevResponseMetrics): void;
13
+ declare function flushDevRequestLogs(metrics: DevResponseMetrics, options: RequestLogOptions): void;
14
+ /** Install App Router request + server action logging on the Vite dev server. */
15
+ declare function installAppRouterDevRequestLogging(middlewares: {
16
+ use: (handler: (req: import("node:http").IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => void) => void;
17
+ }): void;
18
+ //#endregion
19
+ export { DevResponseMetrics, flushDevRequestLogs, installAppRouterDevRequestLogging, interceptDevResponseHeaders, parseVinextTimingHeader };
@@ -0,0 +1,78 @@
1
+ import "./headers.js";
2
+ import { parseServerActionLogHeader } from "./server-action-logger.js";
3
+ import { logRequest, logServerAction, now } from "./request-log.js";
4
+ //#region src/server/dev-response-headers.ts
5
+ function parseVinextTimingHeader(raw, reqStart) {
6
+ const [handlerStart, inHandlerCompileMs, renderMs] = String(raw).split(",").map((v) => Number(v));
7
+ const metrics = {};
8
+ if (!Number.isNaN(handlerStart) && !Number.isNaN(inHandlerCompileMs) && inHandlerCompileMs !== -1) metrics.compileMs = Math.max(0, Math.round(handlerStart - reqStart)) + inHandlerCompileMs;
9
+ if (!Number.isNaN(renderMs) && renderMs !== -1) metrics.renderMs = renderMs;
10
+ return metrics;
11
+ }
12
+ function consumeDevInternalHeader(name, value, reqStart, metrics) {
13
+ const lowerName = name.toLowerCase();
14
+ if (lowerName === "x-vinext-timing") {
15
+ Object.assign(metrics, parseVinextTimingHeader(value, reqStart));
16
+ return true;
17
+ }
18
+ if (lowerName === "x-vinext-action-log") {
19
+ metrics.actionLogRaw = String(value);
20
+ return true;
21
+ }
22
+ return false;
23
+ }
24
+ function stripDevInternalHeadersFromObject(headers, reqStart, metrics) {
25
+ for (const key of Object.keys(headers)) if (consumeDevInternalHeader(key, headers[key], reqStart, metrics)) delete headers[key];
26
+ }
27
+ /** Intercept dev-only headers on a Node response and capture their payloads. */
28
+ function interceptDevResponseHeaders(res, reqStart, metrics) {
29
+ const origSetHeader = res.setHeader.bind(res);
30
+ res.setHeader = function(name, value) {
31
+ if (consumeDevInternalHeader(String(name), value, reqStart, metrics)) return res;
32
+ return origSetHeader(name, value);
33
+ };
34
+ const origWriteHead = res.writeHead.bind(res);
35
+ res.writeHead = function(statusCode, ...args) {
36
+ let headers;
37
+ const [reasonOrHeaders, maybeHeaders] = args;
38
+ if (typeof reasonOrHeaders === "string") headers = maybeHeaders;
39
+ else headers = reasonOrHeaders;
40
+ if (headers && typeof headers === "object" && !Array.isArray(headers)) stripDevInternalHeadersFromObject(headers, reqStart, metrics);
41
+ return origWriteHead(statusCode, ...args);
42
+ };
43
+ }
44
+ function flushDevRequestLogs(metrics, options) {
45
+ logRequest(options);
46
+ const actionLog = metrics.actionLogRaw ? parseServerActionLogHeader(metrics.actionLogRaw) : null;
47
+ if (actionLog) logServerAction(actionLog);
48
+ }
49
+ function shouldSkipDevRequestLogUrl(url) {
50
+ const [pathname] = url.split("?");
51
+ return url.startsWith("/@") || url.startsWith("/__vite") || url.startsWith("/node_modules") || url.includes(".") && !pathname.endsWith(".html") && !pathname.endsWith(".rsc");
52
+ }
53
+ /** Install App Router request + server action logging on the Vite dev server. */
54
+ function installAppRouterDevRequestLogging(middlewares) {
55
+ middlewares.use((req, res, next) => {
56
+ const url = req.url ?? "/";
57
+ if (shouldSkipDevRequestLogUrl(url)) return next();
58
+ const reqStart = now();
59
+ const metrics = {};
60
+ interceptDevResponseHeaders(res, reqStart, metrics);
61
+ res.on("finish", () => {
62
+ const logUrl = url.replace(/\.rsc(\?|$)/, "$1");
63
+ const totalMs = now() - reqStart;
64
+ const resolvedRenderMs = metrics.renderMs !== void 0 ? metrics.renderMs : metrics.compileMs !== void 0 ? Math.max(0, Math.round(totalMs - metrics.compileMs)) : void 0;
65
+ flushDevRequestLogs(metrics, {
66
+ method: req.method ?? "GET",
67
+ url: logUrl,
68
+ status: res.statusCode,
69
+ totalMs,
70
+ compileMs: metrics.compileMs,
71
+ renderMs: resolvedRenderMs
72
+ });
73
+ });
74
+ next();
75
+ });
76
+ }
77
+ //#endregion
78
+ export { flushDevRequestLogs, installAppRouterDevRequestLogging, interceptDevResponseHeaders, parseVinextTimingHeader };
@@ -19,6 +19,8 @@ declare const NEXTJS_CACHE_HEADER = "x-nextjs-cache";
19
19
  declare const VINEXT_STATIC_FILE_HEADER = "x-vinext-static-file";
20
20
  /** Timing metrics: `handlerStart,compileMs,renderMs`. */
21
21
  declare const VINEXT_TIMING_HEADER = "x-vinext-timing";
22
+ /** Dev-only server action log payload (JSON). Stripped before the response reaches the client. */
23
+ declare const VINEXT_ACTION_LOG_HEADER = "x-vinext-action-log";
22
24
  /** Internal endpoint used to evaluate App Router generateStaticParams exports. */
23
25
  declare const VINEXT_PRERENDER_STATIC_PARAMS_PATH = "/__vinext/prerender/static-params";
24
26
  /** Internal endpoint used to evaluate Pages Router getStaticPaths exports. */
@@ -101,4 +103,4 @@ declare const INTERNAL_HEADERS: string[];
101
103
  /** Vinext-only internal headers stripped alongside Next.js protocol internals. */
102
104
  declare const VINEXT_INTERNAL_HEADERS: string[];
103
105
  //#endregion
104
- export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
106
+ export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_ACTION_LOG_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
@@ -18,6 +18,8 @@ const NEXTJS_CACHE_HEADER = "x-nextjs-cache";
18
18
  const VINEXT_STATIC_FILE_HEADER = "x-vinext-static-file";
19
19
  /** Timing metrics: `handlerStart,compileMs,renderMs`. */
20
20
  const VINEXT_TIMING_HEADER = "x-vinext-timing";
21
+ /** Dev-only server action log payload (JSON). Stripped before the response reaches the client. */
22
+ const VINEXT_ACTION_LOG_HEADER = "x-vinext-action-log";
21
23
  /** Internal endpoint used to evaluate App Router generateStaticParams exports. */
22
24
  const VINEXT_PRERENDER_STATIC_PARAMS_PATH = "/__vinext/prerender/static-params";
23
25
  /** Internal endpoint used to evaluate Pages Router getStaticPaths exports. */
@@ -122,4 +124,4 @@ const INTERNAL_HEADERS = [
122
124
  /** Vinext-only internal headers stripped alongside Next.js protocol internals. */
123
125
  const VINEXT_INTERNAL_HEADERS = [VINEXT_PRERENDER_ROUTE_PARAMS_HEADER];
124
126
  //#endregion
125
- export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
127
+ export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_ACTION_LOG_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
@@ -1,17 +1,6 @@
1
+ import { ServerActionLogInfo } from "./server-action-logger.js";
2
+
1
3
  //#region src/server/request-log.d.ts
2
- /**
3
- * Request logging for the vinext dev server.
4
- *
5
- * Matches Next.js's request log format:
6
- * GET /path 200 in 123ms (compile: 45ms, render: 78ms)
7
- *
8
- * Color coding matches Next.js:
9
- * - 2xx: green
10
- * - 3xx: cyan
11
- * - 4xx: yellow
12
- * - 5xx: red
13
- * - Method: bold
14
- */
15
4
  type RequestLogOptions = {
16
5
  method: string;
17
6
  url: string;
@@ -20,6 +9,8 @@ type RequestLogOptions = {
20
9
  compileMs?: number; /** Time spent in React rendering / HTML streaming. */
21
10
  renderMs?: number;
22
11
  };
12
+ /** Print the nested server action log line under the request log. */
13
+ declare function logServerAction(info: ServerActionLogInfo): void;
23
14
  /**
24
15
  * Print a single request log line to stdout.
25
16
  */
@@ -36,4 +27,4 @@ declare function logRequest({
36
27
  */
37
28
  declare function now(): number;
38
29
  //#endregion
39
- export { logRequest, now };
30
+ export { RequestLogOptions, logRequest, logServerAction, now };
@@ -1,3 +1,4 @@
1
+ import { formatActionArgs } from "./server-action-logger.js";
1
2
  //#region src/server/request-log.ts
2
3
  /**
3
4
  * Request logging for the vinext dev server.
@@ -31,6 +32,11 @@ function formatDuration(ms) {
31
32
  if (ms >= 1e3) return `${(ms / 1e3).toFixed(1)}s`;
32
33
  return `${Math.round(ms)}ms`;
33
34
  }
35
+ /** Print the nested server action log line under the request log. */
36
+ function logServerAction(info) {
37
+ const argsStr = formatActionArgs(info.args);
38
+ process.stdout.write(` └─ ƒ ${info.functionName}(${argsStr}) in ${info.duration}ms ${pretty.dim(info.location)}\n`);
39
+ }
34
40
  /**
35
41
  * Print a single request log line to stdout.
36
42
  */
@@ -53,4 +59,4 @@ function now() {
53
59
  return performance.now();
54
60
  }
55
61
  //#endregion
56
- export { logRequest, now };
62
+ export { logRequest, logServerAction, now };
@@ -0,0 +1,39 @@
1
+ //#region src/server/server-action-logger.d.ts
2
+ /**
3
+ * Dev-only Server Action logging — metadata and wire-format helpers.
4
+ *
5
+ * Terminal output lives in `request-log.ts`. Dev middleware interception lives
6
+ * in `dev-response-headers.ts`.
7
+ *
8
+ * Ported from Next.js:
9
+ * - packages/next/src/server/dev/server-action-logger.ts
10
+ * - packages/next/src/server/dev/log-requests.ts
11
+ *
12
+ * https://github.com/vercel/next.js/pull/88277
13
+ */
14
+ type ServerActionLogInfo = {
15
+ functionName: string;
16
+ args: unknown[];
17
+ location: string;
18
+ duration: number;
19
+ };
20
+ declare function isDevServerActionLoggingEnabled(): boolean;
21
+ /**
22
+ * Resolve display metadata from an `x-rsc-action` / `next-action` action id.
23
+ *
24
+ * Action ids encode module path and export name:
25
+ * `/app/actions/actions.ts#echoAction`
26
+ */
27
+ declare function resolveServerActionLogMeta(actionId: string | null): Pick<ServerActionLogInfo, "functionName" | "location"> | null;
28
+ /** Format action arguments for the dev log line. */
29
+ declare function formatActionArgs(args: unknown[]): string;
30
+ declare function serializeServerActionLogHeader(info: ServerActionLogInfo): string;
31
+ declare function parseServerActionLogHeader(value: string): ServerActionLogInfo | null;
32
+ declare function applyServerActionLogHeader(headers: Headers, info: ServerActionLogInfo | null): void;
33
+ declare function createServerActionLogInfo(options: {
34
+ actionId: string | null;
35
+ args: readonly unknown[];
36
+ durationMs: number;
37
+ }): ServerActionLogInfo | null;
38
+ //#endregion
39
+ export { ServerActionLogInfo, applyServerActionLogHeader, createServerActionLogInfo, formatActionArgs, isDevServerActionLoggingEnabled, parseServerActionLogHeader, resolveServerActionLogMeta, serializeServerActionLogHeader };
@@ -0,0 +1,104 @@
1
+ import { VINEXT_ACTION_LOG_HEADER } from "./headers.js";
2
+ //#region src/server/server-action-logger.ts
3
+ /**
4
+ * Dev-only Server Action logging — metadata and wire-format helpers.
5
+ *
6
+ * Terminal output lives in `request-log.ts`. Dev middleware interception lives
7
+ * in `dev-response-headers.ts`.
8
+ *
9
+ * Ported from Next.js:
10
+ * - packages/next/src/server/dev/server-action-logger.ts
11
+ * - packages/next/src/server/dev/log-requests.ts
12
+ *
13
+ * https://github.com/vercel/next.js/pull/88277
14
+ */
15
+ const INLINE_ACTION_PREFIXES = ["$$RSC_SERVER_ACTION_", "$$hoist_"];
16
+ const USE_CACHE_ACTION_PREFIX = "$$RSC_SERVER_CACHE_";
17
+ function isDevServerActionLoggingEnabled() {
18
+ return process.env.NODE_ENV !== "production";
19
+ }
20
+ function isInlineActionExport(exportedName) {
21
+ return INLINE_ACTION_PREFIXES.some((prefix) => exportedName.startsWith(prefix));
22
+ }
23
+ function isUseCacheActionExport(exportedName) {
24
+ return exportedName.startsWith(USE_CACHE_ACTION_PREFIX);
25
+ }
26
+ /**
27
+ * Resolve display metadata from an `x-rsc-action` / `next-action` action id.
28
+ *
29
+ * Action ids encode module path and export name:
30
+ * `/app/actions/actions.ts#echoAction`
31
+ */
32
+ function resolveServerActionLogMeta(actionId) {
33
+ if (!actionId) return null;
34
+ const hashIndex = actionId.lastIndexOf("#");
35
+ if (hashIndex <= 0) return null;
36
+ const exportedName = actionId.slice(hashIndex + 1);
37
+ if (isUseCacheActionExport(exportedName)) return null;
38
+ const location = actionId.slice(0, hashIndex).replace(/\\/g, "/").replace(/^\//, "");
39
+ let functionName;
40
+ if (isInlineActionExport(exportedName)) functionName = "";
41
+ else if (exportedName === "default") functionName = "default";
42
+ else functionName = exportedName;
43
+ return {
44
+ functionName,
45
+ location
46
+ };
47
+ }
48
+ function formatArg(arg, depth = 0) {
49
+ if (arg === null) return "null";
50
+ if (arg === void 0) return "undefined";
51
+ if (typeof arg === "string") return JSON.stringify(arg);
52
+ if (typeof arg === "number" || typeof arg === "boolean" || typeof arg === "bigint") return String(arg);
53
+ if (typeof arg === "symbol") return String(arg);
54
+ if (typeof arg === "function") return "[Function]";
55
+ if (depth >= 2) return "[Object]";
56
+ if (Array.isArray(arg)) {
57
+ const items = arg.slice(0, 3).map((item) => formatArg(item, depth + 1));
58
+ if (arg.length > 3) items.push("...");
59
+ return `[${items.join(",")}]`;
60
+ }
61
+ if (typeof arg === "object") try {
62
+ const formatted = Object.entries(arg).slice(0, 3).map(([key, value]) => `${JSON.stringify(key)}:${formatArg(value, depth + 1)}`);
63
+ if (Object.keys(arg).length > 3) formatted.push("...");
64
+ return `{${formatted.join(",")}}`;
65
+ } catch {
66
+ return "[Object]";
67
+ }
68
+ try {
69
+ return JSON.stringify(arg);
70
+ } catch {
71
+ return "[unserializable]";
72
+ }
73
+ }
74
+ /** Format action arguments for the dev log line. */
75
+ function formatActionArgs(args) {
76
+ return args.map((arg) => formatArg(arg)).join(", ");
77
+ }
78
+ function serializeServerActionLogHeader(info) {
79
+ return JSON.stringify(info);
80
+ }
81
+ function parseServerActionLogHeader(value) {
82
+ try {
83
+ const parsed = JSON.parse(value);
84
+ if (typeof parsed.functionName === "string" && Array.isArray(parsed.args) && typeof parsed.location === "string" && typeof parsed.duration === "number") return parsed;
85
+ } catch {}
86
+ return null;
87
+ }
88
+ function applyServerActionLogHeader(headers, info) {
89
+ if (!info) return;
90
+ headers.set(VINEXT_ACTION_LOG_HEADER, serializeServerActionLogHeader(info));
91
+ }
92
+ function createServerActionLogInfo(options) {
93
+ if (!isDevServerActionLoggingEnabled()) return null;
94
+ const meta = resolveServerActionLogMeta(options.actionId);
95
+ if (!meta) return null;
96
+ const args = Array.isArray(options.args) ? options.args : [options.args];
97
+ return {
98
+ ...meta,
99
+ args: [...args],
100
+ duration: options.durationMs
101
+ };
102
+ }
103
+ //#endregion
104
+ export { applyServerActionLogHeader, createServerActionLogInfo, formatActionArgs, isDevServerActionLoggingEnabled, parseServerActionLogHeader, resolveServerActionLogMeta, serializeServerActionLogHeader };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qzsy/vinext",
3
- "version": "0.1.80",
3
+ "version": "0.1.81",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -93,27 +93,32 @@
93
93
  "publishConfig": {
94
94
  "access": "public"
95
95
  },
96
+ "scripts": {
97
+ "build": "vp pack",
98
+ "prepack": "node --input-type=module -e \"import { copyFileSync } from 'node:fs'; copyFileSync('../../README.md','README.md');\" && vp run build",
99
+ "dev": "vp pack --watch"
100
+ },
96
101
  "dependencies": {
97
- "@unpic/react": "^1.0.2",
98
- "@vercel/og": "^0.8.6",
99
- "image-size": "2.0.2",
100
- "ipaddr.js": "^2.1.0",
101
- "magic-string": "^0.30.21",
102
- "vite-plugin-commonjs": "^0.10.4",
103
- "web-vitals": "^4.2.4"
102
+ "@unpic/react": "catalog:",
103
+ "@vercel/og": "catalog:",
104
+ "image-size": "catalog:",
105
+ "ipaddr.js": "catalog:",
106
+ "magic-string": "catalog:",
107
+ "vite-plugin-commonjs": "catalog:",
108
+ "web-vitals": "catalog:"
104
109
  },
105
110
  "devDependencies": {
106
- "@types/node": "^25.9.2",
107
- "@types/react": "^19.2.16",
108
- "@types/react-dom": "^19.2.3",
109
- "@vitejs/plugin-react": "^6.0.1",
110
- "@vitejs/plugin-rsc": "^0.5.27",
111
- "am-i-vibing": "^0.5.0",
112
- "react-server-dom-webpack": "^19.2.7",
113
- "vite": "npm:@voidzero-dev/vite-plus-core@0.2.1",
114
- "vite-plus": "0.2.1",
115
- "vite-tsconfig-paths": "^6.1.1",
116
- "@vinext/cloudflare": "0.1.2"
111
+ "@types/node": "catalog:",
112
+ "@types/react": "catalog:",
113
+ "@types/react-dom": "catalog:",
114
+ "@vinext/cloudflare": "workspace:*",
115
+ "@vitejs/plugin-react": "catalog:",
116
+ "@vitejs/plugin-rsc": "catalog:",
117
+ "am-i-vibing": "catalog:",
118
+ "react-server-dom-webpack": "catalog:",
119
+ "vite": "catalog:",
120
+ "vite-plus": "catalog:",
121
+ "vite-tsconfig-paths": "catalog:"
117
122
  },
118
123
  "peerDependencies": {
119
124
  "@mdx-js/rollup": "^3.0.0",
@@ -141,9 +146,5 @@
141
146
  },
142
147
  "engines": {
143
148
  "node": ">=22"
144
- },
145
- "scripts": {
146
- "build": "vp pack",
147
- "dev": "vp pack --watch"
148
149
  }
149
- }
150
+ }