mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 11:20:11 +00:00
refactor: change render core export api
This commit is contained in:
parent
c1356bfe70
commit
9d0f178a06
11
packages/engine-core/src/common/uri.ts
Normal file
11
packages/engine-core/src/common/uri.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export interface UriComponents {
|
||||
path: string;
|
||||
}
|
||||
|
||||
export class URI implements UriComponents {
|
||||
readonly path: string;
|
||||
|
||||
constructor(path: string) {
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
@ -100,7 +100,9 @@ export interface IConfigurationPropertySchema extends IJSONSchema {
|
||||
* 扩展信息,用来查找对应属性的源扩展
|
||||
*/
|
||||
export interface IExtensionInfo {
|
||||
name: string;
|
||||
id: string;
|
||||
displayName?: string;
|
||||
version?: string;
|
||||
}
|
||||
|
||||
export type ConfigurationDefaultValueSource = IExtensionInfo | Map<string, IExtensionInfo>;
|
||||
@ -640,7 +642,7 @@ export class ConfigurationRegistry implements IConfigurationRegistry {
|
||||
|
||||
function isSameExtension(a?: IExtensionInfo, b?: IExtensionInfo): boolean {
|
||||
if (!a || !b) return false;
|
||||
return a.name === b.name;
|
||||
return a.id === b.id && a.version === b.version;
|
||||
}
|
||||
|
||||
Registry.add(Extensions.Configuration, new ConfigurationRegistry());
|
||||
|
||||
@ -7,9 +7,10 @@ export type ExtensionInitializer = <Context = any>(ctx: Context) => IExtensionIn
|
||||
* 函数声明插件
|
||||
*/
|
||||
export interface IFunctionExtension extends ExtensionInitializer {
|
||||
name: string;
|
||||
id: string;
|
||||
displayName?: string;
|
||||
version: string;
|
||||
meta?: IExtensionMetadata;
|
||||
metadata?: IExtensionMetadata;
|
||||
}
|
||||
|
||||
export interface IExtensionMetadata {
|
||||
|
||||
@ -2,7 +2,7 @@ import { InstantiationService } from '@alilc/lowcode-shared';
|
||||
import { IWorkbenchService } from './workbench';
|
||||
import { IConfigurationService } from './configuration';
|
||||
|
||||
export class MainApplication {
|
||||
class MainApplication {
|
||||
constructor() {
|
||||
console.log('main application');
|
||||
}
|
||||
|
||||
140
packages/engine-core/src/workspace/file/file.ts
Normal file
140
packages/engine-core/src/workspace/file/file.ts
Normal file
@ -0,0 +1,140 @@
|
||||
import { URI } from '../../common/uri';
|
||||
|
||||
export enum FileType {
|
||||
/**
|
||||
* File is unknown (neither file, directory).
|
||||
*/
|
||||
Unknown = 0,
|
||||
|
||||
/**
|
||||
* File is a normal file.
|
||||
*/
|
||||
File = 1,
|
||||
|
||||
/**
|
||||
* File is a directory.
|
||||
*/
|
||||
Directory = 2,
|
||||
}
|
||||
|
||||
export interface IStat {
|
||||
/**
|
||||
* The file type.
|
||||
*/
|
||||
readonly type: FileType;
|
||||
|
||||
/**
|
||||
* The last modification date represented as millis from unix epoch.
|
||||
*/
|
||||
readonly mtime: number;
|
||||
|
||||
/**
|
||||
* The creation date represented as millis from unix epoch.
|
||||
*/
|
||||
readonly ctime: number;
|
||||
}
|
||||
|
||||
export interface IBaseFileStat {
|
||||
/**
|
||||
* The unified resource identifier of this file or folder.
|
||||
*/
|
||||
readonly resource: URI;
|
||||
|
||||
/**
|
||||
* The name which is the last segment
|
||||
* of the {{path}}.
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* The size of the file.
|
||||
*
|
||||
* The value may or may not be resolved as
|
||||
* it is optional.
|
||||
*/
|
||||
readonly size?: number;
|
||||
|
||||
/**
|
||||
* The last modification date represented as millis from unix epoch.
|
||||
*
|
||||
* The value may or may not be resolved as
|
||||
* it is optional.
|
||||
*/
|
||||
readonly mtime?: number;
|
||||
|
||||
/**
|
||||
* The creation date represented as millis from unix epoch.
|
||||
*
|
||||
* The value may or may not be resolved as
|
||||
* it is optional.
|
||||
*/
|
||||
readonly ctime?: number;
|
||||
|
||||
/**
|
||||
* A unique identifier that represents the
|
||||
* current state of the file or directory.
|
||||
*
|
||||
* The value may or may not be resolved as
|
||||
* it is optional.
|
||||
*/
|
||||
readonly etag?: string;
|
||||
|
||||
/**
|
||||
* File is readonly. Components like editors should not
|
||||
* offer to edit the contents.
|
||||
*/
|
||||
readonly readonly?: boolean;
|
||||
|
||||
/**
|
||||
* File is locked. Components like editors should offer
|
||||
* to edit the contents and ask the user upon saving to
|
||||
* remove the lock.
|
||||
*/
|
||||
readonly locked?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A file resource with meta information and resolved children if any.
|
||||
*/
|
||||
export interface IFileStat extends IBaseFileStat {
|
||||
/**
|
||||
* The resource is a file.
|
||||
*/
|
||||
readonly isFile: boolean;
|
||||
|
||||
/**
|
||||
* The resource is a directory.
|
||||
*/
|
||||
readonly isDirectory: boolean;
|
||||
|
||||
/**
|
||||
* The children of the file stat or undefined if none.
|
||||
*/
|
||||
children: IFileStat[] | undefined;
|
||||
}
|
||||
|
||||
export interface IFileStatWithMetadata extends Required<IFileStat> {
|
||||
readonly children: IFileStatWithMetadata[];
|
||||
}
|
||||
|
||||
export const enum FileOperation {
|
||||
CREATE,
|
||||
DELETE,
|
||||
MOVE,
|
||||
COPY,
|
||||
WRITE,
|
||||
}
|
||||
|
||||
export interface IFileOperationEvent {
|
||||
readonly resource: URI;
|
||||
readonly operation: FileOperation;
|
||||
|
||||
isOperation(operation: FileOperation.DELETE | FileOperation.WRITE): boolean;
|
||||
isOperation(
|
||||
operation: FileOperation.CREATE | FileOperation.MOVE | FileOperation.COPY,
|
||||
): this is IFileOperationEventWithMetadata;
|
||||
}
|
||||
|
||||
export interface IFileOperationEventWithMetadata extends IFileOperationEvent {
|
||||
readonly target: IFileStatWithMetadata;
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* URI -> file content
|
||||
* URI -> file Stat
|
||||
*/
|
||||
|
||||
export interface IFileManagement {}
|
||||
1
packages/engine-core/src/workspace/file/fileService.ts
Normal file
1
packages/engine-core/src/workspace/file/fileService.ts
Normal file
@ -0,0 +1 @@
|
||||
export interface IFileService {}
|
||||
26
packages/engine-core/src/workspace/folder.ts
Normal file
26
packages/engine-core/src/workspace/folder.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { URI } from '../common/uri';
|
||||
|
||||
export interface IWorkspaceFolderData {
|
||||
/**
|
||||
* The associated URI for this workspace folder.
|
||||
*/
|
||||
readonly uri: URI;
|
||||
|
||||
/**
|
||||
* The name of this workspace folder. Defaults to
|
||||
* the basename of its [uri-path](#Uri.path)
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* The ordinal number of this workspace folder.
|
||||
*/
|
||||
readonly index: number;
|
||||
}
|
||||
|
||||
export interface IWorkspaceFolder extends IWorkspaceFolderData {
|
||||
/**
|
||||
* Given workspace folder relative path, returns the resource with the absolute path.
|
||||
*/
|
||||
toResource: (relativePath: string) => URI;
|
||||
}
|
||||
82
packages/engine-core/src/workspace/window/window.ts
Normal file
82
packages/engine-core/src/workspace/window/window.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import { type Event } from '@alilc/lowcode-shared';
|
||||
import { URI } from '../../common/uri';
|
||||
|
||||
export interface IEditWindow {
|
||||
// readonly onWillLoad: Event<ILoadEvent>;
|
||||
readonly onDidSignalReady: Event<void>;
|
||||
readonly onDidDestroy: Event<void>;
|
||||
|
||||
readonly onDidClose: Event<void>;
|
||||
|
||||
readonly id: number;
|
||||
|
||||
readonly config: IWindowConfiguration | undefined;
|
||||
|
||||
readonly isReady: boolean;
|
||||
ready(): Promise<IEditWindow>;
|
||||
|
||||
load(config: IWindowConfiguration, options?: { isReload?: boolean }): void;
|
||||
reload(): void;
|
||||
}
|
||||
|
||||
export interface IWindowConfiguration {
|
||||
filesToOpenOrCreate?: IPath[];
|
||||
}
|
||||
|
||||
export interface IPath<T = any> {
|
||||
/**
|
||||
* Optional editor options to apply in the file
|
||||
*/
|
||||
readonly options?: T;
|
||||
|
||||
/**
|
||||
* The file path to open within the instance
|
||||
*/
|
||||
fileUri?: URI;
|
||||
|
||||
/**
|
||||
* Specifies if the file should be only be opened
|
||||
* if it exists.
|
||||
*/
|
||||
readonly openOnlyIfExists?: boolean;
|
||||
}
|
||||
|
||||
export const enum WindowMode {
|
||||
Maximized,
|
||||
Normal,
|
||||
Fullscreen,
|
||||
Custom,
|
||||
}
|
||||
|
||||
export interface IWindowState {
|
||||
width?: number;
|
||||
height?: number;
|
||||
x?: number;
|
||||
y?: number;
|
||||
mode?: WindowMode;
|
||||
zoomLevel?: number;
|
||||
readonly display?: number;
|
||||
}
|
||||
|
||||
export interface IOpenConfiguration {
|
||||
readonly urisToOpen?: IWindowOpenable[];
|
||||
readonly preferNewWindow?: boolean;
|
||||
readonly forceNewWindow?: boolean;
|
||||
readonly forceNewTabbedWindow?: boolean;
|
||||
readonly forceReuseWindow?: boolean;
|
||||
readonly forceEmpty?: boolean;
|
||||
}
|
||||
|
||||
export interface IBaseWindowOpenable {
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export interface IFolderToOpen extends IBaseWindowOpenable {
|
||||
readonly folderUri: URI;
|
||||
}
|
||||
|
||||
export interface IFileToOpen extends IBaseWindowOpenable {
|
||||
readonly fileUri: URI;
|
||||
}
|
||||
|
||||
export type IWindowOpenable = IFolderToOpen | IFileToOpen;
|
||||
@ -0,0 +1,43 @@
|
||||
import { type Event } from '@alilc/lowcode-shared';
|
||||
import { IEditWindow, IOpenConfiguration } from './window';
|
||||
|
||||
export interface IWindowService {
|
||||
readonly onDidOpenWindow: Event<IEditWindow>;
|
||||
readonly onDidSignalReadyWindow: Event<IEditWindow>;
|
||||
readonly onDidChangeFullScreen: Event<{ window: IEditWindow; fullscreen: boolean }>;
|
||||
readonly onDidDestroyWindow: Event<IEditWindow>;
|
||||
|
||||
open(openConfig: IOpenConfiguration): Promise<IEditWindow[]>;
|
||||
|
||||
sendToFocused(channel: string, ...args: any[]): void;
|
||||
sendToOpeningWindow(channel: string, ...args: any[]): void;
|
||||
sendToAll(channel: string, payload?: any, windowIdsToIgnore?: number[]): void;
|
||||
|
||||
getWindows(): IEditWindow[];
|
||||
getWindowCount(): number;
|
||||
|
||||
getFocusedWindow(): IEditWindow | undefined;
|
||||
getLastActiveWindow(): IEditWindow | undefined;
|
||||
|
||||
getWindowById(windowId: number): IEditWindow | undefined;
|
||||
}
|
||||
|
||||
export class WindowService implements IWindowService {
|
||||
private readonly windows = new Map<number, IEditWindow>();
|
||||
|
||||
getWindows(): IEditWindow[] {
|
||||
return [...this.windows.values()];
|
||||
}
|
||||
|
||||
getWindowCount(): number {
|
||||
return this.windows.size;
|
||||
}
|
||||
|
||||
getFocusedWindow(): IEditWindow | undefined {
|
||||
return this.getWindows().find((w) => w.focused);
|
||||
}
|
||||
|
||||
getLastActiveWindow(): IEditWindow | undefined {
|
||||
return this.getWindows().find((w) => w.lastActive);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,31 @@
|
||||
import { IWorkspaceFolder } from './folder';
|
||||
|
||||
/**
|
||||
* 工作空间:一个或多个项目的集合
|
||||
* workspace -> one or more folders -> virtual files
|
||||
* file -> editWindow
|
||||
* editorView -> component tree schema
|
||||
*
|
||||
* project = (one or muti folders -> files) + some configs
|
||||
*/
|
||||
export interface Workspace {}
|
||||
export interface IWorkspace {
|
||||
readonly id: string;
|
||||
|
||||
/**
|
||||
* Folders in the workspace.
|
||||
*/
|
||||
readonly folders: IWorkspaceFolder[];
|
||||
}
|
||||
|
||||
export class Workspace implements IWorkspace {
|
||||
private _folders: IWorkspaceFolder[] = [];
|
||||
|
||||
constructor(private _id: string) {}
|
||||
|
||||
get id() {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get folders() {
|
||||
return this._folders;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,8 @@
|
||||
import { createDecorator, Provide } from '@alilc/lowcode-shared';
|
||||
|
||||
export interface IWorkspaceService {
|
||||
mount(container: HTMLElement): void;
|
||||
}
|
||||
export interface IWorkspaceService {}
|
||||
|
||||
export const IWorkspaceService = createDecorator<IWorkspaceService>('workspaceService');
|
||||
|
||||
@Provide(IWorkspaceService)
|
||||
export class WorkspaceService implements IWorkspaceService {
|
||||
mount(container: HTMLElement): void {}
|
||||
}
|
||||
export class WorkspaceService implements IWorkspaceService {}
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import { createRenderer } from '@alilc/lowcode-renderer-core';
|
||||
import { type Root, createRoot } from 'react-dom/client';
|
||||
import { RendererContext } from './context';
|
||||
import { RendererContext, getRenderInstancesByAccessor } from './context';
|
||||
import { ApplicationView, boosts } from '../app';
|
||||
import { type ReactAppOptions } from './types';
|
||||
|
||||
export const createApp = async (options: ReactAppOptions) => {
|
||||
return createRenderer(async (context) => {
|
||||
const { schema, boostsManager } = context;
|
||||
return createRenderer(async (accessor) => {
|
||||
const instances = getRenderInstancesByAccessor(accessor);
|
||||
|
||||
boostsManager.extend(boosts.toExpose());
|
||||
instances.boostsManager.extend(boosts.toExpose());
|
||||
|
||||
let root: Root | undefined;
|
||||
|
||||
@ -16,9 +16,9 @@ export const createApp = async (options: ReactAppOptions) => {
|
||||
async mount(containerOrId) {
|
||||
if (root) return;
|
||||
|
||||
const defaultId = schema.get('config')?.targetRootID ?? 'app';
|
||||
const defaultId = instances.schema.get('config')?.targetRootID ?? 'app';
|
||||
const rootElement = normalizeContainer(containerOrId, defaultId);
|
||||
const contextValue = { ...context, options };
|
||||
const contextValue = { ...instances, options };
|
||||
|
||||
root = createRoot(rootElement);
|
||||
root.render(
|
||||
|
||||
@ -4,7 +4,7 @@ import {
|
||||
type LowCodeComponentProps,
|
||||
createComponent as createSchemaComponent,
|
||||
} from '../runtime/createComponent';
|
||||
import { RendererContext } from './context';
|
||||
import { RendererContext, getRenderInstancesByAccessor } from './context';
|
||||
import { type ReactAppOptions } from './types';
|
||||
|
||||
interface Render {
|
||||
@ -12,16 +12,16 @@ interface Render {
|
||||
}
|
||||
|
||||
export async function createComponent(options: ReactAppOptions) {
|
||||
const creator = createRenderer<Render>((context) => {
|
||||
const { schema } = context;
|
||||
const componentsTree = schema.get('componentsTree')[0];
|
||||
const creator = createRenderer<Render>((accessor) => {
|
||||
const instances = getRenderInstancesByAccessor(accessor);
|
||||
const componentsTree = instances.schema.get('componentsTree')[0];
|
||||
|
||||
const LowCodeComponent = createSchemaComponent(componentsTree, {
|
||||
displayName: componentsTree.componentName,
|
||||
...options.component,
|
||||
});
|
||||
|
||||
const contextValue = { ...context, options };
|
||||
const contextValue = { ...instances, options };
|
||||
|
||||
function Component(props: LowCodeComponentProps) {
|
||||
return (
|
||||
|
||||
@ -1,10 +1,39 @@
|
||||
import {
|
||||
IBoostsService,
|
||||
IComponentTreeModelService,
|
||||
ILifeCycleService,
|
||||
IPackageManagementService,
|
||||
ISchemaService,
|
||||
} from '@alilc/lowcode-renderer-core';
|
||||
import { InstanceAccessor } from '@alilc/lowcode-shared';
|
||||
import { createContext, useContext } from 'react';
|
||||
import { type RenderContext } from '@alilc/lowcode-renderer-core';
|
||||
import { type ReactAppOptions } from './types';
|
||||
|
||||
export const RendererContext = createContext<RenderContext & { options: ReactAppOptions }>(
|
||||
undefined!,
|
||||
);
|
||||
export interface IRendererContext {
|
||||
readonly options: ReactAppOptions;
|
||||
|
||||
readonly schema: Omit<ISchemaService, 'initialize'>;
|
||||
|
||||
readonly packageManager: IPackageManagementService;
|
||||
|
||||
readonly boostsManager: IBoostsService;
|
||||
|
||||
readonly componentTreeModel: IComponentTreeModelService;
|
||||
|
||||
readonly lifeCycle: ILifeCycleService;
|
||||
}
|
||||
|
||||
export const getRenderInstancesByAccessor = (accessor: InstanceAccessor) => {
|
||||
return {
|
||||
schema: accessor.get(ISchemaService),
|
||||
packageManager: accessor.get(IPackageManagementService),
|
||||
boostsManager: accessor.get(IBoostsService),
|
||||
componentTreeModel: accessor.get(IComponentTreeModelService),
|
||||
lifeCycle: accessor.get(ILifeCycleService),
|
||||
};
|
||||
};
|
||||
|
||||
export const RendererContext = createContext<IRendererContext>(undefined!);
|
||||
|
||||
RendererContext.displayName = 'RendererContext';
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ export { defineRendererPlugin } from './app';
|
||||
export * from './router';
|
||||
export { LifecyclePhase } from '@alilc/lowcode-renderer-core';
|
||||
|
||||
export type { Spec, ProCodeComponent, LowCodeComponent } from '@alilc/lowcode-shared';
|
||||
export type { Package, ProCodeComponent, LowCodeComponent } from '@alilc/lowcode-shared';
|
||||
export type {
|
||||
PackageLoader,
|
||||
CodeScope,
|
||||
|
||||
@ -1,3 +1,10 @@
|
||||
export * from './context';
|
||||
export * from './plugin';
|
||||
export type * from '@alilc/lowcode-renderer-router';
|
||||
export type {
|
||||
RouteLocation,
|
||||
RawLocation,
|
||||
Router,
|
||||
RouterOptions,
|
||||
RouteLocationNormalized,
|
||||
RouterHistory,
|
||||
} from '@alilc/lowcode-renderer-router';
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import { invariant, specTypes, type ComponentTreeRoot } from '@alilc/lowcode-shared';
|
||||
import { forwardRef, useRef, useEffect } from 'react';
|
||||
import { isValidElementType } from 'react-is';
|
||||
import { useRendererContext } from '../api/context';
|
||||
import { useRendererContext, IRendererContext } from '../api/context';
|
||||
import { reactiveStateFactory } from './reactiveState';
|
||||
import { type ReactComponent, type ReactWidget, createElementByWidget } from './elements';
|
||||
import { appendExternalStyle } from '../utils/element';
|
||||
|
||||
import type {
|
||||
RenderContext,
|
||||
IComponentTreeModel,
|
||||
CreateComponentTreeModelOptions,
|
||||
} from '@alilc/lowcode-renderer-core';
|
||||
@ -36,7 +35,7 @@ const lowCodeComponentsCache = new Map<string, ReactComponent>();
|
||||
|
||||
export function getComponentByName(
|
||||
name: string,
|
||||
{ packageManager }: RenderContext,
|
||||
{ packageManager }: IRendererContext,
|
||||
componentOptions: ComponentOptions = {},
|
||||
): ReactComponent {
|
||||
const result = lowCodeComponentsCache.get(name) || packageManager.getComponent(name);
|
||||
|
||||
@ -1,23 +1,22 @@
|
||||
/* --------------- api -------------------- */
|
||||
export { createRenderer } from './main';
|
||||
export { definePackageLoader } from './services/package';
|
||||
export { LifecyclePhase } from './services/lifeCycleService';
|
||||
export { Widget } from './services/widget';
|
||||
export * from '../../shared/src/utils/node';
|
||||
export { IBoostsService, IExtensionHostService } from './services/extension';
|
||||
export { definePackageLoader, IPackageManagementService } from './services/package';
|
||||
export { LifecyclePhase, ILifeCycleService } from './services/lifeCycleService';
|
||||
export { IComponentTreeModelService } from './services/model';
|
||||
export { ICodeRuntimeService } from './services/code-runtime';
|
||||
export { IRuntimeIntlService } from './services/runtimeIntlService';
|
||||
export { IRuntimeUtilService } from './services/runtimeUtilService';
|
||||
export { ISchemaService } from './services/schema';
|
||||
export { Widget } from './widget';
|
||||
export * from './utils/value';
|
||||
|
||||
/* --------------- types ---------------- */
|
||||
export type * from './types';
|
||||
export type {
|
||||
Plugin,
|
||||
IRenderObject,
|
||||
PluginContext,
|
||||
RenderAdapter,
|
||||
RenderContext,
|
||||
} from './services/extension';
|
||||
export type * from './services/extension';
|
||||
export type * from './services/code-runtime';
|
||||
export type * from './services/model';
|
||||
export type * from './services/package';
|
||||
export type * from './services/schema';
|
||||
export type * from './services/widget';
|
||||
export type * from './services/extension';
|
||||
export type * from './widget';
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { invariant, InstantiationService } from '@alilc/lowcode-shared';
|
||||
import { ICodeRuntimeService } from './services/code-runtime';
|
||||
import {
|
||||
IBoostsService,
|
||||
IExtensionHostService,
|
||||
type RenderAdapter,
|
||||
type IRenderObject,
|
||||
@ -9,80 +8,8 @@ import {
|
||||
import { IPackageManagementService } from './services/package';
|
||||
import { ISchemaService } from './services/schema';
|
||||
import { ILifeCycleService, LifecyclePhase } from './services/lifeCycleService';
|
||||
import { IComponentTreeModelService } from './services/model';
|
||||
import type { AppOptions, RendererApplication } from './types';
|
||||
|
||||
export class RendererMain<RenderObject> {
|
||||
private mode: 'development' | 'production' = 'production';
|
||||
|
||||
private initOptions: AppOptions;
|
||||
|
||||
private renderObject: RenderObject;
|
||||
|
||||
private adapter: RenderAdapter<RenderObject>;
|
||||
|
||||
constructor(
|
||||
@ICodeRuntimeService private codeRuntimeService: ICodeRuntimeService,
|
||||
@IPackageManagementService private packageManagementService: IPackageManagementService,
|
||||
@ISchemaService private schemaService: ISchemaService,
|
||||
@IExtensionHostService private extensionHostService: IExtensionHostService,
|
||||
@IComponentTreeModelService private componentTreeModelService: IComponentTreeModelService,
|
||||
@IBoostsService private boostsService: IBoostsService,
|
||||
@ILifeCycleService private lifeCycleService: ILifeCycleService,
|
||||
) {}
|
||||
|
||||
async main(options: AppOptions, adapter: RenderAdapter<RenderObject>) {
|
||||
const { schema, mode, plugins = [] } = options;
|
||||
|
||||
if (mode) this.mode = mode;
|
||||
this.initOptions = { ...options };
|
||||
this.adapter = adapter;
|
||||
|
||||
// valid schema
|
||||
this.schemaService.initialize(schema);
|
||||
|
||||
this.codeRuntimeService.initialize(options.codeRuntime ?? {});
|
||||
|
||||
await this.lifeCycleService.setPhase(LifecyclePhase.OptionsResolved);
|
||||
|
||||
const renderContext = {
|
||||
schema: this.schemaService,
|
||||
packageManager: this.packageManagementService,
|
||||
boostsManager: this.boostsService,
|
||||
componentTreeModel: this.componentTreeModelService,
|
||||
lifeCycle: this.lifeCycleService,
|
||||
};
|
||||
|
||||
this.renderObject = await this.adapter(renderContext);
|
||||
|
||||
await this.extensionHostService.registerPlugin(plugins);
|
||||
// 先加载插件提供 package loader
|
||||
await this.packageManagementService.loadPackages(this.initOptions.packages ?? []);
|
||||
|
||||
await this.lifeCycleService.setPhase(LifecyclePhase.Ready);
|
||||
}
|
||||
|
||||
getApp(): RendererApplication<RenderObject> {
|
||||
// construct application
|
||||
return Object.freeze<RendererApplication<RenderObject>>({
|
||||
// develop use
|
||||
__options: this.initOptions,
|
||||
|
||||
mode: this.mode,
|
||||
schema: this.schemaService,
|
||||
packageManager: this.packageManagementService,
|
||||
...this.renderObject,
|
||||
|
||||
use: (plugin) => {
|
||||
return this.extensionHostService.registerPlugin(plugin);
|
||||
},
|
||||
destroy: async () => {
|
||||
return this.lifeCycleService.setPhase(LifecyclePhase.Destroying);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 createRenderer 的辅助函数
|
||||
* @param schema
|
||||
@ -94,13 +21,51 @@ export function createRenderer<RenderObject = IRenderObject>(
|
||||
): (options: AppOptions) => Promise<RendererApplication<RenderObject>> {
|
||||
invariant(typeof renderAdapter === 'function', 'The first parameter must be a function.');
|
||||
|
||||
const instantiationService = new InstantiationService({ defaultScope: 'Singleton' });
|
||||
const rendererMain = instantiationService.createInstance(
|
||||
RendererMain,
|
||||
) as RendererMain<RenderObject>;
|
||||
const accessor = new InstantiationService({ defaultScope: 'Singleton' });
|
||||
let mode: 'development' | 'production' = 'production';
|
||||
|
||||
const schemaService = accessor.get(ISchemaService);
|
||||
const packageManagementService = accessor.get(IPackageManagementService);
|
||||
const codeRuntimeService = accessor.get(ICodeRuntimeService);
|
||||
const lifeCycleService = accessor.get(ILifeCycleService);
|
||||
const extensionHostService = accessor.get(IExtensionHostService);
|
||||
|
||||
return async (options) => {
|
||||
await rendererMain.main(options, renderAdapter);
|
||||
return rendererMain.getApp();
|
||||
if (options.mode) mode = options.mode;
|
||||
|
||||
// valid schema
|
||||
schemaService.initialize(options.schema);
|
||||
codeRuntimeService.initialize(options.codeRuntime ?? {});
|
||||
await lifeCycleService.setPhase(LifecyclePhase.OptionsResolved);
|
||||
|
||||
const renderObject = await renderAdapter(accessor);
|
||||
|
||||
await extensionHostService.registerPlugin(options.plugins ?? []);
|
||||
// 先加载插件提供 package loader
|
||||
await packageManagementService.loadPackages(options.packages ?? []);
|
||||
|
||||
await lifeCycleService.setPhase(LifecyclePhase.Ready);
|
||||
|
||||
const app: RendererApplication<RenderObject> = {
|
||||
get mode() {
|
||||
return mode;
|
||||
},
|
||||
schema: schemaService,
|
||||
packageManager: packageManagementService,
|
||||
...renderObject,
|
||||
|
||||
use: (plugin) => {
|
||||
return extensionHostService.registerPlugin(plugin);
|
||||
},
|
||||
destroy: async () => {
|
||||
return lifeCycleService.setPhase(LifecyclePhase.Destroying);
|
||||
},
|
||||
};
|
||||
|
||||
if (mode === 'development') {
|
||||
Object.defineProperty(app, '__options', { get: () => options });
|
||||
}
|
||||
|
||||
return app;
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { type EventEmitter, type IStore, type StringDictionary } from '@alilc/lowcode-shared';
|
||||
import { type EventEmitter, type StringDictionary } from '@alilc/lowcode-shared';
|
||||
import { type IBoosts } from './boosts';
|
||||
import { ILifeCycleService } from '../lifeCycleService';
|
||||
import { type ISchemaService } from '../schema';
|
||||
import { type IPackageManagementService } from '../package';
|
||||
import { type IStore } from '../../utils/store';
|
||||
|
||||
export interface PluginContext<BoostsExtends = object> {
|
||||
eventEmitter: EventEmitter;
|
||||
|
||||
@ -1,26 +1,10 @@
|
||||
import { IPackageManagementService } from '../package';
|
||||
import { IBoostsService } from './boosts';
|
||||
import { ISchemaService } from '../schema';
|
||||
import { IComponentTreeModelService } from '../model';
|
||||
import { ILifeCycleService } from '../lifeCycleService';
|
||||
import { type InstanceAccessor } from '@alilc/lowcode-shared';
|
||||
|
||||
export interface IRenderObject {
|
||||
mount: (containerOrId?: string | HTMLElement) => void | Promise<void>;
|
||||
unmount: () => void | Promise<void>;
|
||||
}
|
||||
|
||||
export interface RenderContext {
|
||||
readonly schema: Omit<ISchemaService, 'initialize'>;
|
||||
|
||||
readonly packageManager: IPackageManagementService;
|
||||
|
||||
readonly boostsManager: IBoostsService;
|
||||
|
||||
readonly componentTreeModel: IComponentTreeModelService;
|
||||
|
||||
readonly lifeCycle: ILifeCycleService;
|
||||
}
|
||||
|
||||
export interface RenderAdapter<Render> {
|
||||
(context: RenderContext): Render | Promise<Render>;
|
||||
(accessor: InstanceAccessor): Render | Promise<Render>;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ import {
|
||||
uniqueId,
|
||||
} from '@alilc/lowcode-shared';
|
||||
import { type ICodeRuntime } from '../code-runtime';
|
||||
import { IWidget, Widget } from '../widget';
|
||||
import { IWidget, Widget } from '../../widget';
|
||||
|
||||
export interface NormalizedComponentNode extends ComponentNode {
|
||||
loopArgs: [string, string];
|
||||
|
||||
@ -7,7 +7,7 @@ import {
|
||||
Provide,
|
||||
specTypes,
|
||||
exportByReference,
|
||||
mapPackageToId,
|
||||
mapPackageToUniqueId,
|
||||
type Reference,
|
||||
} from '@alilc/lowcode-shared';
|
||||
import { get as lodashGet } from 'lodash-es';
|
||||
@ -91,7 +91,7 @@ export class PackageManagementService implements IPackageManagementService {
|
||||
}
|
||||
|
||||
getModuleByReference<T = any>(reference: Reference): T | undefined {
|
||||
const id = mapPackageToId(reference);
|
||||
const id = mapPackageToUniqueId(reference);
|
||||
if (this.packageStore.has(id)) {
|
||||
const library = this.packageStore.get(id);
|
||||
const result = exportByReference(library, reference);
|
||||
@ -138,7 +138,7 @@ export class PackageManagementService implements IPackageManagementService {
|
||||
|
||||
const normalized: NormalizedPackage = {
|
||||
package: packageInfo.package,
|
||||
id: mapPackageToId(packageInfo),
|
||||
id: mapPackageToUniqueId(packageInfo),
|
||||
library: packageInfo.library,
|
||||
raw: packageInfo,
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { type NodeType, uniqueId, type ComponentNode } from '@alilc/lowcode-shared';
|
||||
import { IComponentTreeModel } from '../model';
|
||||
import { IComponentTreeModel } from '../services/model';
|
||||
|
||||
export interface IWidget<Component, ComponentInstance = unknown> {
|
||||
readonly key: string;
|
||||
@ -1,7 +1,10 @@
|
||||
import * as Platform from './platform';
|
||||
|
||||
export { Platform };
|
||||
|
||||
export * from './event';
|
||||
export * from './logger';
|
||||
export * from './intl';
|
||||
export * from './instantiation';
|
||||
export * from './signals';
|
||||
export * as Platform from './platform';
|
||||
export * from './linkedList';
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import * as Iterable from './iterable';
|
||||
|
||||
export { Iterable };
|
||||
|
||||
export * from './invariant';
|
||||
export * from './unique-id';
|
||||
export * from './types';
|
||||
export * from './async';
|
||||
export * from './node';
|
||||
export * from './resource';
|
||||
|
||||
export * as Iterable from './iterable';
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
export * as specTypes from './spec';
|
||||
export * as jsonTypes from './json';
|
||||
export * as types from './type';
|
||||
import * as specTypes from './spec';
|
||||
import * as jsonTypes from './json';
|
||||
import * as types from './type';
|
||||
|
||||
export * from './constraint';
|
||||
|
||||
export { specTypes, jsonTypes, types };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user