refactor(types): move runtime types to @ice/types

This commit is contained in:
逆葵 2022-09-02 14:58:51 +08:00 committed by ClarkXia
parent 9ad5e5b5c1
commit ce8f2bccde
23 changed files with 2405 additions and 4385 deletions

View File

@ -29,15 +29,16 @@
"build": "tsc"
},
"devDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0",
"@types/react": "^18.0.8",
"@types/react-dom": "^18.0.3",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"regenerator-runtime": "^0.13.9"
},
"sideEffects": false,
"dependencies": {
"@ice/jsx-runtime": "^0.1.0",
"@ice/types": "workspace:^1.0.0",
"consola": "^2.15.3",
"history": "^5.3.0",
"react-router-dom": "^6.2.2"

View File

@ -1,10 +1,10 @@
import React, { useMemo } from 'react';
import type { Action, Location } from 'history';
import type { Navigator } from 'react-router-dom';
import type { RouteWrapperConfig, AppRouterProps } from '@ice/types';
import AppErrorBoundary from './AppErrorBoundary.js';
import { useAppContext } from './AppContext.js';
import { createRouteElements } from './routes.js';
import type { RouteWrapperConfig, AppRouterProps } from './types.js';
interface Props {
action: Action;

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import type { AppContext } from './types.js';
import type { AppContext } from '@ice/types';
const Context = React.createContext<AppContext | undefined>(undefined);
@ -15,4 +15,4 @@ const AppContextProvider = Context.Provider;
export {
useAppContext,
AppContextProvider,
};
};

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import type { AppExport, AppData, RequestContext } from './types.js';
import type { AppExport, AppData, RequestContext } from '@ice/types';
const Context = React.createContext<AppData | undefined>(undefined);
@ -32,4 +32,4 @@ export {
getAppData,
useAppData,
AppDataProvider,
};
};

View File

@ -1,8 +1,8 @@
import * as React from 'react';
import type { RouteObject } from 'react-router-dom';
import { Router, useRoutes } from 'react-router-dom';
import type { AppRouterProps } from '@ice/types';
import { Router as RouterSingle, useRoutes as useRoutesSingle } from './single-router.js';
import type { AppRouterProps } from './types.js';
const AppRouter: React.ComponentType<AppRouterProps> = (props) => {
const { action, location, navigator, static: staticProps, routes, basename } = props;

View File

@ -1,9 +1,9 @@
import * as React from 'react';
import type { ReactNode } from 'react';
import type { AppContext, RouteMatch, AssetsManifest } from '@ice/types';
import { useAppContext } from './AppContext.js';
import { useAppData } from './AppData.js';
import { getMeta, getTitle, getLinks, getScripts } from './routesConfig.js';
import type { AppContext, RouteMatch, AssetsManifest } from './types.js';
import getCurrentRoutePath from './utils/getCurrentRoutePath.js';
interface DocumentContext {

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import type { RouteData, RouteConfig } from './types.js';
import type { RouteData, RouteConfig } from '@ice/types';
const DataContext = React.createContext<RouteData | undefined>(undefined);
DataContext.displayName = 'Data';

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import type { RouteWrapperConfig } from './types.js';
import type { RouteWrapperConfig } from '@ice/types';
import { useAppContext } from './AppContext.js';
import { DataProvider, ConfigProvider } from './RouteContext.js';
@ -36,4 +36,4 @@ export default function RouteWrapper(props: Props) {
</ConfigProvider>
</DataProvider>
);
}
}

View File

