modules/code-generator/src/cli/solutions/example-solution.ts (739 lines of code) (raw):

export function getLowcodeSolutionTemplateFiles() { return [ { file: '.editorconfig', content: `root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true quote_type = single [*.md] trim_trailing_whitespace = false `, }, { file: '.eslintignore', content: `# 忽略目录 node_modules/ build/ dist/ test-cases/ test/ tests/ output/ es/ lib/ coverage/ # 忽略文件 **/*.min.js **/*-min.js **/*.bundle.js `, }, { file: '.eslintrc.js', content: `module.exports = { extends: 'eslint-config-ali/typescript/react', rules: { 'max-len': ['error', { code: 200 }], 'comma-dangle': 0, }, }; `, }, { file: '.gitignore', content: `# project custom build es lib dist output package-lock.json deploy-space/packages deploy-space/.env generated # IDE .vscode .idea # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release lib # Dependency directories node_modules/ jspm_packages/ # TypeScript v1 declaration files typings/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env .env.test # parcel-bundler cache (https://parceljs.org/) .cache # next.js build output .next # nuxt.js build output .nuxt # vuepress build output .vuepress/dist # Serverless directories .serverless/ # FuseBox cache .fusebox/ # DynamoDB Local files .dynamodb/ # mac config files .DS_Store # codealike codealike.json .node `, }, { file: '.prettierignore', content: '/test-cases/', }, { file: '.prettierrc', content: `{ "tabWidth": 2, "singleQuote": true, "trailingComma": "es5" } `, }, { file: 'CHANGELOG.md', content: '', }, { file: 'CONTRIBUTING.md', content: `# 欢迎共建 # 注意 - 注意解决 eslint 问题 - 注意代码格式化 -- 建议安装 prettier 插件 - 发布前注意要跑通 demo 和所有的单测 ## 本地调试运行 Demo \`\`\`sh > npm run demo \`\`\` ## 本地跑单测 \`\`\`sh > npm test \`\`\` `, }, { file: 'README.md', content: `# 低代码出码自定义方案之 Hello World ## 直接执行 \`\`\`sh > npx ali-lowcode-solution-hello-world demo-schema.json \`\`\` ## 本地调试运行 Demo \`\`\`sh > npm run demo \`\`\` `, }, { file: 'demo-schema.json', content: `{ "version": "1.0.0", "componentsMap": [ { "componentName": "Button", "package": "@alifd/next", "version": "1.19.18", "destructuring": true, "exportName": "Button" }, { "componentName": "Button.Group", "package": "@alifd/next", "version": "1.19.18", "destructuring": true, "exportName": "Button", "subName": "Group" }, { "componentName": "Input", "package": "@alifd/next", "version": "1.19.18", "destructuring": true, "exportName": "Input" }, { "componentName": "Form", "package": "@alifd/next", "version": "1.19.18", "destructuring": true, "exportName": "Form" }, { "componentName": "Form.Item", "package": "@alifd/next", "version": "1.19.18", "destructuring": true, "exportName": "Form", "subName": "Item" }, { "componentName": "NumberPicker", "package": "@alifd/next", "version": "1.19.18", "destructuring": true, "exportName": "NumberPicker" }, { "componentName": "Select", "package": "@alifd/next", "version": "1.19.18", "destructuring": true, "exportName": "Select" } ], "componentsTree": [ { "componentName": "Page", "id": "node$1", "meta": { "title": "测试", "router": "/" }, "props": { "ref": "outterView", "autoLoading": true }, "fileName": "test", "state": { "text": "outter" }, "lifeCycles": { "componentDidMount": { "type": "JSFunction", "value": "function componentDidMount() {\\n console.log('componentDidMount');\\n}" } }, "methodsModule": { "type": "JSModule", "source": "export function helloWorld() {\\n console.log('Hello world!');\\n}\\n" }, "dataSource": { "list": [ { "id": "urlParams", "type": "urlParams" }, { "id": "user", "type": "fetch", "options": { "method": "GET", "uri": "https://shs.xxx.com/mock/1458/demo/user", "isSync": true }, "dataHandler": { "type": "JSExpression", "value": "function (response) {\\nif (!response.data.success){\\n throw new Error(response.data.message);\\n }\\n return response.data.data;\\n}" } }, { "id": "orders", "type": "fetch", "options": { "method": "GET", "uri": "https://shs.xxx.com/mock/1458/demo/orders", "isSync": true }, "dataHandler": { "type": "JSExpression", "value": "function (response) {\\nif (!response.data.success){\\n throw new Error(response.data.message);\\n }\\n return response.data.data.result;\\n}" } } ], "dataHandler": { "type": "JSExpression", "value": "function (dataMap) {\\n console.info(\\"All datasources loaded:\\", dataMap);\\n}" } }, "children": [ { "componentName": "Form", "id": "node$2", "props": { "labelCol": { "type": "JSExpression", "value": "this.state.colNum" }, "style": {}, "ref": "testForm" }, "children": [ { "componentName": "Form.Item", "id": "node$3", "props": { "label": "姓名:", "name": "name", "initValue": "李雷" }, "children": [ { "componentName": "Input", "id": "node$4", "props": { "placeholder": "请输入", "size": "medium", "style": { "width": 320 } } } ] }, { "componentName": "Form.Item", "id": "node$5", "props": { "label": "年龄:", "name": "age", "initValue": "22" }, "children": [ { "componentName": "NumberPicker", "id": "node$6", "props": { "size": "medium", "type": "normal" } } ] }, { "componentName": "Form.Item", "id": "node$7", "props": { "label": "职业:", "name": "profession" }, "children": [ { "componentName": "Select", "id": "node$8", "props": { "dataSource": [ { "label": "教师", "value": "t" }, { "label": "医生", "value": "d" }, { "label": "歌手", "value": "s" } ] } } ] }, { "componentName": "Div", "id": "node$9", "props": { "style": { "textAlign": "center" } }, "children": [ { "componentName": "Button.Group", "id": "node$a", "props": {}, "children": [ { "componentName": "Button", "id": "node$b", "condition": { "type": "JSExpression", "value": "this.index >= 1" }, "loop": ["a", "b", "c"], "props": { "type": "primary", "style": { "margin": "0 5px 0 5px" } }, "children": [ { "type": "JSExpression", "value": "this.item" } ] } ] } ] } ] } ] } ], "constants": { "ENV": "prod", "DOMAIN": "xxx.xxx.com" }, "css": "body {font-size: 12px;} .table { width: 100px;}", "config": { "sdkVersion": "1.0.3", "historyMode": "hash", "targetRootID": "J_Container", "layout": { "componentName": "BasicLayout", "props": { "logo": "...", "name": "测试网站" } }, "theme": { "package": "@alife/theme-fusion", "version": "^0.1.0", "primary": "#ff9966" } }, "meta": { "name": "demo应用", "git_group": "appGroup", "project_name": "app_demo", "description": "这是一个测试应用", "spma": "spa23d", "creator": "月飞" } } `, }, { file: 'jest.config.js', content: `module.exports = { preset: 'ts-jest', testEnvironment: 'node', testPathIgnorePatterns: ['/node_modules/', '/test-cases/', '/static-files/', '/lib/'], }; `, }, { file: 'package.json', content: `{ "name": "ali-lowcode-solution-hello-world", "version": "1.0.0", "description": "AlLowCode Code Generate Solution - Hello World", "files": [ "src", "lib", "tests", "jest.config.js", ".editorconfig", ".eslintignore", ".eslintrc.js", ".gitignore", ".prettierignore", ".prettierrc", "CHANGELOG.md", "CONTRIBUTING.md", "demo-schema.json", "package.json", "README.md", "tsconfig.json" ], "main": "lib/index.js", "scripts": { "start": "jest --watch", "build": "npm run clean && concurrently 'npm run build:ts' 'npm run lint'", "build:ts": "tsc", "check:type": "tsc -p . --noEmit", "clean": "rm -rf build dist lib generated", "dev": "build-scripts start", "lint": "eslint --ext .tsx,.ts,.js,.jsx src", "lintfix": "eslint --fix --color --ext .tsx,.ts,.js,.jsx src", "lint-staged": "lint-staged", "prepublishOnly": "npm run build", "postpublish": "git push origin master --tags", "test": "jest", "test:watch": "jest --watch", "test:update-snapshots": "cross-env UPDATE_EXPECTED=true npx jest", "demo": "npm run build && npx @alilc/lowcode-code-generator --solution . --output generated demo-schema.json" }, "repository": { "type": "git", "url": "git@github.com:your-name/ali-lowcode-solution-hello-world.git" }, "author": "", "license": "ISC", "publishConfig": { "registry": "https://registry.npm.xxx.com" }, "dependencies": { "@alilc/lowcode-code-generator": "^1.0.0", "@alilc/lowcode-types": "^1.0.0", "tslib": "^2.3.0" }, "devDependencies": { "@types/async": "^3.2.3", "@types/jest": "^26.0.17", "@typescript-eslint/eslint-plugin": "^4.28.4", "@typescript-eslint/parser": "^4.28.4", "async": "^3.2.0", "babel-runtime": "^6.26.0", "concurrently": "^5.2.0", "cross-env": "^7.0.0", "debug": "^4.1.1", "eslint": "^7.31.0", "eslint-config-ali": "^12.1.0", "eslint-plugin-import": "^2.23.4", "eslint-plugin-react": "^7.24.0", "eslint-plugin-react-hooks": "^4.2.0", "glob": "^7.2.0", "husky": "4.2.5", "jest": "^26.6.3", "json5": "^2.2.0", "lint-staged": "10.1.x", "lodash": "^4.17.21", "md5": "^2.2.1", "prettier": "^2.3.2", "ts-jest": "^26.4.4", "ts-node": "^9.0.0", "typescript": "4.x" } } `, }, { file: 'tsconfig.json', content: `{ "compilerOptions": { "esModuleInterop": true, "declaration": true, "experimentalDecorators": true, "forceConsistentCasingInFileNames": true, "importHelpers": true, "incremental": false, "jsx": "react", "moduleResolution": "node", "resolveJsonModule": true, "skipLibCheck": true, "sourceMap": true, "strict": true, "stripInternal": true, "outDir": "./lib", "declarationDir": "./lib", "rootDirs": ["./src"], "target": "es6", "module": "commonjs", "lib": ["esnext"], "types": ["jest", "node"], "noUnusedLocals": false, "noUnusedParameters": false }, "include": ["src/**/*", "typings/**/*"] } `, }, { file: 'src/index.ts', content: `import CodeGen from '@alilc/lowcode-code-generator'; import examplePlugin from './plugins/example'; export default function createHelloWorldProjectBuilder() { return CodeGen.createProjectBuilder({ template: CodeGen.solutionParts.icejs.template, plugins: { components: [ CodeGen.plugins.icejs.reactCommonDeps(), CodeGen.plugins.common.esModule({ fileType: 'jsx' }), CodeGen.plugins.common.styleImport(), CodeGen.plugins.icejs.containerClass(), CodeGen.plugins.icejs.containerInjectContext(), CodeGen.plugins.icejs.containerInjectUtils(), CodeGen.plugins.icejs.containerInjectDataSourceEngine(), CodeGen.plugins.icejs.containerInjectI18n(), CodeGen.plugins.icejs.containerInjectConstants(), CodeGen.plugins.icejs.containerInitState(), CodeGen.plugins.icejs.containerLifeCycle(), CodeGen.plugins.icejs.containerMethod(), examplePlugin(), CodeGen.plugins.icejs.jsx({ nodeTypeMapping: { Div: 'div', Component: 'div', Page: 'div', Block: 'div', }, }), CodeGen.plugins.style.css(), ], pages: [ CodeGen.plugins.icejs.reactCommonDeps(), CodeGen.plugins.common.esModule({ fileType: 'jsx' }), CodeGen.plugins.common.styleImport(), CodeGen.plugins.icejs.containerClass(), CodeGen.plugins.icejs.containerInjectContext(), CodeGen.plugins.icejs.containerInjectUtils(), CodeGen.plugins.icejs.containerInjectDataSourceEngine(), CodeGen.plugins.icejs.containerInjectI18n(), CodeGen.plugins.icejs.containerInjectConstants(), CodeGen.plugins.icejs.containerInitState(), CodeGen.plugins.icejs.containerLifeCycle(), CodeGen.plugins.icejs.containerMethod(), examplePlugin(), CodeGen.plugins.icejs.jsx({ nodeTypeMapping: { Div: 'div', Component: 'div', Page: 'div', Block: 'div', }, }), CodeGen.plugins.style.css(), ], router: [ CodeGen.plugins.common.esModule(), CodeGen.solutionParts.icejs.plugins.router(), ], entry: [CodeGen.solutionParts.icejs.plugins.entry()], constants: [CodeGen.plugins.project.constants()], utils: [ CodeGen.plugins.common.esModule(), CodeGen.plugins.project.utils('react'), ], i18n: [CodeGen.plugins.project.i18n()], globalStyle: [CodeGen.solutionParts.icejs.plugins.globalStyle()], htmlEntry: [CodeGen.solutionParts.icejs.plugins.entryHtml()], packageJSON: [CodeGen.solutionParts.icejs.plugins.packageJSON()], }, postProcessors: [CodeGen.postprocessor.prettier()], }); } `, }, { file: 'src/plugins/example.ts', content: `import { ICodeStruct, BuilderComponentPlugin, BuilderComponentPluginFactory, FileType, ChunkType, IContainerInfo, COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER, } from '@alilc/lowcode-code-generator'; export interface PluginConfig { fileType: string; } const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = ( config? ) => { const cfg: PluginConfig = { fileType: FileType.JSX, ...config, }; const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { const next: ICodeStruct = { ...pre, }; const ir = next.ir as IContainerInfo & { methodsModule?: { type?: 'JSModule'; source?: string; }; }; if (ir.methodsModule?.type !== 'JSModule' || !ir.methodsModule?.source) { return next; } // 创建 methods.jsx next.chunks.push({ type: ChunkType.STRING, subModule: 'methods', fileType: cfg.fileType, name: COMMON_CHUNK_NAME.CustomContent, content: ir.methodsModule.source, linkAfter: [], }); // 引入对应的模块 next.chunks.push({ type: ChunkType.STRING, fileType: cfg.fileType, name: COMMON_CHUNK_NAME.InternalDepsImport, content: "import __$$methodsModule from './methods';", linkAfter: [...DEFAULT_LINK_AFTER[COMMON_CHUNK_NAME.InternalDepsImport]], }); // 将导出的东东都放到 class 上实例方法部分 next.chunks.push({ type: ChunkType.STRING, fileType: cfg.fileType, name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, content: 'Object.assign(this, __$$methodsModule);', linkAfter: [ ...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent], ], }); return next; }; return plugin; }; export default pluginFactory; `, }, { file: 'tests/basic.test.ts', content: `test('basic functions should be ok', () => { // 这里放一些单元测试 expect(0).toBe(0); }); `, }, ]; }