@tanstack/start-plugin-core 1.132.0-alpha.3 → 1.132.0-alpha.4
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/plugin.d.ts +1 -1
- package/dist/esm/plugin.js +1 -1
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/{compilers.js → start-compiler-plugin/compilers.js} +58 -57
- package/dist/esm/start-compiler-plugin/compilers.js.map +1 -0
- package/dist/esm/start-compiler-plugin/constants.d.ts +1 -0
- package/dist/esm/start-compiler-plugin/constants.js +14 -0
- package/dist/esm/start-compiler-plugin/constants.js.map +1 -0
- package/dist/esm/{start-compiler-plugin.js → start-compiler-plugin/plugin.js} +3 -11
- package/dist/esm/start-compiler-plugin/plugin.js.map +1 -0
- package/package.json +5 -5
- package/src/plugin.ts +2 -2
- package/src/{compilers.ts → start-compiler-plugin/compilers.ts} +62 -74
- package/src/start-compiler-plugin/constants.ts +10 -0
- package/src/{start-compiler-plugin.ts → start-compiler-plugin/plugin.ts} +2 -11
- package/dist/esm/compilers.js.map +0 -1
- package/dist/esm/start-compiler-plugin.js.map +0 -1
- /package/dist/esm/{compilers.d.ts → start-compiler-plugin/compilers.d.ts} +0 -0
- /package/dist/esm/{start-compiler-plugin.d.ts → start-compiler-plugin/plugin.d.ts} +0 -0
package/dist/esm/plugin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TanStackStartInputConfig } from './schema.js';
|
|
2
2
|
import { PluginOption } from 'vite';
|
|
3
|
-
import { CompileStartFrameworkOptions } from './compilers.js';
|
|
3
|
+
import { CompileStartFrameworkOptions } from './start-compiler-plugin/compilers.js';
|
|
4
4
|
export interface TanStackStartVitePluginCoreOptions {
|
|
5
5
|
framework: CompileStartFrameworkOptions;
|
|
6
6
|
defaultEntryPaths: {
|
package/dist/esm/plugin.js
CHANGED
|
@@ -6,7 +6,7 @@ import * as vite from "vite";
|
|
|
6
6
|
import { crawlFrameworkPkgs } from "vitefu";
|
|
7
7
|
import { join } from "pathe";
|
|
8
8
|
import { startManifestPlugin } from "./start-manifest-plugin/plugin.js";
|
|
9
|
-
import { startCompilerPlugin } from "./start-compiler-plugin.js";
|
|
9
|
+
import { startCompilerPlugin } from "./start-compiler-plugin/plugin.js";
|
|
10
10
|
import { ENTRY_POINTS, VITE_ENVIRONMENT_NAMES } from "./constants.js";
|
|
11
11
|
import { tanStackStartRouter } from "./start-router-plugin/plugin.js";
|
|
12
12
|
import { loadEnvPlugin } from "./load-env-plugin/plugin.js";
|
package/dist/esm/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["../../src/plugin.ts"],"sourcesContent":["import path from 'node:path'\nimport { trimPathRight } from '@tanstack/router-core'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin'\nimport * as vite from 'vite'\nimport { crawlFrameworkPkgs } from 'vitefu'\nimport { join } from 'pathe'\nimport { startManifestPlugin } from './start-manifest-plugin/plugin'\nimport { startCompilerPlugin } from './start-compiler-plugin'\nimport { ENTRY_POINTS, VITE_ENVIRONMENT_NAMES } from './constants'\nimport { tanStackStartRouter } from './start-router-plugin/plugin'\nimport { loadEnvPlugin } from './load-env-plugin/plugin'\nimport { devServerPlugin } from './dev-server-plugin/plugin'\nimport { parseStartConfig } from './schema'\nimport { resolveEntry } from './resolve-entries'\nimport {\n getClientOutputDirectory,\n getServerOutputDirectory,\n} from './output-directory'\nimport { postServerBuild } from './post-server-build'\nimport type { ViteEnvironmentNames } from './constants'\nimport type { TanStackStartInputConfig } from './schema'\nimport type { PluginOption } from 'vite'\nimport type { CompileStartFrameworkOptions } from './compilers'\n\nexport interface TanStackStartVitePluginCoreOptions {\n framework: CompileStartFrameworkOptions\n defaultEntryPaths: {\n client: string\n server: string\n }\n crawlPackages?: (opts: {\n name: string\n peerDependencies: Record<string, any>\n exports?: Record<string, any> | string\n }) => 'include' | 'exclude' | undefined\n}\n\nexport function TanStackStartVitePluginCore(\n corePluginOpts: TanStackStartVitePluginCoreOptions,\n startPluginOpts: TanStackStartInputConfig,\n): Array<PluginOption> {\n const startConfig = parseStartConfig(startPluginOpts)\n\n const capturedBundle: Partial<\n Record<ViteEnvironmentNames, vite.Rollup.OutputBundle>\n > = {}\n\n function getBundle(envName: ViteEnvironmentNames): vite.Rollup.OutputBundle {\n const bundle = capturedBundle[envName]\n if (!bundle) {\n throw new Error(`No bundle captured for environment: ${envName}`)\n }\n return bundle\n }\n\n return [\n tanStackStartRouter({\n ...startConfig.tsr,\n target: corePluginOpts.framework,\n autoCodeSplitting: true,\n }),\n {\n name: 'tanstack-start-core:config',\n async config(viteConfig, { command }) {\n const viteAppBase = trimPathRight(viteConfig.base || '/')\n globalThis.TSS_APP_BASE = viteAppBase\n\n const root = viteConfig.root || process.cwd()\n const resolvedSrcDirectory = join(root, startConfig.tsr.srcDirectory)\n\n const routerFilePath = resolveEntry({\n type: 'router entry',\n configuredEntry: startConfig.router.entry,\n defaultEntry: 'router',\n root,\n resolvedSrcDirectory,\n required: true,\n })\n const clientEntryPath = resolveEntry({\n type: 'client entry',\n configuredEntry: startConfig.client.entry,\n defaultEntry: 'client',\n root,\n resolvedSrcDirectory,\n required: false,\n })\n\n const serverEntryPath = resolveEntry({\n type: 'server entry',\n configuredEntry: startConfig.server.entry,\n defaultEntry: 'server',\n root,\n resolvedSrcDirectory,\n required: false,\n })\n\n let clientAlias: string\n if (clientEntryPath) {\n clientAlias = vite.normalizePath(\n path.join('/@fs', path.resolve(root, clientEntryPath)),\n )\n } else {\n clientAlias = corePluginOpts.defaultEntryPaths.client\n }\n let serverAlias: string\n if (serverEntryPath) {\n serverAlias = vite.normalizePath(path.resolve(root, serverEntryPath))\n } else {\n serverAlias = corePluginOpts.defaultEntryPaths.server\n }\n const entryAliasConfiguration: Record<\n (typeof ENTRY_POINTS)[keyof typeof ENTRY_POINTS],\n string\n > = {\n [ENTRY_POINTS.router]: routerFilePath,\n [ENTRY_POINTS.client]: clientAlias,\n [ENTRY_POINTS.server]: serverAlias,\n }\n\n // TODO\n /* const nitroOutputPublicDir = await (async () => {\n // Create a dummy nitro app to get the resolved public output path\n const dummyNitroApp = await createNitro({\n preset: startConfig.target,\n compatibilityDate: '2024-12-01',\n })\n\n const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir\n await dummyNitroApp.close()\n\n return nitroOutputPublicDir\n })()*/\n\n const startPackageName = `@tanstack/${corePluginOpts.framework}-start`\n const routerPackageName = `@tanstack/${corePluginOpts.framework}-router`\n\n const additionalOptimizeDeps = {\n include: new Set<string>(),\n exclude: new Set<string>(),\n }\n\n // crawl packages that have start in \"peerDependencies\"\n // see https://github.com/svitejs/vitefu/blob/d8d82fa121e3b2215ba437107093c77bde51b63b/src/index.js#L95-L101\n\n // this is currently uncached; could be implemented similarly as vite handles lock file changes\n // see https://github.com/vitejs/vite/blob/557f797d29422027e8c451ca50dd84bf8c41b5f0/packages/vite/src/node/optimizer/index.ts#L1282\n\n const result = await crawlFrameworkPkgs({\n root: process.cwd(),\n isBuild: command === 'build',\n isFrameworkPkgByJson(pkgJson) {\n if ([routerPackageName, startPackageName].includes(pkgJson.name)) {\n return false\n }\n\n const peerDependencies = pkgJson['peerDependencies']\n\n if (peerDependencies) {\n const internalResult = corePluginOpts.crawlPackages?.({\n name: pkgJson.name,\n peerDependencies,\n exports: pkgJson.exports,\n })\n if (internalResult) {\n if (internalResult === 'exclude') {\n additionalOptimizeDeps.exclude.add(pkgJson.name)\n } else {\n additionalOptimizeDeps.include.add(pkgJson.name)\n }\n }\n return (\n startPackageName in peerDependencies ||\n routerPackageName in peerDependencies\n )\n }\n return false\n },\n })\n\n return {\n base: viteAppBase,\n // see https://vite.dev/config/shared-options.html#apptype\n // this will prevent vite from injecting middlewares that we don't want\n appType: viteConfig.appType ?? 'custom',\n environments: {\n [VITE_ENVIRONMENT_NAMES.client]: {\n consumer: 'client',\n build: {\n emptyOutDir:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.client]\n ?.build?.emptyOutDir ?? true,\n rollupOptions: {\n input: {\n main: ENTRY_POINTS.client,\n },\n },\n outDir: getClientOutputDirectory(viteConfig),\n },\n },\n [VITE_ENVIRONMENT_NAMES.server]: {\n consumer: 'server',\n build: {\n emptyOutDir:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.emptyOutDir ?? false,\n ssr: true,\n rollupOptions: {\n input:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.rollupOptions?.input ?? ENTRY_POINTS.server,\n },\n outDir: getServerOutputDirectory(viteConfig),\n commonjsOptions: {\n include: [/node_modules/],\n },\n copyPublicDir:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.copyPublicDir ?? false,\n },\n optimizeDeps: {\n exclude: [\n ...Object.values(VIRTUAL_MODULES),\n ...result.optimizeDeps.exclude.sort(),\n ...additionalOptimizeDeps.exclude,\n `@tanstack/${corePluginOpts.framework}-start/server`,\n ],\n include: [\n ...additionalOptimizeDeps.include,\n ...result.optimizeDeps.include.sort(),\n ],\n },\n },\n },\n resolve: {\n noExternal: [\n '@tanstack/start**',\n `@tanstack/${corePluginOpts.framework}-start**`,\n ...Object.values(VIRTUAL_MODULES),\n startPackageName,\n ...result.ssr.noExternal.sort(),\n ],\n dedupe: [startPackageName],\n alias: {\n ...entryAliasConfiguration,\n },\n },\n optimizeDeps: {\n exclude: [\n ...Object.values(VIRTUAL_MODULES),\n startPackageName,\n ...result.optimizeDeps.exclude.sort(),\n ...additionalOptimizeDeps.exclude,\n ],\n include: [...additionalOptimizeDeps.include],\n },\n /* prettier-ignore */\n define: {\n // define is an esbuild function that replaces the any instances of given keys with the given values\n // i.e: __FRAMEWORK_NAME__ can be replaced with JSON.stringify(\"TanStack Start\")\n // This is not the same as injecting environment variables.\n\n ...defineReplaceEnv('TSS_SERVER_FN_BASE', startConfig.serverFns.base),\n ...defineReplaceEnv('TSS_OUTPUT_PUBLIC_DIR', getClientOutputDirectory(viteConfig)),\n ...defineReplaceEnv('TSS_APP_BASE', viteAppBase),\n ...(command === 'serve' ? defineReplaceEnv('TSS_SHELL', startConfig.spa?.enabled ? 'true' : 'false') : {}),\n ...defineReplaceEnv('TSS_DEV_SERVER', command === 'serve' ? 'true' : 'false'),\n },\n builder: {\n sharedPlugins: true,\n async buildApp(builder) {\n const client = builder.environments[VITE_ENVIRONMENT_NAMES.client]\n const server = builder.environments[VITE_ENVIRONMENT_NAMES.server]\n\n if (!client) {\n throw new Error('Client environment not found')\n }\n\n if (!server) {\n throw new Error('SSR environment not found')\n }\n\n if (!client.isBuilt) {\n // Build the client bundle first\n await builder.build(client)\n }\n if (!server.isBuilt) {\n // Build the SSR bundle\n await builder.build(server)\n }\n const serverBundle = getBundle(VITE_ENVIRONMENT_NAMES.server)\n await postServerBuild({ builder, startConfig, serverBundle })\n },\n },\n }\n },\n },\n // N.B. TanStackStartCompilerPlugin must be before the TanStackServerFnPluginEnv\n startCompilerPlugin(corePluginOpts.framework, {\n client: { envName: VITE_ENVIRONMENT_NAMES.client },\n server: { envName: VITE_ENVIRONMENT_NAMES.server },\n }),\n TanStackServerFnPluginEnv({\n // This is the ID that will be available to look up and import\n // our server function manifest and resolve its module\n manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest,\n client: {\n getRuntimeCode: () =>\n `import { createClientRpc } from '@tanstack/${corePluginOpts.framework}-start/client'`,\n replacer: (d) => `createClientRpc('${d.functionId}')`,\n envName: VITE_ENVIRONMENT_NAMES.client,\n },\n server: {\n getRuntimeCode: () =>\n `import { createServerRpc } from '@tanstack/${corePluginOpts.framework}-start/server'`,\n replacer: (d) => `createServerRpc('${d.functionId}', ${d.fn})`,\n envName: VITE_ENVIRONMENT_NAMES.server,\n },\n }),\n loadEnvPlugin(),\n startManifestPlugin({\n getClientBundle: () => getBundle(VITE_ENVIRONMENT_NAMES.client),\n }),\n devServerPlugin({ startConfig }),\n {\n name: 'tanstack-start:core:capture-bundle',\n applyToEnvironment(e) {\n return (\n e.name === VITE_ENVIRONMENT_NAMES.client ||\n e.name === VITE_ENVIRONMENT_NAMES.server\n )\n },\n enforce: 'post',\n generateBundle(_options, bundle) {\n const environment = this.environment.name as ViteEnvironmentNames\n if (!Object.values(VITE_ENVIRONMENT_NAMES).includes(environment)) {\n throw new Error(`Unknown environment: ${environment}`)\n }\n capturedBundle[environment] = bundle\n },\n },\n ]\n}\n\nfunction defineReplaceEnv<TKey extends string, TValue extends string>(\n key: TKey,\n value: TValue,\n): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } {\n return {\n [`process.env.${key}`]: JSON.stringify(value),\n [`import.meta.env.${key}`]: JSON.stringify(value),\n } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../../src/plugin.ts"],"sourcesContent":["import path from 'node:path'\nimport { trimPathRight } from '@tanstack/router-core'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin'\nimport * as vite from 'vite'\nimport { crawlFrameworkPkgs } from 'vitefu'\nimport { join } from 'pathe'\nimport { startManifestPlugin } from './start-manifest-plugin/plugin'\nimport { startCompilerPlugin } from './start-compiler-plugin/plugin'\nimport { ENTRY_POINTS, VITE_ENVIRONMENT_NAMES } from './constants'\nimport { tanStackStartRouter } from './start-router-plugin/plugin'\nimport { loadEnvPlugin } from './load-env-plugin/plugin'\nimport { devServerPlugin } from './dev-server-plugin/plugin'\nimport { parseStartConfig } from './schema'\nimport { resolveEntry } from './resolve-entries'\nimport {\n getClientOutputDirectory,\n getServerOutputDirectory,\n} from './output-directory'\nimport { postServerBuild } from './post-server-build'\nimport type { ViteEnvironmentNames } from './constants'\nimport type { TanStackStartInputConfig } from './schema'\nimport type { PluginOption } from 'vite'\nimport type { CompileStartFrameworkOptions } from './start-compiler-plugin/compilers'\n\nexport interface TanStackStartVitePluginCoreOptions {\n framework: CompileStartFrameworkOptions\n defaultEntryPaths: {\n client: string\n server: string\n }\n crawlPackages?: (opts: {\n name: string\n peerDependencies: Record<string, any>\n exports?: Record<string, any> | string\n }) => 'include' | 'exclude' | undefined\n}\n\nexport function TanStackStartVitePluginCore(\n corePluginOpts: TanStackStartVitePluginCoreOptions,\n startPluginOpts: TanStackStartInputConfig,\n): Array<PluginOption> {\n const startConfig = parseStartConfig(startPluginOpts)\n\n const capturedBundle: Partial<\n Record<ViteEnvironmentNames, vite.Rollup.OutputBundle>\n > = {}\n\n function getBundle(envName: ViteEnvironmentNames): vite.Rollup.OutputBundle {\n const bundle = capturedBundle[envName]\n if (!bundle) {\n throw new Error(`No bundle captured for environment: ${envName}`)\n }\n return bundle\n }\n\n return [\n tanStackStartRouter({\n ...startConfig.tsr,\n target: corePluginOpts.framework,\n autoCodeSplitting: true,\n }),\n {\n name: 'tanstack-start-core:config',\n async config(viteConfig, { command }) {\n const viteAppBase = trimPathRight(viteConfig.base || '/')\n globalThis.TSS_APP_BASE = viteAppBase\n\n const root = viteConfig.root || process.cwd()\n const resolvedSrcDirectory = join(root, startConfig.tsr.srcDirectory)\n\n const routerFilePath = resolveEntry({\n type: 'router entry',\n configuredEntry: startConfig.router.entry,\n defaultEntry: 'router',\n root,\n resolvedSrcDirectory,\n required: true,\n })\n const clientEntryPath = resolveEntry({\n type: 'client entry',\n configuredEntry: startConfig.client.entry,\n defaultEntry: 'client',\n root,\n resolvedSrcDirectory,\n required: false,\n })\n\n const serverEntryPath = resolveEntry({\n type: 'server entry',\n configuredEntry: startConfig.server.entry,\n defaultEntry: 'server',\n root,\n resolvedSrcDirectory,\n required: false,\n })\n\n let clientAlias: string\n if (clientEntryPath) {\n clientAlias = vite.normalizePath(\n path.join('/@fs', path.resolve(root, clientEntryPath)),\n )\n } else {\n clientAlias = corePluginOpts.defaultEntryPaths.client\n }\n let serverAlias: string\n if (serverEntryPath) {\n serverAlias = vite.normalizePath(path.resolve(root, serverEntryPath))\n } else {\n serverAlias = corePluginOpts.defaultEntryPaths.server\n }\n const entryAliasConfiguration: Record<\n (typeof ENTRY_POINTS)[keyof typeof ENTRY_POINTS],\n string\n > = {\n [ENTRY_POINTS.router]: routerFilePath,\n [ENTRY_POINTS.client]: clientAlias,\n [ENTRY_POINTS.server]: serverAlias,\n }\n\n // TODO\n /* const nitroOutputPublicDir = await (async () => {\n // Create a dummy nitro app to get the resolved public output path\n const dummyNitroApp = await createNitro({\n preset: startConfig.target,\n compatibilityDate: '2024-12-01',\n })\n\n const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir\n await dummyNitroApp.close()\n\n return nitroOutputPublicDir\n })()*/\n\n const startPackageName = `@tanstack/${corePluginOpts.framework}-start`\n const routerPackageName = `@tanstack/${corePluginOpts.framework}-router`\n\n const additionalOptimizeDeps = {\n include: new Set<string>(),\n exclude: new Set<string>(),\n }\n\n // crawl packages that have start in \"peerDependencies\"\n // see https://github.com/svitejs/vitefu/blob/d8d82fa121e3b2215ba437107093c77bde51b63b/src/index.js#L95-L101\n\n // this is currently uncached; could be implemented similarly as vite handles lock file changes\n // see https://github.com/vitejs/vite/blob/557f797d29422027e8c451ca50dd84bf8c41b5f0/packages/vite/src/node/optimizer/index.ts#L1282\n\n const result = await crawlFrameworkPkgs({\n root: process.cwd(),\n isBuild: command === 'build',\n isFrameworkPkgByJson(pkgJson) {\n if ([routerPackageName, startPackageName].includes(pkgJson.name)) {\n return false\n }\n\n const peerDependencies = pkgJson['peerDependencies']\n\n if (peerDependencies) {\n const internalResult = corePluginOpts.crawlPackages?.({\n name: pkgJson.name,\n peerDependencies,\n exports: pkgJson.exports,\n })\n if (internalResult) {\n if (internalResult === 'exclude') {\n additionalOptimizeDeps.exclude.add(pkgJson.name)\n } else {\n additionalOptimizeDeps.include.add(pkgJson.name)\n }\n }\n return (\n startPackageName in peerDependencies ||\n routerPackageName in peerDependencies\n )\n }\n return false\n },\n })\n\n return {\n base: viteAppBase,\n // see https://vite.dev/config/shared-options.html#apptype\n // this will prevent vite from injecting middlewares that we don't want\n appType: viteConfig.appType ?? 'custom',\n environments: {\n [VITE_ENVIRONMENT_NAMES.client]: {\n consumer: 'client',\n build: {\n emptyOutDir:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.client]\n ?.build?.emptyOutDir ?? true,\n rollupOptions: {\n input: {\n main: ENTRY_POINTS.client,\n },\n },\n outDir: getClientOutputDirectory(viteConfig),\n },\n },\n [VITE_ENVIRONMENT_NAMES.server]: {\n consumer: 'server',\n build: {\n emptyOutDir:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.emptyOutDir ?? false,\n ssr: true,\n rollupOptions: {\n input:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.rollupOptions?.input ?? ENTRY_POINTS.server,\n },\n outDir: getServerOutputDirectory(viteConfig),\n commonjsOptions: {\n include: [/node_modules/],\n },\n copyPublicDir:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.copyPublicDir ?? false,\n },\n optimizeDeps: {\n exclude: [\n ...Object.values(VIRTUAL_MODULES),\n ...result.optimizeDeps.exclude.sort(),\n ...additionalOptimizeDeps.exclude,\n `@tanstack/${corePluginOpts.framework}-start/server`,\n ],\n include: [\n ...additionalOptimizeDeps.include,\n ...result.optimizeDeps.include.sort(),\n ],\n },\n },\n },\n resolve: {\n noExternal: [\n '@tanstack/start**',\n `@tanstack/${corePluginOpts.framework}-start**`,\n ...Object.values(VIRTUAL_MODULES),\n startPackageName,\n ...result.ssr.noExternal.sort(),\n ],\n dedupe: [startPackageName],\n alias: {\n ...entryAliasConfiguration,\n },\n },\n optimizeDeps: {\n exclude: [\n ...Object.values(VIRTUAL_MODULES),\n startPackageName,\n ...result.optimizeDeps.exclude.sort(),\n ...additionalOptimizeDeps.exclude,\n ],\n include: [...additionalOptimizeDeps.include],\n },\n /* prettier-ignore */\n define: {\n // define is an esbuild function that replaces the any instances of given keys with the given values\n // i.e: __FRAMEWORK_NAME__ can be replaced with JSON.stringify(\"TanStack Start\")\n // This is not the same as injecting environment variables.\n\n ...defineReplaceEnv('TSS_SERVER_FN_BASE', startConfig.serverFns.base),\n ...defineReplaceEnv('TSS_OUTPUT_PUBLIC_DIR', getClientOutputDirectory(viteConfig)),\n ...defineReplaceEnv('TSS_APP_BASE', viteAppBase),\n ...(command === 'serve' ? defineReplaceEnv('TSS_SHELL', startConfig.spa?.enabled ? 'true' : 'false') : {}),\n ...defineReplaceEnv('TSS_DEV_SERVER', command === 'serve' ? 'true' : 'false'),\n },\n builder: {\n sharedPlugins: true,\n async buildApp(builder) {\n const client = builder.environments[VITE_ENVIRONMENT_NAMES.client]\n const server = builder.environments[VITE_ENVIRONMENT_NAMES.server]\n\n if (!client) {\n throw new Error('Client environment not found')\n }\n\n if (!server) {\n throw new Error('SSR environment not found')\n }\n\n if (!client.isBuilt) {\n // Build the client bundle first\n await builder.build(client)\n }\n if (!server.isBuilt) {\n // Build the SSR bundle\n await builder.build(server)\n }\n const serverBundle = getBundle(VITE_ENVIRONMENT_NAMES.server)\n await postServerBuild({ builder, startConfig, serverBundle })\n },\n },\n }\n },\n },\n // N.B. TanStackStartCompilerPlugin must be before the TanStackServerFnPluginEnv\n startCompilerPlugin(corePluginOpts.framework, {\n client: { envName: VITE_ENVIRONMENT_NAMES.client },\n server: { envName: VITE_ENVIRONMENT_NAMES.server },\n }),\n TanStackServerFnPluginEnv({\n // This is the ID that will be available to look up and import\n // our server function manifest and resolve its module\n manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest,\n client: {\n getRuntimeCode: () =>\n `import { createClientRpc } from '@tanstack/${corePluginOpts.framework}-start/client'`,\n replacer: (d) => `createClientRpc('${d.functionId}')`,\n envName: VITE_ENVIRONMENT_NAMES.client,\n },\n server: {\n getRuntimeCode: () =>\n `import { createServerRpc } from '@tanstack/${corePluginOpts.framework}-start/server'`,\n replacer: (d) => `createServerRpc('${d.functionId}', ${d.fn})`,\n envName: VITE_ENVIRONMENT_NAMES.server,\n },\n }),\n loadEnvPlugin(),\n startManifestPlugin({\n getClientBundle: () => getBundle(VITE_ENVIRONMENT_NAMES.client),\n }),\n devServerPlugin({ startConfig }),\n {\n name: 'tanstack-start:core:capture-bundle',\n applyToEnvironment(e) {\n return (\n e.name === VITE_ENVIRONMENT_NAMES.client ||\n e.name === VITE_ENVIRONMENT_NAMES.server\n )\n },\n enforce: 'post',\n generateBundle(_options, bundle) {\n const environment = this.environment.name as ViteEnvironmentNames\n if (!Object.values(VITE_ENVIRONMENT_NAMES).includes(environment)) {\n throw new Error(`Unknown environment: ${environment}`)\n }\n capturedBundle[environment] = bundle\n },\n },\n ]\n}\n\nfunction defineReplaceEnv<TKey extends string, TValue extends string>(\n key: TKey,\n value: TValue,\n): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } {\n return {\n [`process.env.${key}`]: JSON.stringify(value),\n [`import.meta.env.${key}`]: JSON.stringify(value),\n } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,58 @@ import * as t from "@babel/types";
|
|
|
3
3
|
import { codeFrameColumns } from "@babel/code-frame";
|
|
4
4
|
import { findReferencedIdentifiers, deadCodeElimination } from "babel-dead-code-elimination";
|
|
5
5
|
import { parseAst, generateFromAst } from "@tanstack/router-utils";
|
|
6
|
+
import { transformFuncs } from "./constants.js";
|
|
7
|
+
const getIdentifiers = (framework) => ({
|
|
8
|
+
createServerRootRoute: {
|
|
9
|
+
name: "createServerRootRoute",
|
|
10
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
11
|
+
framework,
|
|
12
|
+
"createServerRootRoute"
|
|
13
|
+
),
|
|
14
|
+
paths: []
|
|
15
|
+
},
|
|
16
|
+
createServerRoute: {
|
|
17
|
+
name: "createServerRoute",
|
|
18
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
19
|
+
framework,
|
|
20
|
+
"createServerRoute"
|
|
21
|
+
),
|
|
22
|
+
paths: []
|
|
23
|
+
},
|
|
24
|
+
createServerFileRoute: {
|
|
25
|
+
name: "createServerFileRoute",
|
|
26
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
27
|
+
framework,
|
|
28
|
+
"createServerFileRoute"
|
|
29
|
+
),
|
|
30
|
+
paths: []
|
|
31
|
+
},
|
|
32
|
+
createServerFn: {
|
|
33
|
+
name: "createServerFn",
|
|
34
|
+
handleCallExpression: handleCreateServerFnCallExpression,
|
|
35
|
+
paths: []
|
|
36
|
+
},
|
|
37
|
+
createMiddleware: {
|
|
38
|
+
name: "createMiddleware",
|
|
39
|
+
handleCallExpression: handleCreateMiddlewareCallExpression,
|
|
40
|
+
paths: []
|
|
41
|
+
},
|
|
42
|
+
serverOnly: {
|
|
43
|
+
name: "serverOnly",
|
|
44
|
+
handleCallExpression: handleServerOnlyCallExpression,
|
|
45
|
+
paths: []
|
|
46
|
+
},
|
|
47
|
+
clientOnly: {
|
|
48
|
+
name: "clientOnly",
|
|
49
|
+
handleCallExpression: handleClientOnlyCallExpression,
|
|
50
|
+
paths: []
|
|
51
|
+
},
|
|
52
|
+
createIsomorphicFn: {
|
|
53
|
+
name: "createIsomorphicFn",
|
|
54
|
+
handleCallExpression: handleCreateIsomorphicFnCallExpression,
|
|
55
|
+
paths: []
|
|
56
|
+
}
|
|
57
|
+
});
|
|
6
58
|
function compileStartOutputFactory(framework) {
|
|
7
59
|
return function compileStartOutput(opts) {
|
|
8
60
|
const ast = parseAst(opts);
|
|
@@ -11,65 +63,14 @@ function compileStartOutputFactory(framework) {
|
|
|
11
63
|
babel.traverse(ast, {
|
|
12
64
|
Program: {
|
|
13
65
|
enter(programPath) {
|
|
14
|
-
const identifiers =
|
|
15
|
-
createServerRootRoute: {
|
|
16
|
-
name: "createServerRootRoute",
|
|
17
|
-
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
18
|
-
framework,
|
|
19
|
-
"createServerRootRoute"
|
|
20
|
-
),
|
|
21
|
-
paths: []
|
|
22
|
-
},
|
|
23
|
-
createServerRoute: {
|
|
24
|
-
name: "createServerRoute",
|
|
25
|
-
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
26
|
-
framework,
|
|
27
|
-
"createServerRoute"
|
|
28
|
-
),
|
|
29
|
-
paths: []
|
|
30
|
-
},
|
|
31
|
-
createServerFileRoute: {
|
|
32
|
-
name: "createServerFileRoute",
|
|
33
|
-
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
34
|
-
framework,
|
|
35
|
-
"createServerFileRoute"
|
|
36
|
-
),
|
|
37
|
-
paths: []
|
|
38
|
-
},
|
|
39
|
-
createServerFn: {
|
|
40
|
-
name: "createServerFn",
|
|
41
|
-
handleCallExpression: handleCreateServerFnCallExpression,
|
|
42
|
-
paths: []
|
|
43
|
-
},
|
|
44
|
-
createMiddleware: {
|
|
45
|
-
name: "createMiddleware",
|
|
46
|
-
handleCallExpression: handleCreateMiddlewareCallExpression,
|
|
47
|
-
paths: []
|
|
48
|
-
},
|
|
49
|
-
serverOnly: {
|
|
50
|
-
name: "serverOnly",
|
|
51
|
-
handleCallExpression: handleServerOnlyCallExpression,
|
|
52
|
-
paths: []
|
|
53
|
-
},
|
|
54
|
-
clientOnly: {
|
|
55
|
-
name: "clientOnly",
|
|
56
|
-
handleCallExpression: handleClientOnlyCallExpression,
|
|
57
|
-
paths: []
|
|
58
|
-
},
|
|
59
|
-
createIsomorphicFn: {
|
|
60
|
-
name: "createIsomorphicFn",
|
|
61
|
-
handleCallExpression: handleCreateIsomorphicFnCallExpression,
|
|
62
|
-
paths: []
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
const identifierKeys = Object.keys(identifiers);
|
|
66
|
+
const identifiers = getIdentifiers(framework);
|
|
66
67
|
programPath.traverse({
|
|
67
68
|
ImportDeclaration: (path) => {
|
|
68
69
|
if (path.node.source.value !== `@tanstack/${framework}-start`) {
|
|
69
70
|
return;
|
|
70
71
|
}
|
|
71
72
|
path.node.specifiers.forEach((specifier) => {
|
|
72
|
-
|
|
73
|
+
transformFuncs.forEach((identifierKey) => {
|
|
73
74
|
const identifier = identifiers[identifierKey];
|
|
74
75
|
if (specifier.type === "ImportSpecifier" && specifier.imported.type === "Identifier") {
|
|
75
76
|
if (specifier.imported.name === identifierKey) {
|
|
@@ -83,7 +84,7 @@ function compileStartOutputFactory(framework) {
|
|
|
83
84
|
});
|
|
84
85
|
},
|
|
85
86
|
CallExpression: (path) => {
|
|
86
|
-
|
|
87
|
+
transformFuncs.forEach((identifierKey) => {
|
|
87
88
|
if (t.isIdentifier(path.node.callee) && path.node.callee.name === identifiers[identifierKey].name) {
|
|
88
89
|
if (path.scope.getBinding(identifiers[identifierKey].name)?.path.node.type === "FunctionDeclaration") {
|
|
89
90
|
return;
|
|
@@ -105,7 +106,7 @@ function compileStartOutputFactory(framework) {
|
|
|
105
106
|
});
|
|
106
107
|
}
|
|
107
108
|
});
|
|
108
|
-
|
|
109
|
+
transformFuncs.forEach((identifierKey) => {
|
|
109
110
|
identifiers[identifierKey].paths.forEach((path) => {
|
|
110
111
|
identifiers[identifierKey].handleCallExpression(
|
|
111
112
|
path,
|
|
@@ -126,9 +127,9 @@ function compileStartOutputFactory(framework) {
|
|
|
126
127
|
});
|
|
127
128
|
};
|
|
128
129
|
}
|
|
129
|
-
function handleCreateServerFileRouteCallExpressionFactory(
|
|
130
|
+
function handleCreateServerFileRouteCallExpressionFactory(framework, method) {
|
|
130
131
|
return function handleCreateServerFileRouteCallExpression(path, opts) {
|
|
131
|
-
const PACKAGES = { start: `@tanstack/${
|
|
132
|
+
const PACKAGES = { start: `@tanstack/${framework}-start/server` };
|
|
132
133
|
let highestParent = path;
|
|
133
134
|
while (highestParent.parentPath && !highestParent.parentPath.isProgram()) {
|
|
134
135
|
highestParent = highestParent.parentPath;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compilers.js","sources":["../../../src/start-compiler-plugin/compilers.ts"],"sourcesContent":["import * as babel from '@babel/core'\nimport * as t from '@babel/types'\nimport { codeFrameColumns } from '@babel/code-frame'\n\nimport {\n deadCodeElimination,\n findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport { generateFromAst, parseAst } from '@tanstack/router-utils'\nimport { transformFuncs } from './constants'\nimport type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils'\n\nexport type CompileStartFrameworkOptions = 'react' | 'solid'\n\ntype Identifiers = { [K in (typeof transformFuncs)[number]]: IdentifierConfig }\nconst getIdentifiers = (\n framework: CompileStartFrameworkOptions,\n): Identifiers => ({\n createServerRootRoute: {\n name: 'createServerRootRoute',\n handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(\n framework,\n 'createServerRootRoute',\n ),\n paths: [],\n },\n createServerRoute: {\n name: 'createServerRoute',\n handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(\n framework,\n 'createServerRoute',\n ),\n paths: [],\n },\n createServerFileRoute: {\n name: 'createServerFileRoute',\n handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(\n framework,\n 'createServerFileRoute',\n ),\n paths: [],\n },\n createServerFn: {\n name: 'createServerFn',\n handleCallExpression: handleCreateServerFnCallExpression,\n paths: [],\n },\n createMiddleware: {\n name: 'createMiddleware',\n handleCallExpression: handleCreateMiddlewareCallExpression,\n paths: [],\n },\n serverOnly: {\n name: 'serverOnly',\n handleCallExpression: handleServerOnlyCallExpression,\n paths: [],\n },\n clientOnly: {\n name: 'clientOnly',\n handleCallExpression: handleClientOnlyCallExpression,\n paths: [],\n },\n createIsomorphicFn: {\n name: 'createIsomorphicFn',\n handleCallExpression: handleCreateIsomorphicFnCallExpression,\n paths: [],\n },\n})\n\nexport function compileStartOutputFactory(\n framework: CompileStartFrameworkOptions,\n) {\n return function compileStartOutput(opts: CompileOptions): GeneratorResult {\n const ast = parseAst(opts)\n\n const doDce = opts.dce ?? true\n // find referenced identifiers *before* we transform anything\n const refIdents = doDce ? findReferencedIdentifiers(ast) : undefined\n\n babel.traverse(ast, {\n Program: {\n enter(programPath) {\n const identifiers = getIdentifiers(framework)\n programPath.traverse({\n ImportDeclaration: (path) => {\n if (path.node.source.value !== `@tanstack/${framework}-start`) {\n return\n }\n\n // handle a destructured imports being renamed like \"import { createServerFn as myCreateServerFn } from '@tanstack/react-start';\"\n path.node.specifiers.forEach((specifier) => {\n transformFuncs.forEach((identifierKey) => {\n const identifier = identifiers[identifierKey]\n\n if (\n specifier.type === 'ImportSpecifier' &&\n specifier.imported.type === 'Identifier'\n ) {\n if (specifier.imported.name === identifierKey) {\n identifier.name = specifier.local.name\n }\n }\n\n // handle namespace imports like \"import * as TanStackStart from '@tanstack/react-start';\"\n if (specifier.type === 'ImportNamespaceSpecifier') {\n identifier.name = `${specifier.local.name}.${identifierKey}`\n }\n })\n })\n },\n CallExpression: (path) => {\n transformFuncs.forEach((identifierKey) => {\n // Check to see if the call expression is a call to the\n // identifiers[identifierKey].name\n if (\n t.isIdentifier(path.node.callee) &&\n path.node.callee.name === identifiers[identifierKey].name\n ) {\n // The identifier could be a call to the original function\n // in the source code. If this is case, we need to ignore it.\n // Check the scope to see if the identifier is a function declaration.\n // if it is, then we can ignore it.\n\n if (\n path.scope.getBinding(identifiers[identifierKey].name)?.path\n .node.type === 'FunctionDeclaration'\n ) {\n return\n }\n\n return identifiers[identifierKey].paths.push(path)\n }\n\n if (t.isMemberExpression(path.node.callee)) {\n if (\n t.isIdentifier(path.node.callee.object) &&\n t.isIdentifier(path.node.callee.property)\n ) {\n const callname = [\n path.node.callee.object.name,\n path.node.callee.property.name,\n ].join('.')\n\n if (callname === identifiers[identifierKey].name) {\n identifiers[identifierKey].paths.push(path)\n }\n }\n }\n\n return\n })\n },\n })\n\n transformFuncs.forEach((identifierKey) => {\n identifiers[identifierKey].paths.forEach((path) => {\n identifiers[identifierKey].handleCallExpression(\n path as babel.NodePath<t.CallExpression>,\n opts,\n )\n })\n })\n },\n },\n })\n\n if (doDce) {\n deadCodeElimination(ast, refIdents)\n }\n\n return generateFromAst(ast, {\n sourceMaps: true,\n sourceFileName: opts.filename,\n filename: opts.filename,\n })\n }\n}\n\nfunction handleCreateServerFileRouteCallExpressionFactory(\n framework: CompileStartFrameworkOptions,\n method:\n | 'createServerFileRoute'\n | 'createServerRoute'\n | 'createServerRootRoute',\n) {\n return function handleCreateServerFileRouteCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n ) {\n const PACKAGES = { start: `@tanstack/${framework}-start/server` }\n\n let highestParent: babel.NodePath<any> = path\n\n while (highestParent.parentPath && !highestParent.parentPath.isProgram()) {\n highestParent = highestParent.parentPath\n }\n\n const programPath = highestParent.parentPath as babel.NodePath<t.Program>\n\n // If we're on the client, remove the entire variable\n if (opts.env === 'client') {\n highestParent.remove()\n return\n }\n\n let isCreateServerFileRouteImported = false as boolean\n\n programPath.traverse({\n ImportDeclaration(importPath) {\n const importSource = importPath.node.source.value\n if (importSource === PACKAGES.start) {\n const specifiers = importPath.node.specifiers\n isCreateServerFileRouteImported ||= specifiers.some((specifier) => {\n return (\n t.isImportSpecifier(specifier) &&\n t.isIdentifier(specifier.imported) &&\n specifier.imported.name === method\n )\n })\n }\n },\n })\n\n if (!isCreateServerFileRouteImported) {\n const importDeclaration = t.importDeclaration(\n [t.importSpecifier(t.identifier(method), t.identifier(method))],\n t.stringLiteral(PACKAGES.start),\n )\n programPath.node.body.unshift(importDeclaration)\n }\n }\n}\n\n// build these once and reuse them\nexport const handleServerOnlyCallExpression =\n buildEnvOnlyCallExpressionHandler('server')\nexport const handleClientOnlyCallExpression =\n buildEnvOnlyCallExpressionHandler('client')\n\nexport type CompileOptions = ParseAstOptions & {\n env: 'server' | 'client'\n dce?: boolean\n filename: string\n}\n\nexport type IdentifierConfig = {\n name: string\n handleCallExpression: (\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n ) => void\n paths: Array<babel.NodePath>\n}\n\nexport function handleCreateServerFnCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n) {\n // The function is the 'fn' property of the object passed to createServerFn\n\n // const firstArg = path.node.arguments[0]\n // if (t.isObjectExpression(firstArg)) {\n // // Was called with some options\n // }\n\n // Traverse the member expression and find the call expressions for\n // the validator, handler, and middleware methods. Check to make sure they\n // are children of the createServerFn call expression.\n\n const calledOptions = path.node.arguments[0]\n ? (path.get('arguments.0') as babel.NodePath<t.ObjectExpression>)\n : null\n\n const shouldValidateClient = !!calledOptions?.node.properties.find((prop) => {\n return (\n t.isObjectProperty(prop) &&\n t.isIdentifier(prop.key) &&\n prop.key.name === 'validateClient' &&\n t.isBooleanLiteral(prop.value) &&\n prop.value.value === true\n )\n })\n\n const callExpressionPaths = {\n middleware: null as babel.NodePath<t.CallExpression> | null,\n validator: null as babel.NodePath<t.CallExpression> | null,\n handler: null as babel.NodePath<t.CallExpression> | null,\n }\n\n const validMethods = Object.keys(callExpressionPaths)\n\n const rootCallExpression = getRootCallExpression(path)\n\n // if (debug)\n // console.info(\n // 'Handling createServerFn call expression:',\n // rootCallExpression.toString(),\n // )\n\n // Check if the call is assigned to a variable\n if (!rootCallExpression.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 = rootCallExpression.parentPath.node\n const existingVariableName = (variableDeclarator.id as t.Identifier).name\n\n rootCallExpression.traverse({\n MemberExpression(memberExpressionPath) {\n if (t.isIdentifier(memberExpressionPath.node.property)) {\n const name = memberExpressionPath.node.property\n .name as keyof typeof callExpressionPaths\n\n if (\n validMethods.includes(name) &&\n memberExpressionPath.parentPath.isCallExpression()\n ) {\n callExpressionPaths[name] = memberExpressionPath.parentPath\n }\n }\n },\n })\n\n if (callExpressionPaths.validator) {\n const innerInputExpression = callExpressionPaths.validator.node.arguments[0]\n\n if (!innerInputExpression) {\n throw new Error(\n 'createServerFn().validator() must be called with a validator!',\n )\n }\n\n // If we're on the client, and we're not validating the client, remove the validator call expression\n if (\n opts.env === 'client' &&\n !shouldValidateClient &&\n t.isMemberExpression(callExpressionPaths.validator.node.callee)\n ) {\n callExpressionPaths.validator.replaceWith(\n callExpressionPaths.validator.node.callee.object,\n )\n }\n }\n\n // First, we need to move the handler function to a nested function call\n // that is applied to the arguments passed to the server function.\n\n const handlerFnPath = callExpressionPaths.handler?.get(\n 'arguments.0',\n ) as babel.NodePath<any>\n\n if (!callExpressionPaths.handler || !handlerFnPath.node) {\n throw codeFrameError(\n opts.code,\n path.node.callee.loc!,\n `createServerFn must be called with a \"handler\" property!`,\n )\n }\n\n const handlerFn = handlerFnPath.node\n\n // So, the way we do this is we give the handler function a way\n // to access the serverFn ctx on the server via function scope.\n // The 'use server' extracted function will be called with the\n // payload from the client, then use the scoped serverFn ctx\n // to execute the handler function.\n // This way, we can do things like data and middleware validation\n // in the __execute function without having to AST transform the\n // handler function too much itself.\n\n // .handler((optsOut, ctx) => {\n // return ((optsIn) => {\n // 'use server'\n // ctx.__execute(handlerFn, optsIn)\n // })(optsOut)\n // })\n\n // If the handler function is an identifier and we're on the client, we need to\n // remove the bound function from the file.\n // If we're on the server, you can leave it, since it will get referenced\n // as a second argument.\n\n if (t.isIdentifier(handlerFn)) {\n if (opts.env === 'client') {\n // Find the binding for the handler function\n const binding = handlerFnPath.scope.getBinding(handlerFn.name)\n // Remove it\n if (binding) {\n binding.path.remove()\n }\n }\n // If the env is server, just leave it alone\n }\n\n handlerFnPath.replaceWith(\n t.arrowFunctionExpression(\n [t.identifier('opts'), t.identifier('signal')],\n t.blockStatement(\n // Everything in here is server-only, since the client\n // will strip out anything in the 'use server' directive.\n [\n t.returnStatement(\n t.callExpression(\n t.identifier(`${existingVariableName}.__executeServer`),\n [t.identifier('opts'), t.identifier('signal')],\n ),\n ),\n ],\n [t.directive(t.directiveLiteral('use server'))],\n ),\n ),\n )\n\n if (opts.env === 'server') {\n callExpressionPaths.handler.node.arguments.push(handlerFn)\n }\n}\n\nexport function handleCreateMiddlewareCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n) {\n const rootCallExpression = getRootCallExpression(path)\n\n // if (debug)\n // console.info(\n // 'Handling createMiddleware call expression:',\n // rootCallExpression.toString(),\n // )\n\n const callExpressionPaths = {\n middleware: null as babel.NodePath<t.CallExpression> | null,\n validator: null as babel.NodePath<t.CallExpression> | null,\n client: null as babel.NodePath<t.CallExpression> | null,\n server: null as babel.NodePath<t.CallExpression> | null,\n }\n\n const validMethods = Object.keys(callExpressionPaths)\n\n rootCallExpression.traverse({\n MemberExpression(memberExpressionPath) {\n if (t.isIdentifier(memberExpressionPath.node.property)) {\n const name = memberExpressionPath.node.property\n .name as keyof typeof callExpressionPaths\n\n if (\n validMethods.includes(name) &&\n memberExpressionPath.parentPath.isCallExpression()\n ) {\n callExpressionPaths[name] = memberExpressionPath.parentPath\n }\n }\n },\n })\n\n if (callExpressionPaths.validator) {\n const innerInputExpression = callExpressionPaths.validator.node.arguments[0]\n\n if (!innerInputExpression) {\n throw new Error(\n 'createMiddleware().validator() must be called with a validator!',\n )\n }\n\n // If we're on the client, remove the validator call expression\n if (opts.env === 'client') {\n if (t.isMemberExpression(callExpressionPaths.validator.node.callee)) {\n callExpressionPaths.validator.replaceWith(\n callExpressionPaths.validator.node.callee.object,\n )\n }\n }\n }\n\n const serverFnPath = callExpressionPaths.server?.get(\n 'arguments.0',\n ) as babel.NodePath<any>\n\n if (\n callExpressionPaths.server &&\n serverFnPath.node &&\n opts.env === 'client'\n ) {\n // If we're on the client, remove the server call expression\n if (t.isMemberExpression(callExpressionPaths.server.node.callee)) {\n callExpressionPaths.server.replaceWith(\n callExpressionPaths.server.node.callee.object,\n )\n }\n }\n}\n\nfunction buildEnvOnlyCallExpressionHandler(env: 'client' | 'server') {\n return function envOnlyCallExpressionHandler(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n ) {\n // if (debug)\n // console.info(`Handling ${env}Only call expression:`, path.toString())\n\n const isEnvMatch =\n env === 'client' ? opts.env === 'client' : opts.env === 'server'\n\n if (isEnvMatch) {\n // extract the inner function from the call expression\n const innerInputExpression = path.node.arguments[0]\n\n if (!t.isExpression(innerInputExpression)) {\n throw new Error(\n `${env}Only() functions must be called with a function!`,\n )\n }\n\n path.replaceWith(innerInputExpression)\n return\n }\n\n // If we're on the wrong environment, replace the call expression\n // with a function that always 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 `${env}Only() functions can only be called on the ${env}!`,\n ),\n ]),\n ),\n ]),\n ),\n )\n }\n}\n\nexport function handleCreateIsomorphicFnCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n) {\n const rootCallExpression = getRootCallExpression(path)\n\n // if (debug)\n // console.info(\n // 'Handling createIsomorphicFn call expression:',\n // rootCallExpression.toString(),\n // )\n\n const callExpressionPaths = {\n client: null as babel.NodePath<t.CallExpression> | null,\n server: null as babel.NodePath<t.CallExpression> | null,\n }\n\n const validMethods = Object.keys(callExpressionPaths)\n\n rootCallExpression.traverse({\n MemberExpression(memberExpressionPath) {\n if (t.isIdentifier(memberExpressionPath.node.property)) {\n const name = memberExpressionPath.node.property\n .name as keyof typeof callExpressionPaths\n\n if (\n validMethods.includes(name) &&\n memberExpressionPath.parentPath.isCallExpression()\n ) {\n callExpressionPaths[name] = memberExpressionPath.parentPath\n }\n }\n },\n })\n\n if (\n validMethods.every(\n (method) =>\n !callExpressionPaths[method as keyof typeof callExpressionPaths],\n )\n ) {\n const variableId = rootCallExpression.parentPath.isVariableDeclarator()\n ? rootCallExpression.parentPath.node.id\n : null\n console.warn(\n 'createIsomorphicFn called without a client or server implementation!',\n 'This will result in a no-op function.',\n 'Variable name:',\n t.isIdentifier(variableId) ? variableId.name : 'unknown',\n )\n }\n\n const envCallExpression = callExpressionPaths[opts.env]\n\n if (!envCallExpression) {\n // if we don't have an implementation for this environment, default to a no-op\n rootCallExpression.replaceWith(\n t.arrowFunctionExpression([], t.blockStatement([])),\n )\n return\n }\n\n const innerInputExpression = envCallExpression.node.arguments[0]\n\n if (!t.isExpression(innerInputExpression)) {\n throw new Error(\n `createIsomorphicFn().${opts.env}(func) must be called with a function!`,\n )\n }\n\n rootCallExpression.replaceWith(innerInputExpression)\n}\n\nexport function getRootCallExpression(path: babel.NodePath<t.CallExpression>) {\n // Find the highest callExpression parent\n let rootCallExpression: babel.NodePath<t.CallExpression> = path\n\n // Traverse up the chain of CallExpressions\n while (rootCallExpression.parentPath.isMemberExpression()) {\n const parent = rootCallExpression.parentPath\n if (parent.parentPath.isCallExpression()) {\n rootCallExpression = parent.parentPath\n }\n }\n\n return rootCallExpression\n}\n\nfunction 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"],"names":[],"mappings":";;;;;;AAeA,MAAM,iBAAiB,CACrB,eACiB;AAAA,EACjB,uBAAuB;AAAA,IACrB,MAAM;AAAA,IACN,sBAAsB;AAAA,MACpB;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,mBAAmB;AAAA,IACjB,MAAM;AAAA,IACN,sBAAsB;AAAA,MACpB;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,uBAAuB;AAAA,IACrB,MAAM;AAAA,IACN,sBAAsB;AAAA,MACpB;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,sBAAsB;AAAA,IACtB,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,kBAAkB;AAAA,IAChB,MAAM;AAAA,IACN,sBAAsB;AAAA,IACtB,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,YAAY;AAAA,IACV,MAAM;AAAA,IACN,sBAAsB;AAAA,IACtB,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,YAAY;AAAA,IACV,MAAM;AAAA,IACN,sBAAsB;AAAA,IACtB,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,oBAAoB;AAAA,IAClB,MAAM;AAAA,IACN,sBAAsB;AAAA,IACtB,OAAO,CAAA;AAAA,EAAC;AAEZ;AAEO,SAAS,0BACd,WACA;AACA,SAAO,SAAS,mBAAmB,MAAuC;AACxE,UAAM,MAAM,SAAS,IAAI;AAEzB,UAAM,QAAQ,KAAK,OAAO;AAE1B,UAAM,YAAY,QAAQ,0BAA0B,GAAG,IAAI;AAE3D,UAAM,SAAS,KAAK;AAAA,MAClB,SAAS;AAAA,QACP,MAAM,aAAa;AACjB,gBAAM,cAAc,eAAe,SAAS;AAC5C,sBAAY,SAAS;AAAA,YACnB,mBAAmB,CAAC,SAAS;AAC3B,kBAAI,KAAK,KAAK,OAAO,UAAU,aAAa,SAAS,UAAU;AAC7D;AAAA,cACF;AAGA,mBAAK,KAAK,WAAW,QAAQ,CAAC,cAAc;AAC1C,+BAAe,QAAQ,CAAC,kBAAkB;AACxC,wBAAM,aAAa,YAAY,aAAa;AAE5C,sBACE,UAAU,SAAS,qBACnB,UAAU,SAAS,SAAS,cAC5B;AACA,wBAAI,UAAU,SAAS,SAAS,eAAe;AAC7C,iCAAW,OAAO,UAAU,MAAM;AAAA,oBACpC;AAAA,kBACF;AAGA,sBAAI,UAAU,SAAS,4BAA4B;AACjD,+BAAW,OAAO,GAAG,UAAU,MAAM,IAAI,IAAI,aAAa;AAAA,kBAC5D;AAAA,gBACF,CAAC;AAAA,cACH,CAAC;AAAA,YACH;AAAA,YACA,gBAAgB,CAAC,SAAS;AACxB,6BAAe,QAAQ,CAAC,kBAAkB;AAGxC,oBACE,EAAE,aAAa,KAAK,KAAK,MAAM,KAC/B,KAAK,KAAK,OAAO,SAAS,YAAY,aAAa,EAAE,MACrD;AAMA,sBACE,KAAK,MAAM,WAAW,YAAY,aAAa,EAAE,IAAI,GAAG,KACrD,KAAK,SAAS,uBACjB;AACA;AAAA,kBACF;AAEA,yBAAO,YAAY,aAAa,EAAE,MAAM,KAAK,IAAI;AAAA,gBACnD;AAEA,oBAAI,EAAE,mBAAmB,KAAK,KAAK,MAAM,GAAG;AAC1C,sBACE,EAAE,aAAa,KAAK,KAAK,OAAO,MAAM,KACtC,EAAE,aAAa,KAAK,KAAK,OAAO,QAAQ,GACxC;AACA,0BAAM,WAAW;AAAA,sBACf,KAAK,KAAK,OAAO,OAAO;AAAA,sBACxB,KAAK,KAAK,OAAO,SAAS;AAAA,oBAAA,EAC1B,KAAK,GAAG;AAEV,wBAAI,aAAa,YAAY,aAAa,EAAE,MAAM;AAChD,kCAAY,aAAa,EAAE,MAAM,KAAK,IAAI;AAAA,oBAC5C;AAAA,kBACF;AAAA,gBACF;AAEA;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UAAA,CACD;AAED,yBAAe,QAAQ,CAAC,kBAAkB;AACxC,wBAAY,aAAa,EAAE,MAAM,QAAQ,CAAC,SAAS;AACjD,0BAAY,aAAa,EAAE;AAAA,gBACzB;AAAA,gBACA;AAAA,cAAA;AAAA,YAEJ,CAAC;AAAA,UACH,CAAC;AAAA,QACH;AAAA,MAAA;AAAA,IACF,CACD;AAED,QAAI,OAAO;AACT,0BAAoB,KAAK,SAAS;AAAA,IACpC;AAEA,WAAO,gBAAgB,KAAK;AAAA,MAC1B,YAAY;AAAA,MACZ,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,IAAA,CAChB;AAAA,EACH;AACF;AAEA,SAAS,iDACP,WACA,QAIA;AACA,SAAO,SAAS,0CACd,MACA,MACA;AACA,UAAM,WAAW,EAAE,OAAO,aAAa,SAAS,gBAAA;AAEhD,QAAI,gBAAqC;AAEzC,WAAO,cAAc,cAAc,CAAC,cAAc,WAAW,aAAa;AACxE,sBAAgB,cAAc;AAAA,IAChC;AAEA,UAAM,cAAc,cAAc;AAGlC,QAAI,KAAK,QAAQ,UAAU;AACzB,oBAAc,OAAA;AACd;AAAA,IACF;AAEA,QAAI,kCAAkC;AAEtC,gBAAY,SAAS;AAAA,MACnB,kBAAkB,YAAY;AAC5B,cAAM,eAAe,WAAW,KAAK,OAAO;AAC5C,YAAI,iBAAiB,SAAS,OAAO;AACnC,gBAAM,aAAa,WAAW,KAAK;AACnC,8CAAoC,WAAW,KAAK,CAAC,cAAc;AACjE,mBACE,EAAE,kBAAkB,SAAS,KAC7B,EAAE,aAAa,UAAU,QAAQ,KACjC,UAAU,SAAS,SAAS;AAAA,UAEhC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IAAA,CACD;AAED,QAAI,CAAC,iCAAiC;AACpC,YAAM,oBAAoB,EAAE;AAAA,QAC1B,CAAC,EAAE,gBAAgB,EAAE,WAAW,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC,CAAC;AAAA,QAC9D,EAAE,cAAc,SAAS,KAAK;AAAA,MAAA;AAEhC,kBAAY,KAAK,KAAK,QAAQ,iBAAiB;AAAA,IACjD;AAAA,EACF;AACF;AAGO,MAAM,iCACX,kCAAkC,QAAQ;AACrC,MAAM,iCACX,kCAAkC,QAAQ;AAiBrC,SAAS,mCACd,MACA,MACA;AAYA,QAAM,gBAAgB,KAAK,KAAK,UAAU,CAAC,IACtC,KAAK,IAAI,aAAa,IACvB;AAEJ,QAAM,uBAAuB,CAAC,CAAC,eAAe,KAAK,WAAW,KAAK,CAAC,SAAS;AAC3E,WACE,EAAE,iBAAiB,IAAI,KACvB,EAAE,aAAa,KAAK,GAAG,KACvB,KAAK,IAAI,SAAS,oBAClB,EAAE,iBAAiB,KAAK,KAAK,KAC7B,KAAK,MAAM,UAAU;AAAA,EAEzB,CAAC;AAED,QAAM,sBAAsB;AAAA,IAC1B,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,SAAS;AAAA,EAAA;AAGX,QAAM,eAAe,OAAO,KAAK,mBAAmB;AAEpD,QAAM,qBAAqB,sBAAsB,IAAI;AASrD,MAAI,CAAC,mBAAmB,WAAW,wBAAwB;AACzD,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAGA,QAAM,qBAAqB,mBAAmB,WAAW;AACzD,QAAM,uBAAwB,mBAAmB,GAAoB;AAErE,qBAAmB,SAAS;AAAA,IAC1B,iBAAiB,sBAAsB;AACrC,UAAI,EAAE,aAAa,qBAAqB,KAAK,QAAQ,GAAG;AACtD,cAAM,OAAO,qBAAqB,KAAK,SACpC;AAEH,YACE,aAAa,SAAS,IAAI,KAC1B,qBAAqB,WAAW,oBAChC;AACA,8BAAoB,IAAI,IAAI,qBAAqB;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EAAA,CACD;AAED,MAAI,oBAAoB,WAAW;AACjC,UAAM,uBAAuB,oBAAoB,UAAU,KAAK,UAAU,CAAC;AAE3E,QAAI,CAAC,sBAAsB;AACzB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAGA,QACE,KAAK,QAAQ,YACb,CAAC,wBACD,EAAE,mBAAmB,oBAAoB,UAAU,KAAK,MAAM,GAC9D;AACA,0BAAoB,UAAU;AAAA,QAC5B,oBAAoB,UAAU,KAAK,OAAO;AAAA,MAAA;AAAA,IAE9C;AAAA,EACF;AAKA,QAAM,gBAAgB,oBAAoB,SAAS;AAAA,IACjD;AAAA,EAAA;AAGF,MAAI,CAAC,oBAAoB,WAAW,CAAC,cAAc,MAAM;AACvD,UAAM;AAAA,MACJ,KAAK;AAAA,MACL,KAAK,KAAK,OAAO;AAAA,MACjB;AAAA,IAAA;AAAA,EAEJ;AAEA,QAAM,YAAY,cAAc;AAuBhC,MAAI,EAAE,aAAa,SAAS,GAAG;AAC7B,QAAI,KAAK,QAAQ,UAAU;AAEzB,YAAM,UAAU,cAAc,MAAM,WAAW,UAAU,IAAI;AAE7D,UAAI,SAAS;AACX,gBAAQ,KAAK,OAAA;AAAA,MACf;AAAA,IACF;AAAA,EAEF;AAEA,gBAAc;AAAA,IACZ,EAAE;AAAA,MACA,CAAC,EAAE,WAAW,MAAM,GAAG,EAAE,WAAW,QAAQ,CAAC;AAAA,MAC7C,EAAE;AAAA;AAAA;AAAA,QAGA;AAAA,UACE,EAAE;AAAA,YACA,EAAE;AAAA,cACA,EAAE,WAAW,GAAG,oBAAoB,kBAAkB;AAAA,cACtD,CAAC,EAAE,WAAW,MAAM,GAAG,EAAE,WAAW,QAAQ,CAAC;AAAA,YAAA;AAAA,UAC/C;AAAA,QACF;AAAA,QAEF,CAAC,EAAE,UAAU,EAAE,iBAAiB,YAAY,CAAC,CAAC;AAAA,MAAA;AAAA,IAChD;AAAA,EACF;AAGF,MAAI,KAAK,QAAQ,UAAU;AACzB,wBAAoB,QAAQ,KAAK,UAAU,KAAK,SAAS;AAAA,EAC3D;AACF;AAEO,SAAS,qCACd,MACA,MACA;AACA,QAAM,qBAAqB,sBAAsB,IAAI;AAQrD,QAAM,sBAAsB;AAAA,IAC1B,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAGV,QAAM,eAAe,OAAO,KAAK,mBAAmB;AAEpD,qBAAmB,SAAS;AAAA,IAC1B,iBAAiB,sBAAsB;AACrC,UAAI,EAAE,aAAa,qBAAqB,KAAK,QAAQ,GAAG;AACtD,cAAM,OAAO,qBAAqB,KAAK,SACpC;AAEH,YACE,aAAa,SAAS,IAAI,KAC1B,qBAAqB,WAAW,oBAChC;AACA,8BAAoB,IAAI,IAAI,qBAAqB;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EAAA,CACD;AAED,MAAI,oBAAoB,WAAW;AACjC,UAAM,uBAAuB,oBAAoB,UAAU,KAAK,UAAU,CAAC;AAE3E,QAAI,CAAC,sBAAsB;AACzB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAGA,QAAI,KAAK,QAAQ,UAAU;AACzB,UAAI,EAAE,mBAAmB,oBAAoB,UAAU,KAAK,MAAM,GAAG;AACnE,4BAAoB,UAAU;AAAA,UAC5B,oBAAoB,UAAU,KAAK,OAAO;AAAA,QAAA;AAAA,MAE9C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,oBAAoB,QAAQ;AAAA,IAC/C;AAAA,EAAA;AAGF,MACE,oBAAoB,UACpB,aAAa,QACb,KAAK,QAAQ,UACb;AAEA,QAAI,EAAE,mBAAmB,oBAAoB,OAAO,KAAK,MAAM,GAAG;AAChE,0BAAoB,OAAO;AAAA,QACzB,oBAAoB,OAAO,KAAK,OAAO;AAAA,MAAA;AAAA,IAE3C;AAAA,EACF;AACF;AAEA,SAAS,kCAAkC,KAA0B;AACnE,SAAO,SAAS,6BACd,MACA,MACA;AAIA,UAAM,aACJ,QAAQ,WAAW,KAAK,QAAQ,WAAW,KAAK,QAAQ;AAE1D,QAAI,YAAY;AAEd,YAAM,uBAAuB,KAAK,KAAK,UAAU,CAAC;AAElD,UAAI,CAAC,EAAE,aAAa,oBAAoB,GAAG;AACzC,cAAM,IAAI;AAAA,UACR,GAAG,GAAG;AAAA,QAAA;AAAA,MAEV;AAEA,WAAK,YAAY,oBAAoB;AACrC;AAAA,IACF;AAIA,SAAK;AAAA,MACH,EAAE;AAAA,QACA,CAAA;AAAA,QACA,EAAE,eAAe;AAAA,UACf,EAAE;AAAA,YACA,EAAE,cAAc,EAAE,WAAW,OAAO,GAAG;AAAA,cACrC,EAAE;AAAA,gBACA,GAAG,GAAG,8CAA8C,GAAG;AAAA,cAAA;AAAA,YACzD,CACD;AAAA,UAAA;AAAA,QACH,CACD;AAAA,MAAA;AAAA,IACH;AAAA,EAEJ;AACF;AAEO,SAAS,uCACd,MACA,MACA;AACA,QAAM,qBAAqB,sBAAsB,IAAI;AAQrD,QAAM,sBAAsB;AAAA,IAC1B,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA;AAGV,QAAM,eAAe,OAAO,KAAK,mBAAmB;AAEpD,qBAAmB,SAAS;AAAA,IAC1B,iBAAiB,sBAAsB;AACrC,UAAI,EAAE,aAAa,qBAAqB,KAAK,QAAQ,GAAG;AACtD,cAAM,OAAO,qBAAqB,KAAK,SACpC;AAEH,YACE,aAAa,SAAS,IAAI,KAC1B,qBAAqB,WAAW,oBAChC;AACA,8BAAoB,IAAI,IAAI,qBAAqB;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EAAA,CACD;AAED,MACE,aAAa;AAAA,IACX,CAAC,WACC,CAAC,oBAAoB,MAA0C;AAAA,EAAA,GAEnE;AACA,UAAM,aAAa,mBAAmB,WAAW,qBAAA,IAC7C,mBAAmB,WAAW,KAAK,KACnC;AACJ,YAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,aAAa,UAAU,IAAI,WAAW,OAAO;AAAA,IAAA;AAAA,EAEnD;AAEA,QAAM,oBAAoB,oBAAoB,KAAK,GAAG;AAEtD,MAAI,CAAC,mBAAmB;AAEtB,uBAAmB;AAAA,MACjB,EAAE,wBAAwB,CAAA,GAAI,EAAE,eAAe,CAAA,CAAE,CAAC;AAAA,IAAA;AAEpD;AAAA,EACF;AAEA,QAAM,uBAAuB,kBAAkB,KAAK,UAAU,CAAC;AAE/D,MAAI,CAAC,EAAE,aAAa,oBAAoB,GAAG;AACzC,UAAM,IAAI;AAAA,MACR,wBAAwB,KAAK,GAAG;AAAA,IAAA;AAAA,EAEpC;AAEA,qBAAmB,YAAY,oBAAoB;AACrD;AAEO,SAAS,sBAAsB,MAAwC;AAE5E,MAAI,qBAAuD;AAG3D,SAAO,mBAAmB,WAAW,sBAAsB;AACzD,UAAM,SAAS,mBAAmB;AAClC,QAAI,OAAO,WAAW,oBAAoB;AACxC,2BAAqB,OAAO;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eACP,MACA,KAIA,SACA;AACA,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,MACE,OAAO,IAAI;AAAA,MACX,KAAK,IAAI;AAAA,IAAA;AAAA,IAEX;AAAA,MACE,eAAe;AAAA,MACf;AAAA,IAAA;AAAA,EACF;AAGF,SAAO,IAAI,MAAM,KAAK;AACxB;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const transformFuncs: readonly ["createServerFn", "createMiddleware", "serverOnly", "clientOnly", "createIsomorphicFn", "createServerRoute", "createServerFileRoute", "createServerRootRoute"];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const transformFuncs = [
|
|
2
|
+
"createServerFn",
|
|
3
|
+
"createMiddleware",
|
|
4
|
+
"serverOnly",
|
|
5
|
+
"clientOnly",
|
|
6
|
+
"createIsomorphicFn",
|
|
7
|
+
"createServerRoute",
|
|
8
|
+
"createServerFileRoute",
|
|
9
|
+
"createServerRootRoute"
|
|
10
|
+
];
|
|
11
|
+
export {
|
|
12
|
+
transformFuncs
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../../../src/start-compiler-plugin/constants.ts"],"sourcesContent":["export const transformFuncs = [\n 'createServerFn',\n 'createMiddleware',\n 'serverOnly',\n 'clientOnly',\n 'createIsomorphicFn',\n 'createServerRoute',\n 'createServerFileRoute',\n 'createServerRootRoute',\n] as const\n"],"names":[],"mappings":"AAAO,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;"}
|
|
@@ -2,16 +2,8 @@ import { pathToFileURL, fileURLToPath } from "node:url";
|
|
|
2
2
|
import { logDiff } from "@tanstack/router-utils";
|
|
3
3
|
import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
|
|
4
4
|
import { compileStartOutputFactory } from "./compilers.js";
|
|
5
|
+
import { transformFuncs } from "./constants.js";
|
|
5
6
|
const debug = process.env.TSR_VITE_DEBUG && ["true", "start-plugin"].includes(process.env.TSR_VITE_DEBUG);
|
|
6
|
-
const transformFuncs = [
|
|
7
|
-
"createServerFn",
|
|
8
|
-
"createMiddleware",
|
|
9
|
-
"serverOnly",
|
|
10
|
-
"clientOnly",
|
|
11
|
-
"createIsomorphicFn",
|
|
12
|
-
"createServerFileRoute",
|
|
13
|
-
"createServerRootRoute"
|
|
14
|
-
];
|
|
15
7
|
const tokenRegex = new RegExp(transformFuncs.join("|"));
|
|
16
8
|
function startCompilerPlugin(framework, inputOpts) {
|
|
17
9
|
const opts = {
|
|
@@ -25,7 +17,7 @@ function startCompilerPlugin(framework, inputOpts) {
|
|
|
25
17
|
}
|
|
26
18
|
};
|
|
27
19
|
return {
|
|
28
|
-
name: "
|
|
20
|
+
name: "tanstack-start-core:compiler",
|
|
29
21
|
enforce: "pre",
|
|
30
22
|
applyToEnvironment(env) {
|
|
31
23
|
return [opts.client.envName, opts.server.envName].includes(env.name);
|
|
@@ -75,4 +67,4 @@ function transformCode(opts) {
|
|
|
75
67
|
export {
|
|
76
68
|
startCompilerPlugin
|
|
77
69
|
};
|
|
78
|
-
//# sourceMappingURL=
|
|
70
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../../../src/start-compiler-plugin/plugin.ts"],"sourcesContent":["import { fileURLToPath, pathToFileURL } from 'node:url'\nimport { logDiff } from '@tanstack/router-utils'\n\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { compileStartOutputFactory } from './compilers'\nimport { transformFuncs } from './constants'\nimport type { Plugin } from 'vite'\nimport type { CompileStartFrameworkOptions } from './compilers'\n\nconst debug =\n process.env.TSR_VITE_DEBUG &&\n ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG)\n\nexport type TanStackStartViteOptions = {\n globalMiddlewareEntry: string\n}\n\nconst tokenRegex = new RegExp(transformFuncs.join('|'))\n\nexport function startCompilerPlugin(\n framework: CompileStartFrameworkOptions,\n inputOpts?: {\n client?: {\n envName?: string\n }\n server?: {\n envName?: string\n }\n },\n): Plugin {\n const opts = {\n client: {\n envName: 'client',\n ...inputOpts?.client,\n },\n server: {\n envName: 'server',\n ...inputOpts?.server,\n },\n }\n\n return {\n name: 'tanstack-start-core:compiler',\n enforce: 'pre',\n applyToEnvironment(env) {\n return [opts.client.envName, opts.server.envName].includes(env.name)\n },\n transform: {\n filter: {\n code: tokenRegex,\n id: {\n exclude: VIRTUAL_MODULES.serverFnManifest,\n },\n },\n handler(code, id) {\n const env =\n this.environment.name === opts.client.envName\n ? 'client'\n : this.environment.name === opts.server.envName\n ? 'server'\n : (() => {\n throw new Error(\n `Environment ${this.environment.name} not configured`,\n )\n })()\n\n return transformCode({\n code,\n id,\n env,\n framework,\n })\n },\n },\n }\n}\n\nfunction transformCode(opts: {\n code: string\n id: string\n env: 'server' | 'client'\n framework: CompileStartFrameworkOptions\n}) {\n const { code, env, framework } = opts\n let { id } = opts\n\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n id = fileURLToPath(url).replace(/\\\\/g, '/')\n\n if (debug) console.info(`${env} Compiling Start: `, id)\n\n const compileStartOutput = compileStartOutputFactory(framework)\n const compiled = compileStartOutput({\n code,\n filename: id,\n env,\n })\n\n if (debug) {\n logDiff(code, compiled.code)\n console.log('Output:\\n', compiled.code + '\\n\\n')\n }\n\n return compiled\n}\n"],"names":[],"mappings":";;;;;AASA,MAAM,QACJ,QAAQ,IAAI,kBACZ,CAAC,QAAQ,cAAc,EAAE,SAAS,QAAQ,IAAI,cAAc;AAM9D,MAAM,aAAa,IAAI,OAAO,eAAe,KAAK,GAAG,CAAC;AAE/C,SAAS,oBACd,WACA,WAQQ;AACR,QAAM,OAAO;AAAA,IACX,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,GAAG,WAAW;AAAA,IAAA;AAAA,IAEhB,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,GAAG,WAAW;AAAA,IAAA;AAAA,EAChB;AAGF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,mBAAmB,KAAK;AACtB,aAAO,CAAC,KAAK,OAAO,SAAS,KAAK,OAAO,OAAO,EAAE,SAAS,IAAI,IAAI;AAAA,IACrE;AAAA,IACA,WAAW;AAAA,MACT,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,IAAI;AAAA,UACF,SAAS,gBAAgB;AAAA,QAAA;AAAA,MAC3B;AAAA,MAEF,QAAQ,MAAM,IAAI;AAChB,cAAM,MACJ,KAAK,YAAY,SAAS,KAAK,OAAO,UAClC,WACA,KAAK,YAAY,SAAS,KAAK,OAAO,UACpC,YACC,MAAM;AACL,gBAAM,IAAI;AAAA,YACR,eAAe,KAAK,YAAY,IAAI;AAAA,UAAA;AAAA,QAExC,GAAA;AAER,eAAO,cAAc;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IAAA;AAAA,EACF;AAEJ;AAEA,SAAS,cAAc,MAKpB;AACD,QAAM,EAAE,MAAM,KAAK,UAAA,IAAc;AACjC,MAAI,EAAE,OAAO;AAEb,QAAM,MAAM,cAAc,EAAE;AAC5B,MAAI,aAAa,OAAO,GAAG;AAC3B,OAAK,cAAc,GAAG,EAAE,QAAQ,OAAO,GAAG;AAE1C,MAAI,MAAO,SAAQ,KAAK,GAAG,GAAG,sBAAsB,EAAE;AAEtD,QAAM,qBAAqB,0BAA0B,SAAS;AAC9D,QAAM,WAAW,mBAAmB;AAAA,IAClC;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EAAA,CACD;AAED,MAAI,OAAO;AACT,YAAQ,MAAM,SAAS,IAAI;AAC3B,YAAQ,IAAI,aAAa,SAAS,OAAO,MAAM;AAAA,EACjD;AAEA,SAAO;AACT;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/start-plugin-core",
|
|
3
|
-
"version": "1.132.0-alpha.
|
|
3
|
+
"version": "1.132.0-alpha.4",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
"vitefu": "^1.1.1",
|
|
58
58
|
"xmlbuilder2": "^3.1.1",
|
|
59
59
|
"zod": "^3.24.2",
|
|
60
|
-
"@tanstack/router-core": "1.132.0-alpha.
|
|
61
|
-
"@tanstack/router-generator": "1.132.0-alpha.
|
|
62
|
-
"@tanstack/router-plugin": "1.132.0-alpha.
|
|
60
|
+
"@tanstack/router-core": "1.132.0-alpha.4",
|
|
61
|
+
"@tanstack/router-generator": "1.132.0-alpha.4",
|
|
62
|
+
"@tanstack/router-plugin": "1.132.0-alpha.4",
|
|
63
63
|
"@tanstack/router-utils": "1.132.0-alpha.1",
|
|
64
64
|
"@tanstack/server-functions-plugin": "1.132.0-alpha.3",
|
|
65
|
-
"@tanstack/start-server-core": "1.132.0-alpha.
|
|
65
|
+
"@tanstack/start-server-core": "1.132.0-alpha.4"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/babel__code-frame": "^7.0.6",
|
package/src/plugin.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as vite from 'vite'
|
|
|
6
6
|
import { crawlFrameworkPkgs } from 'vitefu'
|
|
7
7
|
import { join } from 'pathe'
|
|
8
8
|
import { startManifestPlugin } from './start-manifest-plugin/plugin'
|
|
9
|
-
import { startCompilerPlugin } from './start-compiler-plugin'
|
|
9
|
+
import { startCompilerPlugin } from './start-compiler-plugin/plugin'
|
|
10
10
|
import { ENTRY_POINTS, VITE_ENVIRONMENT_NAMES } from './constants'
|
|
11
11
|
import { tanStackStartRouter } from './start-router-plugin/plugin'
|
|
12
12
|
import { loadEnvPlugin } from './load-env-plugin/plugin'
|
|
@@ -21,7 +21,7 @@ import { postServerBuild } from './post-server-build'
|
|
|
21
21
|
import type { ViteEnvironmentNames } from './constants'
|
|
22
22
|
import type { TanStackStartInputConfig } from './schema'
|
|
23
23
|
import type { PluginOption } from 'vite'
|
|
24
|
-
import type { CompileStartFrameworkOptions } from './compilers'
|
|
24
|
+
import type { CompileStartFrameworkOptions } from './start-compiler-plugin/compilers'
|
|
25
25
|
|
|
26
26
|
export interface TanStackStartVitePluginCoreOptions {
|
|
27
27
|
framework: CompileStartFrameworkOptions
|
|
@@ -7,10 +7,66 @@ import {
|
|
|
7
7
|
findReferencedIdentifiers,
|
|
8
8
|
} from 'babel-dead-code-elimination'
|
|
9
9
|
import { generateFromAst, parseAst } from '@tanstack/router-utils'
|
|
10
|
+
import { transformFuncs } from './constants'
|
|
10
11
|
import type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils'
|
|
11
12
|
|
|
12
13
|
export type CompileStartFrameworkOptions = 'react' | 'solid'
|
|
13
14
|
|
|
15
|
+
type Identifiers = { [K in (typeof transformFuncs)[number]]: IdentifierConfig }
|
|
16
|
+
const getIdentifiers = (
|
|
17
|
+
framework: CompileStartFrameworkOptions,
|
|
18
|
+
): Identifiers => ({
|
|
19
|
+
createServerRootRoute: {
|
|
20
|
+
name: 'createServerRootRoute',
|
|
21
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
22
|
+
framework,
|
|
23
|
+
'createServerRootRoute',
|
|
24
|
+
),
|
|
25
|
+
paths: [],
|
|
26
|
+
},
|
|
27
|
+
createServerRoute: {
|
|
28
|
+
name: 'createServerRoute',
|
|
29
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
30
|
+
framework,
|
|
31
|
+
'createServerRoute',
|
|
32
|
+
),
|
|
33
|
+
paths: [],
|
|
34
|
+
},
|
|
35
|
+
createServerFileRoute: {
|
|
36
|
+
name: 'createServerFileRoute',
|
|
37
|
+
handleCallExpression: handleCreateServerFileRouteCallExpressionFactory(
|
|
38
|
+
framework,
|
|
39
|
+
'createServerFileRoute',
|
|
40
|
+
),
|
|
41
|
+
paths: [],
|
|
42
|
+
},
|
|
43
|
+
createServerFn: {
|
|
44
|
+
name: 'createServerFn',
|
|
45
|
+
handleCallExpression: handleCreateServerFnCallExpression,
|
|
46
|
+
paths: [],
|
|
47
|
+
},
|
|
48
|
+
createMiddleware: {
|
|
49
|
+
name: 'createMiddleware',
|
|
50
|
+
handleCallExpression: handleCreateMiddlewareCallExpression,
|
|
51
|
+
paths: [],
|
|
52
|
+
},
|
|
53
|
+
serverOnly: {
|
|
54
|
+
name: 'serverOnly',
|
|
55
|
+
handleCallExpression: handleServerOnlyCallExpression,
|
|
56
|
+
paths: [],
|
|
57
|
+
},
|
|
58
|
+
clientOnly: {
|
|
59
|
+
name: 'clientOnly',
|
|
60
|
+
handleCallExpression: handleClientOnlyCallExpression,
|
|
61
|
+
paths: [],
|
|
62
|
+
},
|
|
63
|
+
createIsomorphicFn: {
|
|
64
|
+
name: 'createIsomorphicFn',
|
|
65
|
+
handleCallExpression: handleCreateIsomorphicFnCallExpression,
|
|
66
|
+
paths: [],
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
|
|
14
70
|
export function compileStartOutputFactory(
|
|
15
71
|
framework: CompileStartFrameworkOptions,
|
|
16
72
|
) {
|
|
@@ -24,74 +80,7 @@ export function compileStartOutputFactory(
|
|
|
24
80
|
babel.traverse(ast, {
|
|
25
81
|
Program: {
|
|
26
82
|
enter(programPath) {
|
|
27
|
-
const identifiers
|
|
28
|
-
createServerRoute: IdentifierConfig
|
|
29
|
-
createServerFileRoute: IdentifierConfig
|
|
30
|
-
createServerFn: IdentifierConfig
|
|
31
|
-
createMiddleware: IdentifierConfig
|
|
32
|
-
serverOnly: IdentifierConfig
|
|
33
|
-
clientOnly: IdentifierConfig
|
|
34
|
-
createIsomorphicFn: IdentifierConfig
|
|
35
|
-
createServerRootRoute: IdentifierConfig
|
|
36
|
-
} = {
|
|
37
|
-
createServerRootRoute: {
|
|
38
|
-
name: 'createServerRootRoute',
|
|
39
|
-
handleCallExpression:
|
|
40
|
-
handleCreateServerFileRouteCallExpressionFactory(
|
|
41
|
-
framework,
|
|
42
|
-
'createServerRootRoute',
|
|
43
|
-
),
|
|
44
|
-
paths: [],
|
|
45
|
-
},
|
|
46
|
-
createServerRoute: {
|
|
47
|
-
name: 'createServerRoute',
|
|
48
|
-
handleCallExpression:
|
|
49
|
-
handleCreateServerFileRouteCallExpressionFactory(
|
|
50
|
-
framework,
|
|
51
|
-
'createServerRoute',
|
|
52
|
-
),
|
|
53
|
-
paths: [],
|
|
54
|
-
},
|
|
55
|
-
createServerFileRoute: {
|
|
56
|
-
name: 'createServerFileRoute',
|
|
57
|
-
handleCallExpression:
|
|
58
|
-
handleCreateServerFileRouteCallExpressionFactory(
|
|
59
|
-
framework,
|
|
60
|
-
'createServerFileRoute',
|
|
61
|
-
),
|
|
62
|
-
paths: [],
|
|
63
|
-
},
|
|
64
|
-
createServerFn: {
|
|
65
|
-
name: 'createServerFn',
|
|
66
|
-
handleCallExpression: handleCreateServerFnCallExpression,
|
|
67
|
-
paths: [],
|
|
68
|
-
},
|
|
69
|
-
createMiddleware: {
|
|
70
|
-
name: 'createMiddleware',
|
|
71
|
-
handleCallExpression: handleCreateMiddlewareCallExpression,
|
|
72
|
-
paths: [],
|
|
73
|
-
},
|
|
74
|
-
serverOnly: {
|
|
75
|
-
name: 'serverOnly',
|
|
76
|
-
handleCallExpression: handleServerOnlyCallExpression,
|
|
77
|
-
paths: [],
|
|
78
|
-
},
|
|
79
|
-
clientOnly: {
|
|
80
|
-
name: 'clientOnly',
|
|
81
|
-
handleCallExpression: handleClientOnlyCallExpression,
|
|
82
|
-
paths: [],
|
|
83
|
-
},
|
|
84
|
-
createIsomorphicFn: {
|
|
85
|
-
name: 'createIsomorphicFn',
|
|
86
|
-
handleCallExpression: handleCreateIsomorphicFnCallExpression,
|
|
87
|
-
paths: [],
|
|
88
|
-
},
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const identifierKeys = Object.keys(identifiers) as Array<
|
|
92
|
-
keyof typeof identifiers
|
|
93
|
-
>
|
|
94
|
-
|
|
83
|
+
const identifiers = getIdentifiers(framework)
|
|
95
84
|
programPath.traverse({
|
|
96
85
|
ImportDeclaration: (path) => {
|
|
97
86
|
if (path.node.source.value !== `@tanstack/${framework}-start`) {
|
|
@@ -100,7 +89,7 @@ export function compileStartOutputFactory(
|
|
|
100
89
|
|
|
101
90
|
// handle a destructured imports being renamed like "import { createServerFn as myCreateServerFn } from '@tanstack/react-start';"
|
|
102
91
|
path.node.specifiers.forEach((specifier) => {
|
|
103
|
-
|
|
92
|
+
transformFuncs.forEach((identifierKey) => {
|
|
104
93
|
const identifier = identifiers[identifierKey]
|
|
105
94
|
|
|
106
95
|
if (
|
|
@@ -120,7 +109,7 @@ export function compileStartOutputFactory(
|
|
|
120
109
|
})
|
|
121
110
|
},
|
|
122
111
|
CallExpression: (path) => {
|
|
123
|
-
|
|
112
|
+
transformFuncs.forEach((identifierKey) => {
|
|
124
113
|
// Check to see if the call expression is a call to the
|
|
125
114
|
// identifiers[identifierKey].name
|
|
126
115
|
if (
|
|
@@ -163,7 +152,7 @@ export function compileStartOutputFactory(
|
|
|
163
152
|
},
|
|
164
153
|
})
|
|
165
154
|
|
|
166
|
-
|
|
155
|
+
transformFuncs.forEach((identifierKey) => {
|
|
167
156
|
identifiers[identifierKey].paths.forEach((path) => {
|
|
168
157
|
identifiers[identifierKey].handleCallExpression(
|
|
169
158
|
path as babel.NodePath<t.CallExpression>,
|
|
@@ -188,7 +177,7 @@ export function compileStartOutputFactory(
|
|
|
188
177
|
}
|
|
189
178
|
|
|
190
179
|
function handleCreateServerFileRouteCallExpressionFactory(
|
|
191
|
-
|
|
180
|
+
framework: CompileStartFrameworkOptions,
|
|
192
181
|
method:
|
|
193
182
|
| 'createServerFileRoute'
|
|
194
183
|
| 'createServerRoute'
|
|
@@ -198,7 +187,7 @@ function handleCreateServerFileRouteCallExpressionFactory(
|
|
|
198
187
|
path: babel.NodePath<t.CallExpression>,
|
|
199
188
|
opts: CompileOptions,
|
|
200
189
|
) {
|
|
201
|
-
const PACKAGES = { start: `@tanstack/${
|
|
190
|
+
const PACKAGES = { start: `@tanstack/${framework}-start/server` }
|
|
202
191
|
|
|
203
192
|
let highestParent: babel.NodePath<any> = path
|
|
204
193
|
|
|
@@ -210,7 +199,6 @@ function handleCreateServerFileRouteCallExpressionFactory(
|
|
|
210
199
|
|
|
211
200
|
// If we're on the client, remove the entire variable
|
|
212
201
|
if (opts.env === 'client') {
|
|
213
|
-
// console.debug('createServerFileRoute -> manifest:\n', manifest)
|
|
214
202
|
highestParent.remove()
|
|
215
203
|
return
|
|
216
204
|
}
|
|
@@ -3,6 +3,7 @@ import { logDiff } from '@tanstack/router-utils'
|
|
|
3
3
|
|
|
4
4
|
import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
|
|
5
5
|
import { compileStartOutputFactory } from './compilers'
|
|
6
|
+
import { transformFuncs } from './constants'
|
|
6
7
|
import type { Plugin } from 'vite'
|
|
7
8
|
import type { CompileStartFrameworkOptions } from './compilers'
|
|
8
9
|
|
|
@@ -14,16 +15,6 @@ export type TanStackStartViteOptions = {
|
|
|
14
15
|
globalMiddlewareEntry: string
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
const transformFuncs = [
|
|
18
|
-
'createServerFn',
|
|
19
|
-
'createMiddleware',
|
|
20
|
-
'serverOnly',
|
|
21
|
-
'clientOnly',
|
|
22
|
-
'createIsomorphicFn',
|
|
23
|
-
'createServerFileRoute',
|
|
24
|
-
'createServerRootRoute',
|
|
25
|
-
]
|
|
26
|
-
|
|
27
18
|
const tokenRegex = new RegExp(transformFuncs.join('|'))
|
|
28
19
|
|
|
29
20
|
export function startCompilerPlugin(
|
|
@@ -49,7 +40,7 @@ export function startCompilerPlugin(
|
|
|
49
40
|
}
|
|
50
41
|
|
|
51
42
|
return {
|
|
52
|
-
name: '
|
|
43
|
+
name: 'tanstack-start-core:compiler',
|
|
53
44
|
enforce: 'pre',
|
|
54
45
|
applyToEnvironment(env) {
|
|
55
46
|
return [opts.client.envName, opts.server.envName].includes(env.name)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compilers.js","sources":["../../src/compilers.ts"],"sourcesContent":["import * as babel from '@babel/core'\nimport * as t from '@babel/types'\nimport { codeFrameColumns } from '@babel/code-frame'\n\nimport {\n deadCodeElimination,\n findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport { generateFromAst, parseAst } from '@tanstack/router-utils'\nimport type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils'\n\nexport type CompileStartFrameworkOptions = 'react' | 'solid'\n\nexport function compileStartOutputFactory(\n framework: CompileStartFrameworkOptions,\n) {\n return function compileStartOutput(opts: CompileOptions): GeneratorResult {\n const ast = parseAst(opts)\n\n const doDce = opts.dce ?? true\n // find referenced identifiers *before* we transform anything\n const refIdents = doDce ? findReferencedIdentifiers(ast) : undefined\n\n babel.traverse(ast, {\n Program: {\n enter(programPath) {\n const identifiers: {\n createServerRoute: IdentifierConfig\n createServerFileRoute: IdentifierConfig\n createServerFn: IdentifierConfig\n createMiddleware: IdentifierConfig\n serverOnly: IdentifierConfig\n clientOnly: IdentifierConfig\n createIsomorphicFn: IdentifierConfig\n createServerRootRoute: IdentifierConfig\n } = {\n createServerRootRoute: {\n name: 'createServerRootRoute',\n handleCallExpression:\n handleCreateServerFileRouteCallExpressionFactory(\n framework,\n 'createServerRootRoute',\n ),\n paths: [],\n },\n createServerRoute: {\n name: 'createServerRoute',\n handleCallExpression:\n handleCreateServerFileRouteCallExpressionFactory(\n framework,\n 'createServerRoute',\n ),\n paths: [],\n },\n createServerFileRoute: {\n name: 'createServerFileRoute',\n handleCallExpression:\n handleCreateServerFileRouteCallExpressionFactory(\n framework,\n 'createServerFileRoute',\n ),\n paths: [],\n },\n createServerFn: {\n name: 'createServerFn',\n handleCallExpression: handleCreateServerFnCallExpression,\n paths: [],\n },\n createMiddleware: {\n name: 'createMiddleware',\n handleCallExpression: handleCreateMiddlewareCallExpression,\n paths: [],\n },\n serverOnly: {\n name: 'serverOnly',\n handleCallExpression: handleServerOnlyCallExpression,\n paths: [],\n },\n clientOnly: {\n name: 'clientOnly',\n handleCallExpression: handleClientOnlyCallExpression,\n paths: [],\n },\n createIsomorphicFn: {\n name: 'createIsomorphicFn',\n handleCallExpression: handleCreateIsomorphicFnCallExpression,\n paths: [],\n },\n }\n\n const identifierKeys = Object.keys(identifiers) as Array<\n keyof typeof identifiers\n >\n\n programPath.traverse({\n ImportDeclaration: (path) => {\n if (path.node.source.value !== `@tanstack/${framework}-start`) {\n return\n }\n\n // handle a destructured imports being renamed like \"import { createServerFn as myCreateServerFn } from '@tanstack/react-start';\"\n path.node.specifiers.forEach((specifier) => {\n identifierKeys.forEach((identifierKey) => {\n const identifier = identifiers[identifierKey]\n\n if (\n specifier.type === 'ImportSpecifier' &&\n specifier.imported.type === 'Identifier'\n ) {\n if (specifier.imported.name === identifierKey) {\n identifier.name = specifier.local.name\n }\n }\n\n // handle namespace imports like \"import * as TanStackStart from '@tanstack/react-start';\"\n if (specifier.type === 'ImportNamespaceSpecifier') {\n identifier.name = `${specifier.local.name}.${identifierKey}`\n }\n })\n })\n },\n CallExpression: (path) => {\n identifierKeys.forEach((identifierKey) => {\n // Check to see if the call expression is a call to the\n // identifiers[identifierKey].name\n if (\n t.isIdentifier(path.node.callee) &&\n path.node.callee.name === identifiers[identifierKey].name\n ) {\n // The identifier could be a call to the original function\n // in the source code. If this is case, we need to ignore it.\n // Check the scope to see if the identifier is a function declaration.\n // if it is, then we can ignore it.\n\n if (\n path.scope.getBinding(identifiers[identifierKey].name)?.path\n .node.type === 'FunctionDeclaration'\n ) {\n return\n }\n\n return identifiers[identifierKey].paths.push(path)\n }\n\n if (t.isMemberExpression(path.node.callee)) {\n if (\n t.isIdentifier(path.node.callee.object) &&\n t.isIdentifier(path.node.callee.property)\n ) {\n const callname = [\n path.node.callee.object.name,\n path.node.callee.property.name,\n ].join('.')\n\n if (callname === identifiers[identifierKey].name) {\n identifiers[identifierKey].paths.push(path)\n }\n }\n }\n\n return\n })\n },\n })\n\n identifierKeys.forEach((identifierKey) => {\n identifiers[identifierKey].paths.forEach((path) => {\n identifiers[identifierKey].handleCallExpression(\n path as babel.NodePath<t.CallExpression>,\n opts,\n )\n })\n })\n },\n },\n })\n\n if (doDce) {\n deadCodeElimination(ast, refIdents)\n }\n\n return generateFromAst(ast, {\n sourceMaps: true,\n sourceFileName: opts.filename,\n filename: opts.filename,\n })\n }\n}\n\nfunction handleCreateServerFileRouteCallExpressionFactory(\n factory: CompileStartFrameworkOptions,\n method:\n | 'createServerFileRoute'\n | 'createServerRoute'\n | 'createServerRootRoute',\n) {\n return function handleCreateServerFileRouteCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n ) {\n const PACKAGES = { start: `@tanstack/${factory}-start/server` }\n\n let highestParent: babel.NodePath<any> = path\n\n while (highestParent.parentPath && !highestParent.parentPath.isProgram()) {\n highestParent = highestParent.parentPath\n }\n\n const programPath = highestParent.parentPath as babel.NodePath<t.Program>\n\n // If we're on the client, remove the entire variable\n if (opts.env === 'client') {\n // console.debug('createServerFileRoute -> manifest:\\n', manifest)\n highestParent.remove()\n return\n }\n\n let isCreateServerFileRouteImported = false as boolean\n\n programPath.traverse({\n ImportDeclaration(importPath) {\n const importSource = importPath.node.source.value\n if (importSource === PACKAGES.start) {\n const specifiers = importPath.node.specifiers\n isCreateServerFileRouteImported ||= specifiers.some((specifier) => {\n return (\n t.isImportSpecifier(specifier) &&\n t.isIdentifier(specifier.imported) &&\n specifier.imported.name === method\n )\n })\n }\n },\n })\n\n if (!isCreateServerFileRouteImported) {\n const importDeclaration = t.importDeclaration(\n [t.importSpecifier(t.identifier(method), t.identifier(method))],\n t.stringLiteral(PACKAGES.start),\n )\n programPath.node.body.unshift(importDeclaration)\n }\n }\n}\n\n// build these once and reuse them\nexport const handleServerOnlyCallExpression =\n buildEnvOnlyCallExpressionHandler('server')\nexport const handleClientOnlyCallExpression =\n buildEnvOnlyCallExpressionHandler('client')\n\nexport type CompileOptions = ParseAstOptions & {\n env: 'server' | 'client'\n dce?: boolean\n filename: string\n}\n\nexport type IdentifierConfig = {\n name: string\n handleCallExpression: (\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n ) => void\n paths: Array<babel.NodePath>\n}\n\nexport function handleCreateServerFnCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n) {\n // The function is the 'fn' property of the object passed to createServerFn\n\n // const firstArg = path.node.arguments[0]\n // if (t.isObjectExpression(firstArg)) {\n // // Was called with some options\n // }\n\n // Traverse the member expression and find the call expressions for\n // the validator, handler, and middleware methods. Check to make sure they\n // are children of the createServerFn call expression.\n\n const calledOptions = path.node.arguments[0]\n ? (path.get('arguments.0') as babel.NodePath<t.ObjectExpression>)\n : null\n\n const shouldValidateClient = !!calledOptions?.node.properties.find((prop) => {\n return (\n t.isObjectProperty(prop) &&\n t.isIdentifier(prop.key) &&\n prop.key.name === 'validateClient' &&\n t.isBooleanLiteral(prop.value) &&\n prop.value.value === true\n )\n })\n\n const callExpressionPaths = {\n middleware: null as babel.NodePath<t.CallExpression> | null,\n validator: null as babel.NodePath<t.CallExpression> | null,\n handler: null as babel.NodePath<t.CallExpression> | null,\n }\n\n const validMethods = Object.keys(callExpressionPaths)\n\n const rootCallExpression = getRootCallExpression(path)\n\n // if (debug)\n // console.info(\n // 'Handling createServerFn call expression:',\n // rootCallExpression.toString(),\n // )\n\n // Check if the call is assigned to a variable\n if (!rootCallExpression.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 = rootCallExpression.parentPath.node\n const existingVariableName = (variableDeclarator.id as t.Identifier).name\n\n rootCallExpression.traverse({\n MemberExpression(memberExpressionPath) {\n if (t.isIdentifier(memberExpressionPath.node.property)) {\n const name = memberExpressionPath.node.property\n .name as keyof typeof callExpressionPaths\n\n if (\n validMethods.includes(name) &&\n memberExpressionPath.parentPath.isCallExpression()\n ) {\n callExpressionPaths[name] = memberExpressionPath.parentPath\n }\n }\n },\n })\n\n if (callExpressionPaths.validator) {\n const innerInputExpression = callExpressionPaths.validator.node.arguments[0]\n\n if (!innerInputExpression) {\n throw new Error(\n 'createServerFn().validator() must be called with a validator!',\n )\n }\n\n // If we're on the client, and we're not validating the client, remove the validator call expression\n if (\n opts.env === 'client' &&\n !shouldValidateClient &&\n t.isMemberExpression(callExpressionPaths.validator.node.callee)\n ) {\n callExpressionPaths.validator.replaceWith(\n callExpressionPaths.validator.node.callee.object,\n )\n }\n }\n\n // First, we need to move the handler function to a nested function call\n // that is applied to the arguments passed to the server function.\n\n const handlerFnPath = callExpressionPaths.handler?.get(\n 'arguments.0',\n ) as babel.NodePath<any>\n\n if (!callExpressionPaths.handler || !handlerFnPath.node) {\n throw codeFrameError(\n opts.code,\n path.node.callee.loc!,\n `createServerFn must be called with a \"handler\" property!`,\n )\n }\n\n const handlerFn = handlerFnPath.node\n\n // So, the way we do this is we give the handler function a way\n // to access the serverFn ctx on the server via function scope.\n // The 'use server' extracted function will be called with the\n // payload from the client, then use the scoped serverFn ctx\n // to execute the handler function.\n // This way, we can do things like data and middleware validation\n // in the __execute function without having to AST transform the\n // handler function too much itself.\n\n // .handler((optsOut, ctx) => {\n // return ((optsIn) => {\n // 'use server'\n // ctx.__execute(handlerFn, optsIn)\n // })(optsOut)\n // })\n\n // If the handler function is an identifier and we're on the client, we need to\n // remove the bound function from the file.\n // If we're on the server, you can leave it, since it will get referenced\n // as a second argument.\n\n if (t.isIdentifier(handlerFn)) {\n if (opts.env === 'client') {\n // Find the binding for the handler function\n const binding = handlerFnPath.scope.getBinding(handlerFn.name)\n // Remove it\n if (binding) {\n binding.path.remove()\n }\n }\n // If the env is server, just leave it alone\n }\n\n handlerFnPath.replaceWith(\n t.arrowFunctionExpression(\n [t.identifier('opts'), t.identifier('signal')],\n t.blockStatement(\n // Everything in here is server-only, since the client\n // will strip out anything in the 'use server' directive.\n [\n t.returnStatement(\n t.callExpression(\n t.identifier(`${existingVariableName}.__executeServer`),\n [t.identifier('opts'), t.identifier('signal')],\n ),\n ),\n ],\n [t.directive(t.directiveLiteral('use server'))],\n ),\n ),\n )\n\n if (opts.env === 'server') {\n callExpressionPaths.handler.node.arguments.push(handlerFn)\n }\n}\n\nexport function handleCreateMiddlewareCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n) {\n const rootCallExpression = getRootCallExpression(path)\n\n // if (debug)\n // console.info(\n // 'Handling createMiddleware call expression:',\n // rootCallExpression.toString(),\n // )\n\n const callExpressionPaths = {\n middleware: null as babel.NodePath<t.CallExpression> | null,\n validator: null as babel.NodePath<t.CallExpression> | null,\n client: null as babel.NodePath<t.CallExpression> | null,\n server: null as babel.NodePath<t.CallExpression> | null,\n }\n\n const validMethods = Object.keys(callExpressionPaths)\n\n rootCallExpression.traverse({\n MemberExpression(memberExpressionPath) {\n if (t.isIdentifier(memberExpressionPath.node.property)) {\n const name = memberExpressionPath.node.property\n .name as keyof typeof callExpressionPaths\n\n if (\n validMethods.includes(name) &&\n memberExpressionPath.parentPath.isCallExpression()\n ) {\n callExpressionPaths[name] = memberExpressionPath.parentPath\n }\n }\n },\n })\n\n if (callExpressionPaths.validator) {\n const innerInputExpression = callExpressionPaths.validator.node.arguments[0]\n\n if (!innerInputExpression) {\n throw new Error(\n 'createMiddleware().validator() must be called with a validator!',\n )\n }\n\n // If we're on the client, remove the validator call expression\n if (opts.env === 'client') {\n if (t.isMemberExpression(callExpressionPaths.validator.node.callee)) {\n callExpressionPaths.validator.replaceWith(\n callExpressionPaths.validator.node.callee.object,\n )\n }\n }\n }\n\n const serverFnPath = callExpressionPaths.server?.get(\n 'arguments.0',\n ) as babel.NodePath<any>\n\n if (\n callExpressionPaths.server &&\n serverFnPath.node &&\n opts.env === 'client'\n ) {\n // If we're on the client, remove the server call expression\n if (t.isMemberExpression(callExpressionPaths.server.node.callee)) {\n callExpressionPaths.server.replaceWith(\n callExpressionPaths.server.node.callee.object,\n )\n }\n }\n}\n\nfunction buildEnvOnlyCallExpressionHandler(env: 'client' | 'server') {\n return function envOnlyCallExpressionHandler(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n ) {\n // if (debug)\n // console.info(`Handling ${env}Only call expression:`, path.toString())\n\n const isEnvMatch =\n env === 'client' ? opts.env === 'client' : opts.env === 'server'\n\n if (isEnvMatch) {\n // extract the inner function from the call expression\n const innerInputExpression = path.node.arguments[0]\n\n if (!t.isExpression(innerInputExpression)) {\n throw new Error(\n `${env}Only() functions must be called with a function!`,\n )\n }\n\n path.replaceWith(innerInputExpression)\n return\n }\n\n // If we're on the wrong environment, replace the call expression\n // with a function that always 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 `${env}Only() functions can only be called on the ${env}!`,\n ),\n ]),\n ),\n ]),\n ),\n )\n }\n}\n\nexport function handleCreateIsomorphicFnCallExpression(\n path: babel.NodePath<t.CallExpression>,\n opts: CompileOptions,\n) {\n const rootCallExpression = getRootCallExpression(path)\n\n // if (debug)\n // console.info(\n // 'Handling createIsomorphicFn call expression:',\n // rootCallExpression.toString(),\n // )\n\n const callExpressionPaths = {\n client: null as babel.NodePath<t.CallExpression> | null,\n server: null as babel.NodePath<t.CallExpression> | null,\n }\n\n const validMethods = Object.keys(callExpressionPaths)\n\n rootCallExpression.traverse({\n MemberExpression(memberExpressionPath) {\n if (t.isIdentifier(memberExpressionPath.node.property)) {\n const name = memberExpressionPath.node.property\n .name as keyof typeof callExpressionPaths\n\n if (\n validMethods.includes(name) &&\n memberExpressionPath.parentPath.isCallExpression()\n ) {\n callExpressionPaths[name] = memberExpressionPath.parentPath\n }\n }\n },\n })\n\n if (\n validMethods.every(\n (method) =>\n !callExpressionPaths[method as keyof typeof callExpressionPaths],\n )\n ) {\n const variableId = rootCallExpression.parentPath.isVariableDeclarator()\n ? rootCallExpression.parentPath.node.id\n : null\n console.warn(\n 'createIsomorphicFn called without a client or server implementation!',\n 'This will result in a no-op function.',\n 'Variable name:',\n t.isIdentifier(variableId) ? variableId.name : 'unknown',\n )\n }\n\n const envCallExpression = callExpressionPaths[opts.env]\n\n if (!envCallExpression) {\n // if we don't have an implementation for this environment, default to a no-op\n rootCallExpression.replaceWith(\n t.arrowFunctionExpression([], t.blockStatement([])),\n )\n return\n }\n\n const innerInputExpression = envCallExpression.node.arguments[0]\n\n if (!t.isExpression(innerInputExpression)) {\n throw new Error(\n `createIsomorphicFn().${opts.env}(func) must be called with a function!`,\n )\n }\n\n rootCallExpression.replaceWith(innerInputExpression)\n}\n\nexport function getRootCallExpression(path: babel.NodePath<t.CallExpression>) {\n // Find the highest callExpression parent\n let rootCallExpression: babel.NodePath<t.CallExpression> = path\n\n // Traverse up the chain of CallExpressions\n while (rootCallExpression.parentPath.isMemberExpression()) {\n const parent = rootCallExpression.parentPath\n if (parent.parentPath.isCallExpression()) {\n rootCallExpression = parent.parentPath\n }\n }\n\n return rootCallExpression\n}\n\nfunction 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"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"start-compiler-plugin.js","sources":["../../src/start-compiler-plugin.ts"],"sourcesContent":["import { fileURLToPath, pathToFileURL } from 'node:url'\nimport { logDiff } from '@tanstack/router-utils'\n\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { compileStartOutputFactory } from './compilers'\nimport type { Plugin } from 'vite'\nimport type { CompileStartFrameworkOptions } from './compilers'\n\nconst debug =\n process.env.TSR_VITE_DEBUG &&\n ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG)\n\nexport type TanStackStartViteOptions = {\n globalMiddlewareEntry: string\n}\n\nconst transformFuncs = [\n 'createServerFn',\n 'createMiddleware',\n 'serverOnly',\n 'clientOnly',\n 'createIsomorphicFn',\n 'createServerFileRoute',\n 'createServerRootRoute',\n]\n\nconst tokenRegex = new RegExp(transformFuncs.join('|'))\n\nexport function startCompilerPlugin(\n framework: CompileStartFrameworkOptions,\n inputOpts?: {\n client?: {\n envName?: string\n }\n server?: {\n envName?: string\n }\n },\n): Plugin {\n const opts = {\n client: {\n envName: 'client',\n ...inputOpts?.client,\n },\n server: {\n envName: 'server',\n ...inputOpts?.server,\n },\n }\n\n return {\n name: 'vite-plugin-tanstack-start-create-server-fn',\n enforce: 'pre',\n applyToEnvironment(env) {\n return [opts.client.envName, opts.server.envName].includes(env.name)\n },\n transform: {\n filter: {\n code: tokenRegex,\n id: {\n exclude: VIRTUAL_MODULES.serverFnManifest,\n },\n },\n handler(code, id) {\n const env =\n this.environment.name === opts.client.envName\n ? 'client'\n : this.environment.name === opts.server.envName\n ? 'server'\n : (() => {\n throw new Error(\n `Environment ${this.environment.name} not configured`,\n )\n })()\n\n return transformCode({\n code,\n id,\n env,\n framework,\n })\n },\n },\n }\n}\n\nfunction transformCode(opts: {\n code: string\n id: string\n env: 'server' | 'client'\n framework: CompileStartFrameworkOptions\n}) {\n const { code, env, framework } = opts\n let { id } = opts\n\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n id = fileURLToPath(url).replace(/\\\\/g, '/')\n\n if (debug) console.info(`${env} Compiling Start: `, id)\n\n const compileStartOutput = compileStartOutputFactory(framework)\n const compiled = compileStartOutput({\n code,\n filename: id,\n env,\n })\n\n if (debug) {\n logDiff(code, compiled.code)\n console.log('Output:\\n', compiled.code + '\\n\\n')\n }\n\n return compiled\n}\n"],"names":[],"mappings":";;;;AAQA,MAAM,QACJ,QAAQ,IAAI,kBACZ,CAAC,QAAQ,cAAc,EAAE,SAAS,QAAQ,IAAI,cAAc;AAM9D,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,aAAa,IAAI,OAAO,eAAe,KAAK,GAAG,CAAC;AAE/C,SAAS,oBACd,WACA,WAQQ;AACR,QAAM,OAAO;AAAA,IACX,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,GAAG,WAAW;AAAA,IAAA;AAAA,IAEhB,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,GAAG,WAAW;AAAA,IAAA;AAAA,EAChB;AAGF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,mBAAmB,KAAK;AACtB,aAAO,CAAC,KAAK,OAAO,SAAS,KAAK,OAAO,OAAO,EAAE,SAAS,IAAI,IAAI;AAAA,IACrE;AAAA,IACA,WAAW;AAAA,MACT,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,IAAI;AAAA,UACF,SAAS,gBAAgB;AAAA,QAAA;AAAA,MAC3B;AAAA,MAEF,QAAQ,MAAM,IAAI;AAChB,cAAM,MACJ,KAAK,YAAY,SAAS,KAAK,OAAO,UAClC,WACA,KAAK,YAAY,SAAS,KAAK,OAAO,UACpC,YACC,MAAM;AACL,gBAAM,IAAI;AAAA,YACR,eAAe,KAAK,YAAY,IAAI;AAAA,UAAA;AAAA,QAExC,GAAA;AAER,eAAO,cAAc;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IAAA;AAAA,EACF;AAEJ;AAEA,SAAS,cAAc,MAKpB;AACD,QAAM,EAAE,MAAM,KAAK,UAAA,IAAc;AACjC,MAAI,EAAE,OAAO;AAEb,QAAM,MAAM,cAAc,EAAE;AAC5B,MAAI,aAAa,OAAO,GAAG;AAC3B,OAAK,cAAc,GAAG,EAAE,QAAQ,OAAO,GAAG;AAE1C,MAAI,MAAO,SAAQ,KAAK,GAAG,GAAG,sBAAsB,EAAE;AAEtD,QAAM,qBAAqB,0BAA0B,SAAS;AAC9D,QAAM,WAAW,mBAAmB;AAAA,IAClC;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EAAA,CACD;AAED,MAAI,OAAO;AACT,YAAQ,MAAM,SAAS,IAAI;AAC3B,YAAQ,IAAI,aAAa,SAAS,OAAO,MAAM;AAAA,EACjD;AAEA,SAAO;AACT;"}
|
|
File without changes
|
|
File without changes
|