API 是组件的属性解释,给开发者作为组件属性配置的参考。为了保持 API 的一致性,我们制定这个 API 命名规范。对于业界通用的,约定俗成的命名,我们遵循社区的约定。对于业界有多种规则难以确定的,我们确定其中一种,大家共同遵守。
-#### 通用规则
+##### 通用规则
- 所有的 API 采用小驼峰的书写规则,如 `onChange`、`direction`、`defaultVisible`。
- 标签名采用大驼峰书写规则,如 `Menu`、`Slider`、`DatePicker`。
-#### 通用命名
+##### 通用命名
| API 名称 | 类型 | 描述 | 常见变量 |
| :------------- | :------------- | :----------------------------------------------------------- | :---------------------------------------------------- |
@@ -262,7 +261,7 @@ API 是组件的属性解释,给开发者作为组件属性配置的参考。
| has+'属性' | boolean | 拥有某个属性 | 例如 `hasArrow`, `hasHeader`, `hasClose` 等等 |
-#### 多选枚举
+##### 多选枚举
当某个 API 的接口,允许用户指定多个枚举值的时候,我们把这个接口定义为多选枚举。一个很典型的例子是某个弹层组件的 `closable` 属性,我们会允许:键盘 esc 按键、点击 mask、点击 close 按钮、点击组件以外的任何区域进行关闭。
@@ -281,11 +280,11 @@ true 表示触发规则都会关闭,false 表示触发规则不会关闭。
- `
`,任何情况下都不关闭,只能通过受控设置 visible
- `
`,用户按 esc 或者点击关闭按钮会关闭
-#### 事件
+##### 事件
- 标准事件或者自定义的符合 w3c 标准的事件,命名必须 on 开头, 即 `on` + 事件名,如 onExpand。
-#### 表单规范
+##### 表单规范
- 支持[受控模式](https://reactjs.org/docs/forms.html#controlled-components)(value + onChange) (A)
- value 控制组件数据展现
@@ -293,7 +292,7 @@ true 表示触发规则都会关闭,false 表示触发规则不会关闭。
- `value={undefined}`的时候清空数据,field 的 reset 函数会给所有组件下发 undefined 数据 (AA))
- 一次完整操作抛一次 onChange 事件 `建议` 比如有 Process 表示进展中的状态,建议增加 API `onProcess`;如果有 Start 表示启动状态,建议增加 API `onStart` (AA)
-#### 属性的传递
+##### 属性的传递
**1. 原子组件(Atomic Component)**
> 最小粒子,不能再拆分的组件
@@ -355,7 +354,7 @@ $ iceworks sync
文件命名采取 [bcp47](https://tools.ietf.org/html/bcp47) 规范
-#### 目录规范
+##### 目录规范
在 `src` 目录新增 `locale` 目录用于管理不同语言的文案。
@@ -368,7 +367,7 @@ $ iceworks sync
|------ ja-JP.js
```
-#### 定义不同的语言
+##### 定义不同的语言
```javascript
// zh-CN.js
@@ -391,7 +390,7 @@ export default {
};
```
-#### 组件支持多语言建议方案
+##### 组件支持多语言建议方案
```jsx
// index.jsx
@@ -418,7 +417,7 @@ export default class BizHello extends Component {
}
```
-#### 组件支持全局替换国际化文案
+##### 组件支持全局替换国际化文案
配合 ConfigProvider 支持全局替换国际化文案。
@@ -452,7 +451,7 @@ export default ConfigProvider.config(BizHello, {
业务组件中如果有自定义的需要跟随主题色的 UI,一定要引入变量的形式,增加组件的流通性。
-#### src/index.scss
+##### src/index.scss
```css
/* 如果需要引入主题变量引入此段 */
@@ -504,7 +503,7 @@ api 属性标准参考 [https://fusion.design/help.html#/dev-biz](https://fusio
无障碍需要符合 [WCAG 2.1 A 级标准](https://www.w3.org/TR/WCAG21/),可参考 [W3C 无障碍最佳实践](https://www.w3.org/TR/wai-aria-practices-1.1/)、[Fusion 无障碍指引 2.3.1](https://alibaba-fusion.github.io/next/part1/basics.html) 章节等。
-#### 增加 a11y.md 无障碍 demo
+##### 增加 a11y.md 无障碍 demo
必须借助 API 才能完成无障碍工作的组件必须为开发者提供无障碍的使用文档,请[参考](https://fusion.design/pc/component/select?themeid=2#accessibility-container)组件 API 中 `ARIA and Keyboard` ,建议在 `demo` 目录新增 `a11y.md` 文件用于演示组件的无障碍使用。
@@ -518,7 +517,7 @@ component
详细指引查看无障碍开发指南 [https://alibaba-fusion.github.io/next/part1/basics.html](https://alibaba-fusion.github.io/next/part1/basics.html)。
-#### 通过键盘快速访问
+##### 通过键盘快速访问
一般键盘事件有 Up Arrow/Down Arrow/Enter/Esc/Tab
@@ -532,7 +531,7 @@ component
| Esc | 关闭列表 |
-#### 对读屏软件友好
+##### 对读屏软件友好
- 对于组件,我们为开发者内置 `role` 和特定 `aria-_属性`,开发者也可以对非组件 API 属性都可以透传至 DOM 元素,进行修改 `role` 和 `aria-_参数`,但是要注意对应关系,请[参考](https://alibaba-fusion.github.io/next/part1/WAI-ARIA.html)。
- 对一些特殊的组件传递参数才能支持无障碍,设置 `id`,`autoFocus` 和传参数,如下:
@@ -926,18 +925,18 @@ props 数组下对象字段描述:
|initialChildren | 组件拖入“设计器”时根据此配置自动生成 children 节点 schema |NodeData[]/Function NodeData[] | ((target: SettingTarget) => NodeData[]);|
|getResizingHandlers| 用于配置设计器中组件 resize 操作工具的样式和内容 | Function| (currentNode: any) => Array<{ type: 'N' | 'W' | 'S' | 'E' | 'NW' | 'NE' | 'SE' | 'SW'; content?: ReactElement; propTarget?: string; appearOn?: 'mouse-enter' | 'mouse-hover' | 'selected' | 'always'; }> / ReactElement[];
|callbacks| 配置 callbacks 可捕获引擎抛出的一些事件,例如 onNodeAdd、onResize 等 | Callback| -
-|callbacks.onNodeAdd| 在容器中拖入组件时触发的事件回调| Function| (e: MouseEvent, currentNode: any) => any
-|callbacks.onNodeRemove| 在容器中删除组件时触发的事件回调| Function| (e: MouseEvent, currentNode: any) => any
+|callbacks.onNodeAdd| 在容器中拖入组件时触发的事件回调 | Function| (e: MouseEvent, currentNode: any) => any
+|callbacks.onNodeRemove| 在容器中删除组件时触发的事件回调 | Function| (e: MouseEvent, currentNode: any) => any
|callbacks.onResize| 调整容器尺寸时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义
|callbacks.onResizeStart| 调整容器尺寸开始时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义
|callbacks.onResizeEnd| 调整容器尺寸结束时触发的事件回调,常常与 getResizingHandlers 搭配使用 | Function| 详见 Types 定义
-|callbacks.onSubtreeModified| 容器节点结构树发生变化时触发的回调| Function| (currentNode: any, options: any) => void;
-|callbacks.onMouseDownHook| 鼠标按下操作回调| Function| (e: MouseEvent, currentNode: any) => any;
-|callbacks.onClickHook| 鼠标单击操作回调| Function| (e: MouseEvent, currentNode: any) => any;
-|callbacks.onDblClickHook| 鼠标双击操作回调| Function| (e: MouseEvent, currentNode: any) => any;
+|callbacks.onSubtreeModified| 容器节点结构树发生变化时触发的回调 | Function| (currentNode: any, options: any) => void;
+|callbacks.onMouseDownHook| 鼠标按下操作回调 | Function| (e: MouseEvent, currentNode: any) => any;
+|callbacks.onClickHook| 鼠标单击操作回调 | Function| (e: MouseEvent, currentNode: any) => any;
+|callbacks.onDblClickHook| 鼠标双击操作回调 | Function| (e: MouseEvent, currentNode: any) => any;
|callbacks.onMoveHook| 节点被拖动回调 | Function| (currentNode: any) => boolean;
|callbacks.onHoverHook| 节点被 hover 回调 | Function| (currentNode: any) => boolean;
-|callbacks.onChildMoveHook| 容器节点的子节点被拖动回调| Function| (childNode: any, currentNode: any) => boolean;
+|callbacks.onChildMoveHook| 容器节点的子节点被拖动回调 | Function| (childNode: any, currentNode: any) => boolean;
描述举例:
@@ -1544,7 +1543,7 @@ block/
```
-#### 入口文件
+##### 入口文件
(/src/index.jsx)
@@ -1560,7 +1559,7 @@ const App = hot(router);
ReactDOM.render(
, document.getElementById(pkg.config && pkg.config.targetRootID || 'root'));
```
-#### 应用参数配置文件
+##### 应用参数配置文件
(/src/config/app.js)
@@ -1597,7 +1596,7 @@ export default {
}
```
-#### 应用扩展配置规范:
+##### 应用扩展配置规范:
(/src/utils/index.js)
@@ -1619,7 +1618,7 @@ export default {
}
```
-#### 应用常量配置
+##### 应用常量配置
(/src/config/constants.js)
@@ -1629,7 +1628,7 @@ export default {
}
```
-#### 应用样式配置
+##### 应用样式配置
(/src/global.scss)
diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js
index 97a0237b4..0aaa4c50f 100644
--- a/docs/docusaurus.config.js
+++ b/docs/docusaurus.config.js
@@ -39,7 +39,6 @@ const config = {
presets: [
[
'classic',
- /** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: require.resolve('./config/sidebars.js'),
@@ -55,7 +54,6 @@ const config = {
],
themeConfig:
- /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
docs: {
sidebar: {
@@ -76,7 +74,7 @@ const config = {
metadata: [{ name: 'referrer', content: 'no-referrer' }],
tableOfContents: {
minHeadingLevel: 2,
- maxHeadingLevel: 5,
+ maxHeadingLevel: 6,
},
}),
diff --git a/docs/package.json b/docs/package.json
index d03668ad9..3a07ecd67 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -1,6 +1,6 @@
{
"name": "@alilc/lowcode-engine-docs",
- "version": "1.0.8",
+ "version": "1.0.18",
"description": "低代码引擎版本化文档",
"license": "MIT",
"files": [
@@ -16,7 +16,8 @@
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
- "typecheck": "tsc"
+ "typecheck": "tsc",
+ "syncOss": "node ./scripts/sync-oss.js"
},
"dependencies": {
"@docusaurus/core": "^2.2.0",
diff --git a/docs/scripts/getDocsFromDir.js b/docs/scripts/getDocsFromDir.js
index 1d3236fe6..18e67e718 100644
--- a/docs/scripts/getDocsFromDir.js
+++ b/docs/scripts/getDocsFromDir.js
@@ -8,8 +8,14 @@ module.exports = function getDocsFromDir(dir, cateList) {
const baseDir = path.join(__dirname, '../docs/');
const docsDir = path.join(baseDir, dir);
+ function isNil(value) {
+ return value === undefined || value === null;
+ }
+
function getMarkdownOrder(filepath) {
- return (matter(fs.readFileSync(filepath, 'utf-8')).data || {}).order || 100;
+ const { data } = matter(fs.readFileSync(filepath, 'utf-8'));
+ const { sidebar_position } = data || {};
+ return isNil(sidebar_position) ? 100 : sidebar_position;
}
const docs = glob.sync('*.md?(x)', {
@@ -18,8 +24,8 @@ module.exports = function getDocsFromDir(dir, cateList) {
});
const result = docs
- .filter(doc => !/^index.md(x)?$/.test(doc))
- .map(doc => {
+ .filter((doc) => !/^index.md(x)?$/.test(doc))
+ .map((doc) => {
return path.join(docsDir, doc);
})
.sort((a, b) => {
@@ -28,7 +34,7 @@ module.exports = function getDocsFromDir(dir, cateList) {
return orderA - orderB;
})
- .map(filepath => {
+ .map((filepath) => {
// /Users/xxx/site/docs/guide/basic/router.md => guide/basic/router
const id = path
.relative(baseDir, filepath)
@@ -37,7 +43,7 @@ module.exports = function getDocsFromDir(dir, cateList) {
return id;
});
- (cateList || []).forEach(item => {
+ (cateList || []).forEach((item) => {
const { dir, subCategory, ...otherConfig } = item;
const indexList = glob.sync('index.md?(x)', {
cwd: path.join(baseDir, dir),
diff --git a/docs/scripts/sync-oss.js b/docs/scripts/sync-oss.js
new file mode 100644
index 000000000..9518a8ea7
--- /dev/null
+++ b/docs/scripts/sync-oss.js
@@ -0,0 +1,47 @@
+#!/usr/bin/env node
+const http = require('http');
+const package = require('../package.json');
+const { version, name } = package;
+const options = {
+ method: 'PUT',
+ hostname: 'uipaas-node.alibaba-inc.com',
+ path: '/staticAssets/cdn/packages',
+ headers: {
+ 'Content-Type': 'application/json',
+ Cookie: 'locale=en-us',
+ },
+ maxRedirects: 20,
+};
+
+const onResponse = function (res) {
+ const chunks = [];
+ res.on('data', (chunk) => {
+ chunks.push(chunk);
+ });
+
+ res.on('end', (chunk) => {
+ const body = Buffer.concat(chunks);
+ console.table(JSON.stringify(JSON.parse(body.toString()), null, 2));
+ });
+
+ res.on('error', (error) => {
+ console.error(error);
+ });
+};
+
+const req = http.request(options, onResponse);
+
+const postData = JSON.stringify({
+ packages: [
+ {
+ packageName: name,
+ version,
+ },
+ ],
+ // 可以发布指定源的 npm 包,默认公网 npm
+ useTnpm: false,
+});
+
+req.write(postData);
+
+req.end();
\ No newline at end of file
diff --git a/lerna.json b/lerna.json
index af393cf27..dc8950db4 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
{
"lerna": "4.0.0",
- "version": "1.0.18",
+ "version": "1.1.0",
"npmClient": "yarn",
"useWorkspaces": true,
"packages": [
diff --git a/modules/code-generator/babel.config.js b/modules/code-generator/babel.config.js
new file mode 100644
index 000000000..c5986f2bc
--- /dev/null
+++ b/modules/code-generator/babel.config.js
@@ -0,0 +1 @@
+module.exports = require('../../babel.config');
\ No newline at end of file
diff --git a/modules/code-generator/bin/lowcode-code-generator.js b/modules/code-generator/bin/lowcode-code-generator.js
index 6259a5a6f..79c36c49a 100755
--- a/modules/code-generator/bin/lowcode-code-generator.js
+++ b/modules/code-generator/bin/lowcode-code-generator.js
@@ -14,6 +14,7 @@ program
.option('-c, --cwd
', 'specify the working directory', '.')
.option('-q, --quiet', 'be quiet, do not output anything unless get error', false)
.option('-v, --verbose', 'be verbose, output more information', false)
+ .option('--solution-options ', 'specify the solution options', '{}')
.arguments('[input-schema] ali lowcode schema JSON file')
.action(function doGenerate(inputSchema, command) {
var options = command.opts();
diff --git a/modules/code-generator/package.json b/modules/code-generator/package.json
index 3e7898e39..97863584c 100644
--- a/modules/code-generator/package.json
+++ b/modules/code-generator/package.json
@@ -1,6 +1,6 @@
{
"name": "@alilc/lowcode-code-generator",
- "version": "1.0.7-beta.3",
+ "version": "1.0.7",
"description": "出码引擎 for LowCode Engine",
"license": "MIT",
"main": "lib/index.js",
@@ -98,6 +98,7 @@
"qs": "^6.10.1",
"semver": "^7.3.4",
"short-uuid": "^3.1.1",
+ "babel-jest": "^26.5.2",
"tslib": "^2.3.1"
},
"browser": {
@@ -125,11 +126,11 @@
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
- "jest": "^27.4.7",
+ "jest": "^26.5.2",
"jest-util": "^27.4.2",
"rimraf": "^3.0.2",
"standard-version": "^9.1.1",
- "ts-jest": "^27.1.3",
+ "ts-jest": "^26.5.2",
"ts-loader": "^6.2.2",
"ts-node": "^8.10.2",
"tsconfig-paths": "^3.9.0",
diff --git a/modules/code-generator/src/analyzer/componentAnalyzer.ts b/modules/code-generator/src/analyzer/componentAnalyzer.ts
index 952295a15..69e8ad482 100644
--- a/modules/code-generator/src/analyzer/componentAnalyzer.ts
+++ b/modules/code-generator/src/analyzer/componentAnalyzer.ts
@@ -1,13 +1,13 @@
-import type { NodeSchema, CompositeObject } from '@alilc/lowcode-types';
+import type { IPublicTypeNodeSchema, IPublicTypeCompositeObject } from '@alilc/lowcode-types';
import type { TComponentAnalyzer } from '../types';
import { handleSubNodes } from '../utils/schema';
export const componentAnalyzer: TComponentAnalyzer = (container) => {
let hasRefAttr = false;
- const nodeValidator = (n: NodeSchema) => {
+ const nodeValidator = (n: IPublicTypeNodeSchema) => {
if (n.props) {
- const props = n.props as CompositeObject;
+ const props = n.props as IPublicTypeCompositeObject;
if (props.ref) {
hasRefAttr = true;
}
diff --git a/modules/code-generator/src/cli/run.ts b/modules/code-generator/src/cli/run.ts
index db66b4601..ec6814f76 100644
--- a/modules/code-generator/src/cli/run.ts
+++ b/modules/code-generator/src/cli/run.ts
@@ -9,7 +9,7 @@ import * as path from 'path';
import { getErrorMessage } from '../utils/errors';
import CodeGenerator from '..';
import type { IProjectBuilder } from '..';
-import type { ProjectSchema } from '@alilc/lowcode-types';
+import type { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
/**
* 执行出码 CLI 命令
@@ -25,6 +25,7 @@ export async function run(
output?: string;
quiet?: boolean;
verbose?: boolean;
+ solutionOptions?: string;
},
): Promise {
try {
@@ -41,6 +42,19 @@ export async function run(
);
}
+ let solutionOptions = {};
+
+ if (options.solutionOptions) {
+ try {
+ solutionOptions = JSON.parse(options.solutionOptions);
+ } catch (err: any) {
+ throw new Error(
+ `solution options parse error, error message is "${err.message}"`,
+ );
+ }
+ }
+
+
// 读取 Schema
const schema = await loadSchemaFile(schemaFile);
@@ -48,7 +62,7 @@ export async function run(
const createProjectBuilder = await getProjectBuilderFactory(options.solution, {
quiet: options.quiet,
});
- const builder = createProjectBuilder();
+ const builder = createProjectBuilder(solutionOptions);
// 生成代码
const generatedSourceCodes = await builder.generateProject(schema);
@@ -75,7 +89,7 @@ export async function run(
async function getProjectBuilderFactory(
solution: string,
{ quiet }: { quiet?: boolean },
-): Promise<() => IProjectBuilder> {
+): Promise<(options: {[prop: string]: any}) => IProjectBuilder> {
if (solution in CodeGenerator.solutions) {
return CodeGenerator.solutions[solution as 'icejs' | 'rax'];
}
@@ -117,7 +131,7 @@ function isLocalSolution(solution: string) {
return solution.startsWith('.') || solution.startsWith('/') || solution.startsWith('~');
}
-async function loadSchemaFile(schemaFile: string): Promise {
+async function loadSchemaFile(schemaFile: string): Promise {
if (!schemaFile) {
throw new Error('invalid schema file name');
}
diff --git a/modules/code-generator/src/cli/solutions/example-solution.ts b/modules/code-generator/src/cli/solutions/example-solution.ts
index 2efff780c..fe303f360 100644
--- a/modules/code-generator/src/cli/solutions/example-solution.ts
+++ b/modules/code-generator/src/cli/solutions/example-solution.ts
@@ -559,8 +559,8 @@ codealike.json
"registry": "https://registry.npm.xxx.com"
},
"dependencies": {
- "@alilc/lowcode-code-generator": "^1.0.0-beta.16",
- "@alilc/lowcode-types": "^1.0.0-beta.21",
+ "@alilc/lowcode-code-generator": "^1.0.0",
+ "@alilc/lowcode-types": "^1.0.0",
"tslib": "^2.3.0"
},
"devDependencies": {
diff --git a/modules/code-generator/src/generator/ModuleBuilder.ts b/modules/code-generator/src/generator/ModuleBuilder.ts
index f4554ef61..755ca20c6 100644
--- a/modules/code-generator/src/generator/ModuleBuilder.ts
+++ b/modules/code-generator/src/generator/ModuleBuilder.ts
@@ -1,4 +1,4 @@
-import { ProjectSchema, ResultFile, ResultDir } from '@alilc/lowcode-types';
+import { IPublicTypeProjectSchema, ResultFile, ResultDir } from '@alilc/lowcode-types';
import {
BuilderComponentPlugin,
@@ -77,7 +77,7 @@ export function createModuleBuilder(
};
};
- const generateModuleCode = async (schema: ProjectSchema | string): Promise => {
+ const generateModuleCode = async (schema: IPublicTypeProjectSchema | string): Promise => {
// Init
const schemaParser: ISchemaParser = new SchemaParser();
const parseResult: IParseResult = schemaParser.parse(schema);
diff --git a/modules/code-generator/src/generator/ProjectBuilder.ts b/modules/code-generator/src/generator/ProjectBuilder.ts
index 2a1282d6e..819f37c5c 100644
--- a/modules/code-generator/src/generator/ProjectBuilder.ts
+++ b/modules/code-generator/src/generator/ProjectBuilder.ts
@@ -1,4 +1,4 @@
-import { ResultDir, ResultFile, ProjectSchema } from '@alilc/lowcode-types';
+import { ResultDir, ResultFile, IPublicTypeProjectSchema } from '@alilc/lowcode-types';
import {
IModuleBuilder,
@@ -40,6 +40,11 @@ export interface ProjectBuilderInitOptions {
inStrictMode?: boolean;
/** 一些额外的上下文数据 */
extraContextData?: Record;
+ /**
+ * Hook which is used to customize original options, we can reorder/add/remove plugins/processors
+ * of the existing solution.
+ */
+ customizeBuilderOptions?(originalOptions: ProjectBuilderInitOptions): ProjectBuilderInitOptions;
}
export class ProjectBuilder implements IProjectBuilder {
@@ -62,21 +67,26 @@ export class ProjectBuilder implements IProjectBuilder {
private projectPostProcessors: ProjectPostProcessor[];
/** 是否处于严格模式 */
- public readonly inStrictMode: boolean;
+ readonly inStrictMode: boolean;
/** 一些额外的上下文数据 */
- public readonly extraContextData: IContextData;
+ readonly extraContextData: IContextData;
- constructor({
- template,
- plugins,
- postProcessors,
- schemaParser = new SchemaParser(),
- projectPreProcessors = [],
- projectPostProcessors = [],
- inStrictMode = false,
- extraContextData = {},
- }: ProjectBuilderInitOptions) {
+ constructor(builderOptions: ProjectBuilderInitOptions) {
+ let customBuilderOptions = builderOptions;
+ if (typeof builderOptions.customizeBuilderOptions === 'function') {
+ customBuilderOptions = builderOptions.customizeBuilderOptions(builderOptions);
+ }
+ const {
+ template,
+ plugins,
+ postProcessors,
+ schemaParser = new SchemaParser(),
+ projectPreProcessors = [],
+ projectPostProcessors = [],
+ inStrictMode = false,
+ extraContextData = {},
+ } = customBuilderOptions;
this.template = template;
this.plugins = plugins;
this.postProcessors = postProcessors;
@@ -87,34 +97,37 @@ export class ProjectBuilder implements IProjectBuilder {
this.extraContextData = extraContextData;
}
- async generateProject(originalSchema: ProjectSchema | string): Promise {
+ async generateProject(originalSchema: IPublicTypeProjectSchema | string): Promise {
// Init
const { schemaParser } = this;
- const builders = this.createModuleBuilders();
const projectRoot = await this.template.generateTemplate();
- let schema: ProjectSchema =
+ let schema: IPublicTypeProjectSchema =
typeof originalSchema === 'string' ? JSON.parse(originalSchema) : originalSchema;
- // Validate
- if (!schemaParser.validate(schema)) {
- throw new CodeGeneratorError('Schema is invalid');
- }
-
// Parse / Format
-
// Preprocess
for (const preProcessor of this.projectPreProcessors) {
// eslint-disable-next-line no-await-in-loop
schema = await preProcessor(schema);
}
+ // Validate
+ if (!schemaParser.validate(schema)) {
+ throw new CodeGeneratorError('Schema is invalid');
+ }
+
// Collect Deps
// Parse JSExpression
const parseResult: IParseResult = schemaParser.parse(schema);
let buildResult: IModuleInfo[] = [];
+ const builders = this.createModuleBuilders({
+ extraContextData: {
+ projectRemark: parseResult?.project?.projectRemark,
+ },
+ });
// Generator Code module
// components
// pages
@@ -241,14 +254,24 @@ export class ProjectBuilder implements IProjectBuilder {
});
}
+ // demo
+ if (parseResult.project && builders.demo) {
+ const { files } = await builders.demo.generateModule(parseResult.project);
+ buildResult.push({
+ path: this.template.slots.demo.path,
+ files,
+ });
+ }
+
// TODO: 更多 slots 的处理??是不是可以考虑把 template 中所有的 slots 都处理下?
// Post Process
-
+ const isSingleComponent = parseResult?.project?.projectRemark?.isSingleComponent;
// Combine Modules
buildResult.forEach((moduleInfo) => {
let targetDir = getDirFromRoot(projectRoot, moduleInfo.path);
- if (moduleInfo.moduleName) {
+ // if project only contain single component, skip creation of directory.
+ if (moduleInfo.moduleName && !isSingleComponent) {
const dir = createResultDir(moduleInfo.moduleName);
addDirectory(targetDir, dir);
targetDir = dir;
@@ -260,13 +283,17 @@ export class ProjectBuilder implements IProjectBuilder {
let finalResult = projectRoot;
for (const projectPostProcessor of this.projectPostProcessors) {
// eslint-disable-next-line no-await-in-loop
- finalResult = await projectPostProcessor(finalResult, schema, originalSchema);
+ finalResult = await projectPostProcessor(finalResult, schema, originalSchema, {
+ template: this.template,
+ parseResult,
+ });
}
return finalResult;
}
- private createModuleBuilders(): Record {
+ private createModuleBuilders(extraContextData: Record = {}):
+ Record {
const builders: Record = {};
Object.keys(this.plugins).forEach((pluginName) => {
@@ -279,10 +306,12 @@ export class ProjectBuilder implements IProjectBuilder {
plugins: this.plugins[pluginName],
postProcessors: this.postProcessors,
contextData: {
+ // template: this.template,
inStrictMode: this.inStrictMode,
tolerateEvalErrors: true,
evalErrorsHandler: '',
...this.extraContextData,
+ ...extraContextData,
},
...options,
});
diff --git a/modules/code-generator/src/parser/SchemaParser.ts b/modules/code-generator/src/parser/SchemaParser.ts
index 2e526d88b..3108fee47 100644
--- a/modules/code-generator/src/parser/SchemaParser.ts
+++ b/modules/code-generator/src/parser/SchemaParser.ts
@@ -4,14 +4,14 @@
*/
import changeCase from 'change-case';
import {
- UtilItem,
- NodeDataType,
- NodeSchema,
- ContainerSchema,
- ProjectSchema,
- PropsMap,
- NodeData,
- NpmInfo,
+ IPublicTypeUtilItem,
+ IPublicTypeNodeDataType,
+ IPublicTypeNodeSchema,
+ IPublicTypeContainerSchema,
+ IPublicTypeProjectSchema,
+ IPublicTypePropsMap,
+ IPublicTypeNodeData,
+ IPublicTypeNpmInfo,
} from '@alilc/lowcode-types';
import {
IPageMeta,
@@ -32,10 +32,11 @@ import {
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
import { getErrorMessage } from '../utils/errors';
-import { handleSubNodes } from '../utils/schema';
+import { handleSubNodes, isValidContainerType } from '../utils/schema';
import { uniqueArray } from '../utils/common';
import { componentAnalyzer } from '../analyzer/componentAnalyzer';
import { ensureValidClassName } from '../utils/validate';
+import type { ProjectRemark } from '../types/intermediate';
const defaultContainer: IContainerInfo = {
containerType: 'Component',
@@ -71,18 +72,18 @@ function getRootComponentName(typeName: string, maps: Record = {};
const internalDeps: Record = {};
@@ -139,9 +140,9 @@ export class SchemaParser implements ISchemaParser {
let containers: IContainerInfo[];
// Test if this is a lowcode component without container
if (schema.componentsTree.length > 0) {
- const firstRoot: ContainerSchema = schema.componentsTree[0] as ContainerSchema;
+ const firstRoot: IPublicTypeContainerSchema = schema.componentsTree[0] as IPublicTypeContainerSchema;
- if (!('fileName' in firstRoot) || !firstRoot.fileName) {
+ if (!firstRoot.fileName && !isValidContainerType(firstRoot)) {
// 整个 schema 描述一个容器,且无根节点定义
const container: IContainerInfo = {
...firstRoot,
@@ -149,13 +150,13 @@ export class SchemaParser implements ISchemaParser {
props: firstRoot.props || defaultContainer.props,
css: firstRoot.css || defaultContainer.css,
moduleName: (firstRoot as IContainerInfo).moduleName || defaultContainer.moduleName,
- children: schema.componentsTree as NodeSchema[],
+ children: schema.componentsTree as IPublicTypeNodeSchema[],
};
containers = [container];
} else {
// 普通带 1 到多个容器的 schema
containers = schema.componentsTree.map((n) => {
- const subRoot = n as ContainerSchema;
+ const subRoot = n as IPublicTypeContainerSchema;
const container: IContainerInfo = {
...subRoot,
componentName: getRootComponentName(subRoot.componentName, compDeps),
@@ -172,7 +173,7 @@ export class SchemaParser implements ISchemaParser {
// 分析引用能力的依赖
containers = containers.map((con) => ({
...con,
- analyzeResult: componentAnalyzer(con as ContainerSchema),
+ analyzeResult: componentAnalyzer(con as IPublicTypeContainerSchema),
}));
// 建立所有容器的内部依赖索引
@@ -210,7 +211,7 @@ export class SchemaParser implements ISchemaParser {
handleSubNodes(
container.children,
{
- node: (i: NodeSchema) => processChildren(i),
+ node: (i: IPublicTypeNodeSchema) => processChildren(i),
},
{
rerun: true,
@@ -254,13 +255,12 @@ export class SchemaParser implements ISchemaParser {
.filter((dep) => !!dep);
// 分析 Utils 依赖
- let utils: UtilItem[];
+ let utils: IPublicTypeUtilItem[];
if (schema.utils) {
utils = schema.utils;
utilsDeps = schema.utils
.filter(
- (u): u is { name: string; type: 'npm' | 'tnpm'; content: NpmInfo } =>
- u.type !== 'function',
+ (u): u is { name: string; type: 'npm' | 'tnpm'; content: IPublicTypeNpmInfo } => u.type !== 'function',
)
.map(
(u): IExternalDependency => ({
@@ -320,15 +320,22 @@ export class SchemaParser implements ISchemaParser {
utilsDeps,
packages: npms || [],
dataSourcesTypes: this.collectDataSourcesTypes(schema),
+ projectRemark: this.getProjectRemark(containers),
},
};
}
- getComponentNames(children: NodeDataType): string[] {
+ getProjectRemark(containers: IContainerInfo[]): ProjectRemark {
+ return {
+ isSingleComponent: containers.length === 1 && containers[0].containerType === 'Component',
+ };
+ }
+
+ getComponentNames(children: IPublicTypeNodeDataType): string[] {
return handleSubNodes(
children,
{
- node: (i: NodeSchema) => i.componentName,
+ node: (i: IPublicTypeNodeSchema) => i.componentName,
},
{
rerun: true,
@@ -336,8 +343,8 @@ export class SchemaParser implements ISchemaParser {
);
}
- decodeSchema(schemaSrc: string | ProjectSchema): ProjectSchema {
- let schema: ProjectSchema;
+ decodeSchema(schemaSrc: string | IPublicTypeProjectSchema): IPublicTypeProjectSchema {
+ let schema: IPublicTypeProjectSchema;
if (typeof schemaSrc === 'string') {
try {
schema = JSON.parse(schemaSrc);
@@ -352,7 +359,7 @@ export class SchemaParser implements ISchemaParser {
return schema;
}
- private collectDataSourcesTypes(schema: ProjectSchema): string[] {
+ private collectDataSourcesTypes(schema: IPublicTypeProjectSchema): string[] {
const dataSourcesTypes = new Set();
// 数据源的默认类型为 fetch
diff --git a/modules/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts b/modules/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts
index 446b1d3f8..cb7a9e8c3 100644
--- a/modules/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts
+++ b/modules/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/indent */
import {
- CompositeValue,
- JSExpression,
+ IPublicTypeCompositeValue,
+ IPublicTypeJSExpression,
InterpretDataSourceConfig,
isJSExpression,
isJSFunction,
@@ -56,7 +56,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
(dataSourceConfig && dataSourceConfig.list) || [];
const dataSourceEngineOptions = { runtimeConfig: true };
if (dataSourceItems.length > 0) {
- const requestHandlersMap: Record = {};
+ const requestHandlersMap: Record = {};
dataSourceItems.forEach((ds) => {
const dsType = ds.type || 'fetch';
@@ -178,7 +178,7 @@ _defineDataSourceConfig() {
export default pluginFactory;
-function wrapAsFunction(value: CompositeValue, scope: IScope): CompositeValue {
+function wrapAsFunction(value: IPublicTypeCompositeValue, scope: IScope): IPublicTypeCompositeValue {
if (isJSExpression(value) || isJSFunction(value)) {
return {
type: 'JSExpression',
diff --git a/modules/code-generator/src/plugins/component/rax/jsx.ts b/modules/code-generator/src/plugins/component/rax/jsx.ts
index e0c6dd01f..98c80a492 100644
--- a/modules/code-generator/src/plugins/component/rax/jsx.ts
+++ b/modules/code-generator/src/plugins/component/rax/jsx.ts
@@ -1,8 +1,8 @@
import {
- NodeSchema,
- JSExpression,
- NpmInfo,
- CompositeValue,
+ IPublicTypeNodeSchema,
+ IPublicTypeJSExpression,
+ IPublicTypeNpmInfo,
+ IPublicTypeCompositeValue,
isJSExpression,
} from '@alilc/lowcode-types';
@@ -86,7 +86,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
// 2. 小程序出码的时候,很容易出现 Uncaught TypeError: Cannot read property 'avatar' of undefined 这样的异常(如下图的 50 行) -- 因为若直接出码,Rax 构建到小程序的时候会立即计算所有在视图中用到的变量
// 3. 通过 this.xxx 能拿到的东西太多了,而且自定义的 methods 可能会无意间破坏 Rax 框架或小程序框架在页面 this 上的东东
const customHandlers: HandlerSet = {
- expression(input: JSExpression, scope: IScope) {
+ expression(input: IPublicTypeJSExpression, scope: IScope) {
return transformJsExpr(generateExpression(input, scope), scope, {
dontWrapEval: !tolerateEvalErrors,
});
@@ -171,7 +171,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
return next;
function generateRaxLoopCtrl(
- nodeItem: NodeSchema,
+ nodeItem: IPublicTypeNodeSchema,
scope: IScope,
config?: NodeGeneratorConfig,
next?: NodePlugin,
@@ -218,7 +218,7 @@ function isImportAliasDefineChunk(chunk: ICodeChunk): chunk is ICodeChunk & {
ext: {
aliasName: string;
originalName: string;
- dependency: NpmInfo;
+ dependency: IPublicTypeNpmInfo;
};
} {
return (
@@ -226,13 +226,13 @@ function isImportAliasDefineChunk(chunk: ICodeChunk): chunk is ICodeChunk & {
!!chunk.ext &&
typeof chunk.ext.aliasName === 'string' &&
typeof chunk.ext.originalName === 'string' &&
- !!(chunk.ext.dependency as NpmInfo | null)?.componentName
+ !!(chunk.ext.dependency as IPublicTypeNpmInfo | null)?.componentName
);
}
function generateNodeAttrForRax(
this: { cfg: PluginConfig },
- attrData: { attrName: string; attrValue: CompositeValue },
+ attrData: { attrName: string; attrValue: IPublicTypeCompositeValue },
scope: IScope,
config?: NodeGeneratorConfig,
next?: AttrPlugin,
@@ -257,7 +257,7 @@ function generateNodeAttrForRax(
function generateEventHandlerAttrForRax(
attrName: string,
- attrValue: CompositeValue,
+ attrValue: IPublicTypeCompositeValue,
scope: IScope,
config?: NodeGeneratorConfig,
): CodePiece[] {
diff --git a/modules/code-generator/src/plugins/component/react/containerInjectDataSourceEngine.ts b/modules/code-generator/src/plugins/component/react/containerInjectDataSourceEngine.ts
index 20302dea9..bc5fa54ba 100644
--- a/modules/code-generator/src/plugins/component/react/containerInjectDataSourceEngine.ts
+++ b/modules/code-generator/src/plugins/component/react/containerInjectDataSourceEngine.ts
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/indent */
import {
- CompositeValue,
- JSExpression,
+ IPublicTypeCompositeValue,
+ IPublicTypeJSExpression,
InterpretDataSourceConfig,
isJSExpression,
isJSFunction,
@@ -27,7 +27,7 @@ import {
import { generateCompositeType } from '../../../utils/compositeType';
import { parseExpressionConvertThis2Context } from '../../../utils/expressionParser';
-import { isContainerSchema } from '../../../utils/schema';
+import { isValidContainerType } from '../../../utils/schema';
import { REACT_CHUNK_NAME } from './const';
export interface PluginConfig {
@@ -67,12 +67,12 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
};
const scope = Scope.createRootScope();
- const dataSourceConfig = isContainerSchema(pre.ir) ? pre.ir.dataSource : null;
+ const dataSourceConfig = isValidContainerType(pre.ir) ? pre.ir.dataSource : null;
const dataSourceItems: InterpretDataSourceConfig[] =
(dataSourceConfig && dataSourceConfig.list) || [];
const dataSourceEngineOptions = { runtimeConfig: true };
if (dataSourceItems.length > 0) {
- const requestHandlersMap: Record = {};
+ const requestHandlersMap: Record = {};
dataSourceItems.forEach((ds) => {
const dsType = ds.type || 'fetch';
@@ -187,7 +187,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
export default pluginFactory;
-function wrapAsFunction(value: CompositeValue, scope: IScope): CompositeValue {
+function wrapAsFunction(value: IPublicTypeCompositeValue, scope: IScope): IPublicTypeCompositeValue {
if (isJSExpression(value) || isJSFunction(value)) {
return {
type: 'JSExpression',
diff --git a/modules/code-generator/src/plugins/component/react/containerInjectUtils.ts b/modules/code-generator/src/plugins/component/react/containerInjectUtils.ts
index 6c614f143..33fc8c28d 100644
--- a/modules/code-generator/src/plugins/component/react/containerInjectUtils.ts
+++ b/modules/code-generator/src/plugins/component/react/containerInjectUtils.ts
@@ -11,6 +11,7 @@ import {
FileType,
ICodeStruct,
IContainerInfo,
+ IProjectTemplate,
} from '../../../types';
export interface PluginConfig {
@@ -32,6 +33,19 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
next.contextData.useRefApi = true;
const useRef = !!ir.analyzeResult?.isUsingRef;
+ // const isSingleComponent = next.contextData?.projectRemark?.isSingleComponent;
+ // const template = next.contextData?.template;
+
+ // function getRelativeUtilsPath(template: IProjectTemplate, isSingleComponent: boolean) {
+ // let relativeUtilsPath = '../../utils';
+ // const utilsPath = template.slots.utils.path;
+ // if (ir.containerType === 'Component') {
+ // // TODO: isSingleComponent
+ // relativeUtilsPath = getRelativePath(template.slots.components.path.join('/'), utilsPath.join('/'));
+ // }
+ // return relativeUtilsPath;
+ // }
+
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
@@ -89,7 +103,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
type: ChunkType.STRING,
fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
- content: ` $ = () => null; `,
+ content: ' $ = () => null; ',
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
});
@@ -97,7 +111,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
type: ChunkType.STRING,
fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
- content: ` $$ = () => []; `,
+ content: ' $$ = () => []; ',
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
});
}
diff --git a/modules/code-generator/src/plugins/component/react/jsx.ts b/modules/code-generator/src/plugins/component/react/jsx.ts
index 445dce7a5..7cf5bd9de 100644
--- a/modules/code-generator/src/plugins/component/react/jsx.ts
+++ b/modules/code-generator/src/plugins/component/react/jsx.ts
@@ -16,7 +16,7 @@ import { COMMON_CHUNK_NAME } from '../../../const/generator';
import { createReactNodeGenerator } from '../../../utils/nodeToJSX';
import { Scope } from '../../../utils/Scope';
-import { JSExpression } from '@alilc/lowcode-types';
+import { IPublicTypeJSExpression } from '@alilc/lowcode-types';
import { generateExpression } from '../../../utils/jsExpression';
import { transformJsExpr } from '../../../core/jsx/handlers/transformJsExpression';
import { transformThis2Context } from '../../../core/jsx/handlers/transformThis2Context';
@@ -47,7 +47,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
// 这里会将内部的一些子上下文的访问(this.xxx)转换为 __$$context.xxx 的形式
// 与 Rax 所不同的是,这里不会将最顶层的 this 转换掉
const customHandlers: HandlerSet = {
- expression(input: JSExpression, scope: IScope, config) {
+ expression(input: IPublicTypeJSExpression, scope: IScope, config) {
return transformJsExpr(generateExpression(input, scope), scope, {
dontWrapEval: !(config?.tolerateEvalErrors ?? tolerateEvalErrors),
dontTransformThis2ContextAtRootScope: true,
@@ -120,7 +120,7 @@ const pluginFactory: BuilderComponentPluginFactory = (config?) =>
function __$$eval(expr) {
try {
return expr();
- } catch (error) {
+ } catch (error) {
${evalErrorsHandler}
}
}
diff --git a/modules/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts b/modules/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts
index e95a3dc0b..401ba3f97 100644
--- a/modules/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts
+++ b/modules/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts
@@ -1,4 +1,4 @@
-import { NpmInfo, PackageJSON } from '@alilc/lowcode-types';
+import { IPublicTypeNpmInfo, PackageJSON } from '@alilc/lowcode-types';
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
import {
@@ -84,9 +84,9 @@ const pluginFactory: BuilderComponentPluginFactory = (cfg)
export default pluginFactory;
-function getNpmDependencies(project: IProjectInfo): NpmInfo[] {
- const npmDeps: NpmInfo[] = [];
- const npmNameToPkgMap = new Map();
+function getNpmDependencies(project: IProjectInfo): IPublicTypeNpmInfo[] {
+ const npmDeps: IPublicTypeNpmInfo[] = [];
+ const npmNameToPkgMap = new Map();
const allDeps = project.packages;
diff --git a/modules/code-generator/src/postprocessor/prettier/index.ts b/modules/code-generator/src/postprocessor/prettier/index.ts
index afdcc6225..d4e61e3c0 100644
--- a/modules/code-generator/src/postprocessor/prettier/index.ts
+++ b/modules/code-generator/src/postprocessor/prettier/index.ts
@@ -9,7 +9,7 @@ const PARSERS = ['css', 'scss', 'less', 'json', 'html', 'vue'];
export interface ProcessorConfig {
customFileTypeParser: Record;
- plugins?: Array;
+ plugins?: prettier.Plugin[];
}
const factory: PostProcessorFactory = (config?: ProcessorConfig) => {
@@ -33,6 +33,8 @@ const factory: PostProcessorFactory = (config?: ProcessorConfig
return prettier.format(content, {
parser,
plugins: [parserBabel, parserPostCss, parserHtml, ...(cfg.plugins || [])],
+ singleQuote: true,
+ jsxSingleQuote: false,
});
};
diff --git a/modules/code-generator/src/solutions/icejs.ts b/modules/code-generator/src/solutions/icejs.ts
index 85ce7c1f5..1b3dec4af 100644
--- a/modules/code-generator/src/solutions/icejs.ts
+++ b/modules/code-generator/src/solutions/icejs.ts
@@ -91,6 +91,7 @@ export default function createIceJsProjectBuilder(
packageJSON: [icejs.plugins.packageJSON()],
},
postProcessors: [prettier()],
+ customizeBuilderOptions: options?.customizeBuilderOptions,
});
}
diff --git a/modules/code-generator/src/solutions/rax-app.ts b/modules/code-generator/src/solutions/rax-app.ts
index c2b3adac5..f7e903835 100644
--- a/modules/code-generator/src/solutions/rax-app.ts
+++ b/modules/code-generator/src/solutions/rax-app.ts
@@ -71,6 +71,7 @@ export default function createRaxProjectBuilder(
packageJSON: [raxApp.plugins.packageJSON(options)],
},
postProcessors: [prettier()],
+ customizeBuilderOptions: options?.customizeBuilderOptions,
});
}
diff --git a/modules/code-generator/src/standalone-loader.ts b/modules/code-generator/src/standalone-loader.ts
index 882b1de9d..0c8903ddc 100644
--- a/modules/code-generator/src/standalone-loader.ts
+++ b/modules/code-generator/src/standalone-loader.ts
@@ -1,5 +1,5 @@
import fetch from 'node-fetch';
-import type { ProjectSchema, ResultDir } from '@alilc/lowcode-types';
+import type { IPublicTypeProjectSchema, ResultDir } from '@alilc/lowcode-types';
import type { FlattenFile } from './types/file';
declare const Worker: any;
@@ -26,7 +26,7 @@ export type Result = ResultDir | FlattenFile[];
export async function generateCode(options: {
solution: 'icejs' | 'rax';
- schema: ProjectSchema;
+ schema: IPublicTypeProjectSchema;
flattenResult?: boolean;
workerJsUrl?: string;
timeoutInMs?: number;
diff --git a/modules/code-generator/src/standalone-worker.ts b/modules/code-generator/src/standalone-worker.ts
index 71f56e67a..e00a4877b 100644
--- a/modules/code-generator/src/standalone-worker.ts
+++ b/modules/code-generator/src/standalone-worker.ts
@@ -1,5 +1,5 @@
/* eslint-disable no-console */
-import type { ProjectSchema } from '@alilc/lowcode-types';
+import type { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
import CodeGen from './standalone';
declare const self: any;
@@ -13,7 +13,7 @@ self.onmessage = (event: any) => {
self.postMessage({ type: 'ready' });
-async function run(msg: { solution: string; schema: ProjectSchema; flattenResult?: boolean }) {
+async function run(msg: { solution: string; schema: IPublicTypeProjectSchema; flattenResult?: boolean }) {
try {
print('begin run...');
self.postMessage({ type: 'run:begin' });
diff --git a/modules/code-generator/src/types/analyze.ts b/modules/code-generator/src/types/analyze.ts
index 43de30743..3bf444d29 100644
--- a/modules/code-generator/src/types/analyze.ts
+++ b/modules/code-generator/src/types/analyze.ts
@@ -1,7 +1,7 @@
-import type { ContainerSchema } from '@alilc/lowcode-types';
+import type { IPublicTypeContainerSchema } from '@alilc/lowcode-types';
export interface ICompAnalyzeResult {
isUsingRef: boolean;
}
-export type TComponentAnalyzer = (container: ContainerSchema) => ICompAnalyzeResult;
+export type TComponentAnalyzer = (container: IPublicTypeContainerSchema) => ICompAnalyzeResult;
diff --git a/modules/code-generator/src/types/core.ts b/modules/code-generator/src/types/core.ts
index 99ca8c97a..39e4c32ba 100644
--- a/modules/code-generator/src/types/core.ts
+++ b/modules/code-generator/src/types/core.ts
@@ -1,19 +1,20 @@
import {
- JSONArray,
- JSONObject,
- CompositeArray,
- CompositeObject,
+ IPublicTypeJSONArray,
+ IPublicTypeJSONObject,
+ IPublicTypeCompositeArray,
+ IPublicTypeCompositeObject,
ResultDir,
ResultFile,
- NodeDataType,
- ProjectSchema,
- JSExpression,
- JSFunction,
- JSSlot,
+ IPublicTypeNodeDataType,
+ IPublicTypeProjectSchema,
+ IPublicTypeJSExpression,
+ IPublicTypeJSFunction,
+ IPublicTypeJSSlot,
} from '@alilc/lowcode-types';
import { IParseResult } from './intermediate';
import { IScopeBindings } from '../utils/ScopeBindings';
+import type { ProjectBuilderInitOptions } from '../generator/ProjectBuilder';
export enum FileType {
CSS = 'css',
@@ -25,6 +26,7 @@ export enum FileType {
TS = 'ts',
TSX = 'tsx',
JSON = 'json',
+ MD = 'md',
}
export enum ChunkType {
@@ -64,7 +66,10 @@ export interface ICodeStruct extends IBaseCodeStruct {
/** 上下文数据,用来在插件之间共享一些数据 */
export interface IContextData extends IProjectBuilderOptions {
- /** 是否使用了 Ref 的 API (this.$/this.$$) */
+
+ /**
+ * 是否使用了 Ref 的 API (this.$/this.$$)
+ * */
useRefApi?: boolean;
/**
@@ -95,7 +100,7 @@ export interface ICompiledModule {
export interface IModuleBuilder {
generateModule: (input: unknown) => Promise;
- generateModuleCode: (schema: ProjectSchema | string) => Promise;
+ generateModuleCode: (schema: IPublicTypeProjectSchema | string) => Promise;
linkCodeChunks: (chunks: Record, fileName: string) => ResultFile[];
addPlugin: (plugin: BuilderComponentPlugin) => void;
}
@@ -107,19 +112,20 @@ export interface IModuleBuilder {
* @interface ICodeGenerator
*/
export interface ICodeGenerator {
+
/**
* 出码接口,把 Schema 转换成代码文件系统描述
*
- * @param {(ProjectSchema)} schema 传入的 Schema
+ * @param {(IPublicTypeProjectSchema)} schema 传入的 Schema
* @returns {ResultDir}
* @memberof ICodeGenerator
*/
- toCode: (schema: ProjectSchema) => Promise;
+ toCode: (schema: IPublicTypeProjectSchema) => Promise;
}
export interface ISchemaParser {
- validate: (schema: ProjectSchema) => boolean;
- parse: (schema: ProjectSchema | string) => IParseResult;
+ validate: (schema: IPublicTypeProjectSchema) => boolean;
+ parse: (schema: IPublicTypeProjectSchema | string) => IParseResult;
}
export interface IProjectTemplate {
@@ -137,44 +143,56 @@ export interface IProjectPlugins {
}
export interface IProjectBuilderOptions {
- /** 是否处于严格模式(默认: 否) */
+
+ /** 是否处于严格模式 (默认:否) */
inStrictMode?: boolean;
/**
* 是否要容忍对 JSExpression 求值时的异常
* 默认:true
- * 注: 如果容忍异常,则会在求值时包裹 try-catch 块,
+ * 注:如果容忍异常,则会在求值时包裹 try-catch 块,
* catch 到异常时默认会抛出一个 CustomEvent 事件里面包含异常信息和求值的表达式
*/
tolerateEvalErrors?: boolean;
/**
* 容忍异常的时候的的错误处理语句块
- * 默认: 无
+ * 默认:无
* 您可以设置为一个语句块,比如:
* window.dispatchEvent(new CustomEvent('lowcode-eval-error', { error, expr }))
*
* 一般可以结合埋点监控模块用来监控求值异常
*
- * 其中:
+ * 其中:
* - error: 异常信息
* - expr: 求值的表达式
*/
evalErrorsHandler?: string;
+ /**
+ * Hook which is used to customize original options, we can reorder/add/remove plugins/processors
+ * of the existing solution.
+ */
+ customizeBuilderOptions?(originalOptions: ProjectBuilderInitOptions): ProjectBuilderInitOptions;
}
export interface IProjectBuilder {
- generateProject: (schema: ProjectSchema | string) => Promise;
+ generateProject: (schema: IPublicTypeProjectSchema | string) => Promise;
}
/** 项目级别的前置处理器 */
-export type ProjectPreProcessor = (schema: ProjectSchema) => Promise | ProjectSchema;
+export type ProjectPreProcessor = (schema: IPublicTypeProjectSchema) => Promise | IPublicTypeProjectSchema;
+
+export interface ProjectPostProcessorOptions {
+ parseResult?: IParseResult;
+ template?: IProjectTemplate;
+}
/** 项目级别的后置处理器 */
export type ProjectPostProcessor = (
result: ResultDir,
- schema: ProjectSchema,
- originalSchema: ProjectSchema | string,
+ schema: IPublicTypeProjectSchema,
+ originalSchema: IPublicTypeProjectSchema | string,
+ options: ProjectPostProcessorOptions,
) => Promise | ResultDir;
/** 模块级别的后置处理器的工厂方法 */
@@ -198,20 +216,20 @@ type CompositeTypeGenerator =
| BaseGenerator
| Array>;
-export type NodeGenerator = (nodeItem: NodeDataType, scope: IScope) => T;
+export type NodeGenerator = (nodeItem: IPublicTypeNodeDataType, scope: IScope) => T;
// FIXME: 在新的实现中,添加了第一参数 this: CustomHandlerSet 作为上下文。究其本质
// scopeBindings?: IScopeBindings;
-// 这个组合只用来用来处理 CompositeValue 类型,不是这个类型的不要放在这里
+// 这个组合只用来用来处理 IPublicTypeCompositeValue 类型,不是这个类型的不要放在这里
export interface HandlerSet {
string?: CompositeTypeGenerator;
boolean?: CompositeTypeGenerator;
number?: CompositeTypeGenerator;
- expression?: CompositeTypeGenerator;
- function?: CompositeTypeGenerator;
- slot?: CompositeTypeGenerator;
- array?: CompositeTypeGenerator;
- object?: CompositeTypeGenerator;
+ expression?: CompositeTypeGenerator;
+ function?: CompositeTypeGenerator;
+ slot?: CompositeTypeGenerator;
+ array?: CompositeTypeGenerator;
+ object?: CompositeTypeGenerator;
}
export interface CompositeValueGeneratorOptions {
diff --git a/modules/code-generator/src/types/intermediate.ts b/modules/code-generator/src/types/intermediate.ts
index 43d8f0e84..30d6c4f7f 100644
--- a/modules/code-generator/src/types/intermediate.ts
+++ b/modules/code-generator/src/types/intermediate.ts
@@ -1,4 +1,9 @@
-import { I18nMap, UtilsMap, ContainerSchema, JSONObject } from '@alilc/lowcode-types';
+import {
+ IPublicTypeI18nMap,
+ IPublicTypeUtilsMap,
+ IPublicTypeContainerSchema,
+ IPublicTypeJSONObject,
+} from '@alilc/lowcode-types';
import { IDependency, INpmPackage } from './deps';
import { ICompAnalyzeResult } from './analyze';
@@ -6,7 +11,7 @@ import { ICompAnalyzeResult } from './analyze';
export interface IParseResult {
containers: IContainerInfo[];
globalUtils?: IUtilInfo;
- globalI18n?: I18nMap;
+ globalI18n?: IPublicTypeI18nMap;
globalRouter?: IRouterInfo;
project?: IProjectInfo;
}
@@ -15,14 +20,14 @@ export interface IWithDependency {
deps?: IDependency[];
}
-export interface IContainerInfo extends ContainerSchema, IWithDependency {
+export interface IContainerInfo extends IPublicTypeContainerSchema, IWithDependency {
containerType: string;
moduleName: string;
analyzeResult?: ICompAnalyzeResult;
}
export interface IUtilInfo extends IWithDependency {
- utils: UtilsMap;
+ utils: IPublicTypeUtilsMap;
}
export interface IRouterInfo extends IWithDependency {
@@ -33,16 +38,25 @@ export interface IRouterInfo extends IWithDependency {
}>;
}
+/**
+ * project's remarks
+ */
+export interface ProjectRemark {
+ /** if current project only contain one container which type is `Component` */
+ isSingleComponent?: boolean;
+}
+
export interface IProjectInfo {
css?: string;
containersDeps?: IDependency[];
utilsDeps?: IDependency[];
- constants?: JSONObject;
- i18n?: I18nMap;
+ constants?: IPublicTypeJSONObject;
+ i18n?: IPublicTypeI18nMap;
packages: INpmPackage[];
meta?: { name?: string; title?: string } | Record;
config?: Record;
dataSourcesTypes?: string[];
+ projectRemark?: ProjectRemark;
}
export interface IPageMeta {
diff --git a/modules/code-generator/src/types/jsx.ts b/modules/code-generator/src/types/jsx.ts
index c79f1d207..28f948d63 100644
--- a/modules/code-generator/src/types/jsx.ts
+++ b/modules/code-generator/src/types/jsx.ts
@@ -1,4 +1,4 @@
-import { NodeSchema, CompositeValue } from '@alilc/lowcode-types';
+import { IPublicTypeNodeSchema, IPublicTypeCompositeValue } from '@alilc/lowcode-types';
import { HandlerSet, BaseGenerator, NodeGenerator } from './core';
export enum PIECE_TYPE {
@@ -17,11 +17,11 @@ export interface CodePiece {
export interface AttrData {
attrName: string;
- attrValue: CompositeValue;
+ attrValue: IPublicTypeCompositeValue;
}
-// 对 JSX 出码的理解,目前定制点包含 【包装】【标签名】【属性】
+// 对 JSX 出码的理解,目前定制点包含【包装】【标签名】【属性】
export type AttrPlugin = BaseGenerator;
-export type NodePlugin = BaseGenerator;
+export type NodePlugin = BaseGenerator;
export interface NodeGeneratorConfig {
handlers?: HandlerSet;
@@ -33,7 +33,7 @@ export interface NodeGeneratorConfig {
/**
* 是否要容忍对 JSExpression 求值时的异常
* 默认:true
- * 注: 如果容忍异常,则会在求值时包裹 try-catch 块 -- 通过 __$$eval / __$$evalArray
+ * 注:如果容忍异常,则会在求值时包裹 try-catch 块 -- 通过 __$$eval / __$$evalArray
* catch 到异常时默认会抛出一个 CustomEvent 事件里面包含异常信息和求值的表达式
*/
tolerateEvalErrors?: boolean;
diff --git a/modules/code-generator/src/utils/compositeType.ts b/modules/code-generator/src/utils/compositeType.ts
index b66e1279c..2e09e2da0 100644
--- a/modules/code-generator/src/utils/compositeType.ts
+++ b/modules/code-generator/src/utils/compositeType.ts
@@ -1,13 +1,13 @@
import {
- CompositeArray,
- CompositeValue,
- CompositeObject,
- JSFunction,
- JSExpression,
+ IPublicTypeCompositeArray,
+ IPublicTypeCompositeValue,
+ IPublicTypeCompositeObject,
+ IPublicTypeJSFunction,
+ IPublicTypeJSExpression,
isJSExpression,
isJSFunction,
isJSSlot,
- JSSlot,
+ IPublicTypeJSSlot,
} from '@alilc/lowcode-types';
import _ from 'lodash';
@@ -43,7 +43,7 @@ function isDataSource(v: unknown): v is DataSource {
}
function generateArray(
- value: CompositeArray,
+ value: IPublicTypeCompositeArray,
scope: IScope,
options: CompositeValueGeneratorOptions = {},
): string {
@@ -52,7 +52,7 @@ function generateArray(
}
function generateObject(
- value: CompositeObject,
+ value: IPublicTypeCompositeObject,
scope: IScope,
options: CompositeValueGeneratorOptions = {},
): string {
@@ -88,7 +88,7 @@ function generateBool(value: boolean): string {
return value ? 'true' : 'false';
}
-function genFunction(value: JSFunction): string {
+function genFunction(value: IPublicTypeJSFunction): string {
const globalVars = parseExpressionGetKeywords(value.value);
if (globalVars.includes('arguments')) {
@@ -98,7 +98,7 @@ function genFunction(value: JSFunction): string {
return generateFunction(value, { isArrow: true });
}
-function genJsSlot(value: JSSlot, scope: IScope, options: CompositeValueGeneratorOptions = {}) {
+function genJsSlot(value: IPublicTypeJSSlot, scope: IScope, options: CompositeValueGeneratorOptions = {}) {
if (options.nodeGenerator) {
return generateJsSlot(value, scope, options.nodeGenerator);
}
@@ -106,7 +106,7 @@ function genJsSlot(value: JSSlot, scope: IScope, options: CompositeValueGenerato
}
function generateUnknownType(
- value: CompositeValue,
+ value: IPublicTypeCompositeValue,
scope: IScope,
options: CompositeValueGeneratorOptions = {},
): string {
@@ -128,7 +128,7 @@ function generateUnknownType(
// FIXME: 这个是临时方案
// 在遇到 type variable 私有类型时,转换为 JSExpression
if (isVariable(value)) {
- const transValue: JSExpression = {
+ const transValue: IPublicTypeJSExpression = {
type: 'JSExpression',
value: value.variable,
};
@@ -188,7 +188,7 @@ function generateUnknownType(
if (options.handlers?.object) {
return executeFunctionStack(value, scope, options.handlers.object, generateObject, options);
}
- return generateObject(value as CompositeObject, scope, options);
+ return generateObject(value as IPublicTypeCompositeObject, scope, options);
}
if (_.isString(value)) {
@@ -218,7 +218,7 @@ function generateUnknownType(
// 这一层曾经是对产出做最外层包装的,但其实包装逻辑不应该属于这一层
// 这一层先不去掉,做冗余,方便后续重构
export function generateCompositeType(
- value: CompositeValue,
+ value: IPublicTypeCompositeValue,
scope: IScope,
options: CompositeValueGeneratorOptions = {},
): string {
diff --git a/modules/code-generator/src/utils/dataSource.ts b/modules/code-generator/src/utils/dataSource.ts
index 610f39934..cd1035162 100644
--- a/modules/code-generator/src/utils/dataSource.ts
+++ b/modules/code-generator/src/utils/dataSource.ts
@@ -1,7 +1,7 @@
import changeCase from 'change-case';
import type { IProjectInfo } from '../types/intermediate';
-export type DataSourceDependenciesConfig = {
+export interface DataSourceDependenciesConfig {
/** 数据源引擎的版本 */
engineVersion?: string;
/** 数据源引擎的包名 */
@@ -14,7 +14,7 @@ export type DataSourceDependenciesConfig = {
handlersPackages?: {
[key: string]: string;
};
-};
+}
export function buildDataSourceDependencies(
ir: IProjectInfo,
@@ -22,13 +22,13 @@ export function buildDataSourceDependencies(
): Record {
return {
// 数据源引擎的依赖包
- [cfg.enginePackage || '@alilc/lowcode-datasource-engine']: cfg.engineVersion || 'latest',
+ [cfg.enginePackage || '@alilc/lowcode-datasource-engine']: cfg.engineVersion || '^1.0.0',
// 各种数据源的 handlers 的依赖包
...(ir.dataSourcesTypes || []).reduce(
(acc, dsType) => ({
...acc,
- [getDataSourceHandlerPackageName(dsType)]: cfg.handlersVersion?.[dsType] || 'latest',
+ [getDataSourceHandlerPackageName(dsType)]: cfg.handlersVersion?.[dsType] || '^1.0.0',
}),
{},
),
diff --git a/modules/code-generator/src/utils/index.ts b/modules/code-generator/src/utils/index.ts
index ff5194172..cac63d415 100644
--- a/modules/code-generator/src/utils/index.ts
+++ b/modules/code-generator/src/utils/index.ts
@@ -11,6 +11,7 @@ import * as schema from './schema';
import * as version from './version';
import * as scope from './Scope';
import * as expressionParser from './expressionParser';
+import * as dataSource from './dataSource';
export {
common,
@@ -25,4 +26,5 @@ export {
version,
scope,
expressionParser,
+ dataSource,
};
diff --git a/modules/code-generator/src/utils/jsExpression.ts b/modules/code-generator/src/utils/jsExpression.ts
index d6dc8c027..1162d0820 100644
--- a/modules/code-generator/src/utils/jsExpression.ts
+++ b/modules/code-generator/src/utils/jsExpression.ts
@@ -2,7 +2,7 @@ import * as parser from '@babel/parser';
import generate from '@babel/generator';
import traverse from '@babel/traverse';
import * as t from '@babel/types';
-import { JSExpression, JSFunction, isJSExpression, isJSFunction } from '@alilc/lowcode-types';
+import { IPublicTypeJSExpression, IPublicTypeJSFunction, isJSExpression, isJSFunction } from '@alilc/lowcode-types';
import { CodeGeneratorError, IScope } from '../types';
import { transformExpressionLocalRef, ParseError } from './expressionParser';
@@ -84,7 +84,7 @@ export function isJsCode(value: unknown): boolean {
export function generateExpression(value: any, scope: IScope): string {
if (isJSExpression(value)) {
- const exprVal = (value as JSExpression).value.trim();
+ const exprVal = (value as IPublicTypeJSExpression).value.trim();
if (!exprVal) {
return 'null';
}
@@ -113,7 +113,7 @@ export function generateFunction(
},
) {
if (isJsCode(value)) {
- const functionCfg = value as JSFunction;
+ const functionCfg = value as IPublicTypeJSFunction;
if (config.isMember) {
return transformFuncExpr2MethodMember(config.name || '', functionCfg.value);
}
diff --git a/modules/code-generator/src/utils/jsSlot.ts b/modules/code-generator/src/utils/jsSlot.ts
index 49f7b3170..265f6857f 100644
--- a/modules/code-generator/src/utils/jsSlot.ts
+++ b/modules/code-generator/src/utils/jsSlot.ts
@@ -1,4 +1,4 @@
-import { JSSlot, isJSSlot, NodeData } from '@alilc/lowcode-types';
+import { IPublicTypeJSSlot, isJSSlot, IPublicTypeNodeData } from '@alilc/lowcode-types';
import { CodeGeneratorError, NodeGenerator, IScope } from '../types';
import { unwrapJsExprQuoteInJsx } from './jsxHelpers';
@@ -8,7 +8,7 @@ function generateSingleLineComment(commentText: string): string {
export function generateJsSlot(slot: any, scope: IScope, generator: NodeGenerator): string {
if (isJSSlot(slot)) {
- const { title, params, value } = slot as JSSlot;
+ const { title, params, value } = slot as IPublicTypeJSSlot;
// slot 也是分有参数和无参数的
// - 有参数的 slot 就是类似一个 render 函数,需要创建子作用域
@@ -39,7 +39,7 @@ export function generateJsSlot(slot: any, scope: IScope, generator: NodeGenerato
}
function generateNodeDataOrArrayForJsSlot(
- value: NodeData | NodeData[],
+ value: IPublicTypeNodeData | IPublicTypeNodeData[],
generator: NodeGenerator,
scope: IScope,
) {
diff --git a/modules/code-generator/src/utils/nodeToJSX.ts b/modules/code-generator/src/utils/nodeToJSX.ts
index 0b5919902..73dba862c 100644
--- a/modules/code-generator/src/utils/nodeToJSX.ts
+++ b/modules/code-generator/src/utils/nodeToJSX.ts
@@ -1,6 +1,6 @@
import _ from 'lodash';
import { pipe } from 'fp-ts/function';
-import { NodeSchema, isNodeSchema, NodeDataType, CompositeValue } from '@alilc/lowcode-types';
+import { IPublicTypeNodeSchema, isNodeSchema, IPublicTypeNodeDataType, IPublicTypeCompositeValue } from '@alilc/lowcode-types';
import {
IScope,
@@ -57,7 +57,7 @@ export function isPureString(v: string) {
}
function generateAttrValue(
- attrData: { attrName: string; attrValue: CompositeValue },
+ attrData: { attrName: string; attrValue: IPublicTypeCompositeValue },
scope: IScope,
config?: NodeGeneratorConfig,
): CodePiece[] {
@@ -76,7 +76,7 @@ function generateAttrValue(
function generateAttr(
attrName: string,
- attrValue: CompositeValue,
+ attrValue: IPublicTypeCompositeValue,
scope: IScope,
config?: NodeGeneratorConfig,
): CodePiece[] {
@@ -115,7 +115,7 @@ function generateAttr(
}
function generateAttrs(
- nodeItem: NodeSchema,
+ nodeItem: IPublicTypeNodeSchema,
scope: IScope,
config?: NodeGeneratorConfig,
): CodePiece[] {
@@ -144,7 +144,7 @@ function generateAttrs(
}
function generateBasicNode(
- nodeItem: NodeSchema,
+ nodeItem: IPublicTypeNodeSchema,
scope: IScope,
config?: NodeGeneratorConfig,
): CodePiece[] {
@@ -160,7 +160,7 @@ function generateBasicNode(
}
function generateSimpleNode(
- nodeItem: NodeSchema,
+ nodeItem: IPublicTypeNodeSchema,
scope: IScope,
config?: NodeGeneratorConfig,
): CodePiece[] {
@@ -182,7 +182,7 @@ function generateSimpleNode(
function linkPieces(pieces: CodePiece[]): string {
const tagsPieces = pieces.filter((p) => p.type === PIECE_TYPE.TAG);
if (tagsPieces.length !== 1) {
- throw new CodeGeneratorError('One node only need one tag define');
+ throw new CodeGeneratorError('Only one tag definition required', tagsPieces);
}
const tagName = tagsPieces[0].value;
@@ -216,13 +216,13 @@ function linkPieces(pieces: CodePiece[]): string {
}
function generateNodeSchema(
- nodeItem: NodeSchema,
+ nodeItem: IPublicTypeNodeSchema,
scope: IScope,
config?: NodeGeneratorConfig,
): string {
const pieces: CodePiece[] = [];
if (config?.nodePlugins) {
- const res = executeFunctionStack(
+ const res = executeFunctionStack(
nodeItem,
scope,
config.nodePlugins,
@@ -247,11 +247,11 @@ function generateNodeSchema(
* @type NodePlugin Extended
*
* @export
- * @param {NodeSchema} nodeItem 当前 UI 节点
+ * @param {IPublicTypeNodeSchema} nodeItem 当前 UI 节点
* @returns {CodePiece[]} 实现功能的相关代码片段
*/
export function generateReactLoopCtrl(
- nodeItem: NodeSchema,
+ nodeItem: IPublicTypeNodeSchema,
scope: IScope,
config?: NodeGeneratorConfig,
next?: NodePlugin,
@@ -270,8 +270,7 @@ export function generateReactLoopCtrl(
const loopDataExpr = pipe(
nodeItem.loop,
// 将 JSExpression 转换为 JS 表达式代码:
- (expr) =>
- generateCompositeType(expr, scope, {
+ (expr) => generateCompositeType(expr, scope, {
handlers: config?.handlers,
tolerateEvalErrors: false, // 这个内部不需要包 try catch, 下面会统一加的
}),
@@ -302,11 +301,11 @@ export function generateReactLoopCtrl(
* @type NodePlugin
*
* @export
- * @param {NodeSchema} nodeItem 当前 UI 节点
+ * @param {IPublicTypeNodeSchema} nodeItem 当前 UI 节点
* @returns {CodePiece[]} 实现功能的相关代码片段
*/
export function generateConditionReactCtrl(
- nodeItem: NodeSchema,
+ nodeItem: IPublicTypeNodeSchema,
scope: IScope,
config?: NodeGeneratorConfig,
next?: NodePlugin,
@@ -337,11 +336,11 @@ export function generateConditionReactCtrl(
* @type NodePlugin
*
* @export
- * @param {NodeSchema} nodeItem 当前 UI 节点
+ * @param {IPublicTypeNodeSchema} nodeItem 当前 UI 节点
* @returns {CodePiece[]} 实现功能的相关代码片段
*/
export function generateReactExprInJS(
- nodeItem: NodeSchema,
+ nodeItem: IPublicTypeNodeSchema,
scope: IScope,
config?: NodeGeneratorConfig,
next?: NodePlugin,
@@ -366,7 +365,7 @@ export function generateReactExprInJS(
const handleChildren = (v: string[]) => v.join('');
export function createNodeGenerator(cfg: NodeGeneratorConfig = {}): NodeGenerator {
- const generateNode = (nodeItem: NodeDataType, scope: IScope): string => {
+ const generateNode = (nodeItem: IPublicTypeNodeDataType, scope: IScope): string => {
if (_.isArray(nodeItem)) {
const resList = nodeItem.map((n) => generateNode(n, scope));
return handleChildren(resList);
@@ -391,8 +390,7 @@ export function createNodeGenerator(cfg: NodeGeneratorConfig = {}): NodeGenerato
return `{${valueStr}}`;
};
- return (nodeItem: NodeDataType, scope: IScope) =>
- unwrapJsExprQuoteInJsx(generateNode(nodeItem, scope));
+ return (nodeItem: IPublicTypeNodeDataType, scope: IScope) => unwrapJsExprQuoteInJsx(generateNode(nodeItem, scope));
}
const defaultReactGeneratorConfig: NodeGeneratorConfig = {
diff --git a/modules/code-generator/src/utils/schema.ts b/modules/code-generator/src/utils/schema.ts
index b2faecbc6..509977277 100644
--- a/modules/code-generator/src/utils/schema.ts
+++ b/modules/code-generator/src/utils/schema.ts
@@ -1,20 +1,20 @@
import * as _ from 'lodash';
import {
- JSExpression,
- NodeData,
- NodeSchema,
+ IPublicTypeJSExpression,
+ IPublicTypeNodeData,
+ IPublicTypeNodeSchema,
isJSExpression,
isJSSlot,
isDOMText,
- ContainerSchema,
- NpmInfo,
- CompositeValue,
+ IPublicTypeContainerSchema,
+ IPublicTypeNpmInfo,
+ IPublicTypeCompositeValue,
isNodeSchema,
isJSFunction,
} from '@alilc/lowcode-types';
import { CodeGeneratorError } from '../types/error';
-export function isContainerSchema(x: any): x is ContainerSchema {
+export function isContainerSchema(x: any): x is IPublicTypeContainerSchema {
return (
typeof x === 'object' &&
x &&
@@ -23,7 +23,7 @@ export function isContainerSchema(x: any): x is ContainerSchema {
);
}
-export function isNpmInfo(x: any): x is NpmInfo {
+export function isNpmInfo(x: any): x is IPublicTypeNpmInfo {
return typeof x === 'object' && x && typeof x.package === 'string';
}
@@ -43,11 +43,11 @@ const DEFAULT_MAX_DEPTH = 100000;
* @returns
*/
export function handleSubNodes(
- children: NodeSchema['children'],
+ children: IPublicTypeNodeSchema['children'],
handlers: {
string?: (i: string) => T;
- expression?: (i: JSExpression) => T;
- node?: (i: NodeSchema) => T;
+ expression?: (i: IPublicTypeJSExpression) => T;
+ node?: (i: IPublicTypeNodeSchema) => T;
},
options?: {
rerun?: boolean;
@@ -64,7 +64,7 @@ export function handleSubNodes(
}
if (Array.isArray(children)) {
- const list: NodeData[] = children as NodeData[];
+ const list: IPublicTypeNodeData[] = children as IPublicTypeNodeData[];
return list
.map((child) => handleSubNodes(child, handlers, { ...opt, maxDepth: maxDepth - 1 }))
.reduce((p, c) => p.concat(c), []);
@@ -84,7 +84,7 @@ export function handleSubNodes(
return handleSubNodes(children.value, handlers, { ...opt, maxDepth: maxDepth - 1 });
} else if (isNodeSchema(children)) {
const handler = handlers.node || noop;
- const child = children as NodeSchema;
+ const child = children as IPublicTypeNodeSchema;
result = handler(child);
if (child.children) {
@@ -115,7 +115,7 @@ export function handleSubNodes(
return childrenRes;
- function handleCompositeValueInProps(value: CompositeValue): T[] {
+ function handleCompositeValueInProps(value: IPublicTypeCompositeValue): T[] {
if (isJSSlot(value)) {
return handleSubNodes(value.value, handlers, { ...opt, maxDepth: maxDepth - 1 });
}
@@ -125,7 +125,7 @@ export function handleSubNodes(
return _.flatMap(value, (v) => handleCompositeValueInProps(v));
}
- // CompositeObject
+ // IPublicTypeCompositeObject
if (
!isJSExpression(value) &&
!isJSFunction(value) &&
@@ -138,3 +138,11 @@ export function handleSubNodes(
return [];
}
}
+
+export function isValidContainerType(schema: IPublicTypeNodeSchema) {
+ return [
+ 'Page',
+ 'Component',
+ 'Block',
+ ].includes(schema.componentName);
+}
\ No newline at end of file
diff --git a/modules/code-generator/tests/bugfix/i18n-with-params.test.ts b/modules/code-generator/tests/bugfix/i18n-with-params.test.ts
index be2d5e9e6..b58afda8c 100644
--- a/modules/code-generator/tests/bugfix/i18n-with-params.test.ts
+++ b/modules/code-generator/tests/bugfix/i18n-with-params.test.ts
@@ -1,7 +1,7 @@
import CodeGenerator from '../../src';
import * as fs from 'fs';
import * as path from 'path';
-import { ProjectSchema } from '@alilc/lowcode-types';
+import { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
import { createDiskPublisher } from '../helpers/solutionHelper';
const testCaseBaseName = path.basename(__filename, '.test.ts');
@@ -19,7 +19,7 @@ describe(testCaseBaseName, () => {
`
@@ -31,7 +31,7 @@ describe(testCaseBaseName, () => {
function exportProject(
importPath: string,
outputPath: string,
- mergeSchema?: Partial,
+ mergeSchema?: Partial,
) {
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
const schema = { ...JSON.parse(schemaJsonStr), ...mergeSchema };
diff --git a/modules/code-generator/tests/bugfix/icejs-import-wrong-naming.test.ts b/modules/code-generator/tests/bugfix/icejs-import-wrong-naming.test.ts
index 51e22b3a9..efb7fd5be 100644
--- a/modules/code-generator/tests/bugfix/icejs-import-wrong-naming.test.ts
+++ b/modules/code-generator/tests/bugfix/icejs-import-wrong-naming.test.ts
@@ -1,7 +1,7 @@
import CodeGenerator from '../../src';
import * as fs from 'fs';
import * as path from 'path';
-import { ProjectSchema } from '@alilc/lowcode-types';
+import { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
import { createDiskPublisher } from '../helpers/solutionHelper';
const testCaseBaseName = path.basename(__filename, '.test.ts');
@@ -27,7 +27,7 @@ describe(testCaseBaseName, () => {
});
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
- expect(generatedPageFileContent).toContain(`import Foo from "example-package/lib/index.js";`);
+ expect(generatedPageFileContent).toContain('import Foo from \'example-package/lib/index.js\';');
});
test('named import with no alias', async () => {
@@ -47,7 +47,7 @@ describe(testCaseBaseName, () => {
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
expect(generatedPageFileContent).toContain(
- `import { Foo } from "example-package/lib/index.js";`,
+ 'import { Foo } from \'example-package/lib/index.js\';',
);
});
@@ -68,7 +68,7 @@ describe(testCaseBaseName, () => {
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
expect(generatedPageFileContent).toContain(
- `import { Bar as Foo } from "example-package/lib/index.js";`,
+ 'import { Bar as Foo } from \'example-package/lib/index.js\';',
);
});
@@ -88,7 +88,7 @@ describe(testCaseBaseName, () => {
});
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
- expect(generatedPageFileContent).toContain(`import Foo from "example-package/lib/index.js";`);
+ expect(generatedPageFileContent).toContain('import Foo from \'example-package/lib/index.js\';');
});
test('default import with sub name and export name', async () => {
@@ -107,9 +107,9 @@ describe(testCaseBaseName, () => {
});
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
- expect(generatedPageFileContent).toContain(`import Bar from "example-package/lib/index.js";`);
+ expect(generatedPageFileContent).toContain('import Bar from \'example-package/lib/index.js\';');
- expect(generatedPageFileContent).toContain(`const Foo = Bar.Baz;`);
+ expect(generatedPageFileContent).toContain('const Foo = Bar.Baz;');
});
test('default import with sub name without export name', async () => {
@@ -129,10 +129,10 @@ describe(testCaseBaseName, () => {
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
expect(generatedPageFileContent).toContain(
- `import __$examplePackage_default from "example-package/lib/index.js";`,
+ 'import __$examplePackage_default from \'example-package/lib/index.js\';',
);
- expect(generatedPageFileContent).toContain(`const Foo = __$examplePackage_default.Baz;`);
+ expect(generatedPageFileContent).toContain('const Foo = __$examplePackage_default.Baz;');
});
test('named import with sub name', async () => {
@@ -152,10 +152,10 @@ describe(testCaseBaseName, () => {
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
expect(generatedPageFileContent).toContain(
- `import { Bar } from "example-package/lib/index.js";`,
+ 'import { Bar } from \'example-package/lib/index.js\';',
);
- expect(generatedPageFileContent).toContain(`const Foo = Bar.Baz;`);
+ expect(generatedPageFileContent).toContain('const Foo = Bar.Baz;');
});
test('default imports with different componentName', async () => {
@@ -187,18 +187,18 @@ describe(testCaseBaseName, () => {
});
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
- expect(generatedPageFileContent).toContain(`import Foo from "example-package";`);
- expect(generatedPageFileContent).toContain(`import Baz from "example-package";`);
+ expect(generatedPageFileContent).toContain('import Foo from \'example-package\';');
+ expect(generatedPageFileContent).toContain('import Baz from \'example-package\';');
- expect(generatedPageFileContent).not.toContain(`const Foo =`);
- expect(generatedPageFileContent).not.toContain(`const Baz =`);
+ expect(generatedPageFileContent).not.toContain('const Foo =');
+ expect(generatedPageFileContent).not.toContain('const Baz =');
});
});
function exportProject(
importPath: string,
outputPath: string,
- mergeSchema?: Partial,
+ mergeSchema?: Partial,
) {
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
const schema = { ...JSON.parse(schemaJsonStr), ...mergeSchema };
diff --git a/modules/code-generator/tests/bugfix/icejs-missing-imports-1.test.ts b/modules/code-generator/tests/bugfix/icejs-missing-imports-1.test.ts
index 17c40a4fa..cad73474a 100644
--- a/modules/code-generator/tests/bugfix/icejs-missing-imports-1.test.ts
+++ b/modules/code-generator/tests/bugfix/icejs-missing-imports-1.test.ts
@@ -22,7 +22,7 @@ test(testCaseBaseName, async () => {
Button,
Typography,
Tag,
-} from "@alilc/antd-lowcode-materials/dist/antd-lowcode.esm.js";`);
+} from '@alilc/antd-lowcode-materials/dist/antd-lowcode.esm.js';`);
});
function exportProject(inputPath: string, outputPath: string) {
diff --git a/modules/code-generator/tests/bugfix/icejs-package-json-dependencies.test.ts b/modules/code-generator/tests/bugfix/icejs-package-json-dependencies.test.ts
index 6edd6b912..88ca02c6b 100644
--- a/modules/code-generator/tests/bugfix/icejs-package-json-dependencies.test.ts
+++ b/modules/code-generator/tests/bugfix/icejs-package-json-dependencies.test.ts
@@ -19,15 +19,15 @@ test(testCaseBaseName, async () => {
// 里面有的数据源则应该生成对应的 dependencies
expect(generatedPackageJson.dependencies).toMatchObject({
- '@alilc/lowcode-datasource-engine': 'latest',
- '@alilc/lowcode-datasource-fetch-handler': 'latest',
+ '@alilc/lowcode-datasource-engine': '^1.0.0',
+ '@alilc/lowcode-datasource-fetch-handler': '^1.0.0',
});
// 里面没有的,则不应该生成对应的 dependencies
expect(generatedPackageJson.dependencies).not.toMatchObject({
- '@alilc/lowcode-datasource-url-params-handler': 'latest',
- '@alilc/lowcode-datasource-mtop-handler': 'latest',
- '@alilc/lowcode-datasource-mopen-handler': 'latest',
+ '@alilc/lowcode-datasource-url-params-handler': '^1.0.0',
+ '@alilc/lowcode-datasource-mtop-handler': '^1.0.0',
+ '@alilc/lowcode-datasource-mopen-handler': '^1.0.0',
});
});
diff --git a/modules/code-generator/tests/bugfix/strict-mode-context-1.test.ts b/modules/code-generator/tests/bugfix/strict-mode-context-1.test.ts
index 9cfb09325..ebca6a26f 100644
--- a/modules/code-generator/tests/bugfix/strict-mode-context-1.test.ts
+++ b/modules/code-generator/tests/bugfix/strict-mode-context-1.test.ts
@@ -1,7 +1,7 @@
import CodeGenerator from '../../src';
import * as fs from 'fs';
import * as path from 'path';
-import { ProjectSchema } from '@alilc/lowcode-types';
+import { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
import { createDiskPublisher } from '../helpers/solutionHelper';
import { IceJsProjectBuilderOptions } from '../../src/solutions/icejs';
@@ -33,7 +33,7 @@ describe(testCaseBaseName, () => {
function exportProject(
importPath: string,
outputPath: string,
- mergeSchema?: Partial,
+ mergeSchema?: Partial,
options?: IceJsProjectBuilderOptions,
) {
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
diff --git a/modules/code-generator/tests/bugfix/tolerate-eval-errors-1-loop.test.ts b/modules/code-generator/tests/bugfix/tolerate-eval-errors-1-loop.test.ts
index 11ba9de05..78f2b50b3 100644
--- a/modules/code-generator/tests/bugfix/tolerate-eval-errors-1-loop.test.ts
+++ b/modules/code-generator/tests/bugfix/tolerate-eval-errors-1-loop.test.ts
@@ -1,7 +1,7 @@
import CodeGenerator from '../../src';
import * as fs from 'fs';
import * as path from 'path';
-import { ProjectSchema } from '@alilc/lowcode-types';
+import { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
import { createDiskPublisher } from '../helpers/solutionHelper';
import { IceJsProjectBuilderOptions } from '../../src/solutions/icejs';
@@ -28,7 +28,7 @@ test('loop should be generated link __$$evalArray(xxx).map', async () => {
function exportProject(
importPath: string,
outputPath: string,
- mergeSchema?: Partial,
+ mergeSchema?: Partial,
options?: IceJsProjectBuilderOptions,
) {
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
diff --git a/modules/code-generator/tests/bugfix/tolerate-eval-errors-2-nested-loop.test.ts b/modules/code-generator/tests/bugfix/tolerate-eval-errors-2-nested-loop.test.ts
index e8b65a544..184200593 100644
--- a/modules/code-generator/tests/bugfix/tolerate-eval-errors-2-nested-loop.test.ts
+++ b/modules/code-generator/tests/bugfix/tolerate-eval-errors-2-nested-loop.test.ts
@@ -1,7 +1,7 @@
import CodeGenerator from '../../src';
import * as fs from 'fs';
import * as path from 'path';
-import { ProjectSchema } from '@alilc/lowcode-types';
+import { IPublicTypeProjectSchema } from '@alilc/lowcode-types';
import { createDiskPublisher } from '../helpers/solutionHelper';
import { IceJsProjectBuilderOptions } from '../../src/solutions/icejs';
@@ -32,7 +32,7 @@ test('loop should be generated link __$$evalArray(xxx).map', async () => {
function exportProject(
importPath: string,
outputPath: string,
- mergeSchema?: Partial,
+ mergeSchema?: Partial,
options?: IceJsProjectBuilderOptions,
) {
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/package.json
index 38cfdd186..fd03ed9bc 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo01/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/package.json
index ca5a0f59c..4d9a77988 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/package.json
@@ -11,9 +11,9 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
- "@alilc/lowcode-datasource-url-params-handler": "latest",
- "@alilc/lowcode-datasource-fetch-handler": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
+ "@alilc/lowcode-datasource-url-params-handler": "^1.0.0",
+ "@alilc/lowcode-datasource-fetch-handler": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/pages/Home/index.jsx b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/pages/Home/index.jsx
index 06e39454d..7bfda59ca 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/pages/Home/index.jsx
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo02/expected/demo-project/src/pages/Home/index.jsx
@@ -253,6 +253,7 @@ class Home$$Page extends Component {
if (!response.success) {
throw new Error(response.message);
}
+
return response.data;
},
isInit: true,
@@ -279,6 +280,7 @@ class Home$$Page extends Component {
if (!response.success) {
throw new Error(response.message);
}
+
return response.data.result;
},
isInit: true,
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/package.json
index 48690ff4d..58b97921b 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo03/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/package.json
index 16fa70bbc..56dda7653 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo04/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/package.json
index 38cfdd186..fd03ed9bc 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo05/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/package.json
index bf31a967e..dc00ba429 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo06-jsslot/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/package.json
index 38cfdd186..fd03ed9bc 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo07-newline-in-props/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/package.json
index bf31a967e..dc00ba429 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo08-jsslot-with-multiple-children/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/package.json
index bf31a967e..dc00ba429 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo09-jsslot-with-conditional-children/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/package.json
index bf31a967e..dc00ba429 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo10-jsslot-with-loop-children/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/package.json
index 60f0cb38a..067cc161d 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo11-utils-name-alias/expected/demo-project/package.json
@@ -11,8 +11,8 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
- "@alilc/lowcode-datasource-url-params-handler": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
+ "@alilc/lowcode-datasource-url-params-handler": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/package.json
index 38cfdd186..fd03ed9bc 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo12-refs/expected/demo-project/package.json
@@ -11,7 +11,7 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/package.json
index 3e59d2984..afadad878 100644
--- a/modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/rax-app/demo13-datasource-prop/expected/demo-project/package.json
@@ -11,8 +11,8 @@
"lint": "npm run eslint && npm run stylelint"
},
"dependencies": {
- "@alilc/lowcode-datasource-engine": "latest",
- "@alilc/lowcode-datasource-http-handler": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
+ "@alilc/lowcode-datasource-http-handler": "^1.0.0",
"universal-env": "^3.2.0",
"intl-messageformat": "^9.3.6",
"rax": "^1.1.0",
diff --git a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/package.json b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/package.json
index 767ec3898..36eaf12f2 100644
--- a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/package.json
+++ b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/package.json
@@ -11,9 +11,9 @@
"intl-messageformat": "^9.3.6",
"@ice/store": "^1.4.3",
"@loadable/component": "^5.15.2",
- "@alilc/lowcode-datasource-engine": "latest",
- "@alilc/lowcode-datasource-url-params-handler": "latest",
- "@alilc/lowcode-datasource-fetch-handler": "latest",
+ "@alilc/lowcode-datasource-engine": "^1.0.0",
+ "@alilc/lowcode-datasource-url-params-handler": "^1.0.0",
+ "@alilc/lowcode-datasource-fetch-handler": "^1.0.0",
"@alifd/next": "1.19.18"
},
"devDependencies": {
diff --git a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/app.js b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/app.js
index fb01b106b..266d8ef71 100644
--- a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/app.js
+++ b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/app.js
@@ -1,11 +1,11 @@
-import { createApp } from "ice";
+import { createApp } from 'ice';
const appConfig = {
app: {
- rootId: "app",
+ rootId: 'app',
},
router: {
- type: "hash",
+ type: 'hash',
},
};
createApp(appConfig);
diff --git a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/constants.js b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/constants.js
index c4a5859ee..91198f904 100644
--- a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/constants.js
+++ b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/constants.js
@@ -1,3 +1,3 @@
-const __$$constants = { ENV: "prod", DOMAIN: "xxx.xxx.com" };
+const __$$constants = { ENV: 'prod', DOMAIN: 'xxx.xxx.com' };
export default __$$constants;
diff --git a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/global.scss b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/global.scss
index 2d97c56b0..ed7204b4a 100644
--- a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/global.scss
+++ b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/global.scss
@@ -1,5 +1,5 @@
// 引入默认全局样式
-@import "@alifd/next/reset.scss";
+@import '@alifd/next/reset.scss';
body {
-webkit-font-smoothing: antialiased;
diff --git a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/i18n.js b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/i18n.js
index 1ae7c84b5..adbbe673d 100644
--- a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/i18n.js
+++ b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/i18n.js
@@ -1,9 +1,9 @@
const i18nConfig = {};
let locale =
- typeof navigator === "object" && typeof navigator.language === "string"
+ typeof navigator === 'object' && typeof navigator.language === 'string'
? navigator.language
- : "zh-CN";
+ : 'zh-CN';
const getLocale = () => locale;
@@ -13,22 +13,22 @@ const setLocale = (target) => {
const isEmptyVariables = (variables) =>
(Array.isArray(variables) && variables.length === 0) ||
- (typeof variables === "object" &&
+ (typeof variables === 'object' &&
(!variables || Object.keys(variables).length === 0));
// 按低代码规范里面的要求进行变量替换
const format = (msg, variables) =>
- typeof msg === "string"
- ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
+ typeof msg === 'string'
+ ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '')
: msg;
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
const msg =
i18nConfig[locale]?.[id] ??
- i18nConfig[locale.replace("-", "_")]?.[id] ??
+ i18nConfig[locale.replace('-', '_')]?.[id] ??
defaultMessage;
if (msg == null) {
- console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
+ console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
return fallback === undefined ? `${id}` : fallback;
}
@@ -49,7 +49,7 @@ const _inject2 = (target) => {
};
target._i18nText = (t) => {
// 优先取直接传过来的语料
- const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
+ const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
if (localMsg != null) {
return format(localMsg, t.params);
}
@@ -61,7 +61,7 @@ const _inject2 = (target) => {
}
// 兜底用 use 指定的或默认语言的
- return format(t[t.use || "zh-CN"] ?? t.en_US, t.params);
+ return format(t[t.use || 'zh-CN'] ?? t.en_US, t.params);
};
// 注入到上下文中去
diff --git a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/pages/Test/index.jsx b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/pages/Test/index.jsx
index b90fe6254..c8db61db7 100644
--- a/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/pages/Test/index.jsx
+++ b/modules/code-generator/tests/fixtures/test-cases/react-app/demo1/expected/demo-project/src/pages/Test/index.jsx
@@ -1,22 +1,22 @@
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
// 例外:react 框架的导出名和各种组件名除外。
-import React from "react";
+import React from 'react';
-import { Form, Input, NumberPicker, Select, Button } from "@alifd/next";
+import { Form, Input, NumberPicker, Select, Button } from '@alifd/next';
-import { createUrlParamsHandler as __$$createUrlParamsRequestHandler } from "@alilc/lowcode-datasource-url-params-handler";
+import { createUrlParamsHandler as __$$createUrlParamsRequestHandler } from '@alilc/lowcode-datasource-url-params-handler';
-import { createFetchHandler as __$$createFetchRequestHandler } from "@alilc/lowcode-datasource-fetch-handler";
+import { createFetchHandler as __$$createFetchRequestHandler } from '@alilc/lowcode-datasource-fetch-handler';
-import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-engine/runtime";
+import { create as __$$createDataSourceEngine } from '@alilc/lowcode-datasource-engine/runtime';
-import utils, { RefsManager } from "../../utils";
+import utils, { RefsManager } from '../../utils';
-import * as __$$i18n from "../../i18n";
+import * as __$$i18n from '../../i18n';
-import __$$constants from "../../constants";
+import __$$constants from '../../constants';
-import "./index.css";
+import './index.css';
class Test$$Page extends React.Component {
_context = this;
@@ -51,7 +51,7 @@ class Test$$Page extends React.Component {
__$$i18n._inject2(this);
- this.state = { text: "outter" };
+ this.state = { text: 'outter' };
}
$ = (refName) => {
@@ -67,8 +67,8 @@ class Test$$Page extends React.Component {
return {
list: [
{
- id: "urlParams",
- type: "urlParams",
+ id: 'urlParams',
+ type: 'urlParams',
isInit: function () {
return undefined;
},
@@ -77,12 +77,12 @@ class Test$$Page extends React.Component {
},
},
{
- id: "user",
- type: "fetch",
+ id: 'user',
+ type: 'fetch',
options: function () {
return {
- method: "GET",
- uri: "https://shs.xxx.com/mock/1458/demo/user",
+ method: 'GET',
+ uri: 'https://shs.xxx.com/mock/1458/demo/user',
isSync: true,
};
},
@@ -90,6 +90,7 @@ class Test$$Page extends React.Component {
if (!response.data.success) {
throw new Error(response.data.message);
}
+
return response.data.data;
},
isInit: function () {
@@ -97,12 +98,12 @@ class Test$$Page extends React.Component {
},
},
{
- id: "orders",
- type: "fetch",
+ id: 'orders',
+ type: 'fetch',
options: function () {
return {
- method: "GET",
- uri: "https://shs.xxx.com/mock/1458/demo/orders",
+ method: 'GET',
+ uri: 'https://shs.xxx.com/mock/1458/demo/orders',
isSync: true,
};
},
@@ -110,6 +111,7 @@ class Test$$Page extends React.Component {
if (!response.data.success) {
throw new Error(response.data.message);
}
+
return response.data.data.result;
},
isInit: function () {
@@ -118,7 +120,7 @@ class Test$$Page extends React.Component {
},
],
dataHandler: function (dataMap) {
- console.info("All datasources loaded:", dataMap);
+ console.info('All datasources loaded:', dataMap);
},
};
}
@@ -126,18 +128,18 @@ class Test$$Page extends React.Component {
componentDidMount() {
this._dataSourceEngine.reloadDataSource();
- console.log("componentDidMount");
+ console.log('componentDidMount');
}
render() {
const __$$context = this._context || this;
const { state } = __$$context;
return (
-
+
@@ -148,18 +150,18 @@ class Test$$Page extends React.Component {
-
+
- {__$$evalArray(() => ["a", "b", "c"]).map((item, index) =>
+ {__$$evalArray(() => ['a', 'b', 'c']).map((item, index) =>
((__$$context) =>
!!__$$eval(() => index >= 1) && (
-