@openuiai/next 16.2.0 → 16.3.0
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/bin/next +2 -2
- package/dist/build/get-babel-loader-config.js +1 -1
- package/dist/build/get-babel-loader-config.js.map +1 -1
- package/dist/build/index.js +3 -3
- package/dist/build/webpack-config.js +6 -4
- package/dist/build/webpack-config.js.map +1 -1
- package/dist/cache/cache-control.js +22 -0
- package/dist/cache/cache-control.js.map +1 -0
- package/dist/cache/clone-response.js +77 -0
- package/dist/cache/clone-response.js.map +1 -0
- package/dist/cache/dedupe-fetch.js +123 -0
- package/dist/cache/dedupe-fetch.js.map +1 -0
- package/dist/cache/lazy-result.js +46 -0
- package/dist/cache/lazy-result.js.map +1 -0
- package/dist/cache/lru-cache.js +177 -0
- package/dist/cache/lru-cache.js.map +1 -0
- package/dist/client/app-bootstrap.js +1 -1
- package/dist/client/index.js +1 -1
- package/dist/compiled/next-server/server.runtime.prod.js.map +1 -1
- package/dist/concurrency/batcher.js +65 -0
- package/dist/concurrency/batcher.js.map +1 -0
- package/dist/concurrency/coalesced-function.js +39 -0
- package/dist/concurrency/coalesced-function.js.map +1 -0
- package/dist/concurrency/scheduler.js +64 -0
- package/dist/concurrency/scheduler.js.map +1 -0
- package/dist/concurrency/wait.js +19 -0
- package/dist/concurrency/wait.js.map +1 -0
- package/dist/concurrency/with-promise-cache.js +24 -0
- package/dist/concurrency/with-promise-cache.js.map +1 -0
- package/dist/config/detect-typo.js +51 -0
- package/dist/config/detect-typo.js.map +1 -0
- package/dist/config/find-config.js +102 -0
- package/dist/config/find-config.js.map +1 -0
- package/dist/config/get-package-version.js +118 -0
- package/dist/config/get-package-version.js.map +1 -0
- package/dist/config/get-project-dir.js +51 -0
- package/dist/config/get-project-dir.js.map +1 -0
- package/dist/config/install-dependencies.js +40 -0
- package/dist/config/install-dependencies.js.map +1 -0
- package/dist/config/needs-experimental-react.js +16 -0
- package/dist/config/needs-experimental-react.js.map +1 -0
- package/dist/config/static-env.js +92 -0
- package/dist/config/static-env.js.map +1 -0
- package/dist/constants/constants.js +397 -0
- package/dist/constants/constants.js.map +1 -0
- package/dist/errors/compile-error.js +14 -0
- package/dist/errors/compile-error.js.map +1 -0
- package/dist/errors/error-source.js +36 -0
- package/dist/errors/error-source.js.map +1 -0
- package/dist/errors/error-telemetry-utils.js +42 -0
- package/dist/errors/error-telemetry-utils.js.map +1 -0
- package/dist/errors/fatal-error.js +14 -0
- package/dist/errors/fatal-error.js.map +1 -0
- package/dist/errors/format-server-error.js +74 -0
- package/dist/errors/format-server-error.js.map +1 -0
- package/dist/errors/invariant-error.js +18 -0
- package/dist/errors/invariant-error.js.map +1 -0
- package/dist/errors/is-error.js +65 -0
- package/dist/errors/is-error.js.map +1 -0
- package/dist/errors/no-fallback-error.js +18 -0
- package/dist/errors/no-fallback-error.js.map +1 -0
- package/dist/esm/build/get-babel-loader-config.js +1 -1
- package/dist/esm/build/get-babel-loader-config.js.map +1 -1
- package/dist/esm/build/index.js +3 -3
- package/dist/esm/build/webpack-config.js +6 -4
- package/dist/esm/build/webpack-config.js.map +1 -1
- package/dist/esm/client/app-bootstrap.js +1 -1
- package/dist/esm/client/index.js +1 -1
- package/dist/esm/lib/metadata/resolvers/resolve-url.js +1 -1
- package/dist/esm/lib/metadata/resolvers/resolve-url.js.map +1 -1
- package/dist/esm/lib/worker.js +1 -1
- package/dist/esm/lib/worker.js.map +1 -1
- package/dist/esm/server/dev/hot-reloader-webpack.js +1 -1
- package/dist/esm/server/lib/app-info-log.js +1 -1
- package/dist/esm/server/lib/start-server.js +1 -1
- package/dist/esm/server/websocket/setup.js +1 -1
- package/dist/esm/server/websocket/setup.js.map +1 -1
- package/dist/esm/server/websocket/types.js +1 -1
- package/dist/esm/server/websocket/types.js.map +1 -1
- package/dist/esm/shared/lib/errors/canary-only-config-error.js +1 -1
- package/dist/filesystem/file-exists.js +53 -0
- package/dist/filesystem/file-exists.js.map +1 -0
- package/dist/filesystem/find-pages-dir.js +65 -0
- package/dist/filesystem/find-pages-dir.js.map +1 -0
- package/dist/filesystem/find-root.js +118 -0
- package/dist/filesystem/find-root.js.map +1 -0
- package/dist/filesystem/get-files-in-dir.js +33 -0
- package/dist/filesystem/get-files-in-dir.js.map +1 -0
- package/dist/filesystem/multi-file-writer.js +75 -0
- package/dist/filesystem/multi-file-writer.js.map +1 -0
- package/dist/filesystem/realpath.js +20 -0
- package/dist/filesystem/realpath.js.map +1 -0
- package/dist/filesystem/recursive-copy.js +76 -0
- package/dist/filesystem/recursive-copy.js.map +1 -0
- package/dist/filesystem/recursive-delete.js +137 -0
- package/dist/filesystem/recursive-delete.js.map +1 -0
- package/dist/filesystem/recursive-readdir.js +124 -0
- package/dist/filesystem/recursive-readdir.js.map +1 -0
- package/dist/filesystem/rename.js +87 -0
- package/dist/filesystem/rename.js.map +1 -0
- package/dist/filesystem/write-atomic.js +28 -0
- package/dist/filesystem/write-atomic.js.map +1 -0
- package/dist/fonts/font-utils.js +43 -0
- package/dist/fonts/font-utils.js.map +1 -0
- package/dist/fonts/get-preloadable-fonts.js +39 -0
- package/dist/fonts/get-preloadable-fonts.js.map +1 -0
- package/dist/hash/bloom-filter.js +85 -0
- package/dist/hash/bloom-filter.js.map +1 -0
- package/dist/hash/etag.js +56 -0
- package/dist/hash/etag.js.map +1 -0
- package/dist/hash/fnv1a.js +56 -0
- package/dist/hash/fnv1a.js.map +1 -0
- package/dist/hash/hash.js +39 -0
- package/dist/hash/hash.js.map +1 -0
- package/dist/hostname/format-hostname.js +16 -0
- package/dist/hostname/format-hostname.js.map +1 -0
- package/dist/hostname/get-hostname.js +23 -0
- package/dist/hostname/get-hostname.js.map +1 -0
- package/dist/hostname/get-network-host.js +44 -0
- package/dist/hostname/get-network-host.js.map +1 -0
- package/dist/hostname/is-ipv6.js +41 -0
- package/dist/hostname/is-ipv6.js.map +1 -0
- package/dist/image/find-closest-quality.js +19 -0
- package/dist/image/find-closest-quality.js.map +1 -0
- package/dist/image/get-img-props.js +573 -0
- package/dist/image/get-img-props.js.map +1 -0
- package/dist/image/image-blur-svg.js +22 -0
- package/dist/image/image-blur-svg.js.map +1 -0
- package/dist/image/image-config-context.shared-runtime.js +19 -0
- package/dist/image/image-config-context.shared-runtime.js.map +1 -0
- package/dist/image/image-config.js +74 -0
- package/dist/image/image-config.js.map +1 -0
- package/dist/image/image-loader.js +91 -0
- package/dist/image/image-loader.js.map +1 -0
- package/dist/image/image-optimizer.js +1019 -0
- package/dist/image/image-optimizer.js.map +1 -0
- package/dist/image/match-local-pattern.js +46 -0
- package/dist/image/match-local-pattern.js.map +1 -0
- package/dist/image/match-remote-pattern.js +63 -0
- package/dist/image/match-remote-pattern.js.map +1 -0
- package/dist/image/mime-type.js +20 -0
- package/dist/image/mime-type.js.map +1 -0
- package/dist/lib/metadata/resolvers/resolve-url.js +1 -1
- package/dist/lib/metadata/resolvers/resolve-url.js.map +1 -1
- package/dist/lib/worker.js +1 -1
- package/dist/lib/worker.js.map +1 -1
- package/dist/memory/gc-observer.js +53 -0
- package/dist/memory/gc-observer.js.map +1 -0
- package/dist/memory/shutdown.js +29 -0
- package/dist/memory/shutdown.js.map +1 -0
- package/dist/memory/startup.js +47 -0
- package/dist/memory/startup.js.map +1 -0
- package/dist/memory/trace.js +109 -0
- package/dist/memory/trace.js.map +1 -0
- package/dist/module/client-and-server-references.js +54 -0
- package/dist/module/client-and-server-references.js.map +1 -0
- package/dist/module/format-dynamic-import-path.js +24 -0
- package/dist/module/format-dynamic-import-path.js.map +1 -0
- package/dist/module/interop-default.js +15 -0
- package/dist/module/interop-default.js.map +1 -0
- package/dist/module/resolve-from.js +79 -0
- package/dist/module/resolve-from.js.map +1 -0
- package/dist/module/semver-noop.js +18 -0
- package/dist/module/semver-noop.js.map +1 -0
- package/dist/object/deep-freeze.js +30 -0
- package/dist/object/deep-freeze.js.map +1 -0
- package/dist/object/deep-readonly.js +10 -0
- package/dist/object/deep-readonly.js.map +1 -0
- package/dist/object/is-plain-object.js +42 -0
- package/dist/object/is-plain-object.js.map +1 -0
- package/dist/object/non-nullable.js +15 -0
- package/dist/object/non-nullable.js.map +1 -0
- package/dist/object/pick.js +19 -0
- package/dist/object/pick.js.map +1 -0
- package/dist/process/setup-exception-listeners.js +11 -0
- package/dist/process/setup-exception-listeners.js.map +1 -0
- package/dist/promise/detached-promise.js +32 -0
- package/dist/promise/detached-promise.js.map +1 -0
- package/dist/promise/is-thenable.js +20 -0
- package/dist/promise/is-thenable.js.map +1 -0
- package/dist/promise/promise-with-resolvers.js +26 -0
- package/dist/promise/promise-with-resolvers.js.map +1 -0
- package/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/dist/server/lib/app-info-log.js +1 -1
- package/dist/server/lib/start-server.js +1 -1
- package/dist/server/websocket/setup.js +1 -1
- package/dist/server/websocket/setup.js.map +1 -1
- package/dist/server/websocket/types.js +1 -1
- package/dist/server/websocket/types.js.map +1 -1
- package/dist/shared/lib/errors/canary-only-config-error.js +1 -1
- package/dist/string/encode-uri-path.js +15 -0
- package/dist/string/encode-uri-path.js.map +1 -0
- package/dist/string/escape-regexp.js +22 -0
- package/dist/string/escape-regexp.js.map +1 -0
- package/dist/string/normalize-path.js +21 -0
- package/dist/string/normalize-path.js.map +1 -0
- package/dist/string/oxford-comma-list.js +15 -0
- package/dist/string/oxford-comma-list.js.map +1 -0
- package/dist/string/pretty-bytes.js +74 -0
- package/dist/string/pretty-bytes.js.map +1 -0
- package/dist/telemetry/anonymous-meta.js +1 -1
- package/dist/telemetry/events/session-stopped.js +2 -2
- package/dist/telemetry/events/version.js +2 -2
- package/dist/typescript/diagnosticFormatter.js +240 -0
- package/dist/typescript/diagnosticFormatter.js.map +1 -0
- package/dist/typescript/getTypeScriptConfiguration.js +73 -0
- package/dist/typescript/getTypeScriptConfiguration.js.map +1 -0
- package/dist/typescript/getTypeScriptIntent.js +52 -0
- package/dist/typescript/getTypeScriptIntent.js.map +1 -0
- package/dist/typescript/missingDependencyError.js +27 -0
- package/dist/typescript/missingDependencyError.js.map +1 -0
- package/dist/typescript/runTypeCheck.js +95 -0
- package/dist/typescript/runTypeCheck.js.map +1 -0
- package/dist/typescript/writeAppTypeDeclarations.js +65 -0
- package/dist/typescript/writeAppTypeDeclarations.js.map +1 -0
- package/dist/typescript/writeConfigurationDefaults.js +403 -0
- package/dist/typescript/writeConfigurationDefaults.js.map +1 -0
- package/dist/validation/is-serializable-props.js +106 -0
- package/dist/validation/is-serializable-props.js.map +1 -0
- package/index.d.ts +2 -2
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../server/websocket/setup.ts"],"sourcesContent":["// File: packages/next/src/server/websocket/setup.ts\n/* eslint-disable react-hooks/rules-of-hooks */\n\nimport type { IncomingMessage } from 'http'\nimport type { Socket as NetSocket } from 'net'\nimport { WebSocketServer, type WebSocket } from 'next/dist/compiled/ws'\n\nimport * as Log from '../../build/output/log'\nimport setupDebug from 'next/dist/compiled/debug'\nimport type NextNodeServer from '../next-server'\nimport { createServerAdapter, getWebSocketConfig } from './server-adapter'\nimport { getConnectionTracker } from './connection-tracker'\nimport { resolveWebSocketRoute, isWebSocketSupported } from './route-resolver'\nimport { GracefulWebSocketHandler } from './graceful-handler'\nimport { getWebSocketServerOptions, getRouteConfig } from './config'\nimport { getOrInitializeConnectionHandler } from './route-handler'\nimport {\n initializeHealthMonitor,\n setupHealthCheckEndpoint,\n getHealthMonitor,\n} from './health-check'\nimport { rateLimiterManager } from './rate-limiter'\nimport { initializeConnectionPool } from './performance'\nimport { getMemoryManager } from './memory-manager'\nimport {\n useHttpServer,\n useWebSocketServer,\n clearWebSocketServer,\n} from './persistent-servers'\n\nconst debug = setupDebug('next:websocket:setup')\nimport { clearConnectionHandlerCache } from './route-handler'\n\n// Centralized error handler for WebSocket connections\nfunction handleConnectionError(\n error: unknown,\n connectionId: string,\n pathname: string,\n context: string\n): void {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n // Log the error with context\n debug(\n `${context} error:`,\n pathname,\n 'connection id:',\n connectionId,\n 'error:',\n errorMessage\n )\n\n // Report to health monitor if available\n const healthMonitor = getHealthMonitor()\n if (healthMonitor) {\n healthMonitor.recordError()\n }\n\n // Log to Next.js error system\n Log.error(`WebSocket ${context}:`, pathname, errorMessage)\n}\n\n// Track servers that already have WebSocket listeners to prevent duplicates\nconst serverListenerMap = new WeakMap<\n any,\n {\n handler: Function\n wsServer: WebSocketServer\n }\n>()\n\n// Cleanup function to remove WebSocket listeners and clean up resources\nfunction cleanupWebSocketServer(httpServer: any, wsServer: WebSocketServer) {\n const existingSetup = serverListenerMap.get(httpServer)\n if (existingSetup) {\n httpServer.removeListener('upgrade', existingSetup.handler)\n serverListenerMap.delete(httpServer)\n }\n\n // Clear connection handler cache\n clearConnectionHandlerCache()\n\n // Close WebSocket server\n wsServer.close(() => {\n debug('WebSocket closed')\n })\n}\n\n// Sets up the WebSocket server and attaches it to the Next.js HTTP server.\n// This function is called during the NextNodeServer initialization.\n// @param nextServer The Next.js server instance.\nexport function setupWebSocketServer(nextServer: NextNodeServer): void {\n debug('ws setup starting')\n\n // Clear any stale state from previous server instances\n debug('clearing stale websocket state')\n clearWebSocketServer()\n clearConnectionHandlerCache()\n\n // Debug: Log initial state\n const initialStats = getMemoryManager().getMemoryStats()\n debug(\n 'initial state - app heap usage:',\n `${(initialStats.heapUsed / 1024 / 1024).toFixed(2)}MB (${initialStats.percentage.toFixed(1)}% of ${(initialStats.heapTotal / 1024 / 1024).toFixed(0)}MB allocated heap)`,\n 'ws connections:',\n initialStats.connectionCount\n )\n\n // Check if WebSocket support is available\n if (!isWebSocketSupported(nextServer)) {\n debug('WebSocket support unavailable')\n return\n }\n\n const config = getWebSocketConfig(nextServer)\n if (!config.enabled) {\n debug('WebSocket disabled')\n return\n }\n\n const serverAdapter = createServerAdapter(nextServer)\n const httpServer = useHttpServer(serverAdapter.getHttpServer())\n\n if (httpServer === undefined) {\n // TODO: throw error\n return\n }\n\n // Check if WebSocket listener already exists for this server\n const existingSetup = serverListenerMap.get(httpServer)\n if (existingSetup) {\n debug('ws listener exists')\n return\n }\n\n // Check existing listeners in development\n if (process.env.NODE_ENV === 'development') {\n const existingListeners = httpServer.listeners('upgrade')\n if (existingListeners.length > 0) {\n debug('existing upgrade listeners:', existingListeners.length)\n }\n }\n\n const wsServerOptions = getWebSocketServerOptions(config)\n const wsServer = useWebSocketServer(new WebSocketServer(wsServerOptions))\n // Increase max listeners to prevent warnings\n if (wsServer) {\n wsServer.setMaxListeners(20)\n }\n if (!wsServer) {\n Log.error('WebSocketServer init failed')\n return\n }\n\n // Initialize performance optimizations\n const connectionPool = initializeConnectionPool(\n config.maxConnections,\n config.timeout || 300000 // Use timeout or default 5 minutes for idle cleanup\n )\n\n // Initialize memory management\n const memoryManager = getMemoryManager()\n\n // Initialize health monitoring if enabled\n if (config.monitoring.metrics || config.monitoring.healthCheck?.enabled) {\n initializeHealthMonitor(config, wsServer)\n\n if (config.monitoring.healthCheck?.enabled) {\n setupHealthCheckEndpoint(config, httpServer)\n }\n }\n\n // The primary upgrade handler attached to the HTTP server.\n const handleUpgrade = async (\n request: IncomingMessage,\n socket: NetSocket,\n head: Buffer\n ) => {\n const requestUrl = request.url || '/'\n debug('ws upgrade:', requestUrl)\n\n const tracker = getConnectionTracker()\n\n // Check for rapid duplicate requests\n // if (tracker.isRapidDuplicate(requestUrl, socket)) {\n // debug('duplicate request blocked')\n // return\n // }\n\n // Check if this socket is already being processed\n if (tracker.isSocketActive(socket)) {\n debug('socket busy, ignoring upgrade')\n return\n }\n\n // Mark this socket as being processed\n tracker.markSocketActive(socket)\n\n const parsedUrl = new URL(\n requestUrl,\n `ws://${request.headers.host || 'localhost'}`\n )\n const pathname = parsedUrl.pathname\n\n // Create connection context for error handling\n // const connectionContext = {\n // pathname,\n // socket,\n // request,\n // startTime: Date.now()\n // }\n\n // Exclude Next.js internal paths like HMR\n if (pathname.startsWith('/_next/')) {\n tracker.markSocketInactive(socket)\n return\n }\n\n // Check rate limiting for this route\n const routeConfig = getRouteConfig(config, pathname)\n if (routeConfig.rateLimit) {\n const rateLimit = rateLimiterManager.checkRateLimit(\n pathname,\n routeConfig,\n request,\n socket\n )\n if (!rateLimit.allowed) {\n debug(`Rate limit exceeded for ${pathname}: ${rateLimit.message}`)\n socket.destroy() // Rate limit exceeded - close immediately\n tracker.markSocketInactive(socket)\n return\n }\n }\n\n // Resolve the WebSocket route\n const routeResolution = await resolveWebSocketRoute(nextServer, pathname)\n if (!routeResolution) {\n debug('no ws route found for:', pathname)\n socket.destroy()\n tracker.markSocketInactive(socket)\n return\n }\n\n const { handler: socketHandler, routeParams: _routeParams } =\n routeResolution\n\n // Get route configuration\n const currentRouteConfig = getRouteConfig(config, pathname)\n\n // Get or initialize the connection handler for this route\n const connectionHandler = await getOrInitializeConnectionHandler(\n socketHandler,\n wsServer,\n pathname,\n currentRouteConfig\n )\n\n if (!connectionHandler) {\n Log.error('connection handler init failed:', pathname)\n socket.destroy()\n tracker.markSocketInactive(socket)\n return\n }\n\n // If we found a connection handler, delegate the upgrade to the 'ws' library\n wsServer.handleUpgrade(\n request,\n socket,\n head,\n async (clientWebSocket: WebSocket, httpRequest: IncomingMessage) => {\n // Generate unique connection ID\n const connectionId = crypto.randomUUID()\n debug(\n 'ws connected to route:',\n pathname,\n 'connection id:',\n connectionId\n )\n\n // Check memory usage before accepting connection\n if (!memoryManager.isMemoryUsageAcceptable()) {\n debug('memory high, rejecting connection')\n await GracefulWebSocketHandler.closeWebSocketGracefully(\n clientWebSocket,\n {\n code: 1013,\n reason: 'Server overloaded',\n }\n )\n return\n }\n\n // Add to connection pool\n if (\n !connectionPool.addConnection(connectionId, clientWebSocket, pathname)\n ) {\n debug('connection pool full')\n await GracefulWebSocketHandler.closeWebSocketGracefully(\n clientWebSocket,\n {\n code: 1013,\n reason: 'Server at capacity',\n }\n )\n return\n }\n\n try {\n // Call the connection handler function\n const cleanupFunction = await connectionHandler(\n clientWebSocket,\n httpRequest\n )\n\n // Always attach close handler for cleanup\n clientWebSocket.once('close', (code, reason) => {\n debug(\n 'ws disconnected:',\n pathname,\n 'connection id:',\n connectionId,\n 'code:',\n code,\n 'reason:',\n reason?.toString()\n )\n\n // Prevent double cleanup\n if (tracker.isConnectionCleanedUp(connectionId)) {\n debug('connection already cleaned up:', connectionId)\n return\n }\n tracker.markConnectionCleanedUp(connectionId)\n\n // Remove from connection tracker\n tracker.markSocketInactive(socket)\n\n // Run user cleanup function if provided\n if (typeof cleanupFunction === 'function') {\n try {\n cleanupFunction()\n } catch (e) {\n handleConnectionError(e, connectionId, pathname, 'cleanup')\n }\n }\n })\n\n // Note: Connection pool cleanup is handled automatically by setupConnectionHandlers()\n\n // Add error handler to track connection errors\n clientWebSocket.on('error', (error) => {\n handleConnectionError(error, connectionId, pathname, 'connection')\n })\n\n // Add heartbeat to detect dead connections\n // Use unref() so this interval doesn't prevent the process from exiting\n const heartbeatInterval = setInterval(() => {\n if (clientWebSocket.readyState === clientWebSocket.OPEN) {\n debug('sending ping to:', connectionId)\n clientWebSocket.ping()\n } else {\n debug(\n 'connection not open, clearing heartbeat:',\n connectionId,\n 'state:',\n clientWebSocket.readyState\n )\n clearInterval(heartbeatInterval)\n }\n }, 30000) // 30 second heartbeat\n heartbeatInterval.unref()\n\n // Clear heartbeat on close\n clientWebSocket.once('close', () => {\n if (!tracker.isConnectionCleanedUp(connectionId)) {\n clearInterval(heartbeatInterval)\n }\n })\n\n if (\n typeof cleanupFunction !== 'function' &&\n cleanupFunction !== undefined &&\n cleanupFunction !== null\n ) {\n debug(\n `Connection handler for ${pathname} returned non-function value: ${typeof cleanupFunction}`\n )\n }\n } catch (e) {\n handleConnectionError(e, connectionId, pathname, 'handler')\n clientWebSocket.terminate()\n }\n\n // Connection tracking is automatically cleaned up when socket closes\n }\n )\n }\n\n // Add a unique identifier to the handler for detection\n Object.defineProperty(handleUpgrade, 'name', { value: 'nextWsHandleUpgrade' })\n\n // Store the handler reference for cleanup\n serverListenerMap.set(httpServer, {\n handler: handleUpgrade,\n wsServer,\n })\n\n // Attach our custom upgrade handler to the HTTP server\n httpServer.on('upgrade', handleUpgrade)\n debug('ws upgrade listener ready')\n\n // Set up cleanup when the server closes\n httpServer.on('close', () => {\n debug('cleaning up WebSocket server')\n cleanupWebSocketServer(httpServer, wsServer)\n })\n}\n"],"names":["setupWebSocketServer","debug","setupDebug","handleConnectionError","error","connectionId","pathname","context","errorMessage","Error","message","String","healthMonitor","getHealthMonitor","recordError","Log","serverListenerMap","WeakMap","cleanupWebSocketServer","httpServer","wsServer","existingSetup","get","removeListener","handler","delete","clearConnectionHandlerCache","close","nextServer","config","clearWebSocketServer","initialStats","getMemoryManager","getMemoryStats","heapUsed","toFixed","percentage","heapTotal","connectionCount","isWebSocketSupported","getWebSocketConfig","enabled","serverAdapter","createServerAdapter","useHttpServer","getHttpServer","undefined","process","env","NODE_ENV","existingListeners","listeners","length","wsServerOptions","getWebSocketServerOptions","useWebSocketServer","WebSocketServer","setMaxListeners","connectionPool","initializeConnectionPool","maxConnections","timeout","memoryManager","monitoring","metrics","healthCheck","initializeHealthMonitor","setupHealthCheckEndpoint","handleUpgrade","request","socket","head","requestUrl","url","tracker","getConnectionTracker","isSocketActive","markSocketActive","parsedUrl","URL","headers","host","startsWith","markSocketInactive","routeConfig","getRouteConfig","rateLimit","rateLimiterManager","checkRateLimit","allowed","destroy","routeResolution","resolveWebSocketRoute","socketHandler","routeParams","_routeParams","currentRouteConfig","connectionHandler","getOrInitializeConnectionHandler","clientWebSocket","httpRequest","crypto","randomUUID","isMemoryUsageAcceptable","GracefulWebSocketHandler","closeWebSocketGracefully","code","reason","addConnection","cleanupFunction","once","toString","isConnectionCleanedUp","markConnectionCleanedUp","e","on","heartbeatInterval","setInterval","readyState","OPEN","ping","clearInterval","unref","terminate","Object","defineProperty","value","set"],"mappings":"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","ignoreList":[0]}
|
|
1
|
+
{"version":3,"sources":["../../../server/websocket/setup.ts"],"sourcesContent":["// File: packages/next/server/websocket/setup.ts\n/* eslint-disable react-hooks/rules-of-hooks */\n\nimport type { IncomingMessage } from 'http'\nimport type { Socket as NetSocket } from 'net'\nimport { WebSocketServer, type WebSocket } from 'next/dist/compiled/ws'\n\nimport * as Log from '../../build/output/log'\nimport setupDebug from 'next/dist/compiled/debug'\nimport type NextNodeServer from '../next-server'\nimport { createServerAdapter, getWebSocketConfig } from './server-adapter'\nimport { getConnectionTracker } from './connection-tracker'\nimport { resolveWebSocketRoute, isWebSocketSupported } from './route-resolver'\nimport { GracefulWebSocketHandler } from './graceful-handler'\nimport { getWebSocketServerOptions, getRouteConfig } from './config'\nimport { getOrInitializeConnectionHandler } from './route-handler'\nimport {\n initializeHealthMonitor,\n setupHealthCheckEndpoint,\n getHealthMonitor,\n} from './health-check'\nimport { rateLimiterManager } from './rate-limiter'\nimport { initializeConnectionPool } from './performance'\nimport { getMemoryManager } from './memory-manager'\nimport {\n useHttpServer,\n useWebSocketServer,\n clearWebSocketServer,\n} from './persistent-servers'\n\nconst debug = setupDebug('next:websocket:setup')\nimport { clearConnectionHandlerCache } from './route-handler'\n\n// Centralized error handler for WebSocket connections\nfunction handleConnectionError(\n error: unknown,\n connectionId: string,\n pathname: string,\n context: string\n): void {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n // Log the error with context\n debug(\n `${context} error:`,\n pathname,\n 'connection id:',\n connectionId,\n 'error:',\n errorMessage\n )\n\n // Report to health monitor if available\n const healthMonitor = getHealthMonitor()\n if (healthMonitor) {\n healthMonitor.recordError()\n }\n\n // Log to Next.js error system\n Log.error(`WebSocket ${context}:`, pathname, errorMessage)\n}\n\n// Track servers that already have WebSocket listeners to prevent duplicates\nconst serverListenerMap = new WeakMap<\n any,\n {\n handler: Function\n wsServer: WebSocketServer\n }\n>()\n\n// Cleanup function to remove WebSocket listeners and clean up resources\nfunction cleanupWebSocketServer(httpServer: any, wsServer: WebSocketServer) {\n const existingSetup = serverListenerMap.get(httpServer)\n if (existingSetup) {\n httpServer.removeListener('upgrade', existingSetup.handler)\n serverListenerMap.delete(httpServer)\n }\n\n // Clear connection handler cache\n clearConnectionHandlerCache()\n\n // Close WebSocket server\n wsServer.close(() => {\n debug('WebSocket closed')\n })\n}\n\n// Sets up the WebSocket server and attaches it to the Next.js HTTP server.\n// This function is called during the NextNodeServer initialization.\n// @param nextServer The Next.js server instance.\nexport function setupWebSocketServer(nextServer: NextNodeServer): void {\n debug('ws setup starting')\n\n // Clear any stale state from previous server instances\n debug('clearing stale websocket state')\n clearWebSocketServer()\n clearConnectionHandlerCache()\n\n // Debug: Log initial state\n const initialStats = getMemoryManager().getMemoryStats()\n debug(\n 'initial state - app heap usage:',\n `${(initialStats.heapUsed / 1024 / 1024).toFixed(2)}MB (${initialStats.percentage.toFixed(1)}% of ${(initialStats.heapTotal / 1024 / 1024).toFixed(0)}MB allocated heap)`,\n 'ws connections:',\n initialStats.connectionCount\n )\n\n // Check if WebSocket support is available\n if (!isWebSocketSupported(nextServer)) {\n debug('WebSocket support unavailable')\n return\n }\n\n const config = getWebSocketConfig(nextServer)\n if (!config.enabled) {\n debug('WebSocket disabled')\n return\n }\n\n const serverAdapter = createServerAdapter(nextServer)\n const httpServer = useHttpServer(serverAdapter.getHttpServer())\n\n if (httpServer === undefined) {\n // TODO: throw error\n return\n }\n\n // Check if WebSocket listener already exists for this server\n const existingSetup = serverListenerMap.get(httpServer)\n if (existingSetup) {\n debug('ws listener exists')\n return\n }\n\n // Check existing listeners in development\n if (process.env.NODE_ENV === 'development') {\n const existingListeners = httpServer.listeners('upgrade')\n if (existingListeners.length > 0) {\n debug('existing upgrade listeners:', existingListeners.length)\n }\n }\n\n const wsServerOptions = getWebSocketServerOptions(config)\n const wsServer = useWebSocketServer(new WebSocketServer(wsServerOptions))\n // Increase max listeners to prevent warnings\n if (wsServer) {\n wsServer.setMaxListeners(20)\n }\n if (!wsServer) {\n Log.error('WebSocketServer init failed')\n return\n }\n\n // Initialize performance optimizations\n const connectionPool = initializeConnectionPool(\n config.maxConnections,\n config.timeout || 300000 // Use timeout or default 5 minutes for idle cleanup\n )\n\n // Initialize memory management\n const memoryManager = getMemoryManager()\n\n // Initialize health monitoring if enabled\n if (config.monitoring.metrics || config.monitoring.healthCheck?.enabled) {\n initializeHealthMonitor(config, wsServer)\n\n if (config.monitoring.healthCheck?.enabled) {\n setupHealthCheckEndpoint(config, httpServer)\n }\n }\n\n // The primary upgrade handler attached to the HTTP server.\n const handleUpgrade = async (\n request: IncomingMessage,\n socket: NetSocket,\n head: Buffer\n ) => {\n const requestUrl = request.url || '/'\n debug('ws upgrade:', requestUrl)\n\n const tracker = getConnectionTracker()\n\n // Check for rapid duplicate requests\n // if (tracker.isRapidDuplicate(requestUrl, socket)) {\n // debug('duplicate request blocked')\n // return\n // }\n\n // Check if this socket is already being processed\n if (tracker.isSocketActive(socket)) {\n debug('socket busy, ignoring upgrade')\n return\n }\n\n // Mark this socket as being processed\n tracker.markSocketActive(socket)\n\n const parsedUrl = new URL(\n requestUrl,\n `ws://${request.headers.host || 'localhost'}`\n )\n const pathname = parsedUrl.pathname\n\n // Create connection context for error handling\n // const connectionContext = {\n // pathname,\n // socket,\n // request,\n // startTime: Date.now()\n // }\n\n // Exclude Next.js internal paths like HMR\n if (pathname.startsWith('/_next/')) {\n tracker.markSocketInactive(socket)\n return\n }\n\n // Check rate limiting for this route\n const routeConfig = getRouteConfig(config, pathname)\n if (routeConfig.rateLimit) {\n const rateLimit = rateLimiterManager.checkRateLimit(\n pathname,\n routeConfig,\n request,\n socket\n )\n if (!rateLimit.allowed) {\n debug(`Rate limit exceeded for ${pathname}: ${rateLimit.message}`)\n socket.destroy() // Rate limit exceeded - close immediately\n tracker.markSocketInactive(socket)\n return\n }\n }\n\n // Resolve the WebSocket route\n const routeResolution = await resolveWebSocketRoute(nextServer, pathname)\n if (!routeResolution) {\n debug('no ws route found for:', pathname)\n socket.destroy()\n tracker.markSocketInactive(socket)\n return\n }\n\n const { handler: socketHandler, routeParams: _routeParams } =\n routeResolution\n\n // Get route configuration\n const currentRouteConfig = getRouteConfig(config, pathname)\n\n // Get or initialize the connection handler for this route\n const connectionHandler = await getOrInitializeConnectionHandler(\n socketHandler,\n wsServer,\n pathname,\n currentRouteConfig\n )\n\n if (!connectionHandler) {\n Log.error('connection handler init failed:', pathname)\n socket.destroy()\n tracker.markSocketInactive(socket)\n return\n }\n\n // If we found a connection handler, delegate the upgrade to the 'ws' library\n wsServer.handleUpgrade(\n request,\n socket,\n head,\n async (clientWebSocket: WebSocket, httpRequest: IncomingMessage) => {\n // Generate unique connection ID\n const connectionId = crypto.randomUUID()\n debug(\n 'ws connected to route:',\n pathname,\n 'connection id:',\n connectionId\n )\n\n // Check memory usage before accepting connection\n if (!memoryManager.isMemoryUsageAcceptable()) {\n debug('memory high, rejecting connection')\n await GracefulWebSocketHandler.closeWebSocketGracefully(\n clientWebSocket,\n {\n code: 1013,\n reason: 'Server overloaded',\n }\n )\n return\n }\n\n // Add to connection pool\n if (\n !connectionPool.addConnection(connectionId, clientWebSocket, pathname)\n ) {\n debug('connection pool full')\n await GracefulWebSocketHandler.closeWebSocketGracefully(\n clientWebSocket,\n {\n code: 1013,\n reason: 'Server at capacity',\n }\n )\n return\n }\n\n try {\n // Call the connection handler function\n const cleanupFunction = await connectionHandler(\n clientWebSocket,\n httpRequest\n )\n\n // Always attach close handler for cleanup\n clientWebSocket.once('close', (code, reason) => {\n debug(\n 'ws disconnected:',\n pathname,\n 'connection id:',\n connectionId,\n 'code:',\n code,\n 'reason:',\n reason?.toString()\n )\n\n // Prevent double cleanup\n if (tracker.isConnectionCleanedUp(connectionId)) {\n debug('connection already cleaned up:', connectionId)\n return\n }\n tracker.markConnectionCleanedUp(connectionId)\n\n // Remove from connection tracker\n tracker.markSocketInactive(socket)\n\n // Run user cleanup function if provided\n if (typeof cleanupFunction === 'function') {\n try {\n cleanupFunction()\n } catch (e) {\n handleConnectionError(e, connectionId, pathname, 'cleanup')\n }\n }\n })\n\n // Note: Connection pool cleanup is handled automatically by setupConnectionHandlers()\n\n // Add error handler to track connection errors\n clientWebSocket.on('error', (error) => {\n handleConnectionError(error, connectionId, pathname, 'connection')\n })\n\n // Add heartbeat to detect dead connections\n // Use unref() so this interval doesn't prevent the process from exiting\n const heartbeatInterval = setInterval(() => {\n if (clientWebSocket.readyState === clientWebSocket.OPEN) {\n debug('sending ping to:', connectionId)\n clientWebSocket.ping()\n } else {\n debug(\n 'connection not open, clearing heartbeat:',\n connectionId,\n 'state:',\n clientWebSocket.readyState\n )\n clearInterval(heartbeatInterval)\n }\n }, 30000) // 30 second heartbeat\n heartbeatInterval.unref()\n\n // Clear heartbeat on close\n clientWebSocket.once('close', () => {\n if (!tracker.isConnectionCleanedUp(connectionId)) {\n clearInterval(heartbeatInterval)\n }\n })\n\n if (\n typeof cleanupFunction !== 'function' &&\n cleanupFunction !== undefined &&\n cleanupFunction !== null\n ) {\n debug(\n `Connection handler for ${pathname} returned non-function value: ${typeof cleanupFunction}`\n )\n }\n } catch (e) {\n handleConnectionError(e, connectionId, pathname, 'handler')\n clientWebSocket.terminate()\n }\n\n // Connection tracking is automatically cleaned up when socket closes\n }\n )\n }\n\n // Add a unique identifier to the handler for detection\n Object.defineProperty(handleUpgrade, 'name', { value: 'nextWsHandleUpgrade' })\n\n // Store the handler reference for cleanup\n serverListenerMap.set(httpServer, {\n handler: handleUpgrade,\n wsServer,\n })\n\n // Attach our custom upgrade handler to the HTTP server\n httpServer.on('upgrade', handleUpgrade)\n debug('ws upgrade listener ready')\n\n // Set up cleanup when the server closes\n httpServer.on('close', () => {\n debug('cleaning up WebSocket server')\n cleanupWebSocketServer(httpServer, wsServer)\n })\n}\n"],"names":["setupWebSocketServer","debug","setupDebug","handleConnectionError","error","connectionId","pathname","context","errorMessage","Error","message","String","healthMonitor","getHealthMonitor","recordError","Log","serverListenerMap","WeakMap","cleanupWebSocketServer","httpServer","wsServer","existingSetup","get","removeListener","handler","delete","clearConnectionHandlerCache","close","nextServer","config","clearWebSocketServer","initialStats","getMemoryManager","getMemoryStats","heapUsed","toFixed","percentage","heapTotal","connectionCount","isWebSocketSupported","getWebSocketConfig","enabled","serverAdapter","createServerAdapter","useHttpServer","getHttpServer","undefined","process","env","NODE_ENV","existingListeners","listeners","length","wsServerOptions","getWebSocketServerOptions","useWebSocketServer","WebSocketServer","setMaxListeners","connectionPool","initializeConnectionPool","maxConnections","timeout","memoryManager","monitoring","metrics","healthCheck","initializeHealthMonitor","setupHealthCheckEndpoint","handleUpgrade","request","socket","head","requestUrl","url","tracker","getConnectionTracker","isSocketActive","markSocketActive","parsedUrl","URL","headers","host","startsWith","markSocketInactive","routeConfig","getRouteConfig","rateLimit","rateLimiterManager","checkRateLimit","allowed","destroy","routeResolution","resolveWebSocketRoute","socketHandler","routeParams","_routeParams","currentRouteConfig","connectionHandler","getOrInitializeConnectionHandler","clientWebSocket","httpRequest","crypto","randomUUID","isMemoryUsageAcceptable","GracefulWebSocketHandler","closeWebSocketGracefully","code","reason","addConnection","cleanupFunction","once","toString","isConnectionCleanedUp","markConnectionCleanedUp","e","on","heartbeatInterval","setInterval","readyState","OPEN","ping","clearInterval","unref","terminate","Object","defineProperty","value","set"],"mappings":"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","ignoreList":[0]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../server/websocket/types.ts"],"sourcesContent":["// File: packages/next/
|
|
1
|
+
{"version":3,"sources":["../../../server/websocket/types.ts"],"sourcesContent":["// File: packages/next/server/websocket/types.ts\n\nimport type { IncomingMessage as HttpIncomingMessage } from 'http'\nimport type {\n WebSocket,\n WebSocketServer as WebSocketServerType,\n} from 'next/dist/compiled/ws'\n\n// Awaitable utility type\ntype Awaitable<T> = T | Promise<T>\n\n// Type for the function optionally returned by a connection handler, called on client disconnect.\nexport type OnSocketClose = () => Awaitable<unknown>\n\n// Type for the connection handler function returned by SOCKET\nexport type ConnectionHandler = (\n // The individual WebSocket client that has connected.\n client: WebSocket,\n // The initial HTTP request that initiated the WebSocket upgrade.\n request: HttpIncomingMessage\n) => Awaitable<OnSocketClose | void | unknown>\n\n// Defines the signature for a WebSocket handler function that can be exported\n// from a Next.js App Router API route file under the name `SOCKET`.\n// This function is called ONCE when the server starts up, not for each connection.\nexport type SocketHandler = (\n // The WebSocketServer instance managing all connections for this route\n wss: WebSocketServerType\n) => Awaitable<ConnectionHandler>\n\n// Interface for the structure of a route module that might contain a SOCKET handler.\n// This is used by `route-handler.ts` to safely access the `SOCKET` export,\n// considering potential wrapping by the Next.js compiler or different export styles.\nexport interface RouteModuleWithPossibleSocketHandler {\n // Common App Router structure: `export default <...>`. The resolved default\n // might have a `routeModule.userland` structure.\n default?:\n | Promise<RouteModuleWithPossibleSocketHandler> // Handle async default exports\n | RouteModuleWithPossibleSocketHandler // Handle direct object default exports\n\n // Standard Next.js App Router structure for route handlers\n routeModule?: {\n userland?: {\n SOCKET?: SocketHandler // The target export key\n // other HTTP methods like GET, POST etc. might also be here\n [key: string]: unknown\n }\n }\n\n // Alternative structures sometimes used or found in module objects\n handlers?: {\n SOCKET?: SocketHandler\n // other HTTP methods\n [key: string]: unknown\n }\n\n // Direct export of SOCKET (less common with standard App Router conventions but possible)\n SOCKET?: SocketHandler\n}\n"],"names":[],"mappings":"AAAA,gDAAgD","ignoreList":[0]}
|
|
@@ -21,7 +21,7 @@ _export(exports, {
|
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
function isStableBuild() {
|
|
24
|
-
return !"16.
|
|
24
|
+
return !"16.3.0"?.includes('canary') && !process.env.__NEXT_TEST_MODE && !process.env.NEXT_PRIVATE_LOCAL_DEV;
|
|
25
25
|
}
|
|
26
26
|
class CanaryOnlyConfigError extends Error {
|
|
27
27
|
constructor(arg){
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "encodeURIPath", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return encodeURIPath;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
function encodeURIPath(file) {
|
|
12
|
+
return file.split('/').map((p)=>encodeURIComponent(p)).join('/');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=encode-uri-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../string/encode-uri-path.ts"],"sourcesContent":["export function encodeURIPath(file: string) {\n return file\n .split('/')\n .map((p) => encodeURIComponent(p))\n .join('/')\n}\n"],"names":["encodeURIPath","file","split","map","p","encodeURIComponent","join"],"mappings":";;;;+BAAgBA;;;eAAAA;;;AAAT,SAASA,cAAcC,IAAY;IACxC,OAAOA,KACJC,KAAK,CAAC,KACNC,GAAG,CAAC,CAACC,IAAMC,mBAAmBD,IAC9BE,IAAI,CAAC;AACV","ignoreList":[0]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// regexp is based on https://github.com/sindresorhus/escape-string-regexp
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "escapeStringRegexp", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function() {
|
|
9
|
+
return escapeStringRegexp;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const reHasRegExp = /[|\\{}()[\]^$+*?.-]/;
|
|
13
|
+
const reReplaceRegExp = /[|\\{}()[\]^$+*?.-]/g;
|
|
14
|
+
function escapeStringRegexp(str) {
|
|
15
|
+
// see also: https://github.com/lodash/lodash/blob/2da024c3b4f9947a48517639de7560457cd4ec6c/escapeRegExp.js#L23
|
|
16
|
+
if (reHasRegExp.test(str)) {
|
|
17
|
+
return str.replace(reReplaceRegExp, '\\$&');
|
|
18
|
+
}
|
|
19
|
+
return str;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=escape-regexp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../string/escape-regexp.ts"],"sourcesContent":["// regexp is based on https://github.com/sindresorhus/escape-string-regexp\nconst reHasRegExp = /[|\\\\{}()[\\]^$+*?.-]/\nconst reReplaceRegExp = /[|\\\\{}()[\\]^$+*?.-]/g\n\nexport function escapeStringRegexp(str: string) {\n // see also: https://github.com/lodash/lodash/blob/2da024c3b4f9947a48517639de7560457cd4ec6c/escapeRegExp.js#L23\n if (reHasRegExp.test(str)) {\n return str.replace(reReplaceRegExp, '\\\\$&')\n }\n return str\n}\n"],"names":["escapeStringRegexp","reHasRegExp","reReplaceRegExp","str","test","replace"],"mappings":"AAAA,0EAA0E;;;;;+BAI1DA;;;eAAAA;;;AAHhB,MAAMC,cAAc;AACpB,MAAMC,kBAAkB;AAEjB,SAASF,mBAAmBG,GAAW;IAC5C,+GAA+G;IAC/G,IAAIF,YAAYG,IAAI,CAACD,MAAM;QACzB,OAAOA,IAAIE,OAAO,CAACH,iBAAiB;IACtC;IACA,OAAOC;AACT","ignoreList":[0]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "normalizePath", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return normalizePath;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
|
12
|
+
function _interop_require_default(obj) {
|
|
13
|
+
return obj && obj.__esModule ? obj : {
|
|
14
|
+
default: obj
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function normalizePath(file) {
|
|
18
|
+
return _path.default.sep === '\\' ? file.replace(/\\/g, '/') : file;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=normalize-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../string/normalize-path.ts"],"sourcesContent":["import path from 'path'\n\nexport function normalizePath(file: string) {\n return path.sep === '\\\\' ? file.replace(/\\\\/g, '/') : file\n}\n"],"names":["normalizePath","file","path","sep","replace"],"mappings":";;;;+BAEgBA;;;eAAAA;;;6DAFC;;;;;;AAEV,SAASA,cAAcC,IAAY;IACxC,OAAOC,aAAI,CAACC,GAAG,KAAK,OAAOF,KAAKG,OAAO,CAAC,OAAO,OAAOH;AACxD","ignoreList":[0]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "getOxfordCommaList", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return getOxfordCommaList;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
function getOxfordCommaList(items) {
|
|
12
|
+
return items.map((v, index, { length })=>(index > 0 ? index === length - 1 ? length > 2 ? ', and ' : ' and ' : ', ' : '') + v).join('');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=oxford-comma-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../string/oxford-comma-list.ts"],"sourcesContent":["export function getOxfordCommaList(items: string[]): string {\n return items\n .map(\n (v, index, { length }) =>\n (index > 0\n ? index === length - 1\n ? length > 2\n ? ', and '\n : ' and '\n : ', '\n : '') + v\n )\n .join('')\n}\n"],"names":["getOxfordCommaList","items","map","v","index","length","join"],"mappings":";;;;+BAAgBA;;;eAAAA;;;AAAT,SAASA,mBAAmBC,KAAe;IAChD,OAAOA,MACJC,GAAG,CACF,CAACC,GAAGC,OAAO,EAAEC,MAAM,EAAE,GACnB,AAACD,CAAAA,QAAQ,IACLA,UAAUC,SAAS,IACjBA,SAAS,IACP,WACA,UACF,OACF,EAAC,IAAKF,GAEbG,IAAI,CAAC;AACV","ignoreList":[0]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/*
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
7
|
+
|
|
8
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
9
|
+
|
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
11
|
+
*/ "use strict";
|
|
12
|
+
Object.defineProperty(exports, "__esModule", {
|
|
13
|
+
value: true
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(exports, "default", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function() {
|
|
18
|
+
return prettyBytes;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const UNITS = [
|
|
22
|
+
'B',
|
|
23
|
+
'kB',
|
|
24
|
+
'MB',
|
|
25
|
+
'GB',
|
|
26
|
+
'TB',
|
|
27
|
+
'PB',
|
|
28
|
+
'EB',
|
|
29
|
+
'ZB',
|
|
30
|
+
'YB'
|
|
31
|
+
];
|
|
32
|
+
/*
|
|
33
|
+
Formats the given number using `Number#toLocaleString`.
|
|
34
|
+
- If locale is a string, the value is expected to be a locale-key (for example: `de`).
|
|
35
|
+
- If locale is true, the system default locale is used for translation.
|
|
36
|
+
- If no value for locale is specified, the number is returned unmodified.
|
|
37
|
+
*/ const toLocaleString = (number, locale)=>{
|
|
38
|
+
let result = number;
|
|
39
|
+
if (typeof locale === 'string') {
|
|
40
|
+
result = number.toLocaleString(locale);
|
|
41
|
+
} else if (locale === true) {
|
|
42
|
+
result = number.toLocaleString();
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
function prettyBytes(number, options) {
|
|
47
|
+
if (!Number.isFinite(number)) {
|
|
48
|
+
throw Object.defineProperty(new TypeError(`Expected a finite number, got ${typeof number}: ${number}`), "__NEXT_ERROR_CODE", {
|
|
49
|
+
value: "E572",
|
|
50
|
+
enumerable: false,
|
|
51
|
+
configurable: true
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
options = Object.assign({}, options);
|
|
55
|
+
if (options.signed && number === 0) {
|
|
56
|
+
return ' 0 B';
|
|
57
|
+
}
|
|
58
|
+
const isNegative = number < 0;
|
|
59
|
+
const prefix = isNegative ? '-' : options.signed ? '+' : '';
|
|
60
|
+
if (isNegative) {
|
|
61
|
+
number = -number;
|
|
62
|
+
}
|
|
63
|
+
if (number < 1) {
|
|
64
|
+
const numberString = toLocaleString(number, options.locale);
|
|
65
|
+
return prefix + numberString + ' B';
|
|
66
|
+
}
|
|
67
|
+
const exponent = Math.min(Math.floor(Math.log10(number) / 3), UNITS.length - 1);
|
|
68
|
+
number = Number((number / Math.pow(1000, exponent)).toPrecision(3));
|
|
69
|
+
const numberString = toLocaleString(number, options.locale);
|
|
70
|
+
const unit = UNITS[exponent];
|
|
71
|
+
return prefix + numberString + ' ' + unit;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=pretty-bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../string/pretty-bytes.ts"],"sourcesContent":["/*\nMIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n\nconst UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n\n/*\nFormats the given number using `Number#toLocaleString`.\n- If locale is a string, the value is expected to be a locale-key (for example: `de`).\n- If locale is true, the system default locale is used for translation.\n- If no value for locale is specified, the number is returned unmodified.\n*/\nconst toLocaleString = (number: number, locale: any) => {\n let result: any = number\n if (typeof locale === 'string') {\n result = number.toLocaleString(locale)\n } else if (locale === true) {\n result = number.toLocaleString()\n }\n\n return result\n}\n\nexport default function prettyBytes(number: number, options?: any): string {\n if (!Number.isFinite(number)) {\n throw new TypeError(\n `Expected a finite number, got ${typeof number}: ${number}`\n )\n }\n\n options = Object.assign({}, options)\n\n if (options.signed && number === 0) {\n return ' 0 B'\n }\n\n const isNegative = number < 0\n const prefix = isNegative ? '-' : options.signed ? '+' : ''\n\n if (isNegative) {\n number = -number\n }\n\n if (number < 1) {\n const numberString = toLocaleString(number, options.locale)\n return prefix + numberString + ' B'\n }\n\n const exponent = Math.min(\n Math.floor(Math.log10(number) / 3),\n UNITS.length - 1\n )\n\n number = Number((number / Math.pow(1000, exponent)).toPrecision(3))\n const numberString = toLocaleString(number, options.locale)\n\n const unit = UNITS[exponent]\n\n return prefix + numberString + ' ' + unit\n}\n"],"names":["prettyBytes","UNITS","toLocaleString","number","locale","result","options","Number","isFinite","TypeError","Object","assign","signed","isNegative","prefix","numberString","exponent","Math","min","floor","log10","length","pow","toPrecision","unit"],"mappings":"AAAA;;;;;;;;;;AAUA;;;;+BAqBA;;;eAAwBA;;;AAnBxB,MAAMC,QAAQ;IAAC;IAAK;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;CAAK;AAEnE;;;;;AAKA,GACA,MAAMC,iBAAiB,CAACC,QAAgBC;IACtC,IAAIC,SAAcF;IAClB,IAAI,OAAOC,WAAW,UAAU;QAC9BC,SAASF,OAAOD,cAAc,CAACE;IACjC,OAAO,IAAIA,WAAW,MAAM;QAC1BC,SAASF,OAAOD,cAAc;IAChC;IAEA,OAAOG;AACT;AAEe,SAASL,YAAYG,MAAc,EAAEG,OAAa;IAC/D,IAAI,CAACC,OAAOC,QAAQ,CAACL,SAAS;QAC5B,MAAM,qBAEL,CAFK,IAAIM,UACR,CAAC,8BAA8B,EAAE,OAAON,OAAO,EAAE,EAAEA,QAAQ,GADvD,qBAAA;mBAAA;wBAAA;0BAAA;QAEN;IACF;IAEAG,UAAUI,OAAOC,MAAM,CAAC,CAAC,GAAGL;IAE5B,IAAIA,QAAQM,MAAM,IAAIT,WAAW,GAAG;QAClC,OAAO;IACT;IAEA,MAAMU,aAAaV,SAAS;IAC5B,MAAMW,SAASD,aAAa,MAAMP,QAAQM,MAAM,GAAG,MAAM;IAEzD,IAAIC,YAAY;QACdV,SAAS,CAACA;IACZ;IAEA,IAAIA,SAAS,GAAG;QACd,MAAMY,eAAeb,eAAeC,QAAQG,QAAQF,MAAM;QAC1D,OAAOU,SAASC,eAAe;IACjC;IAEA,MAAMC,WAAWC,KAAKC,GAAG,CACvBD,KAAKE,KAAK,CAACF,KAAKG,KAAK,CAACjB,UAAU,IAChCF,MAAMoB,MAAM,GAAG;IAGjBlB,SAASI,OAAO,AAACJ,CAAAA,SAASc,KAAKK,GAAG,CAAC,MAAMN,SAAQ,EAAGO,WAAW,CAAC;IAChE,MAAMR,eAAeb,eAAeC,QAAQG,QAAQF,MAAM;IAE1D,MAAMoB,OAAOvB,KAAK,CAACe,SAAS;IAE5B,OAAOF,SAASC,eAAe,MAAMS;AACvC","ignoreList":[0]}
|
|
@@ -11,11 +11,11 @@ Object.defineProperty(exports, "eventCliSessionStopped", {
|
|
|
11
11
|
const EVENT_VERSION = 'NEXT_CLI_SESSION_STOPPED';
|
|
12
12
|
function eventCliSessionStopped(event) {
|
|
13
13
|
// This should be an invariant, if it fails our build tooling is broken.
|
|
14
|
-
if (typeof "16.
|
|
14
|
+
if (typeof "16.3.0" !== 'string') {
|
|
15
15
|
return [];
|
|
16
16
|
}
|
|
17
17
|
const payload = {
|
|
18
|
-
nextVersion: "16.
|
|
18
|
+
nextVersion: "16.3.0",
|
|
19
19
|
nodeVersion: process.version,
|
|
20
20
|
cliCommand: event.cliCommand,
|
|
21
21
|
durationMilliseconds: event.durationMilliseconds,
|
|
@@ -12,12 +12,12 @@ const EVENT_VERSION = 'NEXT_CLI_SESSION_STARTED';
|
|
|
12
12
|
function eventCliSession(nextConfig, event) {
|
|
13
13
|
var _nextConfig_experimental_staleTimes, _nextConfig_experimental_staleTimes1, _nextConfig_reactCompiler, _nextConfig_reactCompiler1;
|
|
14
14
|
// This should be an invariant, if it fails our build tooling is broken.
|
|
15
|
-
if (typeof "16.
|
|
15
|
+
if (typeof "16.3.0" !== 'string') {
|
|
16
16
|
return [];
|
|
17
17
|
}
|
|
18
18
|
const { images, i18n } = nextConfig || {};
|
|
19
19
|
const payload = {
|
|
20
|
-
nextVersion: "16.
|
|
20
|
+
nextVersion: "16.3.0",
|
|
21
21
|
nodeVersion: process.version,
|
|
22
22
|
cliCommand: event.cliCommand,
|
|
23
23
|
isSrcDir: event.isSrcDir,
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "getFormattedDiagnostic", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return getFormattedDiagnostic;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _picocolors = require("../lib/picocolors");
|
|
12
|
+
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
|
13
|
+
function _interop_require_default(obj) {
|
|
14
|
+
return obj && obj.__esModule ? obj : {
|
|
15
|
+
default: obj
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function getFormattedLinkDiagnosticMessageText(diagnostic) {
|
|
19
|
+
const message = diagnostic.messageText;
|
|
20
|
+
if (typeof message === 'string' && diagnostic.code === 2322) {
|
|
21
|
+
const match = message.match(/Type '"(.+)"' is not assignable to type 'RouteImpl<.+> \| UrlObject'\./) || message.match(/Type '"(.+)"' is not assignable to type 'UrlObject \| RouteImpl<.+>'\./);
|
|
22
|
+
if (match) {
|
|
23
|
+
const [, href] = match;
|
|
24
|
+
return `"${(0, _picocolors.bold)(href)}" is not an existing route. If it is intentional, please type it explicitly with \`as Route\`.`;
|
|
25
|
+
} else if (message === "Type 'string' is not assignable to type 'UrlObject'.") {
|
|
26
|
+
var _diagnostic_relatedInformation_, _diagnostic_relatedInformation;
|
|
27
|
+
const relatedMessage = (_diagnostic_relatedInformation = diagnostic.relatedInformation) == null ? void 0 : (_diagnostic_relatedInformation_ = _diagnostic_relatedInformation[0]) == null ? void 0 : _diagnostic_relatedInformation_.messageText;
|
|
28
|
+
if (typeof relatedMessage === 'string' && relatedMessage.match(/The expected type comes from property 'href' which is declared here on type 'IntrinsicAttributes & /)) {
|
|
29
|
+
return `Invalid \`href\` property of \`Link\`: the route does not exist. If it is intentional, please type it explicitly with \`as Route\`.`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} else if (typeof message === 'string' && diagnostic.code === 2820) {
|
|
33
|
+
const match = message.match(/Type '"(.+)"' is not assignable to type 'RouteImpl<.+> \| UrlObject'\. Did you mean '"(.+)"'?/) || message.match(/Type '"(.+)"' is not assignable to type 'UrlObject \| RouteImpl<.+>'\. Did you mean '"(.+)"'?/);
|
|
34
|
+
if (match) {
|
|
35
|
+
const [, href, suggestion] = match;
|
|
36
|
+
return `"${(0, _picocolors.bold)(href)}" is not an existing route. Did you mean "${(0, _picocolors.bold)(suggestion)}" instead? If it is intentional, please type it explicitly with \`as Route\`.`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function getFormattedLayoutAndPageDiagnosticMessageText(relativeSourceFilepath, diagnostic) {
|
|
41
|
+
const message = typeof diagnostic.messageText === 'string' ? diagnostic : diagnostic.messageText;
|
|
42
|
+
const messageText = message.messageText;
|
|
43
|
+
if (typeof messageText === 'string') {
|
|
44
|
+
const type = /page\.[^.]+$/.test(relativeSourceFilepath) ? 'Page' : /route\.[^.]+$/.test(relativeSourceFilepath) ? 'Route' : 'Layout';
|
|
45
|
+
// Reference of error codes:
|
|
46
|
+
// https://github.com/Microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
|
|
47
|
+
switch(message.code){
|
|
48
|
+
case 2344:
|
|
49
|
+
const filepathAndType = messageText.match(/typeof import\("(.+)"\)/);
|
|
50
|
+
if (filepathAndType) {
|
|
51
|
+
let main = `${type} "${(0, _picocolors.bold)(relativeSourceFilepath)}" does not match the required types of a Next.js ${type}.`;
|
|
52
|
+
function processNext(indent, next) {
|
|
53
|
+
if (!next) return;
|
|
54
|
+
for (const item of next){
|
|
55
|
+
switch(item.code){
|
|
56
|
+
case 2200:
|
|
57
|
+
const mismatchedField = item.messageText.match(/The types of '(.+)'/);
|
|
58
|
+
if (mismatchedField) {
|
|
59
|
+
main += '\n' + ' '.repeat(indent * 2);
|
|
60
|
+
main += `"${(0, _picocolors.bold)(mismatchedField[1])}" has the wrong type:`;
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 2322:
|
|
64
|
+
const types = item.messageText.match(/Type '(.+)' is not assignable to type '(.+)'./);
|
|
65
|
+
if (types) {
|
|
66
|
+
main += '\n' + ' '.repeat(indent * 2);
|
|
67
|
+
if (types[2] === 'PageComponent' || types[2] === 'LayoutComponent') {
|
|
68
|
+
main += `The exported ${type} component isn't correctly typed.`;
|
|
69
|
+
} else {
|
|
70
|
+
main += `Expected "${(0, _picocolors.bold)(types[2].replace('"__invalid_negative_number__"', 'number (>= 0)'))}", got "${(0, _picocolors.bold)(types[1])}".`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
case 2326:
|
|
75
|
+
const invalidConfig = item.messageText.match(/Types of property '(.+)' are incompatible\./);
|
|
76
|
+
main += '\n' + ' '.repeat(indent * 2);
|
|
77
|
+
main += `Invalid configuration${invalidConfig ? ` "${(0, _picocolors.bold)(invalidConfig[1])}"` : ''}:`;
|
|
78
|
+
break;
|
|
79
|
+
case 2530:
|
|
80
|
+
const invalidField = item.messageText.match(/Property '(.+)' is incompatible with index signature/);
|
|
81
|
+
if (invalidField) {
|
|
82
|
+
main += '\n' + ' '.repeat(indent * 2);
|
|
83
|
+
main += `"${(0, _picocolors.bold)(invalidField[1])}" is not a valid ${type} export field.`;
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
case 2739:
|
|
87
|
+
const invalidProp = item.messageText.match(/Type '(.+)' is missing the following properties from type '(.+)'/);
|
|
88
|
+
if (invalidProp) {
|
|
89
|
+
if (invalidProp[1] === 'LayoutProps' || invalidProp[1] === 'PageProps') {
|
|
90
|
+
main += '\n' + ' '.repeat(indent * 2);
|
|
91
|
+
main += `Prop "${invalidProp[2]}" is incompatible with the ${type}.`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
case 2559:
|
|
96
|
+
const invalid = item.messageText.match(/Type '(.+)' has/);
|
|
97
|
+
if (invalid) {
|
|
98
|
+
main += '\n' + ' '.repeat(indent * 2);
|
|
99
|
+
main += `Type "${(0, _picocolors.bold)(invalid[1])}" isn't allowed.`;
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
case 2741:
|
|
103
|
+
const incompatPageProp = item.messageText.match(/Property '(.+)' is missing in type 'PageProps'/);
|
|
104
|
+
if (incompatPageProp) {
|
|
105
|
+
main += '\n' + ' '.repeat(indent * 2);
|
|
106
|
+
main += `Prop "${(0, _picocolors.bold)(incompatPageProp[1])}" will never be passed. Remove it from the component's props.`;
|
|
107
|
+
} else {
|
|
108
|
+
const extraLayoutProp = item.messageText.match(/Property '(.+)' is missing in type 'LayoutProps' but required in type '(.+)'/);
|
|
109
|
+
if (extraLayoutProp) {
|
|
110
|
+
main += '\n' + ' '.repeat(indent * 2);
|
|
111
|
+
main += `Prop "${(0, _picocolors.bold)(extraLayoutProp[1])}" is not valid for this Layout, remove it to fix.`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
}
|
|
117
|
+
processNext(indent + 1, item.next);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if ('next' in message) processNext(1, message.next);
|
|
121
|
+
return main;
|
|
122
|
+
}
|
|
123
|
+
const invalidExportFnArg = messageText.match(/Type 'OmitWithTag<(.+), .+, "(.+)">' does not satisfy the constraint/);
|
|
124
|
+
if (invalidExportFnArg) {
|
|
125
|
+
const main = `${type} "${(0, _picocolors.bold)(relativeSourceFilepath)}" has an invalid "${(0, _picocolors.bold)(invalidExportFnArg[2])}" export:\n Type "${(0, _picocolors.bold)(invalidExportFnArg[1])}" is not valid.`;
|
|
126
|
+
return main;
|
|
127
|
+
}
|
|
128
|
+
function processNextItems(indent, next) {
|
|
129
|
+
if (!next) return '';
|
|
130
|
+
let result = '';
|
|
131
|
+
for (const item of next){
|
|
132
|
+
switch(item.code){
|
|
133
|
+
case 2322:
|
|
134
|
+
const types = item.messageText.match(/Type '(.+)' is not assignable to type '(.+)'./);
|
|
135
|
+
if (types) {
|
|
136
|
+
result += '\n' + ' '.repeat(indent * 2);
|
|
137
|
+
result += `Expected "${(0, _picocolors.bold)(types[2])}", got "${(0, _picocolors.bold)(types[1])}".`;
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
default:
|
|
141
|
+
}
|
|
142
|
+
result += processNextItems(indent + 1, item.next);
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
const invalidParamFn = messageText.match(/Type '{ __tag__: (.+); __param_position__: "(.*)"; __param_type__: (.+); }' does not satisfy/);
|
|
147
|
+
if (invalidParamFn) {
|
|
148
|
+
let main = `${type} "${(0, _picocolors.bold)(relativeSourceFilepath)}" has an invalid ${invalidParamFn[1]} export:\n Type "${(0, _picocolors.bold)(invalidParamFn[3])}" is not a valid type for the function's ${invalidParamFn[2]} argument.`;
|
|
149
|
+
if ('next' in message) main += processNextItems(1, message.next);
|
|
150
|
+
return main;
|
|
151
|
+
}
|
|
152
|
+
const invalidExportFnReturn = messageText.match(/Type '{ __tag__: "(.+)"; __return_type__: (.+); }' does not satisfy/);
|
|
153
|
+
if (invalidExportFnReturn) {
|
|
154
|
+
let main = `${type} "${(0, _picocolors.bold)(relativeSourceFilepath)}" has an invalid export:\n "${(0, _picocolors.bold)(invalidExportFnReturn[2])}" is not a valid ${invalidExportFnReturn[1]} return type:`;
|
|
155
|
+
if ('next' in message) main += processNextItems(1, message.next);
|
|
156
|
+
return main;
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
159
|
+
case 2345:
|
|
160
|
+
const filepathAndInvalidExport = messageText.match(/'typeof import\("(.+)"\)'.+Impossible<"(.+)">/);
|
|
161
|
+
if (filepathAndInvalidExport) {
|
|
162
|
+
const main = `${type} "${(0, _picocolors.bold)(relativeSourceFilepath)}" exports an invalid "${(0, _picocolors.bold)(filepathAndInvalidExport[2])}" field. ${type} should only export a default React component and configuration options. Learn more: https://nextjs.org/docs/messages/invalid-segment-export`;
|
|
163
|
+
return main;
|
|
164
|
+
}
|
|
165
|
+
break;
|
|
166
|
+
case 2559:
|
|
167
|
+
const invalid = messageText.match(/Type '(.+)' has no properties in common with type '(.+)'/);
|
|
168
|
+
if (invalid) {
|
|
169
|
+
const main = `${type} "${(0, _picocolors.bold)(relativeSourceFilepath)}" contains an invalid type "${(0, _picocolors.bold)(invalid[1])}" as ${invalid[2]}.`;
|
|
170
|
+
return main;
|
|
171
|
+
}
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function getAppEntrySourceFilePath(baseDir, diagnostic) {
|
|
178
|
+
var _diagnostic_file_text_trim_match, _diagnostic_file;
|
|
179
|
+
const sourceFilepath = ((_diagnostic_file = diagnostic.file) == null ? void 0 : (_diagnostic_file_text_trim_match = _diagnostic_file.text.trim().match(/^\/\/ File: (.+)\n/)) == null ? void 0 : _diagnostic_file_text_trim_match[1]) || '';
|
|
180
|
+
return _path.default.relative(baseDir, sourceFilepath);
|
|
181
|
+
}
|
|
182
|
+
function getFormattedDiagnostic(ts, baseDir, distDir, diagnostic, isAppDirEnabled) {
|
|
183
|
+
var _diagnostic_file;
|
|
184
|
+
// If the error comes from .next/types/, we handle it specially.
|
|
185
|
+
const isLayoutOrPageError = isAppDirEnabled && ((_diagnostic_file = diagnostic.file) == null ? void 0 : _diagnostic_file.fileName.startsWith(_path.default.join(baseDir, distDir, 'types')));
|
|
186
|
+
let message = '';
|
|
187
|
+
const appPath = isLayoutOrPageError ? getAppEntrySourceFilePath(baseDir, diagnostic) : null;
|
|
188
|
+
const linkReason = getFormattedLinkDiagnosticMessageText(diagnostic);
|
|
189
|
+
const appReason = !linkReason && isLayoutOrPageError && appPath ? getFormattedLayoutAndPageDiagnosticMessageText(appPath, diagnostic) : null;
|
|
190
|
+
const reason = linkReason || appReason || ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
|
191
|
+
const category = diagnostic.category;
|
|
192
|
+
switch(category){
|
|
193
|
+
// Warning
|
|
194
|
+
case ts.DiagnosticCategory.Warning:
|
|
195
|
+
{
|
|
196
|
+
message += (0, _picocolors.yellow)((0, _picocolors.bold)('Type warning')) + ': ';
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
// Error
|
|
200
|
+
case ts.DiagnosticCategory.Error:
|
|
201
|
+
{
|
|
202
|
+
message += (0, _picocolors.red)((0, _picocolors.bold)('Type error')) + ': ';
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
// 2 = Suggestion, 3 = Message
|
|
206
|
+
case ts.DiagnosticCategory.Suggestion:
|
|
207
|
+
case ts.DiagnosticCategory.Message:
|
|
208
|
+
message += (0, _picocolors.cyan)((0, _picocolors.bold)(category === 2 ? 'Suggestion' : 'Info')) + ': ';
|
|
209
|
+
break;
|
|
210
|
+
default:
|
|
211
|
+
{
|
|
212
|
+
category;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
message += reason + '\n';
|
|
216
|
+
if (!isLayoutOrPageError && diagnostic.file) {
|
|
217
|
+
const { codeFrameColumns } = require('next/dist/compiled/babel/code-frame');
|
|
218
|
+
const pos = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
219
|
+
const line = pos.line + 1;
|
|
220
|
+
const character = pos.character + 1;
|
|
221
|
+
let fileName = _path.default.posix.normalize(_path.default.relative(baseDir, diagnostic.file.fileName).replace(/\\/g, '/'));
|
|
222
|
+
if (!fileName.startsWith('.')) {
|
|
223
|
+
fileName = './' + fileName;
|
|
224
|
+
}
|
|
225
|
+
message = (0, _picocolors.cyan)(fileName) + ':' + (0, _picocolors.yellow)(line.toString()) + ':' + (0, _picocolors.yellow)(character.toString()) + '\n' + message;
|
|
226
|
+
message += '\n' + codeFrameColumns(diagnostic.file.getFullText(diagnostic.file.getSourceFile()), {
|
|
227
|
+
start: {
|
|
228
|
+
line: line,
|
|
229
|
+
column: character
|
|
230
|
+
}
|
|
231
|
+
}, {
|
|
232
|
+
forceColor: true
|
|
233
|
+
});
|
|
234
|
+
} else if (isLayoutOrPageError && appPath) {
|
|
235
|
+
message = (0, _picocolors.cyan)(appPath) + '\n' + message;
|
|
236
|
+
}
|
|
237
|
+
return message;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
//# sourceMappingURL=diagnosticFormatter.js.map
|