@ -1,4 +1,4 @@
import type { AppConfig, AppExport } from './types.js';
import type { AppConfig, AppExport } from '@ice/types';
const defaultAppConfig: AppConfig = {
app: {

View File

@ -1,4 +1,4 @@
import type { GetData } from './types.js';
import type { GetData } from '@ice/types';
import getRequestContext from './requestContext.js';
interface Loaders {

View File

@ -5,6 +5,18 @@ import {
useSearchParams,
useLocation,
} from 'react-router-dom';
import type {
RuntimePlugin,
AppContext,
AppConfig,
RouteConfig,
RouteItem,
ServerContext,
AppProvider,
RouteWrapper,
RenderMode,
GetAppData,
} from '@ice/types';
import Runtime from './runtime.js';
import App from './App.js';
import runClientApp from './runClientApp.js';
@ -19,18 +31,6 @@ import {
Main,
Data,
} from './Document.js';
import type {
RuntimePlugin,
AppContext,
AppConfig,
RouteConfig,
RouteItem,
ServerContext,
AppProvider,
RouteWrapper,
RenderMode,
GetAppData,
} from './types.js';
import dataLoader from './dataLoader.js';
import getAppConfig, { defineAppConfig } from './appConfig.js';
import { routerHistory as history } from './history.js';
@ -72,4 +72,4 @@ export type {
RouteWrapper,
RenderMode,
GetAppData,
};
};

View File

@ -4,8 +4,8 @@
import type { Location } from 'history';
import type { RouteObject } from 'react-router-dom';
import { matchRoutes as originMatchRoutes } from 'react-router-dom';
import type { RouteItem, RouteMatch } from '@ice/types';
import { matchRoutes as matchRoutesSingle } from './single-router.js';
import type { RouteItem, RouteMatch } from './types.js';
export default function matchRoutes(
routes: RouteItem[],

View File

@ -1,4 +1,4 @@
import type { ServerContext, RequestContext } from './types.js';
import type { ServerContext, RequestContext } from '@ice/types';
interface Location {
pathname: string;
@ -49,4 +49,4 @@ function parseSearch(search: string) {
}
return result;
}
}

View File

@ -1,6 +1,6 @@
import React from 'react';
import type { RouteItem, RouteModules, RouteWrapperConfig, RouteMatch, RequestContext, RoutesConfig, RoutesData, RenderMode } from '@ice/types';
import RouteWrapper from './RouteWrapper.js';
import type { RouteItem, RouteModules, RouteWrapperConfig, RouteMatch, RequestContext, RoutesConfig, RoutesData, RenderMode } from './types.js';
import { useAppContext } from './AppContext.js';
type RouteModule = Pick<RouteItem, 'id' | 'load'>;

View File

@ -1,4 +1,4 @@
import type { RouteMatch, RoutesConfig, RouteConfig } from './types.js';
import type { RouteMatch, RoutesConfig, RouteConfig } from '@ice/types';
export function getMeta(matches: RouteMatch[], routesConfig: RoutesConfig) {
return getMergedValue('meta', matches, routesConfig) || [];
@ -164,4 +164,4 @@ async function appendTags(type: string, props: ElementProps) {
document.head.appendChild(tag);
});
}
}

View File

@ -2,16 +2,16 @@ import React, { useLayoutEffect, useState } from 'react';
import * as ReactDOM from 'react-dom/client';
import { createHashHistory, createBrowserHistory, createMemoryHistory } from 'history';
import type { HashHistory, BrowserHistory, Action, Location, InitialEntry, MemoryHistory } from 'history';
import type {
AppContext, AppExport, RouteItem, AppRouterProps, RoutesData, RoutesConfig,
RouteWrapperConfig, RuntimeModules, RouteMatch, RouteModules, AppConfig, DocumentComponent,
} from '@ice/types';
import { createHistory as createHistorySingle } from './single-router.js';
import { setHistory } from './history.js';
import Runtime from './runtime.js';
import App from './App.js';
import { AppContextProvider } from './AppContext.js';
import { AppDataProvider, getAppData } from './AppData.js';
import type {
AppContext, AppExport, RouteItem, AppRouterProps, RoutesData, RoutesConfig,
RouteWrapperConfig, RuntimeModules, RouteMatch, RouteModules, AppConfig, DocumentComponent,
} from './types.js';
import { loadRouteModules, loadRoutesData, getRoutesConfig, filterMatchesToLoad } from './routes.js';
import { updateRoutesConfig } from './routesConfig.js';
import getRequestContext from './requestContext.js';
@ -302,4 +302,4 @@ function createRouterHistory(type: AppConfig['router']['type'], memoryRouter: bo
if (type === 'hash') {
return createHashHistory;
}
}
}

View File

