feat: add vite-plugin-route-builder for dynamic route generation
- Introduced a new plugin to generate React Router routes from a file system-based structure, enhancing routing capabilities similar to Next.js. - Updated various configurations and components to integrate the new plugin, including automatic route generation during build time. - Refactored existing router implementations to utilize generated routes, improving maintainability and performance. Signed-off-by: Innei <i@innei.in> Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
parent
710622a907
commit
1d83313872
|
|
@ -21,4 +21,6 @@ vite.config.*.mjs
|
|||
|
||||
apps/desktop/src/renderer/dev-dist
|
||||
tsconfig.tsbuildinfo
|
||||
buildServer.json
|
||||
buildServer.json
|
||||
|
||||
generated-routes.ts
|
||||
|
|
@ -1,26 +1,55 @@
|
|||
import { dirname, resolve } from "node:path"
|
||||
import { fileURLToPath } from "node:url"
|
||||
|
||||
import { tsImport } from "tsx/esm/api"
|
||||
import type { UserConfig } from "vite"
|
||||
|
||||
import { cleanupUnnecessaryFilesPlugin } from "../plugins/vite/cleanup"
|
||||
import { createPlatformSpecificImportPlugin } from "../plugins/vite/specific-import"
|
||||
import { viteRenderBaseConfig } from "./vite.render.config"
|
||||
|
||||
const routeBuilderPluginV2 = await tsImport(
|
||||
"@follow/vite-plugin-route-builder",
|
||||
import.meta.url,
|
||||
).then((m) => m.default)
|
||||
|
||||
const root = resolve(fileURLToPath(dirname(import.meta.url)), "..")
|
||||
|
||||
const VITE_ROOT = resolve(root, "layer/renderer")
|
||||
export default {
|
||||
...viteRenderBaseConfig,
|
||||
|
||||
plugins: [...viteRenderBaseConfig.plugins, createPlatformSpecificImportPlugin("electron")],
|
||||
plugins: [
|
||||
...viteRenderBaseConfig.plugins,
|
||||
createPlatformSpecificImportPlugin("electron"),
|
||||
routeBuilderPluginV2({
|
||||
pagePattern: `${resolve(VITE_ROOT, "./src/pages")}/**/*.tsx`,
|
||||
outputPath: `${resolve(VITE_ROOT, "./src/generated-routes.ts")}`,
|
||||
enableInDev: true,
|
||||
}),
|
||||
cleanupUnnecessaryFilesPlugin([
|
||||
"og-image.png",
|
||||
"icon-512x512.png",
|
||||
"opengraph-image.png",
|
||||
"favicon.ico",
|
||||
"icon-192x192.png",
|
||||
"favicon-dev.ico",
|
||||
"apple-touch-icon-180x180.png",
|
||||
"maskable-icon-512x512.png",
|
||||
"pwa-64x64.png",
|
||||
"pwa-192x192.png",
|
||||
"pwa-512x512.png",
|
||||
]),
|
||||
],
|
||||
|
||||
root: resolve(root, "layer/renderer"),
|
||||
root: VITE_ROOT,
|
||||
build: {
|
||||
outDir: resolve(root, "dist/renderer"),
|
||||
sourcemap: !!process.env.CI,
|
||||
target: "esnext",
|
||||
rollupOptions: {
|
||||
input: {
|
||||
main: resolve(root, "layer/renderer/index.html"),
|
||||
main: resolve(VITE_ROOT, "index.html"),
|
||||
},
|
||||
},
|
||||
minify: true,
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@ import { resolve } from "node:path"
|
|||
import { defineConfig } from "electron-vite"
|
||||
|
||||
import { getGitHash } from "../../scripts/lib"
|
||||
import { viteRenderBaseConfig } from "./configs/vite.render.config"
|
||||
import { cleanupUnnecessaryFilesPlugin } from "./plugins/vite/cleanup"
|
||||
import { createPlatformSpecificImportPlugin } from "./plugins/vite/specific-import"
|
||||
import rendererConfig from "./configs/vite.electron-render.config"
|
||||
|
||||
export default defineConfig({
|
||||
main: {
|
||||
|
|
@ -42,43 +40,5 @@ export default defineConfig({
|
|||
},
|
||||
},
|
||||
},
|
||||
renderer: {
|
||||
...viteRenderBaseConfig,
|
||||
|
||||
root: "layer/renderer",
|
||||
build: {
|
||||
outDir: "dist/renderer",
|
||||
sourcemap: !!process.env.CI,
|
||||
target: "esnext",
|
||||
rollupOptions: {
|
||||
input: {
|
||||
main: resolve("./layer/renderer/index.html"),
|
||||
},
|
||||
},
|
||||
minify: true,
|
||||
},
|
||||
|
||||
plugins: [
|
||||
...viteRenderBaseConfig.plugins,
|
||||
createPlatformSpecificImportPlugin("electron"),
|
||||
cleanupUnnecessaryFilesPlugin([
|
||||
"og-image.png",
|
||||
"icon-512x512.png",
|
||||
"opengraph-image.png",
|
||||
"favicon.ico",
|
||||
"icon-192x192.png",
|
||||
"favicon-dev.ico",
|
||||
"apple-touch-icon-180x180.png",
|
||||
"maskable-icon-512x512.png",
|
||||
"pwa-64x64.png",
|
||||
"pwa-192x192.png",
|
||||
"pwa-512x512.png",
|
||||
]),
|
||||
],
|
||||
|
||||
define: {
|
||||
...viteRenderBaseConfig.define,
|
||||
ELECTRON: "true",
|
||||
},
|
||||
},
|
||||
renderer: rendererConfig,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
import { IN_ELECTRON } from "@follow/shared/constants"
|
||||
import { buildGlobRoutes } from "@follow/utils/route-builder"
|
||||
import { wrapCreateBrowserRouterV7 } from "@sentry/react"
|
||||
import { createBrowserRouter, createHashRouter } from "react-router"
|
||||
|
||||
import { Component as App } from "./App"
|
||||
import { ErrorElement } from "./components/common/ErrorElement"
|
||||
import { NotFound } from "./components/common/NotFound"
|
||||
|
||||
const globTree = import.meta.glob("./pages/**/*.tsx")
|
||||
const tree = buildGlobRoutes(globTree)
|
||||
import { routes as tree } from "./generated-routes"
|
||||
|
||||
let routerCreator =
|
||||
IN_ELECTRON || globalThis["__DEBUG_PROXY__"] ? createHashRouter : createBrowserRouter
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
import { IN_ELECTRON } from "@follow/shared/constants"
|
||||
import { buildGlobRoutes } from "@follow/utils/route-builder"
|
||||
import { wrapCreateBrowserRouterV7 } from "@sentry/react"
|
||||
import { createBrowserRouter, createHashRouter } from "react-router"
|
||||
|
||||
import { ErrorElement } from "./components/common/ErrorElement"
|
||||
import { NotFound } from "./components/common/NotFound"
|
||||
|
||||
const globTree = import.meta.glob("./pages/**/*.tsx")
|
||||
const tree = buildGlobRoutes(globTree)
|
||||
import { routes as tree } from "./generated-routes"
|
||||
|
||||
let routerCreator =
|
||||
IN_ELECTRON || globalThis["__DEBUG_PROXY__"] ? createHashRouter : createBrowserRouter
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
"@follow/models": "workspace:*",
|
||||
"@follow/shared": "workspace:*",
|
||||
"@follow/utils": "workspace:*",
|
||||
"@follow/vite-plugin-route-builder": "workspace:*",
|
||||
"@pengx17/electron-forge-maker-appimage": "1.2.1",
|
||||
"@sentry/vite-plugin": "3.5.0",
|
||||
"@types/html-minifier-terser": "7.0.2",
|
||||
|
|
@ -85,7 +86,6 @@
|
|||
"tailwindcss-content-visibility": "1.0.2",
|
||||
"tailwindcss-multi": "0.4.6",
|
||||
"tar": "7.4.3",
|
||||
"tsup": "8.5.0",
|
||||
"unplugin-ast": "0.15.0",
|
||||
"utf-8-validate": "6.0.5",
|
||||
"vite-bundle-analyzer": "0.22.0",
|
||||
|
|
|
|||
|
|
@ -2,23 +2,20 @@ import path from "node:path"
|
|||
import { fileURLToPath } from "node:url"
|
||||
|
||||
import { set } from "es-toolkit/compat"
|
||||
import type { Plugin } from "vite"
|
||||
import type { Logger, Plugin } from "vite"
|
||||
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url))
|
||||
const localesDir = path.resolve(__dirname, "../../../../locales")
|
||||
|
||||
export function localesJsonPlugin(): Plugin {
|
||||
let isBuild = false
|
||||
let logger: Logger
|
||||
return {
|
||||
name: "locales-json-transform",
|
||||
enforce: "pre",
|
||||
configResolved(config) {
|
||||
isBuild = config.command === "build"
|
||||
logger = config.logger
|
||||
},
|
||||
async transform(code, id) {
|
||||
if (isBuild) {
|
||||
return null
|
||||
}
|
||||
if (!id.includes(localesDir) || !id.endsWith(".json")) {
|
||||
return null
|
||||
}
|
||||
|
|
@ -31,7 +28,7 @@ export function localesJsonPlugin(): Plugin {
|
|||
set(obj, accessorKey, (content as any)[accessorKey])
|
||||
}
|
||||
|
||||
console.info("[locales-json-transform] Transformed:", id)
|
||||
logger.info(`[locales-json-transform] Transformed: ${id}`)
|
||||
return {
|
||||
code: JSON.stringify(obj),
|
||||
map: null,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import legacy from "@vitejs/plugin-legacy"
|
|||
import { minify as htmlMinify } from "html-minifier-terser"
|
||||
import { cyan, dim, green } from "kolorist"
|
||||
import { parseHTML } from "linkedom"
|
||||
import { tsImport } from "tsx/esm/api"
|
||||
import type { PluginOption, ResolvedConfig, ViteDevServer } from "vite"
|
||||
import { defineConfig, loadEnv } from "vite"
|
||||
import { analyzer } from "vite-bundle-analyzer"
|
||||
|
|
@ -20,9 +21,14 @@ import { localesPlugin } from "./plugins/vite/locales"
|
|||
import manifestPlugin from "./plugins/vite/manifest"
|
||||
import { createPlatformSpecificImportPlugin } from "./plugins/vite/specific-import"
|
||||
|
||||
const routeBuilderPluginV2 = await tsImport(
|
||||
"@follow/vite-plugin-route-builder",
|
||||
import.meta.url,
|
||||
).then((m) => m.default)
|
||||
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url))
|
||||
const isCI = process.env.CI === "true" || process.env.CI === "1"
|
||||
const ROOT = "./layer/renderer"
|
||||
const ROOT = resolve(__dirname, "./layer/renderer")
|
||||
|
||||
const devPrint = (): PluginOption => ({
|
||||
name: "dev-print",
|
||||
|
|
@ -138,6 +144,11 @@ export default ({ mode }) => {
|
|||
plugins: [
|
||||
...((viteRenderBaseConfig.plugins ?? []) as any),
|
||||
|
||||
routeBuilderPluginV2({
|
||||
pagePattern: `${resolve(ROOT, "./src/pages")}/**/*.tsx`,
|
||||
outputPath: `${resolve(ROOT, "./src/generated-routes.ts")}`,
|
||||
enableInDev: true,
|
||||
}),
|
||||
localesPlugin(),
|
||||
isWebBuild &&
|
||||
VitePWA({
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
import { buildGlobRoutes } from "@follow/utils/route-builder"
|
||||
import { wrapCreateBrowserRouterV7 } from "@sentry/react"
|
||||
import { createBrowserRouter, createHashRouter } from "react-router"
|
||||
|
||||
import { NotFound } from "./components/common/404"
|
||||
|
||||
const globTree = import.meta.glob("./pages/**/*.tsx")
|
||||
const tree = buildGlobRoutes(globTree)
|
||||
import tree from "./generated-routes"
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
"@follow/shared": "workspace:*",
|
||||
"@follow/types": "workspace:*",
|
||||
"@follow/utils": "workspace:*",
|
||||
"@follow/vite-plugin-route-builder": "workspace:*",
|
||||
"@types/html-minifier-terser": "7.0.2",
|
||||
"chokidar": "4.0.3",
|
||||
"code-inspector-plugin": "0.20.11",
|
||||
|
|
|
|||
|
|
@ -2,11 +2,17 @@ import { resolve } from "node:path"
|
|||
|
||||
import react from "@vitejs/plugin-react"
|
||||
import { codeInspectorPlugin } from "code-inspector-plugin"
|
||||
import { tsImport } from "tsx/esm/api"
|
||||
import { defineConfig } from "vite"
|
||||
|
||||
import { viteRenderBaseConfig } from "../desktop/configs/vite.render.config"
|
||||
import { astPlugin } from "../desktop/plugins/vite/ast"
|
||||
|
||||
const routeBuilderPluginV2 = await tsImport(
|
||||
"@follow/vite-plugin-route-builder",
|
||||
import.meta.url,
|
||||
).then((m) => m.default)
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
|
|
@ -29,6 +35,11 @@ export default defineConfig({
|
|||
},
|
||||
},
|
||||
plugins: [
|
||||
routeBuilderPluginV2({
|
||||
pagePattern: `${resolve(__dirname, "./client/pages")}/**/*.tsx`,
|
||||
outputPath: `${resolve(__dirname, "./client/generated-routes.ts")}`,
|
||||
enableInDev: true,
|
||||
}),
|
||||
react(),
|
||||
astPlugin,
|
||||
codeInspectorPlugin({
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "@follow/monorepo",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39",
|
||||
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac",
|
||||
"description": "Follow everything in one place",
|
||||
"author": "Folo Team",
|
||||
"license": "GPL-3.0-only",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "@follow/vite-plugin-route-builder",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsdown"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "22.15.23",
|
||||
"es-toolkit": "1.38.0",
|
||||
"fast-glob": "3.3.3",
|
||||
"react-router": "7.6.1",
|
||||
"tsdown": "0.12.8",
|
||||
"typescript": "catalog:",
|
||||
"vite": "6.3.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
# Vite Route Builder Plugin - Technical Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Vite Route Builder plugin is a build-time code generation tool that creates React Router route configurations from a file system-based routing structure, similar to Next.js App Router. It transforms a `pages/` directory structure into optimized route objects with lazy loading and proper component imports.
|
||||
|
||||
## Core Architecture
|
||||
|
||||
### Plugin Flow
|
||||
|
||||
1. **Build-time Generation**: The plugin runs during Vite's build process to generate static route configurations
|
||||
2. **File System Scanning**: Uses glob patterns to discover page and layout files
|
||||
3. **Route Tree Building**: Leverages the existing `route-builder.ts` logic to create route hierarchy
|
||||
4. **Code Generation**: Produces a TypeScript file with lazy-loaded route objects
|
||||
|
||||
### Key Components
|
||||
|
||||
- **`vite-plugin-route-builder.ts`**: Main Vite plugin implementation
|
||||
- **`route-builder.ts`**: Core routing logic for transforming file paths to route objects
|
||||
- **`generated-routes.ts`**: Auto-generated output file containing route configurations
|
||||
|
||||
## File System Routing Conventions
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
pages/
|
||||
├── (main)/ # Route group (doesn't affect URL path)
|
||||
│ ├── layout.tsx # Layout component for grouped routes
|
||||
│ ├── index.tsx # / route
|
||||
│ └── discover.tsx # /discover route
|
||||
├── settings/
|
||||
│ ├── layout.tsx # Layout for /settings/*
|
||||
│ ├── index.tsx # /settings route
|
||||
│ └── profile.tsx # /settings/profile route
|
||||
├── (settings)/ # Another route group
|
||||
│ ├── layout.tsx # Layout component
|
||||
│ └── general.tsx # /general route
|
||||
└── [...404].tsx # Catch-all route
|
||||
```
|
||||
|
||||
### Route Mapping Rules
|
||||
|
||||
1. **Index Routes**: `index.tsx` files create routes for their parent directory path
|
||||
2. **Named Routes**: File names become route paths (e.g., `profile.tsx` → `/profile`)
|
||||
3. **Grouped Routes**: Directories with parentheses `(name)` group routes without affecting URL paths
|
||||
4. **Dynamic Routes**: `[param].tsx` creates dynamic parameter routes
|
||||
5. **Catch-all Routes**: `[...name].tsx` creates catch-all routes
|
||||
6. **Layouts**: `layout.tsx` files provide wrapper components for child routes
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### 1. Route Discovery Process
|
||||
|
||||
```typescript
|
||||
// Plugin discovers files using glob patterns
|
||||
const pageFiles = glob.sync("./src/pages/**/*.{ts,tsx}", {
|
||||
ignore: ["**/*.d.ts", "**/*.test.*", "**/*.spec.*"],
|
||||
})
|
||||
```
|
||||
|
||||
### 2. Route Tree Generation
|
||||
|
||||
The plugin uses the existing `route-builder.ts` logic:
|
||||
|
||||
```typescript
|
||||
import { buildRoute } from "../route-builder"
|
||||
|
||||
// Transform file paths to route objects
|
||||
const routes = buildRoute(pageFiles)
|
||||
```
|
||||
|
||||
### 3. Path Resolution Strategy
|
||||
|
||||
The plugin implements sophisticated path matching to connect route objects with their corresponding files:
|
||||
|
||||
```typescript
|
||||
function findFileForRoute(route: RouteObject, pageFiles: string[]): string | null {
|
||||
const routePath = route.handle?.fs as string
|
||||
if (!routePath) return null
|
||||
|
||||
// Strategy 1: Direct file match (fs.tsx)
|
||||
let targetFile = `./src/pages/${routePath}.tsx`
|
||||
if (pageFiles.includes(targetFile)) return targetFile
|
||||
|
||||
// Strategy 2: Layout file for grouped routes (fs/layout.tsx)
|
||||
targetFile = `./src/pages/${routePath}/layout.tsx`
|
||||
if (pageFiles.includes(targetFile)) return targetFile
|
||||
|
||||
// Strategy 3: Index file (fs/index.tsx)
|
||||
targetFile = `./src/pages/${routePath}/index.tsx`
|
||||
if (pageFiles.includes(targetFile)) return targetFile
|
||||
|
||||
// Strategy 4: Handle paths ending with '/' (index pages)
|
||||
if (routePath.endsWith("/")) {
|
||||
const cleanPath = routePath.slice(0, -1)
|
||||
targetFile = `./src/pages/${cleanPath}/index.tsx`
|
||||
if (pageFiles.includes(targetFile)) return targetFile
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Lazy Loading Implementation
|
||||
|
||||
The plugin generates lazy-loaded components for optimal performance:
|
||||
|
||||
```typescript
|
||||
// Generate lazy imports only for routes that have corresponding files
|
||||
const lazyComponents = new Map<string, string>()
|
||||
let lazyCounter = 1
|
||||
|
||||
function collectLazyFunctions(route: RouteObject, pageFiles: string[]) {
|
||||
const file = findFileForRoute(route, pageFiles)
|
||||
if (file && !lazyComponents.has(file)) {
|
||||
const relativePath = path.relative(
|
||||
path.dirname("./src/generated-routes.ts"),
|
||||
file.replace("./src/", "./src/"),
|
||||
)
|
||||
const varName = `LazyComponent${lazyCounter++}`
|
||||
lazyComponents.set(file, varName)
|
||||
|
||||
return `const ${varName} = lazy(() => import("${relativePath}"))`
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Code Generation
|
||||
|
||||
The final step generates a complete TypeScript file:
|
||||
|
||||
```typescript
|
||||
const output = `
|
||||
// Do not edit manually
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import type { RouteObject } from "react-router"
|
||||
import { lazy } from "react"
|
||||
|
||||
${lazyImports.join("\n")}
|
||||
|
||||
export const routes: RouteObject[] = ${serializedRoutes}
|
||||
`
|
||||
```
|
||||
|
||||
## Route Object Structure
|
||||
|
||||
### Generated Route Format
|
||||
|
||||
```typescript
|
||||
interface RouteObject {
|
||||
path?: string
|
||||
index?: boolean
|
||||
children?: RouteObject[]
|
||||
element?: React.ComponentType
|
||||
// Internal properties removed in final output
|
||||
handle?: { fs: string } // Removed during serialization
|
||||
}
|
||||
```
|
||||
|
||||
### Example Generated Output
|
||||
|
||||
```typescript
|
||||
const LazyComponent1 = lazy(() => import("./pages/(main)/layout"))
|
||||
const LazyComponent2 = lazy(() => import("./pages/(main)/index"))
|
||||
const LazyComponent3 = lazy(() => import("./pages/settings/layout"))
|
||||
|
||||
export const routes: RouteObject[] = [
|
||||
{
|
||||
path: "/",
|
||||
element: LazyComponent1,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: LazyComponent2,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/settings",
|
||||
element: LazyComponent3,
|
||||
children: [
|
||||
// ... nested routes
|
||||
],
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
## Problem Solving Approach
|
||||
|
||||
### Common Issues and Solutions
|
||||
|
||||
1. **Path Mismatch**: Routes generated without corresponding lazy functions
|
||||
|
||||
- **Solution**: Enhanced file matching with multiple strategies and path normalization
|
||||
|
||||
2. **Incorrect Import Paths**: Absolute paths causing import failures
|
||||
|
||||
- **Solution**: Proper relative path calculation using `path.relative()`
|
||||
|
||||
3. **Unused Lazy Variables**: Too many lazy imports for non-existent files
|
||||
|
||||
- **Solution**: Only generate lazy imports for routes with actual file matches
|
||||
|
||||
4. **Index Route Handling**: Paths ending with `/` causing mapping issues
|
||||
- **Solution**: Special handling for index pages and path cleaning
|
||||
|
||||
### Debugging Strategy
|
||||
|
||||
The plugin includes comprehensive logging for troubleshooting:
|
||||
|
||||
```typescript
|
||||
console.log("📁 Page files found:", pageFiles.length)
|
||||
console.log("🎯 Routes with lazy functions:", routesWithLazy)
|
||||
console.log("📝 Generated lazy imports:", lazyComponents.size)
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Build-time Optimization
|
||||
|
||||
- **Static Generation**: All routing logic runs at build time, not runtime
|
||||
- **Lazy Loading**: Components are loaded on-demand, reducing initial bundle size
|
||||
- **Tree Shaking**: Unused routes and components are eliminated during bundling
|
||||
|
||||
### Memory Efficiency
|
||||
|
||||
- **File Caching**: Plugin processes files once and caches results
|
||||
- **Selective Import**: Only imports files that are actually used in routes
|
||||
|
||||
## Integration Points
|
||||
|
||||
### Vite Integration
|
||||
|
||||
```typescript
|
||||
// vite.config.ts
|
||||
import { defineConfig } from "vite"
|
||||
import routeBuilder from "./plugins/vite/vite-plugin-route-builder"
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
routeBuilder(), // Add the route builder plugin
|
||||
// ... other plugins
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
### React Router Integration
|
||||
|
||||
```typescript
|
||||
// App.tsx
|
||||
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
|
||||
import { routes } from './generated-routes'
|
||||
|
||||
const router = createBrowserRouter(routes)
|
||||
|
||||
export default function App() {
|
||||
return <RouterProvider router={router} />
|
||||
}
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Potential Improvements
|
||||
|
||||
1. **Watch Mode**: Real-time route regeneration during development
|
||||
2. **TypeScript Validation**: Compile-time route validation
|
||||
3. **Route Metadata**: Support for route-level metadata and guards
|
||||
4. **Custom Conventions**: Configurable file naming conventions
|
||||
5. **Nested Layouts**: Support for multiple layout levels
|
||||
|
||||
### Extensibility
|
||||
|
||||
The plugin architecture allows for easy extension:
|
||||
|
||||
- Custom file processors for different route types
|
||||
- Pluggable path resolution strategies
|
||||
- Configurable code generation templates
|
||||
- Integration with other meta-frameworks
|
||||
|
||||
## Conclusion
|
||||
|
||||
The Vite Route Builder plugin successfully transforms file system-based routing into optimized React Router configurations. By leveraging build-time generation, it provides excellent performance while maintaining developer ergonomics similar to Next.js App Router. The robust path matching and lazy loading implementation ensures reliable route generation for complex application structures.
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./vite-plugin-route-builder"
|
||||
|
|
@ -0,0 +1,356 @@
|
|||
import { writeFileSync } from "node:fs"
|
||||
import { dirname, relative, resolve } from "node:path"
|
||||
import { inspect } from "node:util"
|
||||
|
||||
import glob from "fast-glob"
|
||||
import type { RouteObject } from "react-router"
|
||||
import type { Logger, Plugin } from "vite"
|
||||
|
||||
import { buildGlobRoutes } from "./utils/route-builder"
|
||||
|
||||
export interface RouteBuilderPluginOptions {
|
||||
/** Page files glob pattern */
|
||||
pagePattern?: string
|
||||
/** Output path for generated routes */
|
||||
outputPath?: string
|
||||
/** Whether to enable in dev mode */
|
||||
enableInDev?: boolean
|
||||
/** Custom file to route path transformation logic */
|
||||
transformPath?: (path: string) => string
|
||||
}
|
||||
|
||||
export function routeBuilderPluginV2(options: RouteBuilderPluginOptions = {}): Plugin {
|
||||
const {
|
||||
pagePattern = "./pages/**/*.tsx",
|
||||
outputPath = "./src/generated-routes.ts",
|
||||
enableInDev = true,
|
||||
transformPath,
|
||||
} = options
|
||||
|
||||
let isProduction = false
|
||||
let root = ""
|
||||
let logger: Logger
|
||||
|
||||
function generateRouteFileContent(
|
||||
routes: RouteObject[],
|
||||
fileToImportMap: Record<string, string>,
|
||||
): string {
|
||||
// Collect all used lazy functions
|
||||
const usedLazyFunctions = new Set<string>()
|
||||
const lazyFunctionMap = new Map<string, string>()
|
||||
let lazyCounter = 0
|
||||
|
||||
// Recursively traverse route tree, collect all used lazy functions
|
||||
function collectUsedLazyFunctions(routes: RouteObject[]) {
|
||||
routes.forEach((route) => {
|
||||
if (route.lazy && route.handle?.fs) {
|
||||
const fsPath = route.handle.fs
|
||||
|
||||
// Try to find the corresponding file
|
||||
let matchedKey: string | undefined
|
||||
|
||||
// Direct match strategy: according to route-builder.ts logic
|
||||
// 1. For grouped routes, fs is segmentPathKey, need to find ${fs}/layout.tsx
|
||||
// 2. For layout files, fs is segmentPathKey, need to find ${fs}.tsx
|
||||
// 3. For normal pages, fs is ${segmentPathKey}/${normalizeKey}, but the actual file is ${segmentPathKey}.tsx
|
||||
|
||||
// Strategy 1: Direct match fs.tsx
|
||||
if (fileToImportMap[`${fsPath}.tsx`]) {
|
||||
matchedKey = `${fsPath}.tsx`
|
||||
}
|
||||
// Strategy 2: layout file (for grouped routes)
|
||||
else if (fileToImportMap[`${fsPath}/layout.tsx`]) {
|
||||
matchedKey = `${fsPath}/layout.tsx`
|
||||
}
|
||||
// Strategy 3: index file
|
||||
else if (fileToImportMap[`${fsPath}/index.tsx`]) {
|
||||
matchedKey = `${fsPath}/index.tsx`
|
||||
}
|
||||
// Strategy 4: For special path correction
|
||||
else {
|
||||
// If fsPath ends with /, it might be an index page
|
||||
if (fsPath.endsWith("/")) {
|
||||
const correctedPath = fsPath.slice(0, -1) // Remove trailing /
|
||||
if (fileToImportMap[`${correctedPath}/index.tsx`]) {
|
||||
matchedKey = `${correctedPath}/index.tsx`
|
||||
} else if (fileToImportMap[`${correctedPath}.tsx`]) {
|
||||
matchedKey = `${correctedPath}.tsx`
|
||||
}
|
||||
}
|
||||
// For dynamic routes, remove /:param part, keep file path
|
||||
else if (fsPath.includes("/:")) {
|
||||
// Handle cases like "./pages/category/[category]/:category"
|
||||
// Remove /:param part, keep the previous path
|
||||
const correctedPath = fsPath.replace(/\/:[^/]+(?:\/.*)?$/, "")
|
||||
if (fileToImportMap[`${correctedPath}.tsx`]) {
|
||||
matchedKey = `${correctedPath}.tsx`
|
||||
}
|
||||
}
|
||||
// If fsPath ends with a repeated path segment, remove the last segment
|
||||
else {
|
||||
const pathParts = fsPath.split("/")
|
||||
if (pathParts.length >= 2) {
|
||||
const lastPart = pathParts.at(-1)
|
||||
const secondLastPart = pathParts.at(-2)
|
||||
|
||||
// If the last two path segments are the same, remove the last one
|
||||
if (lastPart === secondLastPart) {
|
||||
const correctedPath = pathParts.slice(0, -1).join("/")
|
||||
if (fileToImportMap[`${correctedPath}.tsx`]) {
|
||||
matchedKey = `${correctedPath}.tsx`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedKey && fileToImportMap[matchedKey]) {
|
||||
const lazyFuncName = `lazy${lazyCounter++}`
|
||||
usedLazyFunctions.add(matchedKey)
|
||||
lazyFunctionMap.set(matchedKey, lazyFuncName)
|
||||
|
||||
logger.info(
|
||||
`[route-builder-v2] Mapped lazy function: ${fsPath} -> ${matchedKey} -> ${lazyFuncName}`,
|
||||
)
|
||||
} else {
|
||||
logger.warn(`[route-builder-v2] Could not find file for fs path: ${fsPath}`)
|
||||
logger.warn(
|
||||
`[route-builder-v2] Available file keys: ${inspect(Object.keys(fileToImportMap), {
|
||||
depth: null,
|
||||
})}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (route.children) {
|
||||
collectUsedLazyFunctions(route.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
collectUsedLazyFunctions(routes)
|
||||
|
||||
// Generate import statements
|
||||
const imports: string[] = []
|
||||
usedLazyFunctions.forEach((key) => {
|
||||
const importPath = fileToImportMap[key]
|
||||
const lazyFuncName = lazyFunctionMap.get(key)
|
||||
if (importPath && lazyFuncName) {
|
||||
imports.push(`const ${lazyFuncName} = () => import("${importPath}")`)
|
||||
}
|
||||
})
|
||||
|
||||
// Recursively process routes, replace lazy functions and remove handle
|
||||
function processRoutes(routes: RouteObject[]): any {
|
||||
return routes.map((route) => {
|
||||
const newRoute: any = { ...route }
|
||||
|
||||
// Process lazy functions
|
||||
if (route.lazy && route.handle?.fs) {
|
||||
const fsPath = route.handle.fs
|
||||
|
||||
// Find matching file - use the same matching logic
|
||||
let matchedKey: string | undefined
|
||||
|
||||
if (fileToImportMap[`${fsPath}.tsx`]) {
|
||||
matchedKey = `${fsPath}.tsx`
|
||||
} else if (fileToImportMap[`${fsPath}/layout.tsx`]) {
|
||||
matchedKey = `${fsPath}/layout.tsx`
|
||||
} else if (fileToImportMap[`${fsPath}/index.tsx`]) {
|
||||
matchedKey = `${fsPath}/index.tsx`
|
||||
} else {
|
||||
// For special path correction
|
||||
if (fsPath.endsWith("/")) {
|
||||
const correctedPath = fsPath.slice(0, -1) // Remove trailing /
|
||||
if (fileToImportMap[`${correctedPath}/index.tsx`]) {
|
||||
matchedKey = `${correctedPath}/index.tsx`
|
||||
} else if (fileToImportMap[`${correctedPath}.tsx`]) {
|
||||
matchedKey = `${correctedPath}.tsx`
|
||||
}
|
||||
}
|
||||
// For dynamic routes, remove /:param part, keep file path
|
||||
else if (fsPath.includes("/:")) {
|
||||
// Handle cases like "./pages/category/[category]/:category"
|
||||
// Remove /:param part, keep the previous path
|
||||
const correctedPath = fsPath.replace(/\/:[^/]+(?:\/.*)?$/, "")
|
||||
if (fileToImportMap[`${correctedPath}.tsx`]) {
|
||||
matchedKey = `${correctedPath}.tsx`
|
||||
}
|
||||
}
|
||||
// For repeated path segments, try removing the last segment
|
||||
else {
|
||||
const pathParts = fsPath.split("/")
|
||||
if (pathParts.length >= 2) {
|
||||
const lastPart = pathParts.at(-1)
|
||||
const secondLastPart = pathParts.at(-2)
|
||||
|
||||
// If the last two path segments are the same, remove the last one
|
||||
if (lastPart === secondLastPart) {
|
||||
const correctedPath = pathParts.slice(0, -1).join("/")
|
||||
if (fileToImportMap[`${correctedPath}.tsx`]) {
|
||||
matchedKey = `${correctedPath}.tsx`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedKey && lazyFunctionMap.has(matchedKey)) {
|
||||
newRoute.lazy = `__LAZY_${lazyFunctionMap.get(matchedKey)}__`
|
||||
} else {
|
||||
// If no matching file is found, delete lazy property
|
||||
delete newRoute.lazy
|
||||
logger.warn(`[route-builder-v2] No lazy function for route: ${fsPath}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove handle property
|
||||
delete newRoute.handle
|
||||
|
||||
// Recursively process children
|
||||
if (route.children) {
|
||||
newRoute.children = processRoutes(route.children)
|
||||
}
|
||||
|
||||
return newRoute
|
||||
})
|
||||
}
|
||||
|
||||
const processedRoutes = processRoutes(routes)
|
||||
|
||||
// Convert routes object to string and replace lazy function placeholders
|
||||
const routesString = JSON.stringify(processedRoutes, null, 2).replaceAll(
|
||||
/"__LAZY_(\w+)__"/g,
|
||||
"$1",
|
||||
)
|
||||
|
||||
return `// This file is auto-generated by vite-plugin-route-builder
|
||||
// Do not edit manually
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import type { RouteObject } from "react-router"
|
||||
|
||||
// Lazy imports for page components
|
||||
${imports.join("\n")}
|
||||
|
||||
// Generated route configuration
|
||||
export const routes: RouteObject[] = ${routesString}
|
||||
|
||||
export default routes
|
||||
`
|
||||
}
|
||||
|
||||
function generateRoutes() {
|
||||
try {
|
||||
const pageFiles = glob.sync(pagePattern, {
|
||||
cwd: root,
|
||||
absolute: true,
|
||||
})
|
||||
|
||||
logger.info(`[route-builder-v2] Found ${pageFiles.length} page files`)
|
||||
|
||||
// Build glob object, key is the relative path to pages directory
|
||||
const globObject: Record<string, () => Promise<any>> = {}
|
||||
const fileToImportMap: Record<string, string> = {}
|
||||
|
||||
pageFiles.forEach((absolutePath) => {
|
||||
// Get relative path to root
|
||||
const relativePath = relative(root, absolutePath)
|
||||
|
||||
// Convert to ./pages/ format for route-builder
|
||||
let routeKey: string
|
||||
if (relativePath.includes("/pages/")) {
|
||||
routeKey = `./pages/${relativePath.split("/pages/")[1]}`
|
||||
} else if (relativePath.includes("\\pages\\")) {
|
||||
routeKey = `./pages/${relativePath.split("\\pages\\")[1]?.replaceAll("\\", "/")}`
|
||||
} else {
|
||||
// Assume file is in pages directory
|
||||
routeKey = `./${relativePath.replaceAll("\\", "/")}`
|
||||
}
|
||||
|
||||
// Apply custom path transformation
|
||||
if (transformPath) {
|
||||
routeKey = transformPath(routeKey)
|
||||
}
|
||||
|
||||
// Generate relative path for import (relative to output file)
|
||||
const outputDir = dirname(resolve(root, outputPath))
|
||||
let importPath = relative(outputDir, absolutePath)
|
||||
|
||||
// Ensure correct path separator
|
||||
importPath = importPath.replaceAll("\\", "/")
|
||||
|
||||
// Ensure relative path starts with ./ or ../
|
||||
if (!importPath.startsWith(".")) {
|
||||
importPath = `./${importPath}`
|
||||
}
|
||||
|
||||
// Remove .tsx extension
|
||||
importPath = importPath.replace(/\.tsx$/, "")
|
||||
|
||||
globObject[routeKey] = () => Promise.resolve({ default: () => null })
|
||||
fileToImportMap[routeKey] = importPath
|
||||
|
||||
logger.info(`[route-builder-v2] Mapped: ${routeKey} -> ${importPath}`)
|
||||
})
|
||||
|
||||
// Use existing route building logic
|
||||
const routes = buildGlobRoutes(globObject)
|
||||
|
||||
// Generate route file content
|
||||
const routeFileContent = generateRouteFileContent(routes, fileToImportMap)
|
||||
|
||||
const outputFilePath = resolve(root, outputPath)
|
||||
writeFileSync(outputFilePath, routeFileContent, "utf-8")
|
||||
|
||||
logger.info(`[route-builder-v2] Generated routes: ${outputFilePath}`)
|
||||
} catch (error: any) {
|
||||
logger.error(`[route-builder-v2] Error generating routes:${error.message}`)
|
||||
console.error(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: "vite-plugin-route-builder-v2",
|
||||
configResolved(config) {
|
||||
isProduction = config.command === "build"
|
||||
root = config.root
|
||||
logger = config.logger
|
||||
},
|
||||
|
||||
buildStart() {
|
||||
if (isProduction || enableInDev) {
|
||||
generateRoutes()
|
||||
}
|
||||
},
|
||||
|
||||
configureServer(server) {
|
||||
if (!enableInDev) return
|
||||
|
||||
const watchPattern = resolve(root, pagePattern.replace("./", ""))
|
||||
server.watcher.add(watchPattern)
|
||||
|
||||
server.watcher.on("add", handleFileChange)
|
||||
server.watcher.on("unlink", handleFileChange)
|
||||
|
||||
function handleFileChange(path: string) {
|
||||
const relativePath = relative(root, path)
|
||||
if (relativePath.includes("/pages/") && relativePath.endsWith(".tsx")) {
|
||||
logger.info(`[route-builder-v2] Page file changed: ${relativePath}`)
|
||||
generateRoutes()
|
||||
|
||||
// Send custom HMR event
|
||||
server.ws.send({
|
||||
type: "custom",
|
||||
event: "routes-updated",
|
||||
data: { timestamp: Date.now() },
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default routeBuilderPluginV2
|
||||
353
pnpm-lock.yaml
353
pnpm-lock.yaml
|
|
@ -222,6 +222,9 @@ importers:
|
|||
'@follow/utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/internal/utils
|
||||
'@follow/vite-plugin-route-builder':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/vite-plugin-route-builder
|
||||
'@pengx17/electron-forge-maker-appimage':
|
||||
specifier: 1.2.1
|
||||
version: 1.2.1(patch_hash=5b5ab1ba36e8c0d7ffee912ebf29c1a18bc101c9c661ceb1bb0bda3deaf4c667)(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3)
|
||||
|
|
@ -309,9 +312,6 @@ importers:
|
|||
tar:
|
||||
specifier: 7.4.3
|
||||
version: 7.4.3
|
||||
tsup:
|
||||
specifier: 8.5.0
|
||||
version: 8.5.0(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.4)(typescript@5.8.3)(yaml@2.8.0)
|
||||
unplugin-ast:
|
||||
specifier: 0.15.0
|
||||
version: 0.15.0
|
||||
|
|
@ -1236,6 +1236,9 @@ importers:
|
|||
'@follow/utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/internal/utils
|
||||
'@follow/vite-plugin-route-builder':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/vite-plugin-route-builder
|
||||
'@types/html-minifier-terser':
|
||||
specifier: 7.0.2
|
||||
version: 7.0.2
|
||||
|
|
@ -1815,6 +1818,30 @@ importers:
|
|||
specifier: 8.5.0
|
||||
version: 8.5.0(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.4)(typescript@5.8.3)(yaml@2.8.0)
|
||||
|
||||
packages/vite-plugin-route-builder:
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: 22.15.23
|
||||
version: 22.15.23
|
||||
es-toolkit:
|
||||
specifier: 1.38.0
|
||||
version: 1.38.0
|
||||
fast-glob:
|
||||
specifier: 3.3.3
|
||||
version: 3.3.3
|
||||
react-router:
|
||||
specifier: 7.6.1
|
||||
version: 7.6.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
tsdown:
|
||||
specifier: 0.12.8
|
||||
version: 0.12.8(typescript@5.8.3)
|
||||
typescript:
|
||||
specifier: 'catalog:'
|
||||
version: 5.8.3
|
||||
vite:
|
||||
specifier: 6.3.5
|
||||
version: 6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)
|
||||
|
||||
packages:
|
||||
|
||||
7zip-bin@5.2.0:
|
||||
|
|
@ -1892,6 +1919,10 @@ packages:
|
|||
resolution: {integrity: sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/generator@7.27.5':
|
||||
resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-annotate-as-pure@7.27.1':
|
||||
resolution: {integrity: sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
|
@ -1999,6 +2030,11 @@ packages:
|
|||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
'@babel/parser@7.27.5':
|
||||
resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1':
|
||||
resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
|
@ -2585,6 +2621,10 @@ packages:
|
|||
resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/types@7.27.6':
|
||||
resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@better-auth/expo@1.2.7':
|
||||
resolution: {integrity: sha512-g8qBx7lBFfOWvAzWwNUVZr6IWYwBcZ7D/HcTzBG1zoZmD7PbdseQugWlIeS711vZ/Qqez7ZV0mDwpk2h+uT4nQ==}
|
||||
peerDependencies:
|
||||
|
|
@ -4716,6 +4756,13 @@ packages:
|
|||
peerDependencies:
|
||||
'@opentelemetry/api': ^1.1.0
|
||||
|
||||
'@oxc-project/runtime@0.72.3':
|
||||
resolution: {integrity: sha512-FtOS+0v7rZcnjXzYTTqv1vu/KDptD1UztFgoZkYBGe/6TcNFm+SP/jQoLvzau1SPir95WgDOBOUm2Gmsm+bQag==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@oxc-project/types@0.72.3':
|
||||
resolution: {integrity: sha512-CfAC4wrmMkUoISpQkFAIfMVvlPfQV3xg7ZlcqPXPOIMQhdKIId44G8W0mCPgtpWdFFAyJ+SFtiM+9vbyCkoVng==}
|
||||
|
||||
'@peculiar/asn1-android@2.3.16':
|
||||
resolution: {integrity: sha512-a1viIv3bIahXNssrOIkXZIlI2ePpZaNmR30d4aBL99mu2rO+mT9D6zBsp7H6eROWGtmwv0Ionp5olJurIo09dw==}
|
||||
|
||||
|
|
@ -5631,6 +5678,69 @@ packages:
|
|||
resolution: {integrity: sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@rolldown/binding-darwin-arm64@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-YInZppDBLp5DadbJZGc7xBfDrMCSj3P6i2rPlvOCMlvjBQxJi2kX8Jquh+LufsWUiHD3JsvvH5EuUUc/tF5fkA==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rolldown/binding-darwin-x64@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-Zwv8KHU/XdVwLseHG6slJ0FAFklPpiO0sjNvhrcMp1X3F2ajPzUdIO8Cnu3KLmX1GWVSvu6q1kyARLUqPvlh7Q==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rolldown/binding-freebsd-x64@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-FwhNC23Fz9ldHW1/rX4QaoQe4kyOybCgxO9eglue3cbb3ol28KWpQl3xJfvXc9+O6PDefAs4oFBCbtTh8seiUw==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-E60pNliWl4j7EFEVX2oeJZ5VzR+NG6fvDJoqfqRfCl8wtKIf9E1WPWVQIrT+zkz+Fhc5op8g7h25z6rtxsDy9g==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rolldown/binding-linux-arm64-gnu@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-d+qo1LZ/a3EcQW08byIIZy0PBthmG/7dr69pifmNIet/azWR8jbceQaRFFczVc/NwVV3fsZDCmjG8mgJzsNEAg==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rolldown/binding-linux-arm64-musl@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-P1hbtYF+5ftJI2Ergs4iARbAk6Xd6WnTQb3CF9kjN3KfJTsRYdo5/fvU8Lz/gzhZVvkCXXH3NxDd9308UBO8cw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rolldown/binding-linux-x64-gnu@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-Q9NM9uMFN9cjcrW7gd9U087B5WzkEj9dQQHOgoENZSy+vYJYS2fINCIG40ljEVC6jXmVrJgUhJKv7elRZM1nng==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rolldown/binding-linux-x64-musl@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-1tuCWuR8gx9PyW2pxAx2ZqnOnwhoY6NWBVP6ZmrjCKQ16NclYc61BzegFXSdugCy8w1QpBPT8/c5oh2W4E5aeA==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rolldown/binding-wasm32-wasi@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-zrSeYrpTf27hRxMLh0qpkCoWgzRKG8EyR6o09Zt9xkqCOeE5tEK/S3jV1Nii9WSqVCWFRA+OYxKzMNoykV590g==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [wasm32]
|
||||
|
||||
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-diR41DsMUnkvb9hvW8vuIrA0WaacAN1fu6lPseXhYifAOZN6kvxEwKn7Xib8i0zjdrYErLv7GNSQ48W+xiNOnA==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rolldown/binding-win32-ia32-msvc@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-oCbbcDC3Lk8YgdxCkG23UqVrvXVvllIBgmmwq89bhq5okPP899OI/P+oTTDsUTbhljzNq1pH8a+mR6YBxAFfvw==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rolldown/binding-win32-x64-msvc@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-w5hVsOv3dzKo10wAXizmnDvUo1yasn/ps+mcn9H9TiJ/GeRE5/15Y6hG6vUQYRQNLVbYRHUt2qG0MyOoasPcHg==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.15':
|
||||
resolution: {integrity: sha512-lvFtIbidq5EqyAAeiVk41ZNjGRgUoGRBIuqpe1VRJ7R8Av7TLAgGWAwGlHNhO7MFkl7MNRX350CsTtIWIYkNIQ==}
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.9':
|
||||
resolution: {integrity: sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==}
|
||||
|
||||
|
|
@ -6742,6 +6852,10 @@ packages:
|
|||
ansicolors@0.3.2:
|
||||
resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==}
|
||||
|
||||
ansis@4.1.0:
|
||||
resolution: {integrity: sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
any-base@1.1.0:
|
||||
resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==}
|
||||
|
||||
|
|
@ -6851,6 +6965,10 @@ packages:
|
|||
resolution: {integrity: sha512-P63jzlYNz96MF9mCcprU+a7I5/ZQ5QAn3y+mZcPWEcGV3CHF/GWnkFPj3oCrWLUjL47+PD9PNiCUdXxw0cWdsg==}
|
||||
engines: {node: '>=20.18.0'}
|
||||
|
||||
ast-kit@2.1.0:
|
||||
resolution: {integrity: sha512-ROM2LlXbZBZVk97crfw8PGDOBzzsJvN2uJCmwswvPUNyfH14eg90mSN3xNqsri1JS1G9cz0VzeDUhxJkTrr4Ew==}
|
||||
engines: {node: '>=20.18.0'}
|
||||
|
||||
astral-regex@2.0.0:
|
||||
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -7041,6 +7159,9 @@ packages:
|
|||
birecord@0.1.1:
|
||||
resolution: {integrity: sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==}
|
||||
|
||||
birpc@2.4.0:
|
||||
resolution: {integrity: sha512-5IdNxTyhXHv2UlgnPHQ0h+5ypVmkrYHzL8QT+DwFZ//2N/oNV8Ch+BCRmTJ3x6/z9Axo/cXYBc9eprsUVK/Jsg==}
|
||||
|
||||
bl@1.2.3:
|
||||
resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==}
|
||||
|
||||
|
|
@ -8094,6 +8215,10 @@ packages:
|
|||
resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
|
||||
diff@8.0.2:
|
||||
resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
|
||||
diffie-hellman@5.0.3:
|
||||
resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==}
|
||||
|
||||
|
|
@ -8289,6 +8414,15 @@ packages:
|
|||
resolution: {integrity: sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
dts-resolver@2.1.1:
|
||||
resolution: {integrity: sha512-3BiGFhB6mj5Kv+W2vdJseQUYW+SKVzAFJL6YNP6ursbrwy1fXHRotfHi3xLNxe4wZl/K8qbAFeCDjZLjzqxxRw==}
|
||||
engines: {node: '>=20.18.0'}
|
||||
peerDependencies:
|
||||
oxc-resolver: '>=11.0.0'
|
||||
peerDependenciesMeta:
|
||||
oxc-resolver:
|
||||
optional: true
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -8420,6 +8554,10 @@ packages:
|
|||
emoji-regex@9.2.2:
|
||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||
|
||||
empathic@1.1.0:
|
||||
resolution: {integrity: sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
encode-utf8@1.0.3:
|
||||
resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==}
|
||||
|
||||
|
|
@ -9981,6 +10119,9 @@ packages:
|
|||
resolution: {integrity: sha512-QkACju9MiN59CKSY5JsGZCYmPZkA6sIW6OFCUp7qDjZu6S6KHtJHhAc9Uy9mV9F8PJ1/HQ3ybZF2yjCa/73fvQ==}
|
||||
engines: {node: '>=16.9.0'}
|
||||
|
||||
hookable@5.5.3:
|
||||
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
||||
|
||||
hosted-git-info@2.8.9:
|
||||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||
|
||||
|
|
@ -13416,6 +13557,26 @@ packages:
|
|||
resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
||||
rolldown-plugin-dts@0.13.11:
|
||||
resolution: {integrity: sha512-1TScN31JImk8xcq9kdm52z2W8/QX3zeDpEjFkyZmK+GcD0u8QqSWWARBsCEdfS99NyI6D9NIbUpsABXlcpZhig==}
|
||||
engines: {node: '>=20.18.0'}
|
||||
peerDependencies:
|
||||
'@typescript/native-preview': '>=7.0.0-dev.20250601.1'
|
||||
rolldown: ^1.0.0-beta.9
|
||||
typescript: ^5.0.0
|
||||
vue-tsc: ~2.2.0
|
||||
peerDependenciesMeta:
|
||||
'@typescript/native-preview':
|
||||
optional: true
|
||||
typescript:
|
||||
optional: true
|
||||
vue-tsc:
|
||||
optional: true
|
||||
|
||||
rolldown@1.0.0-beta.15:
|
||||
resolution: {integrity: sha512-ep788NsIGl0W5gT+99hBrSGe4Hdhcwc55PqM3O0mR5H0C4ZpGpDGgu9YzTJ8a6mFDLnFnc/LYC+Dszb7oWK/dg==}
|
||||
hasBin: true
|
||||
|
||||
rollup@2.79.2:
|
||||
resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
|
@ -14334,6 +14495,28 @@ packages:
|
|||
typescript:
|
||||
optional: true
|
||||
|
||||
tsdown@0.12.8:
|
||||
resolution: {integrity: sha512-niHeVcFCNjvVZYVGTeoM4BF+/DWxP8pFH2tUs71sEKYdcKtJIbkSdEmtxByaRZeMgwVbVgPb8nv9i9okVwFLAA==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@arethetypeswrong/core': ^0.18.1
|
||||
publint: ^0.3.0
|
||||
typescript: ^5.0.0
|
||||
unplugin-lightningcss: ^0.4.0
|
||||
unplugin-unused: ^0.5.0
|
||||
peerDependenciesMeta:
|
||||
'@arethetypeswrong/core':
|
||||
optional: true
|
||||
publint:
|
||||
optional: true
|
||||
typescript:
|
||||
optional: true
|
||||
unplugin-lightningcss:
|
||||
optional: true
|
||||
unplugin-unused:
|
||||
optional: true
|
||||
|
||||
tslib@1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
|
||||
|
|
@ -15407,6 +15590,14 @@ snapshots:
|
|||
'@jridgewell/trace-mapping': 0.3.25
|
||||
jsesc: 3.1.0
|
||||
|
||||
'@babel/generator@7.27.5':
|
||||
dependencies:
|
||||
'@babel/parser': 7.27.5
|
||||
'@babel/types': 7.27.6
|
||||
'@jridgewell/gen-mapping': 0.3.8
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
jsesc: 3.1.0
|
||||
|
||||
'@babel/helper-annotate-as-pure@7.27.1':
|
||||
dependencies:
|
||||
'@babel/types': 7.27.3
|
||||
|
|
@ -15610,6 +15801,10 @@ snapshots:
|
|||
dependencies:
|
||||
'@babel/types': 7.27.3
|
||||
|
||||
'@babel/parser@7.27.5':
|
||||
dependencies:
|
||||
'@babel/types': 7.27.6
|
||||
|
||||
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.26.10)':
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
|
|
@ -17017,6 +17212,11 @@ snapshots:
|
|||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
|
||||
'@babel/types@7.27.6':
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
|
||||
'@better-auth/expo@1.2.7(better-auth@1.2.8)':
|
||||
dependencies:
|
||||
'@better-fetch/fetch': 1.1.18
|
||||
|
|
@ -20085,6 +20285,10 @@ snapshots:
|
|||
'@opentelemetry/api': 1.9.0
|
||||
'@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0)
|
||||
|
||||
'@oxc-project/runtime@0.72.3': {}
|
||||
|
||||
'@oxc-project/types@0.72.3': {}
|
||||
|
||||
'@peculiar/asn1-android@2.3.16':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.3.15
|
||||
|
|
@ -21064,7 +21268,7 @@ snapshots:
|
|||
debug: 2.6.9
|
||||
invariant: 2.2.4
|
||||
metro: 0.82.4(bufferutil@4.0.9)
|
||||
metro-config: 0.82.4(bufferutil@4.0.9)(utf-8-validate@6.0.5)
|
||||
metro-config: 0.82.4(bufferutil@4.0.9)
|
||||
metro-core: 0.82.4
|
||||
semver: 7.7.2
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -21203,6 +21407,46 @@ snapshots:
|
|||
'@resvg/resvg-js-win32-ia32-msvc': 2.6.2
|
||||
'@resvg/resvg-js-win32-x64-msvc': 2.6.2
|
||||
|
||||
'@rolldown/binding-darwin-arm64@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-darwin-x64@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-freebsd-x64@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-arm64-gnu@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-arm64-musl@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-x64-gnu@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-linux-x64-musl@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-wasm32-wasi@1.0.0-beta.15':
|
||||
dependencies:
|
||||
'@napi-rs/wasm-runtime': 0.2.10
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-win32-ia32-msvc@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/binding-win32-x64-msvc@1.0.0-beta.15':
|
||||
optional: true
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.15': {}
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.9': {}
|
||||
|
||||
'@rollup/plugin-babel@5.3.1(@babel/core@7.27.3)(@types/babel__core@7.20.5)(rollup@2.79.2)':
|
||||
|
|
@ -21969,7 +22213,7 @@ snapshots:
|
|||
|
||||
'@types/yauzl@2.10.3':
|
||||
dependencies:
|
||||
'@types/node': 22.15.3
|
||||
'@types/node': 22.15.23
|
||||
optional: true
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
|
|
@ -22479,6 +22723,8 @@ snapshots:
|
|||
|
||||
ansicolors@0.3.2: {}
|
||||
|
||||
ansis@4.1.0: {}
|
||||
|
||||
any-base@1.1.0: {}
|
||||
|
||||
any-promise@1.3.0: {}
|
||||
|
|
@ -22656,6 +22902,11 @@ snapshots:
|
|||
'@babel/parser': 7.27.3
|
||||
pathe: 2.0.3
|
||||
|
||||
ast-kit@2.1.0:
|
||||
dependencies:
|
||||
'@babel/parser': 7.27.5
|
||||
pathe: 2.0.3
|
||||
|
||||
astral-regex@2.0.0: {}
|
||||
|
||||
async-es@3.2.6: {}
|
||||
|
|
@ -23006,6 +23257,8 @@ snapshots:
|
|||
|
||||
birecord@0.1.1: {}
|
||||
|
||||
birpc@2.4.0: {}
|
||||
|
||||
bl@1.2.3:
|
||||
dependencies:
|
||||
readable-stream: 2.3.8
|
||||
|
|
@ -24222,6 +24475,8 @@ snapshots:
|
|||
|
||||
diff@7.0.0: {}
|
||||
|
||||
diff@8.0.2: {}
|
||||
|
||||
diffie-hellman@5.0.3:
|
||||
dependencies:
|
||||
bn.js: 4.12.2
|
||||
|
|
@ -24370,6 +24625,8 @@ snapshots:
|
|||
nan: 2.22.2
|
||||
optional: true
|
||||
|
||||
dts-resolver@2.1.1: {}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
|
|
@ -24658,6 +24915,8 @@ snapshots:
|
|||
|
||||
emoji-regex@9.2.2: {}
|
||||
|
||||
empathic@1.1.0: {}
|
||||
|
||||
encode-utf8@1.0.3:
|
||||
optional: true
|
||||
|
||||
|
|
@ -26544,7 +26803,7 @@ snapshots:
|
|||
dependencies:
|
||||
array-union: 2.1.0
|
||||
dir-glob: 3.0.1
|
||||
fast-glob: 3.3.2
|
||||
fast-glob: 3.3.3
|
||||
ignore: 5.3.0
|
||||
merge2: 1.4.1
|
||||
slash: 3.0.0
|
||||
|
|
@ -26826,6 +27085,8 @@ snapshots:
|
|||
|
||||
hono@4.7.10(patch_hash=5c74c2d2afaa5880c13d75458dd26c84da568851691b1fb6de6d877c29936d05): {}
|
||||
|
||||
hookable@5.5.3: {}
|
||||
|
||||
hosted-git-info@2.8.9: {}
|
||||
|
||||
hosted-git-info@4.1.0:
|
||||
|
|
@ -28221,6 +28482,21 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
metro-config@0.82.4(bufferutil@4.0.9):
|
||||
dependencies:
|
||||
connect: 3.7.0
|
||||
cosmiconfig: 5.2.1
|
||||
flow-enums-runtime: 0.0.6
|
||||
jest-validate: 29.7.0
|
||||
metro: 0.82.4(bufferutil@4.0.9)
|
||||
metro-cache: 0.82.4
|
||||
metro-core: 0.82.4
|
||||
metro-runtime: 0.82.4
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
metro-config@0.82.4(bufferutil@4.0.9)(utf-8-validate@6.0.5):
|
||||
dependencies:
|
||||
connect: 3.7.0
|
||||
|
|
@ -28235,6 +28511,7 @@ snapshots:
|
|||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
optional: true
|
||||
|
||||
metro-core@0.82.4:
|
||||
dependencies:
|
||||
|
|
@ -28346,6 +28623,7 @@ snapshots:
|
|||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
optional: true
|
||||
|
||||
metro@0.82.4(bufferutil@4.0.9):
|
||||
dependencies:
|
||||
|
|
@ -28373,7 +28651,7 @@ snapshots:
|
|||
metro-babel-transformer: 0.82.4
|
||||
metro-cache: 0.82.4
|
||||
metro-cache-key: 0.82.4
|
||||
metro-config: 0.82.4(bufferutil@4.0.9)(utf-8-validate@6.0.5)
|
||||
metro-config: 0.82.4(bufferutil@4.0.9)
|
||||
metro-core: 0.82.4
|
||||
metro-file-map: 0.82.4
|
||||
metro-resolver: 0.82.4
|
||||
|
|
@ -28440,6 +28718,7 @@ snapshots:
|
|||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
optional: true
|
||||
|
||||
micromark-core-commonmark@2.0.3:
|
||||
dependencies:
|
||||
|
|
@ -30765,6 +31044,43 @@ snapshots:
|
|||
sprintf-js: 1.1.3
|
||||
optional: true
|
||||
|
||||
rolldown-plugin-dts@0.13.11(rolldown@1.0.0-beta.15)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@babel/generator': 7.27.5
|
||||
'@babel/parser': 7.27.5
|
||||
'@babel/types': 7.27.6
|
||||
ast-kit: 2.1.0
|
||||
birpc: 2.4.0
|
||||
debug: 4.4.1(supports-color@8.1.1)
|
||||
dts-resolver: 2.1.1
|
||||
get-tsconfig: 4.10.1
|
||||
rolldown: 1.0.0-beta.15
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- oxc-resolver
|
||||
- supports-color
|
||||
|
||||
rolldown@1.0.0-beta.15:
|
||||
dependencies:
|
||||
'@oxc-project/runtime': 0.72.3
|
||||
'@oxc-project/types': 0.72.3
|
||||
'@rolldown/pluginutils': 1.0.0-beta.15
|
||||
ansis: 4.1.0
|
||||
optionalDependencies:
|
||||
'@rolldown/binding-darwin-arm64': 1.0.0-beta.15
|
||||
'@rolldown/binding-darwin-x64': 1.0.0-beta.15
|
||||
'@rolldown/binding-freebsd-x64': 1.0.0-beta.15
|
||||
'@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.15
|
||||
'@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.15
|
||||
'@rolldown/binding-linux-arm64-musl': 1.0.0-beta.15
|
||||
'@rolldown/binding-linux-x64-gnu': 1.0.0-beta.15
|
||||
'@rolldown/binding-linux-x64-musl': 1.0.0-beta.15
|
||||
'@rolldown/binding-wasm32-wasi': 1.0.0-beta.15
|
||||
'@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.15
|
||||
'@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.15
|
||||
'@rolldown/binding-win32-x64-msvc': 1.0.0-beta.15
|
||||
|
||||
rollup@2.79.2:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
|
@ -31833,6 +32149,29 @@ snapshots:
|
|||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
|
||||
tsdown@0.12.8(typescript@5.8.3):
|
||||
dependencies:
|
||||
ansis: 4.1.0
|
||||
cac: 6.7.14
|
||||
chokidar: 4.0.3
|
||||
debug: 4.4.1(supports-color@8.1.1)
|
||||
diff: 8.0.2
|
||||
empathic: 1.1.0
|
||||
hookable: 5.5.3
|
||||
rolldown: 1.0.0-beta.15
|
||||
rolldown-plugin-dts: 0.13.11(rolldown@1.0.0-beta.15)(typescript@5.8.3)
|
||||
semver: 7.7.2
|
||||
tinyexec: 1.0.1
|
||||
tinyglobby: 0.2.14
|
||||
unconfig: 7.3.2
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- '@typescript/native-preview'
|
||||
- oxc-resolver
|
||||
- supports-color
|
||||
- vue-tsc
|
||||
|
||||
tslib@1.14.1:
|
||||
optional: true
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue