Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/0.84/rollipop-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ interface ImportMetaEnv {

interface ImportMeta {
readonly env: ImportMetaEnv;
readonly glob: ImportGlobFunction;
}
35 changes: 28 additions & 7 deletions examples/0.84/src/navigation/AppNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,27 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { useReactNavigationDevTools } from '@rozenite/react-navigation-plugin';
import { useRef } from 'react';

import { DetailsScreen } from '../screens/DetailsScreen';
import { HomeScreen } from '../screens/HomeScreen';
import type { RootStackParamList } from './types';

interface Screen {
path: string;
component: React.ComponentType<unknown>;
}

const RootStack = createNativeStackNavigator<RootStackParamList>();

const pages = import.meta.glob('../pages/*', { import: 'default', eager: true });
const screens = Object.entries(pages).map(([path, module]) => {
return {
path: parseScreenPath(path),
component: module,
} as Screen;
});

function parseScreenPath(path: string) {
return path.split('/').pop()?.split('.').shift();
}

export function AppNavigator() {
const navigationRef = useRef<NavigationContainerRef<RootStackParamList>>(null!);

Expand All @@ -17,13 +32,19 @@ export function AppNavigator() {
return (
<NavigationContainer ref={navigationRef}>
<RootStack.Navigator
initialRouteName="home"
screenOptions={{
initialRouteName="index"
screenOptions={(props) => ({
headerShown: props.route.name !== 'index',
headerTitle: '',
}}
})}
>
<RootStack.Screen name="home" component={HomeScreen} options={{ headerShown: false }} />
<RootStack.Screen name="details" component={DetailsScreen} />
{screens.map((screen) => (
<RootStack.Screen
key={screen.path}
name={screen.path as keyof RootStackParamList}
component={screen.component}
/>
))}
</RootStack.Navigator>
</NavigationContainer>
);
Expand Down
6 changes: 4 additions & 2 deletions examples/0.84/src/navigation/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/**
* @TODO Sync with the pages/*.ts files.
*/
export type RootStackParamList = {
home: undefined;
index: undefined;
details: undefined;
test_suites: undefined;
};
1 change: 1 addition & 0 deletions examples/0.84/src/pages/details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { DetailsScreen as default } from '../screens/DetailsScreen';
1 change: 1 addition & 0 deletions examples/0.84/src/pages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { HomeScreen as default } from '../screens/HomeScreen';
2 changes: 1 addition & 1 deletion examples/0.84/src/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const breathe: CSSAnimationKeyframes = {
},
};

type HomeNavigation = NativeStackNavigationProp<RootStackParamList, 'home'>;
type HomeNavigation = NativeStackNavigationProp<RootStackParamList, 'index'>;

export function HomeScreen() {
const navigation = useNavigation<HomeNavigation>();
Expand Down
6 changes: 5 additions & 1 deletion packages/rollipop/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ interface ImportMetaEnv {
}

interface ImportMeta {
hot?: import('./dist').HMRContext;
glob: import('./import-glob').ImportGlobFunction;
env: ImportMetaEnv;
/**
* Only available in development mode.
*/
hot?: import('./dist').HMRContext;
}
129 changes: 129 additions & 0 deletions packages/rollipop/import-glob.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/**
* @see https://github.com/vitejs/vite/blob/3dcf7bd9418e02282cbfa0254ace59fe702c11bd/packages/vite/types/importGlob.d.ts
*/

// make input suggestions work
type StringQueryType = `?${keyof KnownAsTypeMap}` | (string & {});
type BaseQueryType = StringQueryType | Record<string, string | number | boolean>;

export interface ImportGlobOptions<
Eager extends boolean,
AsType extends string,
QueryType extends BaseQueryType,
> {
/**
* Import type for the import url.
*
* @deprecated Use `query` instead, e.g. `as: 'url'` -> `query: '?url', import: 'default'`
*/
as?: AsType;
/**
* Import as static or dynamic
*
* @default false
*/
eager?: Eager;
/**
* Import only the specific named export. Set to `default` to import the default export.
*/
import?: string;
/**
* Custom queries
*/
query?: QueryType;
/**
* Search files also inside `node_modules/` and hidden directories (e.g. `.git/`). This might have impact on performance.
*
* @default false
*/
exhaustive?: boolean;
/**
* Base path to resolve relative paths.
*/
base?: string;
/**
* Whether the glob pattern matching should be case-sensitive. Defaults to `true`.
*/
caseSensitive?: boolean;
}

export type ImportGlobOptionsWithoutAs<
Eager extends boolean,
QueryType extends BaseQueryType,
> = Omit<ImportGlobOptions<Eager, string, QueryType>, 'as'> & {
as?: never;
};

export type GeneralImportGlobOptions = ImportGlobOptions<boolean, string, BaseQueryType>;

/**
* Declare Worker in case DOM is not added to the tsconfig lib causing
* Worker interface is not defined. For developers with DOM lib added,
* the Worker interface will be merged correctly.
*/
declare global {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface Worker {}
}

export interface KnownAsTypeMap {
raw: string;
url: string;
worker: Worker;
}

type KnownQueryTypeMap = {
[K in keyof KnownAsTypeMap as `?${K}`]: KnownAsTypeMap[K];
};

export interface ImportGlobFunction {
/**
* Import a list of files with a glob pattern.
*
* Overload 1A: No generic provided, infer the type from `eager` and `query`
*/
<
Eager extends boolean,
Query extends BaseQueryType,
T = Query extends keyof KnownQueryTypeMap ? KnownQueryTypeMap[Query] : unknown,
>(
glob: string | string[],
options?: ImportGlobOptionsWithoutAs<Eager, Query>,
): (Eager extends true ? true : false) extends true
? Record<string, T>
: Record<string, () => Promise<T>>;
/**
* Import a list of files with a glob pattern.
*
* Overload 1B: No generic provided, infer the type from `eager` and `as`
* (deprecated, use `query` instead)
*/
<
Eager extends boolean,
As extends string,
T = As extends keyof KnownAsTypeMap ? KnownAsTypeMap[As] : unknown,
>(
glob: string | string[],
options?: ImportGlobOptions<Eager, As, BaseQueryType>,
): (Eager extends true ? true : false) extends true
? Record<string, T>
: Record<string, () => Promise<T>>;
/**
* Import a list of files with a glob pattern.
*
* Overload 2: Module generic provided, infer the type from `eager: false`
*/
<M>(
glob: string | string[],
options?: ImportGlobOptions<false, string, BaseQueryType>,
): Record<string, () => Promise<M>>;
/**
* Import a list of files with a glob pattern.
*
* Overload 3: Module generic provided, infer the type from `eager: true`
*/
<M>(
glob: string | string[],
options: ImportGlobOptions<true, string, BaseQueryType>,
): Record<string, M>;
}
1 change: 1 addition & 0 deletions packages/rollipop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"bin": "./bin/index.js",
"files": [
"client.d.ts",
"import-glob.d.ts",
"bin",
"dist",
"skills",
Expand Down
14 changes: 14 additions & 0 deletions packages/rollipop/src/core/plugins/import-glob-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type * as rolldown from '@rollipop/rolldown';
import { viteImportGlobPlugin as importGlob } from '@rollipop/rolldown/experimental';

export interface ImportGlobPluginOptions {
root?: string;
sourcemap?: boolean;
restoreQueryExtension?: boolean;
}

function importGlobPlugin(options: ImportGlobPluginOptions): rolldown.Plugin {
return importGlob(options);
}

export { importGlobPlugin as importGlob };
1 change: 1 addition & 0 deletions packages/rollipop/src/core/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './swc-plugin';
export * from './reporter-plugin';
export * from './dev-server-plugin';
export * from './analyze-plugin';
export * from './import-glob-plugin';
12 changes: 12 additions & 0 deletions packages/rollipop/src/core/rolldown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ import {
type BabelPluginOptions,
type DevServerPluginOptions,
type EntryPluginOptions,
type ImportGlobPluginOptions,
type ReactNativePluginOptions,
type ReporterPluginOptions,
type SwcPluginOptions,
analyze,
babel,
devServer,
entry,
importGlob,
reactNative,
reporter,
swc,
Expand Down Expand Up @@ -170,6 +172,7 @@ export async function resolveRolldownOptions(
);

const entryPluginOptions = resolveEntryPluginOptions(config);
const importGlobPluginOptions = resolveImportGlobPluginOptions(config);
const reactNativePluginOptions = await resolveReactNativePluginOptions(
config,
context,
Expand Down Expand Up @@ -200,6 +203,7 @@ export async function resolveRolldownOptions(
},
plugins: withTransformBoundary(context, [
entry(entryPluginOptions),
importGlob(importGlobPluginOptions),
reactNative(reactNativePluginOptions),
babel(babelPluginOptions),
swc(swcPluginOptions),
Expand Down Expand Up @@ -279,6 +283,14 @@ function resolveEntryPluginOptions(config: ResolvedConfig): EntryPluginOptions {
};
}

function resolveImportGlobPluginOptions(config: ResolvedConfig): ImportGlobPluginOptions {
return {
root: config.root,
sourcemap: config.mode === 'development',
restoreQueryExtension: false,
};
}

async function resolveReactNativePluginOptions(
config: ResolvedConfig,
context: BundlerContext,
Expand Down
Loading