@ -4,16 +4,6 @@ import * as ReactDOMServer from 'react-dom/server';
import { Action, parsePath } from 'history';
import type { Location } from 'history';
import { default as consola } from 'consola';
import Runtime from './runtime.js';
import App from './App.js';
import { AppContextProvider } from './AppContext.js';
import { AppDataProvider, getAppData } from './AppData.js';
import getAppConfig from './appConfig.js';
import { DocumentContextProvider } from './Document.js';
import { loadRouteModules, loadRoutesData, getRoutesConfig } from './routes.js';
import { piperToString, renderToNodeStream } from './server/streamRender.js';
import { createStaticNavigator } from './server/navigator.js';
import type { NodeWritablePiper } from './server/streamRender.js';
import type {
AppContext, RouteItem, ServerContext,
AppData,
@ -24,7 +14,17 @@ import type {
RouteModules,
RenderMode,
DocumentComponent,
} from './types.js';
} from '@ice/types';
import Runtime from './runtime.js';
import App from './App.js';
import { AppContextProvider } from './AppContext.js';
import { AppDataProvider, getAppData } from './AppData.js';
import getAppConfig from './appConfig.js';
import { DocumentContextProvider } from './Document.js';
import { loadRouteModules, loadRoutesData, getRoutesConfig } from './routes.js';
import { piperToString, renderToNodeStream } from './server/streamRender.js';
import { createStaticNavigator } from './server/navigator.js';
import type { NodeWritablePiper } from './server/streamRender.js';
import getRequestContext from './requestContext.js';
import matchRoutes from './matchRoutes.js';
import getCurrentRoutePath from './utils/getCurrentRoutePath.js';

View File

@ -14,7 +14,7 @@ import type {
SetRender,
AppRouterProps,
ComponentWithChildren,
} from './types.js';
} from '@ice/types';
import DefaultAppRouter from './AppRouter.js';
import { useData, useConfig } from './RouteContext.js';
import { useAppContext } from './AppContext.js';
@ -103,4 +103,4 @@ class Runtime {
};
}
export default Runtime;
export default Runtime;

View File

@ -1,208 +0,0 @@
import type { IncomingMessage, ServerResponse } from 'http';
import type { Action, InitialEntry, Location } from 'history';
import type { ComponentType, ReactNode, PropsWithChildren } from 'react';
import type { HydrationOptions } from 'react-dom/client';
import type { Navigator, Params } from 'react-router-dom';
import type { useConfig, useData } from './RouteContext.js';
import type { useAppContext } from './AppContext.js';
type VoidFunction = () => void;
type AppLifecycle = 'onShow' | 'onHide' | 'onPageNotFound' | 'onShareAppMessage' | 'onUnhandledRejection' | 'onLaunch' | 'onError' | 'onTabItemClick';
type App = Partial<{
rootId: string;
strict: boolean;
errorBoundary: boolean;
} & Record<AppLifecycle, VoidFunction>>;
export type AppData = any;
export type RouteData = any;
// route.getConfig return value
export interface RouteConfig {
title?: string;
// TODO: fix type
meta?: any[];
links?: any[];
scripts?: any[];
// plugin extends
auth?: string[];
}
export interface AppExport {
default?: AppConfig;
[key: string]: any;
getAppData?: GetAppData;
}
export type GetAppData = (ctx: RequestContext) => Promise<AppData> | AppData;
// app.getData & route.getData
export type GetData = (ctx: RequestContext) => Promise<RouteData> | RouteData;
export type GetServerData = (ctx: RequestContext) => Promise<RouteData> | RouteData;
export type GetStaticData = (ctx: RequestContext) => Promise<RouteData> | RouteData;
// route.getConfig
export type GetConfig = (args: { data: RouteData }) => RouteConfig;
export interface AppConfig {
app?: App;
router?: {
type?: 'hash' | 'browser' | 'memory';
basename?: string;
initialEntries?: InitialEntry[];
};
}
export interface RoutesConfig {
[routeId: string]: RouteConfig;
}
export interface RoutesData {
[routeId: string]: RouteData;
}
// useAppContext
export interface AppContext {
appConfig: AppConfig;
appData: any;
assetsManifest: AssetsManifest;
routesData: RoutesData;
routesConfig: RoutesConfig;
routeModules: RouteModules;
routePath?: string;
matches?: RouteMatch[];
routes?: RouteItem[];
documentOnly?: boolean;
matchedIds?: string[];
appExport?: AppExport;
basename?: string;
}
export type Renderer = (
container: Element | Document,
initialChildren: React.ReactNode,
options?: HydrationOptions,
) => void;
export interface ServerContext {
req?: IncomingMessage;
res?: ServerResponse;
}
export interface RequestContext extends ServerContext {
pathname: string;
query: Record<string, any>;
}
export interface RouteComponent {
default: ComponentType<any>;
getStaticData?: GetStaticData;
getServerData?: GetServerData;
getData?: GetData;
getConfig?: GetConfig;
[key: string]: any;
}
export interface RouteItem {
id: string;
path: string;
element?: ReactNode;
componentName: string;
index?: boolean;
exact?: boolean;
strict?: boolean;
load?: () => Promise<RouteComponent>;
children?: RouteItem[];
layout?: boolean;
}
export type ComponentWithChildren<P = {}> = ComponentType<PropsWithChildren<P>>;
export type DocumentComponent = ComponentWithChildren<{
pagePath: string;
}>;
export interface RouteWrapperConfig {
Wrapper: RouteWrapper;
layout?: boolean;
}
export type AppProvider = ComponentWithChildren<any>;
export type RouteWrapper = ComponentType<any>;
export type SetAppRouter = (AppRouter: ComponentType<AppRouterProps>) => void;
export type AddProvider = (Provider: AppProvider) => void;
export type SetRender = (render: Renderer) => void;
export type AddWrapper = (wrapper: RouteWrapper, forLayout?: boolean) => void;
export interface RouteModules {
[routeId: string]: RouteComponent;
}
export interface AssetsManifest {
dataLoader?: string;
publicPath: string;
entries: string[];
pages: string[];
assets?: {
[assetPath: string]: string;
};
}
export interface RuntimeAPI {
setAppRouter: SetAppRouter;
addProvider: AddProvider;
setRender: SetRender;
addWrapper: AddWrapper;
appContext: AppContext;
useData: typeof useData;
useConfig: typeof useConfig;
useAppContext: typeof useAppContext;
}
export interface RuntimePlugin {
(
apis: RuntimeAPI
): Promise<void> | void;
}
export interface CommonJsRuntime {
default: RuntimePlugin;
}
export type RuntimeModules = (RuntimePlugin | CommonJsRuntime)[];
export interface AppRouterProps {
action: Action;
location: Location;
navigator: Navigator;
routes: RouteItem[];
static?: boolean;
basename?: string;
}
export interface AppRouteProps {
routes: RouteItem[];
}
// rewrite the `RouteMatch` type which is referenced by the react-router-dom
export interface RouteMatch {
/**
* The names and values of dynamic parameters in the URL.
*/
params: Params;
/**
* The portion of the URL pathname that was matched.
*/
pathname: string;
/**
* The portion of the URL pathname that was matched before child routes.
*/
pathnameBase: string;
/**
* The route object that was used to match.
*/
route: RouteItem;
}
export type RenderMode = 'SSR' | 'SSG';

