feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
export const IDEContainerContext = React.createContext<any>({});

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, {
useMemo,
useEffect,
forwardRef,
useImperativeHandle,
type ForwardRefRenderFunction,
} from 'react';
import { type interfaces, Container } from 'inversify';
import { loadPlugins, PluginContext, type PluginsProvider } from '../common';
import { Application, IDEContainerModule } from '../application';
import { IDEContainerContext } from './context';
export interface IDEProviderProps {
containerModules?: interfaces.ContainerModule[]; // 注入的 IOC 包
container?: interfaces.Container;
customPluginContext?: (container: interfaces.Container) => PluginContext; // 自定义插件的上下文
plugins?: PluginsProvider<any>;
children?: React.ReactElement<any, any> | null;
}
export interface IDEProviderRef {
getContainer: () => interfaces.Container | undefined;
}
/**
* IDE 容器
*/
const IDEProviderWithRef: ForwardRefRenderFunction<
IDEProviderRef,
IDEProviderProps
> = (props, ref) => {
const {
containerModules,
customPluginContext,
container: fromContainer,
plugins,
} = props;
/**
* 创建 IOC 包
*/
const container = useMemo(() => {
const mainContainer: interfaces.Container =
fromContainer || new Container();
mainContainer.load(IDEContainerModule);
if (containerModules) {
containerModules.forEach(module => mainContainer.load(module));
}
if (customPluginContext) {
mainContainer
.rebind(PluginContext)
.toConstantValue(customPluginContext(mainContainer));
}
if (plugins) {
loadPlugins(plugins(mainContainer.get(PluginContext)), mainContainer);
}
mainContainer.get(Application).init();
return mainContainer;
// @action 这里 props 数据如果更改不会触发刷新,不允许修改
}, []);
useEffect(() => {
const application = container.get(Application);
application.start();
return () => {
application.dispose();
};
}, [container]);
useImperativeHandle(ref, () => ({
getContainer: () => container,
}));
return (
<IDEContainerContext.Provider value={container}>
{props.children}
</IDEContainerContext.Provider>
);
};
export const IDEProvider = forwardRef(IDEProviderWithRef);

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { useIDEContainer } from './use-ide-container';
export const IDERendererProvider = Symbol('IDERendererProvider');
export type IDERendererProvider = (props: {
className?: string;
}) => React.ReactElement<any, any> | null;
export const IDERenderer: React.FC<{ className?: string }> = ({
className,
}: {
className?: string;
}) => {
const container = useIDEContainer();
const RendererProvider =
container.get<IDERendererProvider>(IDERendererProvider)!;
return <RendererProvider className={className} />;
};

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { useIDEService } from './use-ide-service';
export { useRefresh } from './use-refresh';
export { useIDEContainer } from './use-ide-container';
export { IDEContainerContext } from './context';
export { IDERenderer, IDERendererProvider } from './ide-renderer';
export {
IDEProvider,
type IDEProviderProps,
type IDEProviderRef,
} from './ide-provider';
export { useNavigation } from './use-navigation';
export { useLocation } from './use-location';
export { useStyling } from './use-styling';

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { type interfaces } from 'inversify';
import { IDEContainerContext } from './context';
/**
* 获取 ide inversify container
*/
export function useIDEContainer(): interfaces.Container {
return React.useContext(IDEContainerContext);
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type interfaces } from 'inversify';
import { useIDEContainer } from './use-ide-container';
/**
* 获取IDE的 IOC 模块
* @param identifier
*/
export function useIDEService<T>(identifier: interfaces.ServiceIdentifier): T {
const container = useIDEContainer();
return container.get(identifier) as T;
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useEffect, useState } from 'react';
import { NavigationService } from '../navigation';
import { type URI } from '../common';
import { useIDEService } from './use-ide-service';
interface LocationInfo {
uri?: URI;
canGoBack?: boolean;
canGoForward?: boolean;
}
const useLocation = () => {
const navigation = useIDEService<NavigationService>(NavigationService);
const [location, setLocation] = useState<LocationInfo>({});
useEffect(() => {
const dispose = navigation.onDidHistoryChange(next => {
setLocation({
uri: next?.uri,
canGoBack: navigation.canGoBack(),
canGoForward: navigation.canGoForward(),
});
});
return () => dispose.dispose();
}, []);
return location;
};
export { useLocation };

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useCallback } from 'react';
import { NavigationHistory, NavigationService } from '../navigation';
import { type URI } from '../common';
import { useIDEService } from './use-ide-service';
const useNavigation = (): {
/** 可传入 URI 或 string传入 string 时以 / 开头,和 react-router-dom 对齐 */
navigate: (uri: URI | string, replace?: boolean, options?: any) => void;
history: NavigationHistory;
back: () => Promise<void>;
forward: () => Promise<void>;
} => {
const navigationService = useIDEService<NavigationService>(NavigationService);
const historyService = useIDEService<NavigationHistory>(NavigationHistory);
const navigate = useCallback(
(uri: URI | string, replace?: boolean, options?: any) =>
navigationService.goto(uri, replace, options),
[navigationService],
);
const back = useCallback(() => navigationService.back(), [navigationService]);
const forward = useCallback(
() => navigationService.forward(),
[navigationService],
);
return { navigate, history: historyService, back, forward };
};
export { useNavigation };

View File

@@ -0,0 +1,17 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { useRefresh } from '@flowgram-adapter/common';

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useEffect } from 'react';
import {
StylingService,
type Collector,
type ColorTheme,
ColorService,
} from '../styles';
import { useTheme } from './use-theme';
import { useIDEService } from './use-ide-service';
type Register = (
collector: Pick<Collector, 'prefix'>,
theme: ColorTheme,
) => string;
const useStyling = (
id: string,
fn: Register,
deps: React.DependencyList = [],
) => {
const stylingService = useIDEService<StylingService>(StylingService);
const colorService = useIDEService<ColorService>(ColorService);
const { theme } = useTheme();
useEffect(() => {
const css = fn(
{
prefix: 'flowide',
},
{
type: theme.type,
label: theme.label,
getColor: _id => colorService.getThemeColor(_id, theme.type),
},
);
const dispose = stylingService.register(id, css);
return () => dispose.dispose();
}, [id, theme, ...deps]);
};
export { useStyling };

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useEffect, useState } from 'react';
import { ThemeService } from '../styles';
import { useIDEService } from './use-ide-service';
const useTheme = () => {
const themeService = useIDEService<ThemeService>(ThemeService);
const [theme, setTheme] = useState(themeService.getCurrent());
useEffect(() => {
const dispose = themeService.onDidThemeChange(({ next }) => {
setTheme(next);
});
return () => dispose.dispose();
}, []);
return {
theme,
};
};
export { useTheme };