one
Version:
One is a new React Framework that makes Vite serve both native and web.
466 lines • 19.3 kB
TypeScript
import type { GetTransform } from '@vxrn/compiler';
import type { metroPlugin } from '@vxrn/vite-plugin-metro';
import type { PluginOptions as TSConfigPluginOptions } from 'vite-tsconfig-paths';
import type { AutoDepOptimizationOptions, DepOptimize, DepPatch, AfterBuildProps as VXRNAfterBuildProps, VXRNBuildOptions, VXRNOptions } from 'vxrn';
import type { One as OneShared } from '../interfaces/router';
import type { RouteNode } from '../router/Route';
type MetroPluginOptions = Parameters<typeof metroPlugin>[0];
export type RouteInfo<TRegex = string> = {
file: string;
page: string;
namedRegex: TRegex;
loaderPath?: string;
loaderServerPath?: string;
urlPath: string;
urlCleanPath: string;
routeKeys: Record<string, string>;
layouts?: RouteNode[];
middlewares?: RouteNode[];
type: One.RouteType;
isNotFound?: boolean;
};
export declare namespace One {
export type Options = Omit<VXRNOptions, keyof PluginOptions> & PluginOptions;
export type RouteRenderMode = 'ssg' | 'spa' | 'ssr';
export type RouteType = RouteRenderMode | 'api' | 'layout';
export type ClientData = Record<string, any>;
export type RouteOptions = {
routeModes?: Record<string, RouteRenderMode>;
};
export type FixDependencies = {
[key: string]: DepOptimize | DepPatch['patchFiles'];
};
type PluginPlatformTarget = 'native' | 'web';
export type PluginOptions = {
/**
* Enabling zero does a couple very simple things:
*
* - It makes zero hand of seamelessly from server to client without flicker
*
*/
/**
* Per-file control over how code transforms.
* Defaults to SWC, runs babel before SWC if:
*
* - options.react.compiler is `true`, on tsx files in your app
* - `react-native-reanimated` is in your dependencies and a file contains a reanimated keyword
*
* Otherwise One defaults to using `@swc/core`.
*
* Accepts a function:
*
* (props: {
* id: string
* code: string
* development: boolean
* environment: Environment
* reactForRNVersion: '18' | '19'
* }) =>
* | true // default transforms
* | false // no transforms
* | 'babel' // force babel default transform
* | 'swc' // force swc default transform
*
* // force babel, custom transform
*
* | {
* transform: 'babel'
* excludeDefaultPlugins?: boolean
* } & babel.TransformOptions
*
* // force swc, custom transform
*
* | {
* transform: 'swc'
* } & SWCOptions
*
* Babel defaults to preset `@babel/preset-typescript` with plugins:
*
* - @babel/plugin-transform-destructuring
* - @babel/plugin-transform-runtime
* - @babel/plugin-transform-react-jsx
* - @babel/plugin-transform-async-generator-functions
* - @babel/plugin-transform-async-to-generator
*
*
* SWC defaults to target es5 for native, es2020 for web.
*
*/
transform?: GetTransform;
router?: {
/**
* An array of globs that One uses to ignore files in your routes directory. If a file matches any pattern, it will not be treated as a route.
*
* This is useful for ignoring test or utility files you wish to colocate.
*
* Currently, we only support patterns starting with <code>**/*</code>.
*
* Example:
* * <code>**/*.test.*</code>
*/
ignoredRouteFiles?: Array<`**/*${string}`>;
/**
* Dangerously customize the router root directory. This may lead to unexpected behavior.
*/
root?: string;
experimental?: {
/**
* If enabled, the router will try to avoid unnecessary remounts of _layout components.
*
* We aren't sure that this won't cause any side effects and break things, so this is still experimental and defaults to `false`.
*
* Currently, this will only effect the `<Slot />` navigator, where it will modify the screen element provided by `react-navigation` and set the `key` to a static value to prevent re-mounting.
*/
preventLayoutRemounting?: boolean;
/**
* Auto-generate route type helpers in route files.
*
* Route types are always generated in routes.d.ts. This option controls whether
* One automatically inserts type helpers into your route files.
*
* Options:
* - `false` (default): No auto-generation, manually add types yourself
* - `'type'`: Auto-inserts type-only helpers:
* ```typescript
* import type { RouteType } from 'one'
* type Route = RouteType<'/your/[route]'>
* ```
* - `'runtime'`: Auto-inserts runtime helpers:
* ```typescript
* import { createRoute } from 'one'
* const route = createRoute<'/your/[route]'>()
* ```
*
* The insertion happens automatically when route files are created or modified,
* and respects your existing code (won't modify loaders, etc).
*
* @default false
*/
typedRoutesGeneration?: false | 'type' | 'runtime';
};
};
react?: {
/**
* Enable the React Compiler, for all or specific platforms
* @default false
*/
compiler?: boolean | PluginPlatformTarget;
};
optimization?: {
/**
* Turn on [vite-plugin-barrel](https://github.com/JiangWeixian/vite-plugin-barrel/tree/master).
* Optimizes barrel export files to speed up your build, you must list the packages that have
* barrel exports. Especially useful for icon packs.
*
* @default ['@tamagui/lucide-icons']
*/
barrel?: boolean | string[];
/**
* By default One scans your fs routes and adds them as Vite `entries`, this prevents some hard
* reloads on web as you navigate to new pages, but can slow things startup.
*
* The 'flat' option is default and will automatically add just the routes at the root of your
* app but nothing nested in non-group folders below that.
*
* @default 'flat'
*/
autoEntriesScanning?: boolean | 'flat';
};
/**
* Path to a js or ts file to import before the rest of your app runs
* One controls your root, but you may want to runs some JS before anything else
* Use this to give One the entrypoint to run
*
* Can be a string to use the same file for all environments, or an object to specify
* different files per environment:
*
* @example
* setupFile: './setup.ts'
*
* @example
* setupFile: {
* client: './setup.client.ts',
* server: './setup.server.ts',
* native: './setup.native.ts'
* }
*
* @example
* setupFile: {
* client: './setup.client.ts',
* server: './setup.server.ts',
* ios: './setup.ios.ts',
* android: './setup.android.ts'
* }
*/
setupFile?: string | {
client?: string;
server?: string;
native?: string;
} | {
client?: string;
server?: string;
ios?: string;
android?: string;
};
config?: {
ensureTSConfig?: false;
/**
* One automatically adds vite-tsconfig-paths, set this to false to disable, or
* pass in an object to pass options down. If you add your own vite-tsconfig-paths
* we will avoid adding it again internally.
*
* See: https://github.com/aleclarson/vite-tsconfig-paths
*
* @default false
*/
tsConfigPaths?: boolean | TSConfigPluginOptions;
};
native?: {
/**
* The uid of your native app, this will be used internally in one to call
* `AppRegistry.registerComponent(key)`
*/
key?: string;
/**
* Turns on react-native-css-interop support when importing CSS on native
*/
css?: boolean;
/**
* Specifies the bundler to use for native builds. Defaults to 'vite'.
*
* - 'metro' is recommended for production stability. Note that this option comes with some limitations, see https://onestack.dev/docs/metro-mode#limitations for more info.
* - 'vite' is experimental but offers faster builds with SWC.
*
* Note that the ONE_METRO_MODE environment variable can override this setting to 'metro'.
*/
bundler?: 'metro' | 'vite';
} & ({
bundler: 'metro';
/** Options merging for Metro is not fully implemented in the One plugin, changing this may not work properly. Search for "METRO-OPTIONS-MERGING" in the codebase for details. */
bundlerOptions?: MetroPluginOptions;
} | {
bundler?: 'vite';
/** No configurable options with the default vite bundler. */
bundlerOptions?: {
currentlyHaveNoOptions?: null;
};
});
web?: {
/**
* Choose the default strategy for pages to be rendered on the web.
*
* For sites that are mostly static, choose "ssg":
* SSG stands for "server side generated", in this mode when you run `build`
* your pages will all be fully rendered on the server once during the build,
* outputting a static HTML page with the rendered page and loader data inlined.
* This gives better performance for initial render, and better SEO.
*
*
* For apps that are mostly dynamic, choose "spa":
* SPA stands for "single page app", in this mode when you run `build` your
* pages will only render out an empty shell of HTML and will not attempt to
* server render at all. Loaders will be run on the server side and the data will
* be available to your app on initial render.
*
* @default 'ssg'
*/
defaultRenderMode?: RouteRenderMode;
/**
* An array of redirect objects, works in development and production:
*
* @example
*
* [
* {
* source: '/vite',
* destination: 'https://vxrn.dev',
* permanent: true,
* },
* {
* source: '/docs/components/:slug/:version',
* destination: '/ui/:slug/:version',
* permanent: true,
* },
* ]
*
*/
redirects?: Redirect[];
/**
* Deployment target for production builds.
* - 'node': Default Node.js server using Hono
* - 'vercel': Vercel serverless functions
* - 'cloudflare': Cloudflare Workers
*
* @default node
*/
deploy?: 'node' | 'vercel' | 'cloudflare';
/**
* @experimental
* When true, inlines the CSS content directly into the HTML instead of using <link> tags.
* This can improve performance by eliminating an extra network request for CSS.
*
* @default false
*/
inlineLayoutCSS?: boolean;
/**
* @experimental
* Controls how scripts are loaded for improved performance.
*
* - `'defer-non-critical'`: Critical scripts (framework entry, page, layouts) load immediately.
* Non-critical scripts (component imports, utilities) become modulepreload hints only,
* reducing network/CPU contention.
*
* - `'after-lcp'`: Scripts download immediately via modulepreload but execution is deferred
* until after first paint using double requestAnimationFrame. This allows the browser to
* paint the SSR content before executing JavaScript. Only applies to SSG pages.
*
* - `'after-lcp-aggressive'`: Only modulepreloads critical scripts (entry, layouts).
* Non-critical scripts have no modulepreload hints, reducing network saturation.
* Best for pages with many chunks or slow networks.
*
* @default undefined (all scripts load with async)
*/
experimental_scriptLoading?: 'defer-non-critical' | 'after-lcp' | 'after-lcp-aggressive';
/**
* Generate a sitemap.xml file during build.
*
* Set to `true` for default behavior, or pass an object to configure:
*
* @example
* sitemap: true
*
* @example
* sitemap: {
* baseUrl: 'https://example.com', // defaults to ONE_SERVER_URL env var
* priority: 0.7, // default priority for all routes
* changefreq: 'weekly', // default changefreq for all routes
* exclude: ['/admin/*', '/api/*'], // glob patterns to exclude
* }
*
* Routes can also export sitemap metadata:
* ```ts
* export const sitemap = { priority: 0.9, changefreq: 'daily' }
* // or exclude: export const sitemap = { exclude: true }
* ```
*/
sitemap?: boolean | SitemapOptions;
};
server?: VXRNOptions['server'];
build?: {
server?: VXRNBuildOptions | false;
api?: VXRNBuildOptions;
};
deps?: FixDependencies;
ssr?: {
/**
* One scans dependencies on startup and decides which ones to optimize based on known broken
* dependencies. These include react-native and react, which need to be optimized to work.
* It finds all parent dependencies of the know bad deps and adds them to ssr.optimizeDeps.include.
*
* You can disable with false, or configure the include/exclude with options.
*
* Note: the **full path** (e.g. `<your_project_path>/node_modules/<some_package>`) will be used to match dependencies, if you are using a string to match a package name you may want to add `*` + `/` at the start and `/*` the end.
*
* @default { include: /node_modules/ }
*/
autoDepsOptimization?: boolean | AutoDepOptimizationOptions;
};
};
export interface RouteContext {
keys(): string[];
(id: string): any;
<T>(id: string): T;
resolve(id: string): string;
id: string;
}
export type Redirect = {
source: string;
destination: string;
permanent: boolean;
};
export type BuildInfo = {
constants: {
CACHE_KEY: string;
};
oneOptions?: PluginOptions;
routeToBuildInfo: Record<string, Omit<One.RouteBuildInfo, 'loaderData'>>;
/** A mapping to lookup the full route name from a path */
pathToRoute: Record<string, string>;
routeMap: Record<string, string>;
manifest: {
pageRoutes: RouteInfo[];
apiRoutes: RouteInfo[];
allRoutes: RouteInfo[];
};
preloads: Record<string, boolean>;
cssPreloads: Record<string, boolean>;
loaders: Record<string, boolean>;
useRolldown?: boolean;
};
export type AfterBuildProps = VXRNAfterBuildProps & BuildInfo;
export type RouteBuildInfo = {
type: One.RouteType;
path: string;
routeFile: string;
middlewares: string[];
preloadPath: string;
cssPreloadPath: string;
loaderPath: string;
cleanPath: string;
htmlPath: string;
clientJsPath: string;
serverJsPath: string;
params: object;
loaderData: any;
/** All preloads (for backwards compatibility) */
preloads: string[];
/** Critical preloads that load immediately with async */
criticalPreloads?: string[];
/** Non-critical preloads that are modulepreload hints only */
deferredPreloads?: string[];
css: string[];
/** When inlineLayoutCSS is enabled, contains the actual CSS content */
cssContents?: string[];
};
export type ServerContext = {
css?: string[];
/** When inlineLayoutCSS is enabled, this contains the actual CSS content to inline */
cssContents?: string[];
/** Number of inline CSS entries - used for hydration matching when cssContents is stripped */
cssInlineCount?: number;
postRenderData?: any;
loaderData?: any;
loaderProps?: any;
mode?: 'spa' | 'ssg' | 'ssr';
routePreloads?: Record<string, string>;
};
export type Flags = {
/** See PluginOptions.router.experimental.PreventLayoutRemounting */
experimentalPreventLayoutRemounting?: boolean;
};
export type SitemapChangefreq = OneShared.SitemapChangefreq;
export type RouteSitemap = OneShared.RouteSitemap;
export type SitemapOptions = {
/**
* Base URL for the sitemap. Defaults to ONE_SERVER_URL environment variable.
*/
baseUrl?: string;
/**
* Default priority for all routes (0.0 to 1.0).
* @default 0.5
*/
priority?: number;
/**
* Default change frequency for all routes.
*/
changefreq?: SitemapChangefreq;
/**
* Glob patterns for routes to exclude from the sitemap.
* API routes and not-found routes are always excluded.
*/
exclude?: string[];
};
export {};
}
export {};
//# sourceMappingURL=types.d.ts.map