View File

@ -1,4 +1,4 @@
import type { RouteMatch } from '../types.js';
import type { RouteMatch } from '@ice/types';
/**
* Get the current route path exclude the basename.

View File

@ -30,15 +30,17 @@
"bugs": "https://github.com/ice-lab/ice-next/issues",
"homepage": "https://next.ice.work",
"devDependencies": {
"@swc/core": "1.2.210",
"@ice/route-manifest": "^1.0.0",
"@ice/runtime": "^1.0.0",
"@swc/core": "1.2.210",
"build-scripts": "^2.0.0-24",
"esbuild": "^0.14.51",
"eslint": "^8.14.0",
"eslint-webpack-plugin": "3.1.1",
"fork-ts-checker-webpack-plugin": "7.2.6",
"history": "^5.3.0",
"react": "^18.0.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.2.2",
"terser": "^5.12.1",
"typescript": "^4.6.4",
"unplugin": "^0.9.5",

View File

@ -1,3 +1,210 @@
import type { RuntimePlugin, RouteConfig, AppConfig, AppProvider, RouteWrapper } from '@ice/runtime';
import type { IncomingMessage, ServerResponse } from 'http';
import type { Action, InitialEntry, Location } from 'history';
import type { ComponentType, ReactNode, PropsWithChildren } from 'react';
import type { HydrationOptions } from 'react-dom/client';
import type { Navigator, Params } from 'react-router-dom';
export { RuntimePlugin, RouteConfig, AppConfig, AppProvider, RouteWrapper };
type useConfig = () => RouteConfig;
type useData = () => RouteData;
type useAppContext = () => AppContext;
type VoidFunction = () => void;
type AppLifecycle = 'onShow' | 'onHide' | 'onPageNotFound' | 'onShareAppMessage' | 'onUnhandledRejection' | 'onLaunch' | 'onError' | 'onTabItemClick';
type App = Partial<{
rootId: string;
strict: boolean;
errorBoundary: boolean;
} & Record<AppLifecycle, VoidFunction>>;
export type AppData = any;
export type RouteData = any;
// route.getConfig return value
export interface RouteConfig {
title?: string;
// TODO: fix type
meta?: any[];
links?: any[];
scripts?: any[];
// plugin extends
auth?: string[];
}
export interface AppExport {
default?: AppConfig;
[key: string]: any;
getAppData?: GetAppData;
}
export type GetAppData = (ctx: RequestContext) => Promise<AppData> | AppData;
// app.getData & route.getData
export type GetData = (ctx: RequestContext) => Promise<RouteData> | RouteData;
export type GetServerData = (ctx: RequestContext) => Promise<RouteData> | RouteData;
export type GetStaticData = (ctx: RequestContext) => Promise<RouteData> | RouteData;
// route.getConfig
export type GetConfig = (args: { data: RouteData }) => RouteConfig;
export interface AppConfig {
app?: App;
router?: {
type?: 'hash' | 'browser' | 'memory';
basename?: string;
initialEntries?: InitialEntry[];
};
}
export interface RoutesConfig {
[routeId: string]: RouteConfig;
}
export interface RoutesData {
[routeId: string]: RouteData;
}
// useAppContext
export interface AppContext {
appConfig: AppConfig;
appData: any;
assetsManifest: AssetsManifest;
routesData: RoutesData;
routesConfig: RoutesConfig;
routeModules: RouteModules;
routePath?: string;
matches?: RouteMatch[];
routes?: RouteItem[];
documentOnly?: boolean;
matchedIds?: string[];
appExport?: AppExport;
basename?: string;
}
export type Renderer = (
container: Element | Document,
initialChildren: React.ReactNode,
options?: HydrationOptions,
) => void;
export interface ServerContext {
req?: IncomingMessage;
res?: ServerResponse;
}
export interface RequestContext extends ServerContext {
pathname: string;
query: Record<string, any>;
}
export interface RouteComponent {
default: ComponentType<any>;
getStaticData?: GetStaticData;
getServerData?: GetServerData;
getData?: GetData;
getConfig?: GetConfig;
[key: string]: any;
}
export interface RouteItem {
id: string;
path: string;
element?: ReactNode;
componentName: string;
index?: boolean;
exact?: boolean;
strict?: boolean;
load?: () => Promise<RouteComponent>;
children?: RouteItem[];
layout?: boolean;
}
export type ComponentWithChildren<P = {}> = ComponentType<PropsWithChildren<P>>;
export type DocumentComponent = ComponentWithChildren<{
pagePath: string;
}>;
export interface RouteWrapperConfig {
Wrapper: RouteWrapper;
layout?: boolean;
}
export type AppProvider = ComponentWithChildren<any>;
export type RouteWrapper = ComponentType<any>;
export type SetAppRouter = (AppRouter: ComponentType<AppRouterProps>) => void;
export type AddProvider = (Provider: AppProvider) => void;
export type SetRender = (render: Renderer) => void;
export type AddWrapper = (wrapper: RouteWrapper, forLayout?: boolean) => void;
export interface RouteModules {
[routeId: string]: RouteComponent;
}
export interface AssetsManifest {
dataLoader?: string;
publicPath: string;
entries: string[];
pages: string[];
assets?: {
[assetPath: string]: string;
};
}
export interface RuntimeAPI {
setAppRouter: SetAppRouter;
addProvider: AddProvider;
setRender: SetRender;
addWrapper: AddWrapper;
appContext: AppContext;
useData: useData;
useConfig: useConfig;
useAppContext: useAppContext;
}
export interface RuntimePlugin {
(
apis: RuntimeAPI
): Promise<void> | void;
}
export interface CommonJsRuntime {
default: RuntimePlugin;
}
export type RuntimeModules = (RuntimePlugin | CommonJsRuntime)[];
export interface AppRouterProps {
action: Action;
location: Location;
navigator: Navigator;
routes: RouteItem[];
static?: boolean;
basename?: string;
}
export interface AppRouteProps {
routes: RouteItem[];
}
// rewrite the `RouteMatch` type which is referenced by the react-router-dom
export interface RouteMatch {
/**
* The names and values of dynamic parameters in the URL.
*/
params: Params;
/**
* The portion of the URL pathname that was matched.
*/
pathname: string;
/**
* The portion of the URL pathname that was matched before child routes.
*/
pathnameBase: string;
/**
* The route object that was used to match.
*/
route: RouteItem;
}
export type RenderMode = 'SSR' | 'SSG';

File diff suppressed because it is too large Load Diff