@tanstack/start-plugin-core 1.167.18 → 1.167.19
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/esm/config-context.d.ts +26 -0
- package/dist/esm/config-context.js +81 -0
- package/dist/esm/config-context.js.map +1 -0
- package/dist/esm/constants.d.ts +6 -1
- package/dist/esm/constants.js +3 -2
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js +1 -1
- package/dist/esm/import-protection-plugin/plugin.js +1 -1
- package/dist/esm/import-protection-plugin/virtualModules.js +1 -1
- package/dist/esm/index.d.ts +5 -3
- package/dist/esm/index.js +3 -4
- package/dist/esm/planning.d.ts +40 -0
- package/dist/esm/planning.js +107 -0
- package/dist/esm/planning.js.map +1 -0
- package/dist/esm/schema.d.ts +3093 -44
- package/dist/esm/schema.js +5 -5
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/serialization-adapters-module.d.ts +17 -0
- package/dist/esm/serialization-adapters-module.js +39 -0
- package/dist/esm/serialization-adapters-module.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/compiler.d.ts +2 -3
- package/dist/esm/{start-compiler-plugin → start-compiler}/compiler.js +17 -16
- package/dist/esm/start-compiler/compiler.js.map +1 -0
- package/dist/esm/start-compiler/config.d.ts +4 -0
- package/dist/esm/start-compiler/config.js +54 -0
- package/dist/esm/start-compiler/config.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.js +1 -1
- package/dist/esm/start-compiler/handleClientOnlyJSX.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.js +1 -1
- package/dist/esm/start-compiler/handleCreateIsomorphicFn.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.js +1 -1
- package/dist/esm/start-compiler/handleCreateMiddleware.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateServerFn.js +6 -17
- package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/handleEnvOnly.js +1 -1
- package/dist/esm/start-compiler/handleEnvOnly.js.map +1 -0
- package/dist/esm/start-compiler/host.d.ts +20 -0
- package/dist/esm/start-compiler/host.js +38 -0
- package/dist/esm/start-compiler/host.js.map +1 -0
- package/dist/esm/start-compiler/load-module.d.ts +14 -0
- package/dist/esm/start-compiler/load-module.js +18 -0
- package/dist/esm/start-compiler/load-module.js.map +1 -0
- package/dist/esm/start-compiler/server-fn-resolver-module.d.ts +8 -0
- package/dist/esm/start-compiler/server-fn-resolver-module.js +77 -0
- package/dist/esm/start-compiler/server-fn-resolver-module.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/types.d.ts +4 -0
- package/dist/esm/{start-compiler-plugin → start-compiler}/utils.js +1 -1
- package/dist/esm/start-compiler/utils.js.map +1 -0
- package/dist/esm/start-manifest-plugin/manifestBuilder.d.ts +16 -16
- package/dist/esm/start-manifest-plugin/manifestBuilder.js +14 -45
- package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -1
- package/dist/esm/start-router-plugin/route-tree-footer.d.ts +6 -0
- package/dist/esm/start-router-plugin/route-tree-footer.js +44 -0
- package/dist/esm/start-router-plugin/route-tree-footer.js.map +1 -0
- package/dist/esm/types.d.ts +44 -10
- package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.js +1 -1
- package/dist/esm/vite/dev-server-plugin/dev-styles.js.map +1 -0
- package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.js +1 -1
- package/dist/esm/vite/dev-server-plugin/extract-html-scripts.js.map +1 -0
- package/dist/esm/vite/dev-server-plugin/plugin.d.ts +7 -0
- package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/plugin.js +5 -6
- package/dist/esm/vite/dev-server-plugin/plugin.js.map +1 -0
- package/dist/esm/{load-env-plugin → vite/load-env-plugin}/plugin.js +1 -1
- package/dist/esm/vite/load-env-plugin/plugin.js.map +1 -0
- package/dist/esm/{output-directory.js → vite/output-directory.js} +2 -2
- package/dist/esm/vite/output-directory.js.map +1 -0
- package/dist/esm/vite/planning.d.ts +105 -0
- package/dist/esm/vite/planning.js +116 -0
- package/dist/esm/vite/planning.js.map +1 -0
- package/dist/esm/vite/plugin.d.ts +4 -0
- package/dist/esm/vite/plugin.js +169 -0
- package/dist/esm/vite/plugin.js.map +1 -0
- package/dist/esm/vite/plugins.d.ts +17 -0
- package/dist/esm/vite/plugins.js +50 -0
- package/dist/esm/vite/plugins.js.map +1 -0
- package/dist/esm/{post-server-build.d.ts → vite/post-server-build.d.ts} +1 -1
- package/dist/esm/{post-server-build.js → vite/post-server-build.js} +4 -4
- package/dist/esm/vite/post-server-build.js.map +1 -0
- package/dist/esm/{prerender.d.ts → vite/prerender.d.ts} +1 -1
- package/dist/esm/{prerender.js → vite/prerender.js} +5 -10
- package/dist/esm/vite/prerender.js.map +1 -0
- package/dist/esm/{preview-server-plugin → vite/preview-server-plugin}/plugin.js +4 -4
- package/dist/esm/vite/preview-server-plugin/plugin.js.map +1 -0
- package/dist/esm/vite/schema.d.ts +3373 -0
- package/dist/esm/vite/schema.js +12 -0
- package/dist/esm/vite/schema.js.map +1 -0
- package/dist/esm/vite/serialization-adapters-plugin.d.ts +5 -0
- package/dist/esm/vite/serialization-adapters-plugin.js +42 -0
- package/dist/esm/vite/serialization-adapters-plugin.js.map +1 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.d.ts +3 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js +19 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -0
- package/dist/esm/{start-compiler-plugin → vite/start-compiler-plugin}/plugin.d.ts +4 -3
- package/dist/esm/vite/start-compiler-plugin/plugin.js +202 -0
- package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -0
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.d.ts +6 -0
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js +81 -0
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js.map +1 -0
- package/dist/esm/vite/start-manifest-plugin/plugin.d.ts +6 -0
- package/dist/esm/{start-manifest-plugin → vite/start-manifest-plugin}/plugin.js +14 -9
- package/dist/esm/vite/start-manifest-plugin/plugin.js.map +1 -0
- package/dist/esm/{start-router-plugin → vite/start-router-plugin}/plugin.d.ts +3 -2
- package/dist/esm/{start-router-plugin → vite/start-router-plugin}/plugin.js +14 -37
- package/dist/esm/vite/start-router-plugin/plugin.js.map +1 -0
- package/dist/esm/vite/types.d.ts +15 -0
- package/package.json +12 -1
- package/src/config-context.ts +138 -0
- package/src/constants.ts +7 -3
- package/src/index.ts +5 -5
- package/src/planning.ts +151 -0
- package/src/schema.ts +93 -93
- package/src/serialization-adapters-module.ts +82 -0
- package/src/{start-compiler-plugin → start-compiler}/compiler.ts +67 -61
- package/src/start-compiler/config.ts +73 -0
- package/src/{start-compiler-plugin → start-compiler}/handleCreateServerFn.ts +14 -41
- package/src/start-compiler/host.ts +80 -0
- package/src/start-compiler/load-module.ts +31 -0
- package/src/start-compiler/server-fn-resolver-module.ts +129 -0
- package/src/{start-compiler-plugin → start-compiler}/types.ts +5 -0
- package/src/start-manifest-plugin/manifestBuilder.ts +65 -107
- package/src/start-router-plugin/route-tree-footer.ts +99 -0
- package/src/types.ts +53 -10
- package/src/{dev-server-plugin → vite/dev-server-plugin}/plugin.ts +7 -6
- package/src/{output-directory.ts → vite/output-directory.ts} +2 -2
- package/src/vite/planning.ts +234 -0
- package/src/vite/plugin.ts +276 -0
- package/src/vite/plugins.ts +81 -0
- package/src/{post-server-build.ts → vite/post-server-build.ts} +4 -6
- package/src/{prerender.ts → vite/prerender.ts} +21 -46
- package/src/{preview-server-plugin → vite/preview-server-plugin}/plugin.ts +2 -2
- package/src/vite/schema.ts +30 -0
- package/src/vite/serialization-adapters-plugin.ts +69 -0
- package/src/vite/start-compiler-plugin/module-specifier.ts +31 -0
- package/src/vite/start-compiler-plugin/plugin.ts +345 -0
- package/src/vite/start-manifest-plugin/normalized-client-build.ts +131 -0
- package/src/{start-manifest-plugin → vite/start-manifest-plugin}/plugin.ts +21 -13
- package/src/{start-router-plugin → vite/start-router-plugin}/plugin.ts +14 -80
- package/src/vite/types.ts +18 -0
- package/dist/esm/dev-server-plugin/dev-styles.js.map +0 -1
- package/dist/esm/dev-server-plugin/extract-html-scripts.js.map +0 -1
- package/dist/esm/dev-server-plugin/plugin.d.ts +0 -6
- package/dist/esm/dev-server-plugin/plugin.js.map +0 -1
- package/dist/esm/load-env-plugin/plugin.js.map +0 -1
- package/dist/esm/output-directory.js.map +0 -1
- package/dist/esm/plugin.d.ts +0 -4
- package/dist/esm/plugin.js +0 -301
- package/dist/esm/plugin.js.map +0 -1
- package/dist/esm/post-server-build.js.map +0 -1
- package/dist/esm/prerender.js.map +0 -1
- package/dist/esm/preview-server-plugin/plugin.js.map +0 -1
- package/dist/esm/start-compiler-plugin/compiler.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleClientOnlyJSX.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleCreateIsomorphicFn.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleCreateMiddleware.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleCreateServerFn.js.map +0 -1
- package/dist/esm/start-compiler-plugin/handleEnvOnly.js.map +0 -1
- package/dist/esm/start-compiler-plugin/plugin.js +0 -297
- package/dist/esm/start-compiler-plugin/plugin.js.map +0 -1
- package/dist/esm/start-compiler-plugin/utils.js.map +0 -1
- package/dist/esm/start-manifest-plugin/plugin.d.ts +0 -6
- package/dist/esm/start-manifest-plugin/plugin.js.map +0 -1
- package/dist/esm/start-router-plugin/plugin.js.map +0 -1
- package/src/plugin.ts +0 -471
- package/src/start-compiler-plugin/plugin.ts +0 -478
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleCreateServerFn.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/handleEnvOnly.d.ts +0 -0
- /package/dist/esm/{start-compiler-plugin → start-compiler}/utils.d.ts +0 -0
- /package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.d.ts +0 -0
- /package/dist/esm/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.d.ts +0 -0
- /package/dist/esm/{load-env-plugin → vite/load-env-plugin}/plugin.d.ts +0 -0
- /package/dist/esm/{output-directory.d.ts → vite/output-directory.d.ts} +0 -0
- /package/dist/esm/{preview-server-plugin → vite/preview-server-plugin}/plugin.d.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/handleClientOnlyJSX.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/handleCreateIsomorphicFn.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/handleCreateMiddleware.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/handleEnvOnly.ts +0 -0
- /package/src/{start-compiler-plugin → start-compiler}/utils.ts +0 -0
- /package/src/{dev-server-plugin → vite/dev-server-plugin}/dev-styles.ts +0 -0
- /package/src/{dev-server-plugin → vite/dev-server-plugin}/extract-html-scripts.ts +0 -0
- /package/src/{load-env-plugin → vite/load-env-plugin}/plugin.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handleCreateServerFn.js","names":[],"sources":["../../../src/start-compiler/handleCreateServerFn.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport babel from '@babel/core'\nimport path from 'pathe'\nimport { cleanId, codeFrameError, stripMethodCall } from './utils'\nimport type { CompilationContext, RewriteCandidate, ServerFn } from './types'\nimport type { CompileStartFrameworkOptions } from '../types'\n\nconst TSS_SERVERFN_SPLIT_PARAM = 'tss-serverfn-split'\n\n// ============================================================================\n// Pre-compiled babel templates (compiled once at module load time)\n// ============================================================================\n\n// Template for provider files: createServerRpc(serverFnMeta, fn)\nconst serverRpcTemplate = babel.template.expression(\n `createServerRpc(%%serverFnMeta%%, %%fn%%)`,\n)\n\n// Template for client caller files: createClientRpc(functionId)\nconst clientRpcTemplate = babel.template.expression(\n `createClientRpc(%%functionId%%)`,\n)\n\n// Template for SSR caller files: createSsrRpc(functionId)\nconst ssrRpcManifestTemplate = babel.template.expression(\n `createSsrRpc(%%functionId%%)`,\n)\n\n// ============================================================================\n// Runtime code cache (cached per framework to avoid repeated AST generation)\n// ============================================================================\n\ntype RuntimeCodeType = 'provider' | 'client' | 'ssr'\ntype FrameworkRuntimeCache = Record<RuntimeCodeType, t.Statement>\nconst RuntimeCodeCache = new Map<\n CompileStartFrameworkOptions,\n FrameworkRuntimeCache\n>()\n\nfunction getCachedRuntimeCode(\n framework: CompileStartFrameworkOptions,\n type: RuntimeCodeType,\n): t.Statement {\n let cache = RuntimeCodeCache.get(framework)\n if (!cache) {\n cache = {\n provider: babel.template.ast(\n `import { createServerRpc } from '@tanstack/${framework}-start/server-rpc'`,\n { placeholderPattern: false },\n ) as t.Statement,\n client: babel.template.ast(\n `import { createClientRpc } from '@tanstack/${framework}-start/client-rpc'`,\n { placeholderPattern: false },\n ) as t.Statement,\n ssr: babel.template.ast(\n `import { createSsrRpc } from '@tanstack/${framework}-start/ssr-rpc'`,\n { placeholderPattern: false },\n ) as t.Statement,\n }\n RuntimeCodeCache.set(framework, cache)\n }\n return cache[type]\n}\n\n/**\n * Environment-specific configuration for server function transformation.\n * This is computed internally based on the compilation context.\n */\ninterface EnvConfig {\n /** Whether this environment is a client environment */\n isClientEnvironment: boolean\n /** The runtime code type to use for imports */\n runtimeCodeType: RuntimeCodeType\n}\n\n/**\n * Gets the environment configuration for the current compilation context.\n */\nfunction getEnvConfig(\n context: CompilationContext,\n isProviderFile: boolean,\n): EnvConfig {\n const { env } = context\n\n if (isProviderFile) {\n return {\n isClientEnvironment: false,\n runtimeCodeType: 'provider',\n }\n }\n\n if (env === 'client') {\n return {\n isClientEnvironment: true,\n runtimeCodeType: 'client',\n }\n }\n\n // Server caller (SSR)\n return {\n isClientEnvironment: false,\n runtimeCodeType: 'ssr',\n }\n}\n\n/**\n * Builds the serverFnMeta object literal AST node.\n * The object contains: { id, name, filename }\n */\nfunction buildServerFnMetaObject(\n functionId: string,\n variableName: string,\n filename: string,\n): t.ObjectExpression {\n return t.objectExpression([\n t.objectProperty(t.identifier('id'), t.stringLiteral(functionId)),\n t.objectProperty(t.identifier('name'), t.stringLiteral(variableName)),\n t.objectProperty(t.identifier('filename'), t.stringLiteral(filename)),\n ])\n}\n\n/**\n * Generates the RPC stub expression for provider files.\n * Uses pre-compiled template for performance.\n */\nfunction generateProviderRpcStub(\n serverFnMeta: t.ObjectExpression,\n fn: t.Expression,\n): t.Expression {\n return serverRpcTemplate({\n serverFnMeta,\n fn,\n })\n}\n\n/**\n * Generates the RPC stub expression for caller files.\n * Uses pre-compiled templates for performance.\n * Note: Client and SSR callers only receive the functionId string, not the full metadata.\n */\nfunction generateCallerRpcStub(\n functionId: string,\n envConfig: EnvConfig,\n): t.Expression {\n const functionIdLiteral = t.stringLiteral(functionId)\n\n if (envConfig.runtimeCodeType === 'client') {\n return clientRpcTemplate({\n functionId: functionIdLiteral,\n })\n }\n\n return ssrRpcManifestTemplate({\n functionId: functionIdLiteral,\n })\n}\n\n/**\n * Handles createServerFn transformations for a batch of candidates.\n *\n * This function performs extraction and replacement of server functions\n *\n * For caller files (non-provider):\n * - Replaces the server function with an RPC stub\n * - Does not include the handler function body\n *\n * For provider files:\n * - Creates an extractedFn that calls __executeServer\n * - Modifies .handler() to pass (extractedFn, serverFn) - two arguments\n *\n * @param candidates - All ServerFn candidates to process\n * @param context - The compilation context with helpers and mutable state\n * @returns Result containing runtime code to add, or null if no candidates processed\n */\nexport function handleCreateServerFn(\n candidates: Array<RewriteCandidate>,\n context: CompilationContext,\n) {\n if (candidates.length === 0) {\n return\n }\n\n const isProviderFile = context.id.includes(TSS_SERVERFN_SPLIT_PARAM)\n // Get environment-specific configuration\n const envConfig = getEnvConfig(context, isProviderFile)\n\n // Track function names to ensure uniqueness within this file\n const functionNameSet = new Set<string>()\n\n const exportNames = new Set<string>()\n const serverFnsById: Record<string, ServerFn> = {}\n\n const [baseFilename] = context.id.split('?') as [string]\n const extractedFilename = `${baseFilename}?${TSS_SERVERFN_SPLIT_PARAM}`\n const relativeFilename = path.relative(context.root, baseFilename)\n const knownFns = context.getKnownServerFns()\n const cleanedContextId = cleanId(context.id)\n\n for (const candidate of candidates) {\n const { path: candidatePath, methodChain } = candidate\n const { inputValidator, handler } = methodChain\n\n // Check if the call is assigned to a variable\n if (!candidatePath.parentPath.isVariableDeclarator()) {\n throw new Error('createServerFn must be assigned to a variable!')\n }\n\n // Get the identifier name of the variable\n const variableDeclarator = candidatePath.parentPath.node\n if (!t.isIdentifier(variableDeclarator.id)) {\n throw codeFrameError(\n context.code,\n variableDeclarator.id.loc!,\n 'createServerFn must be assigned to a simple identifier, not a destructuring pattern',\n )\n }\n const existingVariableName = variableDeclarator.id.name\n\n // Generate unique function name with _createServerFn_handler suffix\n // The function name is derived from the variable name\n let functionName = `${existingVariableName}_createServerFn_handler`\n while (functionNameSet.has(functionName)) {\n functionName = incrementFunctionNameVersion(functionName)\n }\n functionNameSet.add(functionName)\n\n // Generate function ID using pre-computed relative filename\n const functionId = context.generateFunctionId({\n filename: relativeFilename,\n functionName,\n extractedFilename,\n })\n\n // Check if this function was already discovered by the client build\n const knownFn = knownFns[functionId]\n // A server function is client-referenced when:\n // 1. We're in the client (browser) environment, OR\n // 2. It was already discovered by another environment (knownFn), OR\n // 3. We're in an SSR caller environment — any server function reachable from\n // SSR module graph is callable via client navigation HTTP requests\n const isClientReferenced =\n envConfig.isClientEnvironment ||\n !!knownFn ||\n envConfig.runtimeCodeType === 'ssr'\n\n // Use canonical extracted filename from known functions if available\n const canonicalExtractedFilename =\n knownFn?.extractedFilename ?? extractedFilename\n\n // Handle input validator - remove on client\n if (inputValidator) {\n const innerInputExpression = inputValidator.callPath.node.arguments[0]\n\n if (!innerInputExpression) {\n throw new Error(\n 'createServerFn().inputValidator() must be called with a validator!',\n )\n }\n\n // If we're on the client, remove the validator call expression\n if (context.env === 'client') {\n stripMethodCall(inputValidator.callPath)\n }\n }\n\n const handlerFnPath = handler?.firstArgPath\n\n if (!handler || !handlerFnPath?.node) {\n throw codeFrameError(\n context.code,\n candidatePath.node.callee.loc!,\n `createServerFn must be called with a \"handler\" property!`,\n )\n }\n\n // Validate the handler argument is an expression (not a SpreadElement, etc.)\n if (!t.isExpression(handlerFnPath.node)) {\n throw codeFrameError(\n context.code,\n handlerFnPath.node.loc!,\n `handler() must be called with an expression, not a ${handlerFnPath.node.type}`,\n )\n }\n\n const handlerFn = handlerFnPath.node\n\n // Register function only from caller files (not provider files)\n // to avoid duplicates - provider files process the same functions\n\n if (!isProviderFile) {\n serverFnsById[functionId] = {\n functionName,\n functionId,\n filename: cleanedContextId,\n extractedFilename: canonicalExtractedFilename,\n isClientReferenced,\n }\n }\n\n if (isProviderFile) {\n // PROVIDER FILE: This is the extracted file that contains the actual implementation\n // We need to:\n // 1. Create an extractedFn that calls __executeServer\n // 2. Modify .handler() to pass (extractedFn, serverFn) - two arguments\n //\n // Expected output format:\n // const extractedFn = createServerRpc({id, name, filename}, (opts) => varName.__executeServer(opts));\n // const varName = createServerFn().handler(extractedFn, originalHandler);\n\n // Build the arrow function: (opts) => varName.__executeServer(opts)\n // The signal parameter is passed through to allow abort signal propagation\n const executeServerArrowFn = t.arrowFunctionExpression(\n [t.identifier('opts')],\n t.callExpression(\n t.memberExpression(\n t.identifier(existingVariableName),\n t.identifier('__executeServer'),\n ),\n [t.identifier('opts')],\n ),\n )\n\n // Build the serverFnMeta object\n const serverFnMeta = buildServerFnMetaObject(\n functionId,\n existingVariableName,\n relativeFilename,\n )\n\n // Generate the replacement using pre-compiled template\n const extractedFnInit = generateProviderRpcStub(\n serverFnMeta,\n executeServerArrowFn,\n )\n\n // Build the extracted function statement\n const extractedFnStatement = t.variableDeclaration('const', [\n t.variableDeclarator(t.identifier(functionName), extractedFnInit),\n ])\n\n // Find the variable declaration statement containing our createServerFn\n const variableDeclaration = candidatePath.parentPath.parentPath\n if (!variableDeclaration.isVariableDeclaration()) {\n throw new Error(\n 'Expected createServerFn to be in a VariableDeclaration',\n )\n }\n\n // Insert the extracted function statement before the variable declaration\n variableDeclaration.insertBefore(extractedFnStatement)\n\n // Modify the .handler() call to pass two arguments: (extractedFn, serverFn)\n // The handlerFnPath.node contains the original serverFn\n const extractedFnIdentifier = t.identifier(functionName)\n const serverFnNode = t.cloneNode(handlerFn, true)\n\n // Replace handler's arguments with [extractedFn, serverFn]\n handler.callPath.node.arguments = [extractedFnIdentifier, serverFnNode]\n\n // Only export the extracted handler (e.g., myFn_createServerFn_handler)\n // The manifest and all import paths only look up this suffixed name.\n // The original variable (e.g., myFn) stays in the file but is not exported\n // since it's only used internally.\n exportNames.add(functionName)\n } else {\n // CALLER FILE: This file calls the server function but doesn't contain the implementation\n // We need to:\n // 1. Remove the handler function body (it will be in the provider file)\n // 2. Replace the handler argument with an RPC stub\n //\n // IMPORTANT: We must keep the createServerFn().handler(extractedFn) structure\n // so that the client middleware chain can unwrap the {result, error, context} response.\n //\n // Expected output format:\n // const myFn = createServerFn().handler(createClientRpc(\"id\"))\n // or\n // const myFn = createServerFn().handler(createSsrRpc(\"id\"))\n\n // If the handler function is an identifier, we need to remove the bound function\n // from the file since it won't be needed\n if (t.isIdentifier(handlerFn)) {\n const binding = handlerFnPath.scope.getBinding(handlerFn.name)\n if (binding) {\n binding.path.remove()\n }\n }\n\n // Generate the RPC stub using pre-compiled templates\n // Note: Caller files only pass functionId, not the full serverFnMeta\n const rpcStub = generateCallerRpcStub(functionId, envConfig)\n\n // Replace ONLY the handler argument with the RPC stub\n // Keep the createServerFn().handler() wrapper intact for client middleware\n handlerFnPath.replaceWith(rpcStub)\n }\n }\n\n // For provider files, add exports for all extracted functions\n if (isProviderFile) {\n // Remove all existing exports first\n safeRemoveExports(context.ast)\n\n // Export all server function related variables from exportNames\n // These were populated by handleCreateServerFn:\n // 1. Extracted handlers: const fn_createServerFn_handler = createServerRpc(...)\n // 2. Original variables: const fn = createServerFn().handler(...)\n if (exportNames.size > 0) {\n context.ast.program.body.push(\n t.exportNamedDeclaration(\n undefined,\n Array.from(exportNames).map((name) =>\n t.exportSpecifier(t.identifier(name), t.identifier(name)),\n ),\n ),\n )\n }\n }\n\n // Notify about discovered functions (only for non-provider files)\n if (\n !isProviderFile &&\n Object.keys(serverFnsById).length > 0 &&\n context.onServerFnsById\n ) {\n context.onServerFnsById(serverFnsById)\n }\n\n // Add runtime import using cached AST node\n const runtimeCode = getCachedRuntimeCode(\n context.framework,\n envConfig.runtimeCodeType,\n )\n context.ast.program.body.unshift(t.cloneNode(runtimeCode))\n}\n\n/**\n * Makes an identifier safe for use as a JavaScript identifier.\n */\nfunction makeIdentifierSafe(identifier: string): string {\n return identifier\n .replace(/[^a-zA-Z0-9_$]/g, '_') // Replace unsafe chars with underscore\n .replace(/^[0-9]/, '_$&') // Prefix leading number with underscore\n .replace(/^\\$/, '_$') // Prefix leading $ with underscore\n .replace(/_{2,}/g, '_') // Collapse multiple underscores\n .replace(/^_|_$/g, '') // Trim leading/trailing underscores\n}\n\n/**\n * Increments the version number suffix on a function name.\n */\nfunction incrementFunctionNameVersion(functionName: string): string {\n const [realReferenceName, count] = functionName.split(/_(\\d+)$/)\n const resolvedCount = Number(count || '0')\n const suffix = `_${resolvedCount + 1}`\n return makeIdentifierSafe(realReferenceName!) + suffix\n}\n\n/**\n * Removes all exports from the AST while preserving the declarations.\n * Used for provider files where we want to re-export only the server functions.\n */\nfunction safeRemoveExports(ast: t.File): void {\n ast.program.body = ast.program.body.flatMap((node) => {\n if (\n t.isExportNamedDeclaration(node) ||\n t.isExportDefaultDeclaration(node)\n ) {\n if (\n t.isFunctionDeclaration(node.declaration) ||\n t.isClassDeclaration(node.declaration) ||\n t.isVariableDeclaration(node.declaration)\n ) {\n // do not remove export if it is an anonymous function / class,\n // otherwise this would produce a syntax error\n if (\n t.isFunctionDeclaration(node.declaration) ||\n t.isClassDeclaration(node.declaration)\n ) {\n if (!node.declaration.id) {\n return node\n }\n }\n return node.declaration\n } else if (node.declaration === null) {\n // remove e.g. `export { RouteComponent as component }`\n return []\n }\n }\n return node\n })\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handleEnvOnly.js","names":[],"sources":["../../../src/start-compiler/handleEnvOnly.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport type { CompilationContext, RewriteCandidate } from './types'\nimport type { LookupKind } from './compiler'\n\nfunction capitalize(str: string) {\n if (!str) return ''\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()\n}\n\n/**\n * Handles serverOnly/clientOnly function transformations for a batch of candidates.\n *\n * @param candidates - All EnvOnly candidates to process (all same kind)\n * @param context - The compilation context\n * @param kind - The specific kind (ServerOnlyFn or ClientOnlyFn)\n */\nexport function handleEnvOnlyFn(\n candidates: Array<RewriteCandidate>,\n context: CompilationContext,\n kind: LookupKind,\n): void {\n const targetEnv = kind === 'ClientOnlyFn' ? 'client' : 'server'\n\n for (const candidate of candidates) {\n const { path } = candidate\n\n if (context.env === targetEnv) {\n // Matching environment - extract the inner function\n const innerFn = path.node.arguments[0]\n\n if (!t.isExpression(innerFn)) {\n throw new Error(\n `create${capitalize(targetEnv)}OnlyFn() must be called with a function!`,\n )\n }\n\n path.replaceWith(innerFn)\n } else {\n // Wrong environment - replace with a function that throws an error\n path.replaceWith(\n t.arrowFunctionExpression(\n [],\n t.blockStatement([\n t.throwStatement(\n t.newExpression(t.identifier('Error'), [\n t.stringLiteral(\n `create${capitalize(targetEnv)}OnlyFn() functions can only be called on the ${targetEnv}!`,\n ),\n ]),\n ),\n ]),\n ),\n )\n }\n }\n}\n"],"mappings":";;AAIA,SAAS,WAAW,KAAa;AAC/B,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO,IAAI,OAAO,EAAE,CAAC,aAAa,GAAG,IAAI,MAAM,EAAE,CAAC,aAAa;;;;;;;;;AAUjE,SAAgB,gBACd,YACA,SACA,MACM;CACN,MAAM,YAAY,SAAS,iBAAiB,WAAW;AAEvD,MAAK,MAAM,aAAa,YAAY;EAClC,MAAM,EAAE,SAAS;AAEjB,MAAI,QAAQ,QAAQ,WAAW;GAE7B,MAAM,UAAU,KAAK,KAAK,UAAU;AAEpC,OAAI,CAAC,EAAE,aAAa,QAAQ,CAC1B,OAAM,IAAI,MACR,SAAS,WAAW,UAAU,CAAC,0CAChC;AAGH,QAAK,YAAY,QAAQ;QAGzB,MAAK,YACH,EAAE,wBACA,EAAE,EACF,EAAE,eAAe,CACf,EAAE,eACA,EAAE,cAAc,EAAE,WAAW,QAAQ,EAAE,CACrC,EAAE,cACA,SAAS,WAAW,UAAU,CAAC,+CAA+C,UAAU,GACzF,CACF,CAAC,CACH,CACF,CAAC,CACH,CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { StartCompiler } from './compiler.js';
|
|
2
|
+
import { CompileStartFrameworkOptions } from '../types.js';
|
|
3
|
+
import { DevServerFnModuleSpecifierEncoder, GenerateFunctionIdFnOptional, ServerFn } from './types.js';
|
|
4
|
+
export interface CreateStartCompilerOptions {
|
|
5
|
+
env: 'client' | 'server';
|
|
6
|
+
envName: string;
|
|
7
|
+
root: string;
|
|
8
|
+
framework: CompileStartFrameworkOptions;
|
|
9
|
+
providerEnvName: string;
|
|
10
|
+
mode: 'dev' | 'build';
|
|
11
|
+
generateFunctionId?: GenerateFunctionIdFnOptional;
|
|
12
|
+
onServerFnsById?: (d: Record<string, ServerFn>) => void;
|
|
13
|
+
getKnownServerFns?: () => Record<string, ServerFn>;
|
|
14
|
+
encodeModuleSpecifierInDev?: DevServerFnModuleSpecifierEncoder;
|
|
15
|
+
loadModule: (id: string) => Promise<void>;
|
|
16
|
+
resolveId: (id: string, importer?: string) => Promise<string | null>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createStartCompiler(options: CreateStartCompilerOptions): StartCompiler;
|
|
19
|
+
export declare function mergeServerFnsById(current: Record<string, ServerFn>, next: Record<string, ServerFn>): void;
|
|
20
|
+
export declare function matchesCodeFilters(code: string, filters: ReadonlyArray<RegExp>): boolean;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { LookupKindsPerEnv, StartCompiler } from "./compiler.js";
|
|
2
|
+
import { getLookupConfigurationsForEnv } from "./config.js";
|
|
3
|
+
//#region src/start-compiler/host.ts
|
|
4
|
+
function createStartCompiler(options) {
|
|
5
|
+
return new StartCompiler({
|
|
6
|
+
env: options.env,
|
|
7
|
+
envName: options.envName,
|
|
8
|
+
root: options.root,
|
|
9
|
+
lookupKinds: LookupKindsPerEnv[options.env],
|
|
10
|
+
lookupConfigurations: getLookupConfigurationsForEnv(options.env, options.framework),
|
|
11
|
+
mode: options.mode,
|
|
12
|
+
framework: options.framework,
|
|
13
|
+
providerEnvName: options.providerEnvName,
|
|
14
|
+
generateFunctionId: options.generateFunctionId,
|
|
15
|
+
onServerFnsById: options.onServerFnsById,
|
|
16
|
+
getKnownServerFns: options.getKnownServerFns,
|
|
17
|
+
devServerFnModuleSpecifierEncoder: options.encodeModuleSpecifierInDev,
|
|
18
|
+
loadModule: options.loadModule,
|
|
19
|
+
resolveId: options.resolveId
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function mergeServerFnsById(current, next) {
|
|
23
|
+
for (const [id, fn] of Object.entries(next)) {
|
|
24
|
+
const existing = current[id];
|
|
25
|
+
if (existing) {
|
|
26
|
+
current[id] = {
|
|
27
|
+
...fn,
|
|
28
|
+
isClientReferenced: existing.isClientReferenced || fn.isClientReferenced
|
|
29
|
+
};
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
current[id] = fn;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { createStartCompiler, mergeServerFnsById };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","names":[],"sources":["../../../src/start-compiler/host.ts"],"sourcesContent":["import { LookupKindsPerEnv, StartCompiler } from './compiler'\nimport { getLookupConfigurationsForEnv } from './config'\nimport type { CompileStartFrameworkOptions } from '../types'\nimport type {\n DevServerFnModuleSpecifierEncoder,\n GenerateFunctionIdFnOptional,\n ServerFn,\n} from './types'\n\nexport interface CreateStartCompilerOptions {\n env: 'client' | 'server'\n envName: string\n root: string\n framework: CompileStartFrameworkOptions\n providerEnvName: string\n mode: 'dev' | 'build'\n generateFunctionId?: GenerateFunctionIdFnOptional\n onServerFnsById?: (d: Record<string, ServerFn>) => void\n getKnownServerFns?: () => Record<string, ServerFn>\n encodeModuleSpecifierInDev?: DevServerFnModuleSpecifierEncoder\n loadModule: (id: string) => Promise<void>\n resolveId: (id: string, importer?: string) => Promise<string | null>\n}\n\nexport function createStartCompiler(\n options: CreateStartCompilerOptions,\n): StartCompiler {\n return new StartCompiler({\n env: options.env,\n envName: options.envName,\n root: options.root,\n lookupKinds: LookupKindsPerEnv[options.env],\n lookupConfigurations: getLookupConfigurationsForEnv(\n options.env,\n options.framework,\n ),\n mode: options.mode,\n framework: options.framework,\n providerEnvName: options.providerEnvName,\n generateFunctionId: options.generateFunctionId,\n onServerFnsById: options.onServerFnsById,\n getKnownServerFns: options.getKnownServerFns,\n devServerFnModuleSpecifierEncoder: options.encodeModuleSpecifierInDev,\n loadModule: options.loadModule,\n resolveId: options.resolveId,\n })\n}\n\nexport function mergeServerFnsById(\n current: Record<string, ServerFn>,\n next: Record<string, ServerFn>,\n): void {\n for (const [id, fn] of Object.entries(next)) {\n const existing = current[id]\n\n if (existing) {\n current[id] = {\n ...fn,\n isClientReferenced:\n existing.isClientReferenced || fn.isClientReferenced,\n }\n continue\n }\n\n current[id] = fn\n }\n}\n\nexport function matchesCodeFilters(\n code: string,\n filters: ReadonlyArray<RegExp>,\n): boolean {\n for (const pattern of filters) {\n if (pattern.test(code)) {\n return true\n }\n }\n\n return false\n}\n"],"mappings":";;;AAwBA,SAAgB,oBACd,SACe;AACf,QAAO,IAAI,cAAc;EACvB,KAAK,QAAQ;EACb,SAAS,QAAQ;EACjB,MAAM,QAAQ;EACd,aAAa,kBAAkB,QAAQ;EACvC,sBAAsB,8BACpB,QAAQ,KACR,QAAQ,UACT;EACD,MAAM,QAAQ;EACd,WAAW,QAAQ;EACnB,iBAAiB,QAAQ;EACzB,oBAAoB,QAAQ;EAC5B,iBAAiB,QAAQ;EACzB,mBAAmB,QAAQ;EAC3B,mCAAmC,QAAQ;EAC3C,YAAY,QAAQ;EACpB,WAAW,QAAQ;EACpB,CAAC;;AAGJ,SAAgB,mBACd,SACA,MACM;AACN,MAAK,MAAM,CAAC,IAAI,OAAO,OAAO,QAAQ,KAAK,EAAE;EAC3C,MAAM,WAAW,QAAQ;AAEzB,MAAI,UAAU;AACZ,WAAQ,MAAM;IACZ,GAAG;IACH,oBACE,SAAS,sBAAsB,GAAG;IACrC;AACD;;AAGF,UAAQ,MAAM"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StartCompiler } from './compiler.js';
|
|
2
|
+
interface ViteCompilerModuleLoaderOptions {
|
|
3
|
+
compiler: StartCompiler;
|
|
4
|
+
mode: string;
|
|
5
|
+
fetchModule?: (id: string) => Promise<unknown>;
|
|
6
|
+
loadModule: (opts: {
|
|
7
|
+
id: string;
|
|
8
|
+
}) => Promise<{
|
|
9
|
+
code?: string | null;
|
|
10
|
+
}>;
|
|
11
|
+
id: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function loadModuleForViteCompiler(opts: ViteCompilerModuleLoaderOptions): Promise<void>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SERVER_FN_LOOKUP } from "../constants.js";
|
|
2
|
+
//#region src/start-compiler/load-module.ts
|
|
3
|
+
async function loadModuleForViteCompiler(opts) {
|
|
4
|
+
if (opts.mode === "build") {
|
|
5
|
+
const code = (await opts.loadModule({ id: opts.id })).code ?? "";
|
|
6
|
+
opts.compiler.ingestModule({
|
|
7
|
+
code,
|
|
8
|
+
id: opts.id
|
|
9
|
+
});
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (opts.mode !== "dev" || !opts.fetchModule) throw new Error(`could not load module ${opts.id}: unknown environment mode ${opts.mode}`);
|
|
13
|
+
await opts.fetchModule(`${opts.id}?${SERVER_FN_LOOKUP}`);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { loadModuleForViteCompiler };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=load-module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-module.js","names":[],"sources":["../../../src/start-compiler/load-module.ts"],"sourcesContent":["import { SERVER_FN_LOOKUP } from '../constants'\nimport type { StartCompiler } from './compiler'\n\ninterface ViteCompilerModuleLoaderOptions {\n compiler: StartCompiler\n mode: string\n fetchModule?: (id: string) => Promise<unknown>\n loadModule: (opts: { id: string }) => Promise<{ code?: string | null }>\n id: string\n}\n\nexport async function loadModuleForViteCompiler(\n opts: ViteCompilerModuleLoaderOptions,\n): Promise<void> {\n if (opts.mode === 'build') {\n const loaded = await opts.loadModule({ id: opts.id })\n const code = loaded.code ?? ''\n\n opts.compiler.ingestModule({ code, id: opts.id })\n\n return\n }\n\n if (opts.mode !== 'dev' || !opts.fetchModule) {\n throw new Error(\n `could not load module ${opts.id}: unknown environment mode ${opts.mode}`,\n )\n }\n\n await opts.fetchModule(`${opts.id}?${SERVER_FN_LOOKUP}`)\n}\n"],"mappings":";;AAWA,eAAsB,0BACpB,MACe;AACf,KAAI,KAAK,SAAS,SAAS;EAEzB,MAAM,QADS,MAAM,KAAK,WAAW,EAAE,IAAI,KAAK,IAAI,CAAC,EACjC,QAAQ;AAE5B,OAAK,SAAS,aAAa;GAAE;GAAM,IAAI,KAAK;GAAI,CAAC;AAEjD;;AAGF,KAAI,KAAK,SAAS,SAAS,CAAC,KAAK,YAC/B,OAAM,IAAI,MACR,yBAAyB,KAAK,GAAG,6BAA6B,KAAK,OACpE;AAGH,OAAM,KAAK,YAAY,GAAG,KAAK,GAAG,GAAG,mBAAmB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ServerFn } from './types.js';
|
|
2
|
+
interface GenerateServerFnResolverModuleOptions {
|
|
3
|
+
serverFnsById: Record<string, ServerFn>;
|
|
4
|
+
includeClientReferencedCheck: boolean;
|
|
5
|
+
useStaticImports?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function generateServerFnResolverModule(opts: GenerateServerFnResolverModuleOptions): string;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
//#region src/start-compiler/server-fn-resolver-module.ts
|
|
2
|
+
function getResolverManifestEntries(serverFnsById) {
|
|
3
|
+
return Object.entries(serverFnsById).map(([id, fn]) => ({
|
|
4
|
+
id,
|
|
5
|
+
functionName: fn.functionName,
|
|
6
|
+
extractedFilename: fn.extractedFilename,
|
|
7
|
+
isClientReferenced: fn.isClientReferenced ?? true
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
10
|
+
function getClientReferencedCheck(includeClientReferencedCheck) {
|
|
11
|
+
if (!includeClientReferencedCheck) return "";
|
|
12
|
+
return `
|
|
13
|
+
if (access.origin === 'client' && !serverFnInfo.isClientReferenced) {
|
|
14
|
+
throw new Error('Server function not accessible from client: ' + id)
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
}
|
|
18
|
+
function getResolverBody() {
|
|
19
|
+
return `
|
|
20
|
+
export async function getServerFnById(id, access) {
|
|
21
|
+
const serverFnInfo = manifest[id]
|
|
22
|
+
if (!serverFnInfo) {
|
|
23
|
+
throw new Error('Server function info not found for ' + id)
|
|
24
|
+
}
|
|
25
|
+
__CLIENT_REFERENCED_CHECK__
|
|
26
|
+
const fnModule = serverFnInfo.module ?? (await serverFnInfo.importer())
|
|
27
|
+
if (!fnModule) {
|
|
28
|
+
throw new Error('Server function module not resolved for ' + id)
|
|
29
|
+
}
|
|
30
|
+
const action = fnModule[serverFnInfo.functionName]
|
|
31
|
+
if (!action) {
|
|
32
|
+
throw new Error('Server function module export not resolved for serverFn ID: ' + id)
|
|
33
|
+
}
|
|
34
|
+
return action
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
function getResolverManifestModuleAccess(opts) {
|
|
39
|
+
if (opts.useStaticImports) return `module: ${opts.moduleRef}`;
|
|
40
|
+
return `importer: () => import(${JSON.stringify(opts.extractedFilename)})`;
|
|
41
|
+
}
|
|
42
|
+
function getResolverManifestEntry(opts) {
|
|
43
|
+
const clientReferenced = opts.includeClientReferencedCheck ? `,\n isClientReferenced: ${opts.entry.isClientReferenced}` : "";
|
|
44
|
+
return `'${opts.entry.id}': {
|
|
45
|
+
functionName: '${opts.entry.functionName}',
|
|
46
|
+
${opts.moduleAccess}${clientReferenced}
|
|
47
|
+
}`;
|
|
48
|
+
}
|
|
49
|
+
function generateServerFnResolverModule(opts) {
|
|
50
|
+
const manifestEntries = getResolverManifestEntries(opts.serverFnsById);
|
|
51
|
+
const staticImports = [];
|
|
52
|
+
const manifest = manifestEntries.map((entry, index) => {
|
|
53
|
+
const moduleRef = `serverFnModule${index}`;
|
|
54
|
+
if (opts.useStaticImports) staticImports.push(`import * as ${moduleRef} from ${JSON.stringify(entry.extractedFilename)}`);
|
|
55
|
+
return getResolverManifestEntry({
|
|
56
|
+
entry,
|
|
57
|
+
moduleAccess: getResolverManifestModuleAccess({
|
|
58
|
+
useStaticImports: opts.useStaticImports,
|
|
59
|
+
extractedFilename: entry.extractedFilename,
|
|
60
|
+
moduleRef
|
|
61
|
+
}),
|
|
62
|
+
includeClientReferencedCheck: opts.includeClientReferencedCheck
|
|
63
|
+
});
|
|
64
|
+
}).join(",\n ");
|
|
65
|
+
const body = getResolverBody().replace("__CLIENT_REFERENCED_CHECK__", getClientReferencedCheck(opts.includeClientReferencedCheck));
|
|
66
|
+
return `
|
|
67
|
+
${staticImports.join("\n")}
|
|
68
|
+
const manifest = {
|
|
69
|
+
${manifest}
|
|
70
|
+
}
|
|
71
|
+
${body}
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { generateServerFnResolverModule };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=server-fn-resolver-module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-fn-resolver-module.js","names":[],"sources":["../../../src/start-compiler/server-fn-resolver-module.ts"],"sourcesContent":["import type { ServerFn } from './types'\n\ninterface ResolverManifestEntry {\n id: string\n functionName: string\n extractedFilename: string\n isClientReferenced: boolean\n}\n\ninterface GenerateServerFnResolverModuleOptions {\n serverFnsById: Record<string, ServerFn>\n includeClientReferencedCheck: boolean\n useStaticImports?: boolean\n}\n\nfunction getResolverManifestEntries(\n serverFnsById: Record<string, ServerFn>,\n): Array<ResolverManifestEntry> {\n return Object.entries(serverFnsById).map(([id, fn]) => ({\n id,\n functionName: fn.functionName,\n extractedFilename: fn.extractedFilename,\n isClientReferenced: fn.isClientReferenced ?? true,\n }))\n}\n\nfunction getClientReferencedCheck(\n includeClientReferencedCheck: boolean,\n): string {\n if (!includeClientReferencedCheck) {\n return ''\n }\n\n return `\n if (access.origin === 'client' && !serverFnInfo.isClientReferenced) {\n throw new Error('Server function not accessible from client: ' + id)\n }\n`\n}\n\nfunction getResolverBody(): string {\n return `\nexport async function getServerFnById(id, access) {\n const serverFnInfo = manifest[id]\n if (!serverFnInfo) {\n throw new Error('Server function info not found for ' + id)\n }\n__CLIENT_REFERENCED_CHECK__\n const fnModule = serverFnInfo.module ?? (await serverFnInfo.importer())\n if (!fnModule) {\n throw new Error('Server function module not resolved for ' + id)\n }\n const action = fnModule[serverFnInfo.functionName]\n if (!action) {\n throw new Error('Server function module export not resolved for serverFn ID: ' + id)\n }\n return action\n}\n`\n}\n\nfunction getResolverManifestModuleAccess(opts: {\n useStaticImports?: boolean\n extractedFilename: string\n moduleRef: string\n}): string {\n if (opts.useStaticImports) {\n return `module: ${opts.moduleRef}`\n }\n\n return `importer: () => import(${JSON.stringify(opts.extractedFilename)})`\n}\n\nfunction getResolverManifestEntry(opts: {\n entry: ResolverManifestEntry\n moduleAccess: string\n includeClientReferencedCheck: boolean\n}): string {\n const clientReferenced = opts.includeClientReferencedCheck\n ? `,\\n isClientReferenced: ${opts.entry.isClientReferenced}`\n : ''\n\n return `'${opts.entry.id}': {\n functionName: '${opts.entry.functionName}',\n ${opts.moduleAccess}${clientReferenced}\n }`\n}\n\nexport function generateServerFnResolverModule(\n opts: GenerateServerFnResolverModuleOptions,\n): string {\n const manifestEntries = getResolverManifestEntries(opts.serverFnsById)\n const staticImports: Array<string> = []\n\n const manifest = manifestEntries\n .map((entry, index) => {\n const moduleRef = `serverFnModule${index}`\n\n if (opts.useStaticImports) {\n staticImports.push(\n `import * as ${moduleRef} from ${JSON.stringify(entry.extractedFilename)}`,\n )\n }\n\n return getResolverManifestEntry({\n entry,\n moduleAccess: getResolverManifestModuleAccess({\n useStaticImports: opts.useStaticImports,\n extractedFilename: entry.extractedFilename,\n moduleRef,\n }),\n includeClientReferencedCheck: opts.includeClientReferencedCheck,\n })\n })\n .join(',\\n ')\n\n const body = getResolverBody().replace(\n '__CLIENT_REFERENCED_CHECK__',\n getClientReferencedCheck(opts.includeClientReferencedCheck),\n )\n\n return `\n${staticImports.join('\\n')}\nconst manifest = {\n ${manifest}\n}\n${body}\n`\n}\n"],"mappings":";AAeA,SAAS,2BACP,eAC8B;AAC9B,QAAO,OAAO,QAAQ,cAAc,CAAC,KAAK,CAAC,IAAI,SAAS;EACtD;EACA,cAAc,GAAG;EACjB,mBAAmB,GAAG;EACtB,oBAAoB,GAAG,sBAAsB;EAC9C,EAAE;;AAGL,SAAS,yBACP,8BACQ;AACR,KAAI,CAAC,6BACH,QAAO;AAGT,QAAO;;;;;;AAOT,SAAS,kBAA0B;AACjC,QAAO;;;;;;;;;;;;;;;;;;;AAoBT,SAAS,gCAAgC,MAI9B;AACT,KAAI,KAAK,iBACP,QAAO,WAAW,KAAK;AAGzB,QAAO,0BAA0B,KAAK,UAAU,KAAK,kBAAkB,CAAC;;AAG1E,SAAS,yBAAyB,MAIvB;CACT,MAAM,mBAAmB,KAAK,+BAC1B,8BAA8B,KAAK,MAAM,uBACzC;AAEJ,QAAO,IAAI,KAAK,MAAM,GAAG;qBACN,KAAK,MAAM,aAAa;MACvC,KAAK,eAAe,iBAAiB;;;AAI3C,SAAgB,+BACd,MACQ;CACR,MAAM,kBAAkB,2BAA2B,KAAK,cAAc;CACtE,MAAM,gBAA+B,EAAE;CAEvC,MAAM,WAAW,gBACd,KAAK,OAAO,UAAU;EACrB,MAAM,YAAY,iBAAiB;AAEnC,MAAI,KAAK,iBACP,eAAc,KACZ,eAAe,UAAU,QAAQ,KAAK,UAAU,MAAM,kBAAkB,GACzE;AAGH,SAAO,yBAAyB;GAC9B;GACA,cAAc,gCAAgC;IAC5C,kBAAkB,KAAK;IACvB,mBAAmB,MAAM;IACzB;IACD,CAAC;GACF,8BAA8B,KAAK;GACpC,CAAC;GACF,CACD,KAAK,QAAQ;CAEhB,MAAM,OAAO,iBAAiB,CAAC,QAC7B,+BACA,yBAAyB,KAAK,6BAA6B,CAC5D;AAED,QAAO;EACP,cAAc,KAAK,KAAK,CAAC;;IAEvB,SAAS;;EAEX,KAAK"}
|
|
@@ -95,6 +95,10 @@ export type GenerateFunctionIdFnOptional = (opts: Omit<Parameters<GenerateFuncti
|
|
|
95
95
|
* Function type for generating replacement code for server functions.
|
|
96
96
|
* Used internally by handleCreateServerFn.
|
|
97
97
|
*/
|
|
98
|
+
export type DevServerFnModuleSpecifierEncoder = (opts: {
|
|
99
|
+
extractedFilename: string;
|
|
100
|
+
root: string;
|
|
101
|
+
}) => string;
|
|
98
102
|
export type ReplacerFn = (opts: {
|
|
99
103
|
/** Placeholder for the original function expression */
|
|
100
104
|
fn: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
2
|
import { codeFrameColumns } from "@babel/code-frame";
|
|
3
|
-
//#region src/start-compiler
|
|
3
|
+
//#region src/start-compiler/utils.ts
|
|
4
4
|
function codeFrameError(code, loc, message) {
|
|
5
5
|
const frame = codeFrameColumns(code, {
|
|
6
6
|
start: loc.start,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../src/start-compiler/utils.ts"],"sourcesContent":["import { codeFrameColumns } from '@babel/code-frame'\nimport * as t from '@babel/types'\nimport type babel from '@babel/core'\n\nexport function codeFrameError(\n code: string,\n loc: {\n start: { line: number; column: number }\n end: { line: number; column: number }\n },\n message: string,\n) {\n const frame = codeFrameColumns(\n code,\n {\n start: loc.start,\n end: loc.end,\n },\n {\n highlightCode: true,\n message,\n },\n )\n\n return new Error(frame)\n}\n\nexport function cleanId(id: string): string {\n // Remove null byte prefix used by Vite/Rollup for virtual modules\n if (id.startsWith('\\0')) {\n id = id.slice(1)\n }\n const queryIndex = id.indexOf('?')\n return queryIndex === -1 ? id : id.substring(0, queryIndex)\n}\n\n/**\n * Strips a method call by replacing it with its callee object.\n * E.g., `foo().bar()` -> `foo()`\n *\n * This is a common pattern used when removing method calls from chains\n * (e.g., removing .server() from middleware on client, or .inputValidator() on client).\n *\n * @param callPath - The path to the CallExpression to strip\n */\nexport function stripMethodCall(\n callPath: babel.NodePath<t.CallExpression>,\n): void {\n if (t.isMemberExpression(callPath.node.callee)) {\n callPath.replaceWith(callPath.node.callee.object)\n }\n}\n"],"mappings":";;;AAIA,SAAgB,eACd,MACA,KAIA,SACA;CACA,MAAM,QAAQ,iBACZ,MACA;EACE,OAAO,IAAI;EACX,KAAK,IAAI;EACV,EACD;EACE,eAAe;EACf;EACD,CACF;AAED,QAAO,IAAI,MAAM,MAAM;;AAGzB,SAAgB,QAAQ,IAAoB;AAE1C,KAAI,GAAG,WAAW,KAAK,CACrB,MAAK,GAAG,MAAM,EAAE;CAElB,MAAM,aAAa,GAAG,QAAQ,IAAI;AAClC,QAAO,eAAe,KAAK,KAAK,GAAG,UAAU,GAAG,WAAW;;;;;;;;;;;AAY7D,SAAgB,gBACd,UACM;AACN,KAAI,EAAE,mBAAmB,SAAS,KAAK,OAAO,CAC5C,UAAS,YAAY,SAAS,KAAK,OAAO,OAAO"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { getRouteFilePathsFromModuleIds, normalizeViteClientBuild, normalizeViteClientChunk } from '../vite/start-manifest-plugin/normalized-client-build.js';
|
|
1
2
|
import { RouterManagedTag } from '@tanstack/router-core';
|
|
2
|
-
import {
|
|
3
|
+
import { NormalizedClientBuild, NormalizedClientChunk } from '../types.js';
|
|
3
4
|
type RouteTreeRoute = {
|
|
4
5
|
filePath?: string;
|
|
5
6
|
preloads?: Array<string>;
|
|
@@ -8,44 +9,43 @@ type RouteTreeRoute = {
|
|
|
8
9
|
};
|
|
9
10
|
type RouteTreeRoutes = Record<string, RouteTreeRoute>;
|
|
10
11
|
interface ScannedClientChunks {
|
|
11
|
-
entryChunk:
|
|
12
|
-
chunksByFileName:
|
|
13
|
-
routeChunksByFilePath:
|
|
14
|
-
routeEntryChunks:
|
|
12
|
+
entryChunk: NormalizedClientChunk;
|
|
13
|
+
chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>;
|
|
14
|
+
routeChunksByFilePath: ReadonlyMap<string, Array<NormalizedClientChunk>>;
|
|
15
|
+
routeEntryChunks: ReadonlySet<NormalizedClientChunk>;
|
|
15
16
|
}
|
|
16
17
|
interface ManifestAssetResolvers {
|
|
17
18
|
getAssetPath: (fileName: string) => string;
|
|
18
|
-
getChunkPreloads: (chunk:
|
|
19
|
+
getChunkPreloads: (chunk: NormalizedClientChunk) => Array<string>;
|
|
19
20
|
getStylesheetAsset: (cssFile: string) => RouterManagedTag;
|
|
20
21
|
}
|
|
21
22
|
export declare function appendUniqueStrings(target: Array<string> | undefined, source: Array<string>): string[] | undefined;
|
|
22
23
|
export declare function appendUniqueAssets(target: Array<RouterManagedTag> | undefined, source: Array<RouterManagedTag>): RouterManagedTag[] | undefined;
|
|
23
24
|
export declare function buildStartManifest(options: {
|
|
24
|
-
|
|
25
|
+
clientBuild: NormalizedClientBuild;
|
|
25
26
|
routeTreeRoutes: RouteTreeRoutes;
|
|
26
27
|
basePath: string;
|
|
27
28
|
}): {
|
|
28
29
|
routes: Record<string, RouteTreeRoute>;
|
|
29
30
|
clientEntry: string;
|
|
30
31
|
};
|
|
31
|
-
export declare function scanClientChunks(
|
|
32
|
-
export declare function
|
|
33
|
-
export declare function collectDynamicImportCss(routeEntryChunks: Set<Rollup.OutputChunk>, chunksByFileName: Map<string, Rollup.OutputChunk>, entryChunk?: Rollup.OutputChunk): Set<string>;
|
|
32
|
+
export declare function scanClientChunks(clientBuild: NormalizedClientBuild): ScannedClientChunks;
|
|
33
|
+
export declare function collectDynamicImportCss(routeEntryChunks: ReadonlySet<NormalizedClientChunk>, chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>, entryChunk?: NormalizedClientChunk): Set<string>;
|
|
34
34
|
export declare function createManifestAssetResolvers(options: {
|
|
35
35
|
basePath: string;
|
|
36
36
|
hashedCssFiles?: Set<string>;
|
|
37
37
|
}): ManifestAssetResolvers;
|
|
38
38
|
export declare function createChunkCssAssetCollector(options: {
|
|
39
|
-
chunksByFileName:
|
|
39
|
+
chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>;
|
|
40
40
|
getStylesheetAsset: (cssFile: string) => RouterManagedTag;
|
|
41
41
|
}): {
|
|
42
|
-
getChunkCssAssets: (chunk:
|
|
42
|
+
getChunkCssAssets: (chunk: NormalizedClientChunk) => Array<RouterManagedTag>;
|
|
43
43
|
};
|
|
44
44
|
export declare function buildRouteManifestRoutes(options: {
|
|
45
45
|
routeTreeRoutes: RouteTreeRoutes;
|
|
46
|
-
routeChunksByFilePath:
|
|
47
|
-
chunksByFileName:
|
|
48
|
-
entryChunk:
|
|
46
|
+
routeChunksByFilePath: ReadonlyMap<string, ReadonlyArray<NormalizedClientChunk>>;
|
|
47
|
+
chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>;
|
|
48
|
+
entryChunk: NormalizedClientChunk;
|
|
49
49
|
assetResolvers: ManifestAssetResolvers;
|
|
50
50
|
}): Record<string, RouteTreeRoute>;
|
|
51
|
-
export {};
|
|
51
|
+
export { getRouteFilePathsFromModuleIds, normalizeViteClientBuild, normalizeViteClientChunk, };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import "../vite/start-manifest-plugin/normalized-client-build.js";
|
|
1
2
|
import { resolveManifestAssetLink, rootRouteId } from "@tanstack/router-core";
|
|
2
3
|
import { joinURL } from "ufo";
|
|
3
|
-
import { tsrSplit } from "@tanstack/router-plugin";
|
|
4
4
|
//#region src/start-manifest-plugin/manifestBuilder.ts
|
|
5
5
|
var ROUTER_MANAGED_MODE = 1;
|
|
6
6
|
var NON_ROUTE_DYNAMIC_MODE = 2;
|
|
@@ -53,7 +53,7 @@ function mergeRouteChunkData(options) {
|
|
|
53
53
|
options.route.preloads = appendUniqueStrings(options.route.preloads, chunkPreloads);
|
|
54
54
|
}
|
|
55
55
|
function buildStartManifest(options) {
|
|
56
|
-
const scannedChunks = scanClientChunks(options.
|
|
56
|
+
const scannedChunks = scanClientChunks(options.clientBuild);
|
|
57
57
|
const hashedCssFiles = collectDynamicImportCss(scannedChunks.routeEntryChunks, scannedChunks.chunksByFileName, scannedChunks.entryChunk);
|
|
58
58
|
const assetResolvers = createManifestAssetResolvers({
|
|
59
59
|
basePath: options.basePath,
|
|
@@ -78,60 +78,29 @@ function buildStartManifest(options) {
|
|
|
78
78
|
clientEntry: assetResolvers.getAssetPath(scannedChunks.entryChunk.fileName)
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
|
-
function scanClientChunks(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const routeChunksByFilePath = /* @__PURE__ */ new Map();
|
|
81
|
+
function scanClientChunks(clientBuild) {
|
|
82
|
+
const entryChunk = clientBuild.chunksByFileName.get(clientBuild.entryChunkFileName);
|
|
83
|
+
if (!entryChunk) throw new Error(`Missing entry chunk: ${clientBuild.entryChunkFileName}`);
|
|
85
84
|
const routeEntryChunks = /* @__PURE__ */ new Set();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (bundleEntry.isEntry) {
|
|
91
|
-
if (entryChunk) throw new Error(`multiple entries detected: ${entryChunk.fileName} ${bundleEntry.fileName}`);
|
|
92
|
-
entryChunk = bundleEntry;
|
|
93
|
-
}
|
|
94
|
-
const routeFilePaths = getRouteFilePathsFromModuleIds(bundleEntry.moduleIds);
|
|
95
|
-
if (routeFilePaths.length === 0) continue;
|
|
96
|
-
routeEntryChunks.add(bundleEntry);
|
|
97
|
-
for (let i = 0; i < routeFilePaths.length; i++) {
|
|
98
|
-
const routeFilePath = routeFilePaths[i];
|
|
85
|
+
const routeChunksByFilePath = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const chunk of clientBuild.chunksByFileName.values()) if (chunk.routeFilePaths.length > 0) {
|
|
87
|
+
routeEntryChunks.add(chunk);
|
|
88
|
+
for (const routeFilePath of chunk.routeFilePaths) {
|
|
99
89
|
let chunks = routeChunksByFilePath.get(routeFilePath);
|
|
100
90
|
if (chunks === void 0) {
|
|
101
91
|
chunks = [];
|
|
102
92
|
routeChunksByFilePath.set(routeFilePath, chunks);
|
|
103
93
|
}
|
|
104
|
-
chunks.push(
|
|
94
|
+
chunks.push(chunk);
|
|
105
95
|
}
|
|
106
96
|
}
|
|
107
|
-
if (!entryChunk) throw new Error("No entry file found");
|
|
108
97
|
return {
|
|
109
98
|
entryChunk,
|
|
110
|
-
chunksByFileName,
|
|
99
|
+
chunksByFileName: clientBuild.chunksByFileName,
|
|
111
100
|
routeChunksByFilePath,
|
|
112
101
|
routeEntryChunks
|
|
113
102
|
};
|
|
114
103
|
}
|
|
115
|
-
function getRouteFilePathsFromModuleIds(moduleIds) {
|
|
116
|
-
let routeFilePaths;
|
|
117
|
-
let seenRouteFilePaths;
|
|
118
|
-
for (const moduleId of moduleIds) {
|
|
119
|
-
const queryIndex = moduleId.indexOf("?");
|
|
120
|
-
if (queryIndex < 0) continue;
|
|
121
|
-
const query = moduleId.slice(queryIndex + 1);
|
|
122
|
-
if (!query.includes(tsrSplit)) continue;
|
|
123
|
-
if (!new URLSearchParams(query).has(tsrSplit)) continue;
|
|
124
|
-
const routeFilePath = moduleId.slice(0, queryIndex);
|
|
125
|
-
if (seenRouteFilePaths?.has(routeFilePath)) continue;
|
|
126
|
-
if (routeFilePaths === void 0) {
|
|
127
|
-
routeFilePaths = [];
|
|
128
|
-
seenRouteFilePaths = /* @__PURE__ */ new Set();
|
|
129
|
-
}
|
|
130
|
-
routeFilePaths.push(routeFilePath);
|
|
131
|
-
seenRouteFilePaths.add(routeFilePath);
|
|
132
|
-
}
|
|
133
|
-
return routeFilePaths ?? [];
|
|
134
|
-
}
|
|
135
104
|
function collectDynamicImportCss(routeEntryChunks, chunksByFileName, entryChunk) {
|
|
136
105
|
const routerManagedCssFiles = /* @__PURE__ */ new Set();
|
|
137
106
|
const nonRouteDynamicCssFiles = /* @__PURE__ */ new Set();
|
|
@@ -153,8 +122,8 @@ function collectDynamicImportCss(routeEntryChunks, chunksByFileName, entryChunk)
|
|
|
153
122
|
const previousMode = visitedByChunk.get(chunk) ?? 0;
|
|
154
123
|
if ((previousMode & mode) === mode) continue;
|
|
155
124
|
visitedByChunk.set(chunk, previousMode | mode);
|
|
156
|
-
if ((mode & ROUTER_MANAGED_MODE) !== 0) for (const cssFile of chunk.
|
|
157
|
-
if ((mode & NON_ROUTE_DYNAMIC_MODE) !== 0) for (const cssFile of chunk.
|
|
125
|
+
if ((mode & ROUTER_MANAGED_MODE) !== 0) for (const cssFile of chunk.css) routerManagedCssFiles.add(cssFile);
|
|
126
|
+
if ((mode & NON_ROUTE_DYNAMIC_MODE) !== 0) for (const cssFile of chunk.css) nonRouteDynamicCssFiles.add(cssFile);
|
|
158
127
|
for (let i = 0; i < chunk.imports.length; i++) {
|
|
159
128
|
const importedChunk = chunksByFileName.get(chunk.imports[i]);
|
|
160
129
|
if (importedChunk) {
|
|
@@ -229,7 +198,7 @@ function createChunkCssAssetCollector(options) {
|
|
|
229
198
|
stateByChunk.set(chunk, VISITING_CHUNK);
|
|
230
199
|
const assets = [];
|
|
231
200
|
const seenAssets = /* @__PURE__ */ new Set();
|
|
232
|
-
for (const cssFile of chunk.
|
|
201
|
+
for (const cssFile of chunk.css) appendAsset(assets, seenAssets, options.getStylesheetAsset(cssFile));
|
|
233
202
|
for (let i = 0; i < chunk.imports.length; i++) {
|
|
234
203
|
const importedChunk = options.chunksByFileName.get(chunk.imports[i]);
|
|
235
204
|
if (!importedChunk) continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifestBuilder.js","names":[],"sources":["../../../src/start-manifest-plugin/manifestBuilder.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/prefer-for-of */\nimport { joinURL } from 'ufo'\nimport { resolveManifestAssetLink, rootRouteId } from '@tanstack/router-core'\nimport { tsrSplit } from '@tanstack/router-plugin'\nimport type { ManifestAssetLink, RouterManagedTag } from '@tanstack/router-core'\nimport type { Rollup } from 'vite'\n\nconst ROUTER_MANAGED_MODE = 1\nconst NON_ROUTE_DYNAMIC_MODE = 2\nconst VISITING_CHUNK = 1\n\ntype RouteTreeRoute = {\n filePath?: string\n preloads?: Array<string>\n assets?: Array<RouterManagedTag>\n children?: Array<string>\n}\n\ntype RouteTreeRoutes = Record<string, RouteTreeRoute>\n\ninterface ScannedClientChunks {\n entryChunk: Rollup.OutputChunk\n chunksByFileName: Map<string, Rollup.OutputChunk>\n routeChunksByFilePath: Map<string, Array<Rollup.OutputChunk>>\n routeEntryChunks: Set<Rollup.OutputChunk>\n}\n\ninterface ManifestAssetResolvers {\n getAssetPath: (fileName: string) => string\n getChunkPreloads: (chunk: Rollup.OutputChunk) => Array<string>\n getStylesheetAsset: (cssFile: string) => RouterManagedTag\n}\n\ntype DedupeRoute = {\n preloads?: Array<ManifestAssetLink>\n assets?: Array<RouterManagedTag>\n children?: Array<string>\n}\n\nexport function appendUniqueStrings(\n target: Array<string> | undefined,\n source: Array<string>,\n) {\n // Similar to Set.prototype.union, but for ordered arrays.\n // It preserves first-seen order and returns the original target array when\n // source contributes no new values, which avoids extra allocations.\n if (source.length === 0) {\n return target\n }\n\n if (!target || target.length === 0) {\n return source\n }\n\n const seen = new Set(target)\n let result: Array<string> | undefined\n\n for (const value of source) {\n if (seen.has(value)) {\n continue\n }\n\n seen.add(value)\n if (!result) {\n result = target.slice()\n }\n result.push(value)\n }\n\n return result ?? target\n}\n\nexport function appendUniqueAssets(\n target: Array<RouterManagedTag> | undefined,\n source: Array<RouterManagedTag>,\n) {\n // Same semantics as appendUniqueStrings, but uniqueness is based on the\n // serialized asset identity instead of object reference.\n if (source.length === 0) {\n return target\n }\n\n if (!target || target.length === 0) {\n return source\n }\n\n const seen = new Set(target.map(getAssetIdentity))\n let result: Array<RouterManagedTag> | undefined\n\n for (const asset of source) {\n const identity = getAssetIdentity(asset)\n if (seen.has(identity)) {\n continue\n }\n\n seen.add(identity)\n if (!result) {\n result = target.slice()\n }\n result.push(asset)\n }\n\n return result ?? target\n}\n\nfunction getAssetIdentity(asset: RouterManagedTag) {\n if (asset.tag === 'link' || asset.tag === 'script') {\n const attrs = asset.attrs ?? {}\n return [\n asset.tag,\n 'href' in attrs ? String(attrs.href) : '',\n 'src' in attrs ? String(attrs.src) : '',\n 'rel' in attrs ? String(attrs.rel) : '',\n 'type' in attrs ? String(attrs.type) : '',\n asset.children ?? '',\n ].join('|')\n }\n\n return JSON.stringify(asset)\n}\n\nfunction mergeRouteChunkData(options: {\n route: RouteTreeRoute\n chunk: Rollup.OutputChunk\n getChunkCssAssets: (chunk: Rollup.OutputChunk) => Array<RouterManagedTag>\n getChunkPreloads: (chunk: Rollup.OutputChunk) => Array<string>\n}) {\n const chunkAssets = options.getChunkCssAssets(options.chunk)\n const chunkPreloads = options.getChunkPreloads(options.chunk)\n\n options.route.assets = appendUniqueAssets(options.route.assets, chunkAssets)\n options.route.preloads = appendUniqueStrings(\n options.route.preloads,\n chunkPreloads,\n )\n}\n\nexport function buildStartManifest(options: {\n clientBundle: Rollup.OutputBundle\n routeTreeRoutes: RouteTreeRoutes\n basePath: string\n}) {\n const scannedChunks = scanClientChunks(options.clientBundle)\n const hashedCssFiles = collectDynamicImportCss(\n scannedChunks.routeEntryChunks,\n scannedChunks.chunksByFileName,\n scannedChunks.entryChunk,\n )\n const assetResolvers = createManifestAssetResolvers({\n basePath: options.basePath,\n hashedCssFiles,\n })\n\n const routes = buildRouteManifestRoutes({\n routeTreeRoutes: options.routeTreeRoutes,\n routeChunksByFilePath: scannedChunks.routeChunksByFilePath,\n chunksByFileName: scannedChunks.chunksByFileName,\n entryChunk: scannedChunks.entryChunk,\n assetResolvers,\n })\n\n dedupeNestedRouteManifestEntries(rootRouteId, routes[rootRouteId]!, routes)\n\n // Prune routes with no assets or preloads from the manifest\n for (const routeId of Object.keys(routes)) {\n const route = routes[routeId]!\n const hasAssets = route.assets && route.assets.length > 0\n const hasPreloads = route.preloads && route.preloads.length > 0\n if (!hasAssets && !hasPreloads) {\n delete routes[routeId]\n }\n }\n\n return {\n routes,\n clientEntry: assetResolvers.getAssetPath(scannedChunks.entryChunk.fileName),\n }\n}\n\nexport function scanClientChunks(\n clientBundle: Rollup.OutputBundle,\n): ScannedClientChunks {\n let entryChunk: Rollup.OutputChunk | undefined\n const chunksByFileName = new Map<string, Rollup.OutputChunk>()\n const routeChunksByFilePath = new Map<string, Array<Rollup.OutputChunk>>()\n const routeEntryChunks = new Set<Rollup.OutputChunk>()\n\n for (const fileName in clientBundle) {\n const bundleEntry = clientBundle[fileName]!\n if (bundleEntry.type !== 'chunk') {\n continue\n }\n\n chunksByFileName.set(bundleEntry.fileName, bundleEntry)\n\n if (bundleEntry.isEntry) {\n if (entryChunk) {\n throw new Error(\n `multiple entries detected: ${entryChunk.fileName} ${bundleEntry.fileName}`,\n )\n }\n entryChunk = bundleEntry\n }\n\n const routeFilePaths = getRouteFilePathsFromModuleIds(bundleEntry.moduleIds)\n if (routeFilePaths.length === 0) {\n continue\n }\n\n routeEntryChunks.add(bundleEntry)\n\n for (let i = 0; i < routeFilePaths.length; i++) {\n const routeFilePath = routeFilePaths[i]!\n let chunks = routeChunksByFilePath.get(routeFilePath)\n if (chunks === undefined) {\n chunks = []\n routeChunksByFilePath.set(routeFilePath, chunks)\n }\n chunks.push(bundleEntry)\n }\n }\n\n if (!entryChunk) {\n throw new Error('No entry file found')\n }\n\n return {\n entryChunk,\n chunksByFileName,\n routeChunksByFilePath,\n routeEntryChunks,\n }\n}\n\nexport function getRouteFilePathsFromModuleIds(moduleIds: Array<string>) {\n let routeFilePaths: Array<string> | undefined\n let seenRouteFilePaths: Set<string> | undefined\n\n for (const moduleId of moduleIds) {\n const queryIndex = moduleId.indexOf('?')\n\n if (queryIndex < 0) {\n continue\n }\n\n const query = moduleId.slice(queryIndex + 1)\n\n // Fast check before allocating URLSearchParams\n if (!query.includes(tsrSplit)) {\n continue\n }\n\n if (!new URLSearchParams(query).has(tsrSplit)) {\n continue\n }\n\n const routeFilePath = moduleId.slice(0, queryIndex)\n\n if (seenRouteFilePaths?.has(routeFilePath)) {\n continue\n }\n\n if (routeFilePaths === undefined) {\n routeFilePaths = []\n seenRouteFilePaths = new Set<string>()\n }\n\n routeFilePaths.push(routeFilePath)\n seenRouteFilePaths!.add(routeFilePath)\n }\n\n return routeFilePaths ?? []\n}\n\nexport function collectDynamicImportCss(\n routeEntryChunks: Set<Rollup.OutputChunk>,\n chunksByFileName: Map<string, Rollup.OutputChunk>,\n entryChunk?: Rollup.OutputChunk,\n) {\n const routerManagedCssFiles = new Set<string>()\n const nonRouteDynamicCssFiles = new Set<string>()\n const hashedCssFiles = new Set<string>()\n const visitedByChunk = new Map<Rollup.OutputChunk, number>()\n const chunkStack: Array<Rollup.OutputChunk> = []\n const modeStack: Array<number> = []\n\n for (const routeEntryChunk of routeEntryChunks) {\n chunkStack.push(routeEntryChunk)\n modeStack.push(ROUTER_MANAGED_MODE)\n }\n\n if (entryChunk) {\n chunkStack.push(entryChunk)\n modeStack.push(ROUTER_MANAGED_MODE)\n }\n\n while (chunkStack.length > 0) {\n const chunk = chunkStack.pop()!\n const mode = modeStack.pop()!\n const previousMode = visitedByChunk.get(chunk) ?? 0\n\n if ((previousMode & mode) === mode) {\n continue\n }\n\n visitedByChunk.set(chunk, previousMode | mode)\n\n if ((mode & ROUTER_MANAGED_MODE) !== 0) {\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n routerManagedCssFiles.add(cssFile)\n }\n }\n\n if ((mode & NON_ROUTE_DYNAMIC_MODE) !== 0) {\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n nonRouteDynamicCssFiles.add(cssFile)\n }\n }\n\n for (let i = 0; i < chunk.imports.length; i++) {\n const importedChunk = chunksByFileName.get(chunk.imports[i]!)\n if (importedChunk) {\n chunkStack.push(importedChunk)\n modeStack.push(mode)\n }\n }\n\n for (let i = 0; i < chunk.dynamicImports.length; i++) {\n const dynamicImportedChunk = chunksByFileName.get(\n chunk.dynamicImports[i]!,\n )\n if (dynamicImportedChunk) {\n chunkStack.push(dynamicImportedChunk)\n modeStack.push(\n (mode & NON_ROUTE_DYNAMIC_MODE) !== 0 ||\n !routeEntryChunks.has(dynamicImportedChunk)\n ? NON_ROUTE_DYNAMIC_MODE\n : ROUTER_MANAGED_MODE,\n )\n }\n }\n }\n\n for (const cssFile of routerManagedCssFiles) {\n if (nonRouteDynamicCssFiles.has(cssFile)) {\n hashedCssFiles.add(cssFile)\n }\n }\n\n return hashedCssFiles\n}\n\nexport function createManifestAssetResolvers(options: {\n basePath: string\n hashedCssFiles?: Set<string>\n}): ManifestAssetResolvers {\n const assetPathByFileName = new Map<string, string>()\n const stylesheetAssetByFileName = new Map<string, RouterManagedTag>()\n const preloadsByChunk = new Map<Rollup.OutputChunk, Array<string>>()\n\n const getAssetPath = (fileName: string) => {\n const cachedPath = assetPathByFileName.get(fileName)\n if (cachedPath) {\n return cachedPath\n }\n\n const assetPath = joinURL(options.basePath, fileName)\n assetPathByFileName.set(fileName, assetPath)\n return assetPath\n }\n\n const getStylesheetAsset = (cssFile: string) => {\n const cachedAsset = stylesheetAssetByFileName.get(cssFile)\n if (cachedAsset) {\n return cachedAsset\n }\n\n const href = getAssetPath(cssFile)\n const asset = {\n tag: 'link',\n attrs: {\n rel: 'stylesheet',\n href: options.hashedCssFiles?.has(cssFile) ? `${href}#` : href,\n type: 'text/css',\n },\n } satisfies RouterManagedTag\n\n stylesheetAssetByFileName.set(cssFile, asset)\n return asset\n }\n\n const getChunkPreloads = (chunk: Rollup.OutputChunk) => {\n const cachedPreloads = preloadsByChunk.get(chunk)\n if (cachedPreloads) {\n return cachedPreloads\n }\n\n const preloads = [getAssetPath(chunk.fileName)]\n\n for (let i = 0; i < chunk.imports.length; i++) {\n preloads.push(getAssetPath(chunk.imports[i]!))\n }\n\n preloadsByChunk.set(chunk, preloads)\n return preloads\n }\n\n return {\n getAssetPath,\n getChunkPreloads,\n getStylesheetAsset,\n }\n}\n\nexport function createChunkCssAssetCollector(options: {\n chunksByFileName: Map<string, Rollup.OutputChunk>\n getStylesheetAsset: (cssFile: string) => RouterManagedTag\n}) {\n const assetsByChunk = new Map<Rollup.OutputChunk, Array<RouterManagedTag>>()\n const stateByChunk = new Map<Rollup.OutputChunk, number>()\n\n const appendAsset = (\n assets: Array<RouterManagedTag>,\n seenAssets: Set<string>,\n asset: RouterManagedTag,\n ) => {\n const identity = getAssetIdentity(asset)\n if (seenAssets.has(identity)) {\n return\n }\n\n seenAssets.add(identity)\n assets.push(asset)\n }\n\n const getChunkCssAssets = (\n chunk: Rollup.OutputChunk,\n ): Array<RouterManagedTag> => {\n const cachedAssets = assetsByChunk.get(chunk)\n if (cachedAssets) {\n return cachedAssets\n }\n\n if (stateByChunk.get(chunk) === VISITING_CHUNK) {\n return []\n }\n stateByChunk.set(chunk, VISITING_CHUNK)\n\n const assets: Array<RouterManagedTag> = []\n const seenAssets = new Set<string>()\n\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n appendAsset(assets, seenAssets, options.getStylesheetAsset(cssFile))\n }\n\n for (let i = 0; i < chunk.imports.length; i++) {\n const importedChunk = options.chunksByFileName.get(chunk.imports[i]!)\n if (!importedChunk) {\n continue\n }\n\n const importedAssets = getChunkCssAssets(importedChunk)\n for (let j = 0; j < importedAssets.length; j++) {\n appendAsset(assets, seenAssets, importedAssets[j]!)\n }\n }\n\n stateByChunk.delete(chunk)\n assetsByChunk.set(chunk, assets)\n return assets\n }\n\n return { getChunkCssAssets }\n}\n\nexport function buildRouteManifestRoutes(options: {\n routeTreeRoutes: RouteTreeRoutes\n routeChunksByFilePath: Map<string, Array<Rollup.OutputChunk>>\n chunksByFileName: Map<string, Rollup.OutputChunk>\n entryChunk: Rollup.OutputChunk\n assetResolvers: ManifestAssetResolvers\n}) {\n const routes: Record<string, RouteTreeRoute> = {}\n const getChunkCssAssets = createChunkCssAssetCollector({\n chunksByFileName: options.chunksByFileName,\n getStylesheetAsset: options.assetResolvers.getStylesheetAsset,\n }).getChunkCssAssets\n\n for (const [routeId, route] of Object.entries(options.routeTreeRoutes)) {\n if (!route.filePath) {\n if (routeId === rootRouteId) {\n routes[routeId] = route\n continue\n }\n\n throw new Error(`expected filePath to be set for ${routeId}`)\n }\n\n const chunks = options.routeChunksByFilePath.get(route.filePath)\n if (!chunks) {\n routes[routeId] = route\n continue\n }\n\n const existing = routes[routeId]\n const targetRoute = (routes[routeId] = existing ? existing : { ...route })\n\n for (const chunk of chunks) {\n mergeRouteChunkData({\n route: targetRoute,\n chunk,\n getChunkCssAssets,\n getChunkPreloads: options.assetResolvers.getChunkPreloads,\n })\n }\n }\n\n const rootRoute = (routes[rootRouteId] = routes[rootRouteId] || {})\n mergeRouteChunkData({\n route: rootRoute,\n chunk: options.entryChunk,\n getChunkCssAssets,\n getChunkPreloads: options.assetResolvers.getChunkPreloads,\n })\n\n return routes\n}\n\nfunction dedupeNestedRouteManifestEntries(\n routeId: string,\n route: DedupeRoute,\n routesById: Record<string, DedupeRoute>,\n seenPreloads = new Set<string>(),\n seenAssets = new Set<string>(),\n) {\n let routePreloads = route.preloads\n let routeAssets = route.assets\n\n if (routePreloads && routePreloads.length > 0) {\n let dedupedPreloads: Array<ManifestAssetLink> | undefined\n\n for (let i = 0; i < routePreloads.length; i++) {\n const preload = routePreloads[i]!\n const preloadHref = resolveManifestAssetLink(preload).href\n\n if (seenPreloads.has(preloadHref)) {\n if (dedupedPreloads === undefined) {\n dedupedPreloads = routePreloads.slice(0, i)\n }\n continue\n }\n\n seenPreloads.add(preloadHref)\n\n if (dedupedPreloads) {\n dedupedPreloads.push(preload)\n }\n }\n\n if (dedupedPreloads) {\n routePreloads = dedupedPreloads\n route.preloads = dedupedPreloads\n }\n }\n\n if (routeAssets && routeAssets.length > 0) {\n let dedupedAssets: Array<RouterManagedTag> | undefined\n\n for (let i = 0; i < routeAssets.length; i++) {\n const asset = routeAssets[i]!\n const identity = getAssetIdentity(asset)\n\n if (seenAssets.has(identity)) {\n if (dedupedAssets === undefined) {\n dedupedAssets = routeAssets.slice(0, i)\n }\n continue\n }\n\n seenAssets.add(identity)\n\n if (dedupedAssets) {\n dedupedAssets.push(asset)\n }\n }\n\n if (dedupedAssets) {\n routeAssets = dedupedAssets\n route.assets = dedupedAssets\n }\n }\n\n if (route.children) {\n for (const childRouteId of route.children) {\n const childRoute = routesById[childRouteId]\n\n if (!childRoute) {\n throw new Error(\n `Route tree references child route ${childRouteId} from ${routeId}, but no route entry was found`,\n )\n }\n\n dedupeNestedRouteManifestEntries(\n childRouteId,\n childRoute,\n routesById,\n seenPreloads,\n seenAssets,\n )\n }\n }\n\n if (routePreloads) {\n for (let i = routePreloads.length - 1; i >= 0; i--) {\n seenPreloads.delete(resolveManifestAssetLink(routePreloads[i]!).href)\n }\n }\n\n if (routeAssets) {\n for (let i = routeAssets.length - 1; i >= 0; i--) {\n seenAssets.delete(getAssetIdentity(routeAssets[i]!))\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"manifestBuilder.js","names":[],"sources":["../../../src/start-manifest-plugin/manifestBuilder.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/prefer-for-of */\nimport { joinURL } from 'ufo'\nimport { resolveManifestAssetLink, rootRouteId } from '@tanstack/router-core'\nimport {\n getRouteFilePathsFromModuleIds,\n normalizeViteClientBuild,\n normalizeViteClientChunk,\n} from '../vite/start-manifest-plugin/normalized-client-build'\nimport type { ManifestAssetLink, RouterManagedTag } from '@tanstack/router-core'\nimport type { NormalizedClientBuild, NormalizedClientChunk } from '../types'\n\nconst ROUTER_MANAGED_MODE = 1\nconst NON_ROUTE_DYNAMIC_MODE = 2\nconst VISITING_CHUNK = 1\n\ntype RouteTreeRoute = {\n filePath?: string\n preloads?: Array<string>\n assets?: Array<RouterManagedTag>\n children?: Array<string>\n}\n\ntype RouteTreeRoutes = Record<string, RouteTreeRoute>\n\ninterface ScannedClientChunks {\n entryChunk: NormalizedClientChunk\n chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>\n routeChunksByFilePath: ReadonlyMap<string, Array<NormalizedClientChunk>>\n routeEntryChunks: ReadonlySet<NormalizedClientChunk>\n}\n\ninterface ManifestAssetResolvers {\n getAssetPath: (fileName: string) => string\n getChunkPreloads: (chunk: NormalizedClientChunk) => Array<string>\n getStylesheetAsset: (cssFile: string) => RouterManagedTag\n}\n\ntype DedupeRoute = {\n preloads?: Array<ManifestAssetLink>\n assets?: Array<RouterManagedTag>\n children?: Array<string>\n}\n\nexport function appendUniqueStrings(\n target: Array<string> | undefined,\n source: Array<string>,\n) {\n // Similar to Set.prototype.union, but for ordered arrays.\n // It preserves first-seen order and returns the original target array when\n // source contributes no new values, which avoids extra allocations.\n if (source.length === 0) {\n return target\n }\n\n if (!target || target.length === 0) {\n return source\n }\n\n const seen = new Set(target)\n let result: Array<string> | undefined\n\n for (const value of source) {\n if (seen.has(value)) {\n continue\n }\n\n seen.add(value)\n if (!result) {\n result = target.slice()\n }\n result.push(value)\n }\n\n return result ?? target\n}\n\nexport function appendUniqueAssets(\n target: Array<RouterManagedTag> | undefined,\n source: Array<RouterManagedTag>,\n) {\n // Same semantics as appendUniqueStrings, but uniqueness is based on the\n // serialized asset identity instead of object reference.\n if (source.length === 0) {\n return target\n }\n\n if (!target || target.length === 0) {\n return source\n }\n\n const seen = new Set(target.map(getAssetIdentity))\n let result: Array<RouterManagedTag> | undefined\n\n for (const asset of source) {\n const identity = getAssetIdentity(asset)\n if (seen.has(identity)) {\n continue\n }\n\n seen.add(identity)\n if (!result) {\n result = target.slice()\n }\n result.push(asset)\n }\n\n return result ?? target\n}\n\nfunction getAssetIdentity(asset: RouterManagedTag) {\n if (asset.tag === 'link' || asset.tag === 'script') {\n const attrs = asset.attrs ?? {}\n return [\n asset.tag,\n 'href' in attrs ? String(attrs.href) : '',\n 'src' in attrs ? String(attrs.src) : '',\n 'rel' in attrs ? String(attrs.rel) : '',\n 'type' in attrs ? String(attrs.type) : '',\n asset.children ?? '',\n ].join('|')\n }\n\n return JSON.stringify(asset)\n}\n\nfunction mergeRouteChunkData(options: {\n route: RouteTreeRoute\n chunk: NormalizedClientChunk\n getChunkCssAssets: (chunk: NormalizedClientChunk) => Array<RouterManagedTag>\n getChunkPreloads: (chunk: NormalizedClientChunk) => Array<string>\n}) {\n const chunkAssets = options.getChunkCssAssets(options.chunk)\n const chunkPreloads = options.getChunkPreloads(options.chunk)\n\n options.route.assets = appendUniqueAssets(options.route.assets, chunkAssets)\n options.route.preloads = appendUniqueStrings(\n options.route.preloads,\n chunkPreloads,\n )\n}\n\nexport function buildStartManifest(options: {\n clientBuild: NormalizedClientBuild\n routeTreeRoutes: RouteTreeRoutes\n basePath: string\n}) {\n const scannedChunks = scanClientChunks(options.clientBuild)\n const hashedCssFiles = collectDynamicImportCss(\n scannedChunks.routeEntryChunks,\n scannedChunks.chunksByFileName,\n scannedChunks.entryChunk,\n )\n const assetResolvers = createManifestAssetResolvers({\n basePath: options.basePath,\n hashedCssFiles,\n })\n\n const routes = buildRouteManifestRoutes({\n routeTreeRoutes: options.routeTreeRoutes,\n routeChunksByFilePath: scannedChunks.routeChunksByFilePath,\n chunksByFileName: scannedChunks.chunksByFileName,\n entryChunk: scannedChunks.entryChunk,\n assetResolvers,\n })\n\n dedupeNestedRouteManifestEntries(rootRouteId, routes[rootRouteId]!, routes)\n\n // Prune routes with no assets or preloads from the manifest\n for (const routeId of Object.keys(routes)) {\n const route = routes[routeId]!\n const hasAssets = route.assets && route.assets.length > 0\n const hasPreloads = route.preloads && route.preloads.length > 0\n if (!hasAssets && !hasPreloads) {\n delete routes[routeId]\n }\n }\n\n return {\n routes,\n clientEntry: assetResolvers.getAssetPath(scannedChunks.entryChunk.fileName),\n }\n}\n\nexport function scanClientChunks(\n clientBuild: NormalizedClientBuild,\n): ScannedClientChunks {\n const entryChunk = clientBuild.chunksByFileName.get(\n clientBuild.entryChunkFileName,\n )\n\n if (!entryChunk) {\n throw new Error(`Missing entry chunk: ${clientBuild.entryChunkFileName}`)\n }\n\n const routeEntryChunks = new Set<NormalizedClientChunk>()\n const routeChunksByFilePath = new Map<string, Array<NormalizedClientChunk>>()\n\n for (const chunk of clientBuild.chunksByFileName.values()) {\n if (chunk.routeFilePaths.length > 0) {\n routeEntryChunks.add(chunk)\n\n for (const routeFilePath of chunk.routeFilePaths) {\n let chunks = routeChunksByFilePath.get(routeFilePath)\n if (chunks === undefined) {\n chunks = []\n routeChunksByFilePath.set(routeFilePath, chunks)\n }\n chunks.push(chunk)\n }\n }\n }\n\n return {\n entryChunk,\n chunksByFileName: clientBuild.chunksByFileName,\n routeChunksByFilePath,\n routeEntryChunks,\n }\n}\n\nexport function collectDynamicImportCss(\n routeEntryChunks: ReadonlySet<NormalizedClientChunk>,\n chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>,\n entryChunk?: NormalizedClientChunk,\n) {\n const routerManagedCssFiles = new Set<string>()\n const nonRouteDynamicCssFiles = new Set<string>()\n const hashedCssFiles = new Set<string>()\n const visitedByChunk = new Map<NormalizedClientChunk, number>()\n const chunkStack: Array<NormalizedClientChunk> = []\n const modeStack: Array<number> = []\n\n for (const routeEntryChunk of routeEntryChunks) {\n chunkStack.push(routeEntryChunk)\n modeStack.push(ROUTER_MANAGED_MODE)\n }\n\n if (entryChunk) {\n chunkStack.push(entryChunk)\n modeStack.push(ROUTER_MANAGED_MODE)\n }\n\n while (chunkStack.length > 0) {\n const chunk = chunkStack.pop()!\n const mode = modeStack.pop()!\n const previousMode = visitedByChunk.get(chunk) ?? 0\n\n if ((previousMode & mode) === mode) {\n continue\n }\n\n visitedByChunk.set(chunk, previousMode | mode)\n\n if ((mode & ROUTER_MANAGED_MODE) !== 0) {\n for (const cssFile of chunk.css) {\n routerManagedCssFiles.add(cssFile)\n }\n }\n\n if ((mode & NON_ROUTE_DYNAMIC_MODE) !== 0) {\n for (const cssFile of chunk.css) {\n nonRouteDynamicCssFiles.add(cssFile)\n }\n }\n\n for (let i = 0; i < chunk.imports.length; i++) {\n const importedChunk = chunksByFileName.get(chunk.imports[i]!)\n if (importedChunk) {\n chunkStack.push(importedChunk)\n modeStack.push(mode)\n }\n }\n\n for (let i = 0; i < chunk.dynamicImports.length; i++) {\n const dynamicImportedChunk = chunksByFileName.get(\n chunk.dynamicImports[i]!,\n )\n if (dynamicImportedChunk) {\n chunkStack.push(dynamicImportedChunk)\n modeStack.push(\n (mode & NON_ROUTE_DYNAMIC_MODE) !== 0 ||\n !routeEntryChunks.has(dynamicImportedChunk)\n ? NON_ROUTE_DYNAMIC_MODE\n : ROUTER_MANAGED_MODE,\n )\n }\n }\n }\n\n for (const cssFile of routerManagedCssFiles) {\n if (nonRouteDynamicCssFiles.has(cssFile)) {\n hashedCssFiles.add(cssFile)\n }\n }\n\n return hashedCssFiles\n}\n\nexport function createManifestAssetResolvers(options: {\n basePath: string\n hashedCssFiles?: Set<string>\n}): ManifestAssetResolvers {\n const assetPathByFileName = new Map<string, string>()\n const stylesheetAssetByFileName = new Map<string, RouterManagedTag>()\n const preloadsByChunk = new Map<NormalizedClientChunk, Array<string>>()\n\n const getAssetPath = (fileName: string) => {\n const cachedPath = assetPathByFileName.get(fileName)\n if (cachedPath) {\n return cachedPath\n }\n\n const assetPath = joinURL(options.basePath, fileName)\n assetPathByFileName.set(fileName, assetPath)\n return assetPath\n }\n\n const getStylesheetAsset = (cssFile: string) => {\n const cachedAsset = stylesheetAssetByFileName.get(cssFile)\n if (cachedAsset) {\n return cachedAsset\n }\n\n const href = getAssetPath(cssFile)\n const asset = {\n tag: 'link',\n attrs: {\n rel: 'stylesheet',\n href: options.hashedCssFiles?.has(cssFile) ? `${href}#` : href,\n type: 'text/css',\n },\n } satisfies RouterManagedTag\n\n stylesheetAssetByFileName.set(cssFile, asset)\n return asset\n }\n\n const getChunkPreloads = (chunk: NormalizedClientChunk) => {\n const cachedPreloads = preloadsByChunk.get(chunk)\n if (cachedPreloads) {\n return cachedPreloads\n }\n\n const preloads = [getAssetPath(chunk.fileName)]\n\n for (let i = 0; i < chunk.imports.length; i++) {\n preloads.push(getAssetPath(chunk.imports[i]!))\n }\n\n preloadsByChunk.set(chunk, preloads)\n return preloads\n }\n\n return {\n getAssetPath,\n getChunkPreloads,\n getStylesheetAsset,\n }\n}\n\nexport function createChunkCssAssetCollector(options: {\n chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>\n getStylesheetAsset: (cssFile: string) => RouterManagedTag\n}) {\n const assetsByChunk = new Map<\n NormalizedClientChunk,\n Array<RouterManagedTag>\n >()\n const stateByChunk = new Map<NormalizedClientChunk, number>()\n\n const appendAsset = (\n assets: Array<RouterManagedTag>,\n seenAssets: Set<string>,\n asset: RouterManagedTag,\n ) => {\n const identity = getAssetIdentity(asset)\n if (seenAssets.has(identity)) {\n return\n }\n\n seenAssets.add(identity)\n assets.push(asset)\n }\n\n const getChunkCssAssets = (\n chunk: NormalizedClientChunk,\n ): Array<RouterManagedTag> => {\n const cachedAssets = assetsByChunk.get(chunk)\n if (cachedAssets) {\n return cachedAssets\n }\n\n if (stateByChunk.get(chunk) === VISITING_CHUNK) {\n return []\n }\n stateByChunk.set(chunk, VISITING_CHUNK)\n\n const assets: Array<RouterManagedTag> = []\n const seenAssets = new Set<string>()\n\n for (const cssFile of chunk.css) {\n appendAsset(assets, seenAssets, options.getStylesheetAsset(cssFile))\n }\n\n for (let i = 0; i < chunk.imports.length; i++) {\n const importedChunk = options.chunksByFileName.get(chunk.imports[i]!)\n if (!importedChunk) {\n continue\n }\n\n const importedAssets = getChunkCssAssets(importedChunk)\n for (let j = 0; j < importedAssets.length; j++) {\n appendAsset(assets, seenAssets, importedAssets[j]!)\n }\n }\n\n stateByChunk.delete(chunk)\n assetsByChunk.set(chunk, assets)\n return assets\n }\n\n return { getChunkCssAssets }\n}\n\nexport function buildRouteManifestRoutes(options: {\n routeTreeRoutes: RouteTreeRoutes\n routeChunksByFilePath: ReadonlyMap<\n string,\n ReadonlyArray<NormalizedClientChunk>\n >\n chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>\n entryChunk: NormalizedClientChunk\n assetResolvers: ManifestAssetResolvers\n}) {\n const routes: Record<string, RouteTreeRoute> = {}\n const getChunkCssAssets = createChunkCssAssetCollector({\n chunksByFileName: options.chunksByFileName,\n getStylesheetAsset: options.assetResolvers.getStylesheetAsset,\n }).getChunkCssAssets\n\n for (const [routeId, route] of Object.entries(options.routeTreeRoutes)) {\n if (!route.filePath) {\n if (routeId === rootRouteId) {\n routes[routeId] = route\n continue\n }\n\n throw new Error(`expected filePath to be set for ${routeId}`)\n }\n\n const chunks = options.routeChunksByFilePath.get(route.filePath)\n if (!chunks) {\n routes[routeId] = route\n continue\n }\n\n const existing = routes[routeId]\n const targetRoute = (routes[routeId] = existing ? existing : { ...route })\n\n for (const chunk of chunks) {\n mergeRouteChunkData({\n route: targetRoute,\n chunk,\n getChunkCssAssets,\n getChunkPreloads: options.assetResolvers.getChunkPreloads,\n })\n }\n }\n\n const rootRoute = (routes[rootRouteId] = routes[rootRouteId] || {})\n mergeRouteChunkData({\n route: rootRoute,\n chunk: options.entryChunk,\n getChunkCssAssets,\n getChunkPreloads: options.assetResolvers.getChunkPreloads,\n })\n\n return routes\n}\n\nexport {\n getRouteFilePathsFromModuleIds,\n normalizeViteClientBuild,\n normalizeViteClientChunk,\n}\n\nfunction dedupeNestedRouteManifestEntries(\n routeId: string,\n route: DedupeRoute,\n routesById: Record<string, DedupeRoute>,\n seenPreloads = new Set<string>(),\n seenAssets = new Set<string>(),\n) {\n let routePreloads = route.preloads\n let routeAssets = route.assets\n\n if (routePreloads && routePreloads.length > 0) {\n let dedupedPreloads: Array<ManifestAssetLink> | undefined\n\n for (let i = 0; i < routePreloads.length; i++) {\n const preload = routePreloads[i]!\n const preloadHref = resolveManifestAssetLink(preload).href\n\n if (seenPreloads.has(preloadHref)) {\n if (dedupedPreloads === undefined) {\n dedupedPreloads = routePreloads.slice(0, i)\n }\n continue\n }\n\n seenPreloads.add(preloadHref)\n\n if (dedupedPreloads) {\n dedupedPreloads.push(preload)\n }\n }\n\n if (dedupedPreloads) {\n routePreloads = dedupedPreloads\n route.preloads = dedupedPreloads\n }\n }\n\n if (routeAssets && routeAssets.length > 0) {\n let dedupedAssets: Array<RouterManagedTag> | undefined\n\n for (let i = 0; i < routeAssets.length; i++) {\n const asset = routeAssets[i]!\n const identity = getAssetIdentity(asset)\n\n if (seenAssets.has(identity)) {\n if (dedupedAssets === undefined) {\n dedupedAssets = routeAssets.slice(0, i)\n }\n continue\n }\n\n seenAssets.add(identity)\n\n if (dedupedAssets) {\n dedupedAssets.push(asset)\n }\n }\n\n if (dedupedAssets) {\n routeAssets = dedupedAssets\n route.assets = dedupedAssets\n }\n }\n\n if (route.children) {\n for (const childRouteId of route.children) {\n const childRoute = routesById[childRouteId]\n\n if (!childRoute) {\n throw new Error(\n `Route tree references child route ${childRouteId} from ${routeId}, but no route entry was found`,\n )\n }\n\n dedupeNestedRouteManifestEntries(\n childRouteId,\n childRoute,\n routesById,\n seenPreloads,\n seenAssets,\n )\n }\n }\n\n if (routePreloads) {\n for (let i = routePreloads.length - 1; i >= 0; i--) {\n seenPreloads.delete(resolveManifestAssetLink(routePreloads[i]!).href)\n }\n }\n\n if (routeAssets) {\n for (let i = routeAssets.length - 1; i >= 0; i--) {\n seenAssets.delete(getAssetIdentity(routeAssets[i]!))\n }\n }\n}\n"],"mappings":"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"}
|