From 9f621101b388ad3664c4c3dbd79a4ce9aa991de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=AF=85?= Date: Wed, 12 Aug 2020 11:39:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20=E5=AE=8C=E5=96=84=20Rax?= =?UTF-8?q?=20=E5=87=BA=E7=A0=81,=20=E8=B7=91=E9=80=9A=E7=AC=AC=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=F0=9F=91=8F?= =?UTF-8?q?=F0=9F=91=8F=F0=9F=91=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code-generator/.eslintignore | 1 + packages/code-generator/package.json | 6 ++ .../code-generator/src/const/generator.ts | 11 +++ .../src/plugins/component/rax/const.ts | 8 +- .../plugins/component/rax/containerClass.ts | 40 +++++++-- .../component/rax/containerInjectContext.ts | 86 +++++++++++++++++++ .../rax/containerInjectDataSourceEngine.ts | 78 +++++++++++++++++ .../component/rax/containerInjectUtils.ts | 29 +++++-- .../plugins/component/react/containerClass.ts | 5 +- .../code-generator/src/solutions/rax-app.ts | 14 ++- .../demo-project/src/pages/Home/index.jsx | 54 ++++++++++++ 11 files changed, 307 insertions(+), 25 deletions(-) create mode 100644 packages/code-generator/.eslintignore create mode 100644 packages/code-generator/src/plugins/component/rax/containerInjectContext.ts create mode 100644 packages/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts diff --git a/packages/code-generator/.eslintignore b/packages/code-generator/.eslintignore new file mode 100644 index 000000000..bcfd4b921 --- /dev/null +++ b/packages/code-generator/.eslintignore @@ -0,0 +1 @@ +test-cases/ diff --git a/packages/code-generator/package.json b/packages/code-generator/package.json index 5da8251f0..dcccc42e1 100644 --- a/packages/code-generator/package.json +++ b/packages/code-generator/package.json @@ -8,6 +8,7 @@ "demo" ], "scripts": { + "start": "ava --watch", "build": "rimraf lib && tsc", "demo": "node ./demo/demo.js", "test": "ava", @@ -45,6 +46,11 @@ ], "require": [ "ts-node/register/transpile-only" + ], + "sources": [ + "src/**/*", + "test/**/*", + "test-cases/**/expected/**/*" ] }, "publishConfig": { diff --git a/packages/code-generator/src/const/generator.ts b/packages/code-generator/src/const/generator.ts index 9028b9226..6f471e2a4 100644 --- a/packages/code-generator/src/const/generator.ts +++ b/packages/code-generator/src/const/generator.ts @@ -21,6 +21,7 @@ export const CLASS_DEFINE_CHUNK_NAME = { InsVar: 'CommonClassDefineInsVar', InsVarMethod: 'CommonClassDefineInsVarMethod', InsMethod: 'CommonClassDefineInsMethod', + InsPrivateMethod: 'CommonClassDefineInsPrivateMethod', End: 'CommonClassDefineEnd', }; @@ -82,6 +83,15 @@ export const DEFAULT_LINK_AFTER = { CLASS_DEFINE_CHUNK_NAME.InsVarMethod, CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, ], + [CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod]: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.StaticVar, + CLASS_DEFINE_CHUNK_NAME.StaticMethod, + CLASS_DEFINE_CHUNK_NAME.InsVar, + CLASS_DEFINE_CHUNK_NAME.InsVarMethod, + CLASS_DEFINE_CHUNK_NAME.InsMethod, + CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, + ], [CLASS_DEFINE_CHUNK_NAME.End]: [ CLASS_DEFINE_CHUNK_NAME.Start, CLASS_DEFINE_CHUNK_NAME.StaticVar, @@ -89,6 +99,7 @@ export const DEFAULT_LINK_AFTER = { CLASS_DEFINE_CHUNK_NAME.InsVar, CLASS_DEFINE_CHUNK_NAME.InsVarMethod, CLASS_DEFINE_CHUNK_NAME.InsMethod, + CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, ], [COMMON_CHUNK_NAME.FileMainContent]: [ diff --git a/packages/code-generator/src/plugins/component/rax/const.ts b/packages/code-generator/src/plugins/component/rax/const.ts index 317b41fa8..6a13c92a6 100644 --- a/packages/code-generator/src/plugins/component/rax/const.ts +++ b/packages/code-generator/src/plugins/component/rax/const.ts @@ -1,9 +1,9 @@ export const RAX_CHUNK_NAME = { + ClassDidMountStart: 'RaxComponentClassDidMountStart', + ClassDidMountContent: 'RaxComponentClassDidMountContent', + ClassDidMountEnd: 'RaxComponentClassDidMountEnd', ClassRenderStart: 'RaxComponentClassRenderStart', ClassRenderPre: 'RaxComponentClassRenderPre', - ClassRenderEnd: 'RaxComponentClassRenderEnd', ClassRenderJSX: 'RaxComponentClassRenderJSX', - ClassDidMountStart: 'RaxComponentClassDidMountStart', - ClassDidMountEnd: 'RaxComponentClassDidMountEnd', - ClassDidMountContent: 'RaxComponentClassDidMountContent', + ClassRenderEnd: 'RaxComponentClassRenderEnd', }; diff --git a/packages/code-generator/src/plugins/component/rax/containerClass.ts b/packages/code-generator/src/plugins/component/rax/containerClass.ts index 2f6918a8e..a38d920d4 100644 --- a/packages/code-generator/src/plugins/component/rax/containerClass.ts +++ b/packages/code-generator/src/plugins/component/rax/containerClass.ts @@ -35,12 +35,17 @@ const pluginFactory: BuilderComponentPluginFactory = () => { ], }); + next.chunks.push({ type: ChunkType.STRING, fileType: FileType.JSX, name: CLASS_DEFINE_CHUNK_NAME.End, content: `}`, - linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, RAX_CHUNK_NAME.ClassRenderEnd], + linkAfter: [ + CLASS_DEFINE_CHUNK_NAME.Start, + RAX_CHUNK_NAME.ClassRenderEnd, + CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + ], }); // next.chunks.push({ @@ -62,15 +67,36 @@ const pluginFactory: BuilderComponentPluginFactory = () => { // ], // }); + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: RAX_CHUNK_NAME.ClassDidMountStart, + content: `componentDidMount() {`, + linkAfter: [ + CLASS_DEFINE_CHUNK_NAME.Start, + CLASS_DEFINE_CHUNK_NAME.InsVar, + CLASS_DEFINE_CHUNK_NAME.InsMethod, + ], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: RAX_CHUNK_NAME.ClassDidMountEnd, + content: `}`, + linkAfter: [ + RAX_CHUNK_NAME.ClassDidMountStart, + RAX_CHUNK_NAME.ClassDidMountContent, + ], + }); + next.chunks.push({ type: ChunkType.STRING, fileType: FileType.JSX, name: RAX_CHUNK_NAME.ClassRenderStart, content: 'render() {', linkAfter: [ - CLASS_DEFINE_CHUNK_NAME.Start, - CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, - CLASS_DEFINE_CHUNK_NAME.InsMethod, + RAX_CHUNK_NAME.ClassDidMountEnd, ], }); @@ -79,11 +105,7 @@ const pluginFactory: BuilderComponentPluginFactory = () => { fileType: FileType.JSX, name: RAX_CHUNK_NAME.ClassRenderEnd, content: '}', - linkAfter: [ - RAX_CHUNK_NAME.ClassRenderStart, - RAX_CHUNK_NAME.ClassRenderPre, - RAX_CHUNK_NAME.ClassRenderJSX, - ], + linkAfter: [RAX_CHUNK_NAME.ClassRenderStart, RAX_CHUNK_NAME.ClassRenderPre, RAX_CHUNK_NAME.ClassRenderJSX], }); next.chunks.push({ diff --git a/packages/code-generator/src/plugins/component/rax/containerInjectContext.ts b/packages/code-generator/src/plugins/component/rax/containerInjectContext.ts new file mode 100644 index 000000000..fe5138bf6 --- /dev/null +++ b/packages/code-generator/src/plugins/component/rax/containerInjectContext.ts @@ -0,0 +1,86 @@ +import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, +} from '../../../types'; +import { RAX_CHUNK_NAME } from './const'; + +type PluginConfig = { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + _context = this._createContext(); + `, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + // TODO: 补充数据源的定义 + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + content: ` + _createContext() { + const self = this; + + const context = { + get state() { + return self.state; + }, + setState(newState) { + self.setState(newState); + }, + get dataSourceMap() { + return self._dataSourceEngine?.dataSourceMap || {}; + }, + async reloadDataSource() { + self._dataSourceEngine?.reloadDataSource(); + }, + get utils() { + return self._utils; + }, + get page() { + return context; + }, + get component() { + return context; + }, + get props() { + return self.props; + }, + }; + + return context; + } + `, + linkAfter: [ + RAX_CHUNK_NAME.ClassRenderEnd + ], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/packages/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts b/packages/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts new file mode 100644 index 000000000..e1810fde2 --- /dev/null +++ b/packages/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts @@ -0,0 +1,78 @@ +import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator'; + +import { + BuilderComponentPlugin, + BuilderComponentPluginFactory, + ChunkType, + FileType, + ICodeStruct, +} from '../../../types'; +import { RAX_CHUNK_NAME } from './const'; + +type PluginConfig = { + fileType: string; +} + +const pluginFactory: BuilderComponentPluginFactory = (config?) => { + const cfg: PluginConfig = { + fileType: FileType.JSX, + ...config, + }; + + const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { + const next: ICodeStruct = { + ...pre, + }; + + next.chunks.push({ + type: ChunkType.STRING, + fileType: FileType.JSX, + name: COMMON_CHUNK_NAME.ExternalDepsImport, + content: ` + import { createDataSourceEngine } from '@ali/lowcode-data-source-engine'; + `, + linkAfter: [], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: ` + _dataSourceList = this._defineDataSourceList(); + _dataSourceEngine = createDataSourceEngine(this._dataSourceList, this._context);`, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: RAX_CHUNK_NAME.ClassDidMountContent, + content: ` + this._dataSourceEngine.reloadDataSource(); + `, + linkAfter: [ + RAX_CHUNK_NAME.ClassDidMountStart, + ], + }); + + // TODO: 补充数据源的定义 + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + content: ` + _defineDataSourceList() { + return []; + }`, + linkAfter: [ + RAX_CHUNK_NAME.ClassRenderEnd + ], + }); + + return next; + }; + return plugin; +}; + +export default pluginFactory; diff --git a/packages/code-generator/src/plugins/component/rax/containerInjectUtils.ts b/packages/code-generator/src/plugins/component/rax/containerInjectUtils.ts index b72eb8668..aa9763c23 100644 --- a/packages/code-generator/src/plugins/component/rax/containerInjectUtils.ts +++ b/packages/code-generator/src/plugins/component/rax/containerInjectUtils.ts @@ -7,6 +7,7 @@ import { FileType, ICodeStruct, } from '../../../types'; +import { RAX_CHUNK_NAME } from './const'; type PluginConfig = { fileType: string; @@ -24,13 +25,27 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) => }; // TODO: utils 怎么注入? - // next.chunks.push({ - // type: ChunkType.STRING, - // fileType: cfg.fileType, - // name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, - // content: `this.utils = utils;`, - // linkAfter: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart], - // }); + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsVar, + content: `_utils = this._defineUtils();`, + linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start], + }); + + + next.chunks.push({ + type: ChunkType.STRING, + fileType: cfg.fileType, + name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod, + content: ` + _defineUtils() { + return {}; + }`, + linkAfter: [ + RAX_CHUNK_NAME.ClassRenderEnd + ], + }); return next; }; diff --git a/packages/code-generator/src/plugins/component/react/containerClass.ts b/packages/code-generator/src/plugins/component/react/containerClass.ts index 5dae325c7..f0e591583 100644 --- a/packages/code-generator/src/plugins/component/react/containerClass.ts +++ b/packages/code-generator/src/plugins/component/react/containerClass.ts @@ -40,7 +40,10 @@ const pluginFactory: BuilderComponentPluginFactory = () => { fileType: FileType.JSX, name: CLASS_DEFINE_CHUNK_NAME.End, content: `}`, - linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, REACT_CHUNK_NAME.ClassRenderEnd], + linkAfter: [ + CLASS_DEFINE_CHUNK_NAME.Start, + REACT_CHUNK_NAME.ClassRenderEnd, + ], }); next.chunks.push({ diff --git a/packages/code-generator/src/solutions/rax-app.ts b/packages/code-generator/src/solutions/rax-app.ts index be7c55c31..0a1a55154 100644 --- a/packages/code-generator/src/solutions/rax-app.ts +++ b/packages/code-generator/src/solutions/rax-app.ts @@ -4,10 +4,12 @@ import { createProjectBuilder } from '../generator/ProjectBuilder'; import esModule from '../plugins/common/esmodule'; import containerClass from '../plugins/component/rax/containerClass'; -import containerInitState from '../plugins/component/rax/containerInitState'; -import containerInjectUtils from '../plugins/component/rax/containerInjectUtils'; import containerLifeCycle from '../plugins/component/rax/containerLifeCycle'; import containerMethod from '../plugins/component/rax/containerMethod'; +import containerInitState from '../plugins/component/rax/containerInitState'; +import containerInjectContext from '../plugins/component/rax/containerInjectContext'; +import containerInjectDataSourceEngine from '../plugins/component/rax/containerInjectDataSourceEngine'; +import containerInjectUtils from '../plugins/component/rax/containerInjectUtils'; import jsx from '../plugins/component/rax/jsx'; import commonDeps from '../plugins/component/rax/commonDeps'; import css from '../plugins/component/style/css'; @@ -42,8 +44,10 @@ export default function createIceJsProjectBuilder(): IProjectBuilder { fileType: 'jsx', }), containerClass(), - containerInjectUtils(), containerInitState(), + containerInjectContext(), + containerInjectDataSourceEngine(), + containerInjectUtils(), containerLifeCycle(), containerMethod(), jsx(), @@ -58,6 +62,8 @@ export default function createIceJsProjectBuilder(): IProjectBuilder { htmlEntry: [raxApp.plugins.entryDocument()], packageJSON: [raxApp.plugins.packageJSON()], }, - postProcessors: [prettier()], + postProcessors: [ + // prettier() // 暂且禁用 prettier + ], }); } diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.jsx b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.jsx index acb73cdd4..cfecd9575 100644 --- a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.jsx +++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.jsx @@ -4,9 +4,22 @@ import Page from 'rax-view'; import Text from 'rax-text'; +import { createDataSourceEngine } from '@ali/lowcode-data-source-engine'; + import './index.css'; class Home$$Page extends Component { + _context = this._createContext(); + + _dataSourceList = this._defineDataSourceList(); + _dataSourceEngine = createDataSourceEngine(this._dataSourceList, this._context); + + _utils = this._defineUtils(); + + componentDidMount() { + this._dataSourceEngine.reloadDataSource(); + } + render() { return ( @@ -14,6 +27,47 @@ class Home$$Page extends Component { ); } + + _createContext() { + const self = this; + + const context = { + get state() { + return self.state; + }, + setState(newState) { + self.setState(newState); + }, + get dataSourceMap() { + return self._dataSourceEngine?.dataSourceMap || {}; + }, + async reloadDataSource() { + self._dataSourceEngine?.reloadDataSource(); + }, + get utils() { + return self._utils; + }, + get page() { + return context; + }, + get component() { + return context; + }, + get props() { + return self.props; + }, + }; + + return context; + } + + _defineDataSourceList() { + return []; + } + + _defineUtils() { + return {}; + } } export default Home$$Page;