mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-19 14:04:28 +00:00
Merge commit '624e2f8d1e276f10867541edf7cf573bd535e9c0' into feat/merge-rax-generator
This commit is contained in:
commit
82feb9952a
@ -127,6 +127,16 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildConfig
|
||||||
|
if (builders.buildConfig) {
|
||||||
|
const { files } = await builders.buildConfig.generateModule(parseResult);
|
||||||
|
|
||||||
|
buildResult.push({
|
||||||
|
path: this.template.slots.buildConfig.path,
|
||||||
|
files,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// constants?
|
// constants?
|
||||||
if (parseResult.project && builders.constants && this.template.slots.constants) {
|
if (parseResult.project && builders.constants && this.template.slots.constants) {
|
||||||
const { files } = await builders.constants.generateModule(parseResult.project);
|
const { files } = await builders.constants.generateModule(parseResult.project);
|
||||||
@ -187,6 +197,8 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 更多 slots 的处理??是不是可以考虑把 template 中所有的 slots 都处理下?
|
||||||
|
|
||||||
// Post Process
|
// Post Process
|
||||||
|
|
||||||
// Combine Modules
|
// Combine Modules
|
||||||
|
|||||||
@ -22,6 +22,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
// 例外:rax 框架的导出名和各种组件名除外。
|
// 例外:rax 框架的导出名和各种组件名除外。
|
||||||
import { createElement, Component } from 'rax';
|
import { createElement, Component } from 'rax';
|
||||||
|
import { withRouter as __$$withRouter } from 'rax-app';
|
||||||
`,
|
`,
|
||||||
linkAfter: [],
|
linkAfter: [],
|
||||||
});
|
});
|
||||||
|
|||||||
@ -125,7 +125,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JSX,
|
fileType: FileType.JSX,
|
||||||
name: COMMON_CHUNK_NAME.FileExport,
|
name: COMMON_CHUNK_NAME.FileExport,
|
||||||
content: `export default ${componentClassName};`,
|
content: `export default __$$withRouter(${componentClassName});`,
|
||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -24,6 +24,14 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
...pre,
|
...pre,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: cfg.fileType,
|
||||||
|
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||||
|
content: `import __$$constants from '../../constants';`,
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||||
|
});
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: cfg.fileType,
|
fileType: cfg.fileType,
|
||||||
@ -67,6 +75,9 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
get props() {
|
get props() {
|
||||||
return self.props;
|
return self.props;
|
||||||
},
|
},
|
||||||
|
get constants() {
|
||||||
|
return __$$constants;
|
||||||
|
},
|
||||||
...this._methods,
|
...this._methods,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { CompositeValue, DataSourceConfig, isJSExpression, isJSFunction } from '@ali/lowcode-types';
|
import { CompositeValue, JSExpression, DataSourceConfig, isJSExpression, isJSFunction } from '@ali/lowcode-types';
|
||||||
|
import changeCase from 'change-case';
|
||||||
|
|
||||||
import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
|
import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
|
||||||
|
|
||||||
@ -30,6 +31,36 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
...pre,
|
...pre,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dataSourceConfig = isContainerSchema(pre.ir) ? pre.ir.dataSource : null;
|
||||||
|
const dataSourceItems: DataSourceConfig[] = (dataSourceConfig && dataSourceConfig.list) || [];
|
||||||
|
const dataSourceEngineOptions = { runtimeConfig: true };
|
||||||
|
if (dataSourceItems.length > 0) {
|
||||||
|
const requestHandlersMap = {} as Record<string, JSExpression>;
|
||||||
|
|
||||||
|
dataSourceItems.forEach((ds) => {
|
||||||
|
if (!(ds.type in requestHandlersMap) && ds.type !== 'custom') {
|
||||||
|
const handlerName = '__$$' + changeCase.camelCase(ds.type) + 'RequestHandler';
|
||||||
|
|
||||||
|
requestHandlersMap[ds.type] = {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: handlerName + (ds.type === 'urlParams' ? '({ search: this.props.location.search })' : ''),
|
||||||
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
|
content: `
|
||||||
|
import ${handlerName} from '@ali/lowcode-datasource-engine/handlers/${changeCase.kebabCase(ds.type)}';
|
||||||
|
`,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.assign(dataSourceEngineOptions, { requestHandlersMap });
|
||||||
|
}
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JSX,
|
fileType: FileType.JSX,
|
||||||
@ -46,7 +77,11 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||||
content: `
|
content: `
|
||||||
_dataSourceConfig = this._defineDataSourceConfig();
|
_dataSourceConfig = this._defineDataSourceConfig();
|
||||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });`,
|
_dataSourceEngine = __$$createDataSourceEngine(
|
||||||
|
this._dataSourceConfig,
|
||||||
|
this._context,
|
||||||
|
${generateCompositeType(dataSourceEngineOptions)}
|
||||||
|
);`,
|
||||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,9 +95,6 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
|||||||
linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin],
|
linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin],
|
||||||
});
|
});
|
||||||
|
|
||||||
const dataSourceConfig = isContainerSchema(pre.ir) ? pre.ir.dataSource : null;
|
|
||||||
const dataSourceItems: DataSourceConfig[] = (dataSourceConfig && dataSourceConfig.list) || [];
|
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: cfg.fileType,
|
fileType: cfg.fileType,
|
||||||
|
|||||||
@ -16,15 +16,14 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ir = next.ir as IProjectInfo;
|
const ir = next.ir as IProjectInfo;
|
||||||
if (ir.constants) {
|
const constantStr = generateCompositeType(ir.constants || {});
|
||||||
const constantStr = generateCompositeType(ir.constants);
|
|
||||||
|
|
||||||
next.chunks.push({
|
next.chunks.push({
|
||||||
type: ChunkType.STRING,
|
type: ChunkType.STRING,
|
||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||||
content: `
|
content: `
|
||||||
const constantConfig = ${constantStr};
|
const __$$constants = (${constantStr});
|
||||||
`,
|
`,
|
||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
@ -38,7 +37,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
fileType: FileType.JS,
|
fileType: FileType.JS,
|
||||||
name: COMMON_CHUNK_NAME.FileExport,
|
name: COMMON_CHUNK_NAME.FileExport,
|
||||||
content: `
|
content: `
|
||||||
export default constantConfig;
|
export default __$$constants;
|
||||||
`,
|
`,
|
||||||
linkAfter: [
|
linkAfter: [
|
||||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||||
@ -49,7 +48,6 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
COMMON_CHUNK_NAME.FileMainContent,
|
COMMON_CHUNK_NAME.FileMainContent,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import template from './template';
|
import template from './template';
|
||||||
import entry from './plugins/entry';
|
import entry from './plugins/entry';
|
||||||
import appConfig from './plugins/appConfig';
|
import appConfig from './plugins/appConfig';
|
||||||
|
import buildConfig from './plugins/buildConfig';
|
||||||
import entryDocument from './plugins/entryDocument';
|
import entryDocument from './plugins/entryDocument';
|
||||||
import globalStyle from './plugins/globalStyle';
|
import globalStyle from './plugins/globalStyle';
|
||||||
import packageJSON from './plugins/packageJSON';
|
import packageJSON from './plugins/packageJSON';
|
||||||
@ -9,6 +10,7 @@ export default {
|
|||||||
template,
|
template,
|
||||||
plugins: {
|
plugins: {
|
||||||
appConfig,
|
appConfig,
|
||||||
|
buildConfig,
|
||||||
entry,
|
entry,
|
||||||
entryDocument,
|
entryDocument,
|
||||||
globalStyle,
|
globalStyle,
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
IParseResult,
|
||||||
|
} from '../../../../../types';
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ir = next.ir as IParseResult;
|
||||||
|
const miniAppBuildType = ir.project?.config.miniAppBuildType;
|
||||||
|
|
||||||
|
const buildCfg = {
|
||||||
|
inlineStyle: false,
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
'build-plugin-rax-app',
|
||||||
|
{
|
||||||
|
targets: ['web', 'miniapp'],
|
||||||
|
miniapp: miniAppBuildType
|
||||||
|
? {
|
||||||
|
buildType: miniAppBuildType,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@ali/build-plugin-rax-app-def',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSON,
|
||||||
|
name: COMMON_CHUNK_NAME.CustomContent,
|
||||||
|
content: JSON.stringify(buildCfg, null, 2) + '\n',
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -27,9 +27,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
|||||||
private: true,
|
private: true,
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
scripts: {
|
scripts: {
|
||||||
build:
|
build: 'build-scripts build',
|
||||||
'rm -f ./dist/miniapp.tar.gz && npm run build:miniapp && cd build/miniapp && tar czf ../../dist/miniapp.tar.gz *',
|
|
||||||
'build:miniapp': 'build-scripts build',
|
|
||||||
start: 'build-scripts start',
|
start: 'build-scripts start',
|
||||||
lint: 'eslint --ext .js --ext .jsx ./',
|
lint: 'eslint --ext .js --ext .jsx ./',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,13 +4,12 @@ import { IProjectTemplate } from '../../../../../types';
|
|||||||
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
||||||
import { createResultDir } from '../../../../../utils/resultHelper';
|
import { createResultDir } from '../../../../../utils/resultHelper';
|
||||||
|
|
||||||
import file0 from './files/.editorconfig';
|
import file0 from './files/editorconfig';
|
||||||
import file1 from './files/.eslintignore';
|
import file1 from './files/eslintignore';
|
||||||
import file2 from './files/.eslintrc.js';
|
import file2 from './files/eslintrc.js';
|
||||||
import file3 from './files/.gitignore';
|
import file3 from './files/gitignore';
|
||||||
import file4 from './files/README.md';
|
import file4 from './files/README.md';
|
||||||
import file5 from './files/abc.json';
|
import file5 from './files/abc.json';
|
||||||
import file6 from './files/build.json';
|
|
||||||
|
|
||||||
const raxAppTemplate: IProjectTemplate = {
|
const raxAppTemplate: IProjectTemplate = {
|
||||||
slots: {
|
slots: {
|
||||||
@ -32,6 +31,10 @@ const raxAppTemplate: IProjectTemplate = {
|
|||||||
path: ['src'],
|
path: ['src'],
|
||||||
fileName: 'app',
|
fileName: 'app',
|
||||||
},
|
},
|
||||||
|
buildConfig: {
|
||||||
|
path: [],
|
||||||
|
fileName: 'build',
|
||||||
|
},
|
||||||
constants: {
|
constants: {
|
||||||
path: ['src'],
|
path: ['src'],
|
||||||
fileName: 'constants',
|
fileName: 'constants',
|
||||||
@ -67,7 +70,6 @@ const raxAppTemplate: IProjectTemplate = {
|
|||||||
runFileGenerator(root, file3);
|
runFileGenerator(root, file3);
|
||||||
runFileGenerator(root, file4);
|
runFileGenerator(root, file4);
|
||||||
runFileGenerator(root, file5);
|
runFileGenerator(root, file5);
|
||||||
runFileGenerator(root, file6);
|
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
|
import * as defaultFs from 'fs';
|
||||||
|
|
||||||
import { ResultDir } from '@ali/lowcode-types';
|
import { ResultDir } from '@ali/lowcode-types';
|
||||||
import { PublisherFactory, IPublisher, IPublisherFactoryParams, PublisherError } from '../../types';
|
import { PublisherFactory, IPublisher, IPublisherFactoryParams, PublisherError } from '../../types';
|
||||||
import { writeFolder } from './utils';
|
import { writeFolder, IFileSystem } from './utils';
|
||||||
|
|
||||||
export interface IDiskFactoryParams extends IPublisherFactoryParams {
|
export interface IDiskFactoryParams extends IPublisherFactoryParams {
|
||||||
outputPath?: string;
|
outputPath?: string;
|
||||||
projectSlug?: string;
|
projectSlug?: string;
|
||||||
createProjectFolder?: boolean;
|
createProjectFolder?: boolean;
|
||||||
|
fs?: IFileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDiskPublisher extends IPublisher<IDiskFactoryParams, string> {
|
export interface IDiskPublisher extends IPublisher<IDiskFactoryParams, string> {
|
||||||
@ -17,6 +20,7 @@ export const createDiskPublisher: PublisherFactory<IDiskFactoryParams, IDiskPubl
|
|||||||
params: IDiskFactoryParams = {},
|
params: IDiskFactoryParams = {},
|
||||||
): IDiskPublisher => {
|
): IDiskPublisher => {
|
||||||
let { project, outputPath = './' } = params;
|
let { project, outputPath = './' } = params;
|
||||||
|
const { fs = defaultFs } = params;
|
||||||
|
|
||||||
const getProject = (): ResultDir => {
|
const getProject = (): ResultDir => {
|
||||||
if (!project) {
|
if (!project) {
|
||||||
@ -50,7 +54,7 @@ export const createDiskPublisher: PublisherFactory<IDiskFactoryParams, IDiskPubl
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await writeFolder(projectToPublish, projectOutputPath, createProjectFolder);
|
await writeFolder(projectToPublish, projectOutputPath, createProjectFolder, fs);
|
||||||
return { success: true, payload: projectOutputPath };
|
return { success: true, payload: projectOutputPath };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new PublisherError(error);
|
throw new PublisherError(error);
|
||||||
|
|||||||
@ -1,36 +1,43 @@
|
|||||||
import { existsSync, mkdir, writeFile } from 'fs';
|
import * as systemFs from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { ResultDir, ResultFile } from '@ali/lowcode-types';
|
import { ResultDir, ResultFile } from '@ali/lowcode-types';
|
||||||
|
|
||||||
|
export interface IFileSystem {
|
||||||
|
existsSync: typeof systemFs.existsSync;
|
||||||
|
mkdir: typeof systemFs.mkdir;
|
||||||
|
writeFile: typeof systemFs.writeFile;
|
||||||
|
}
|
||||||
|
|
||||||
export const writeFolder = async (
|
export const writeFolder = async (
|
||||||
folder: ResultDir,
|
folder: ResultDir,
|
||||||
currentPath: string,
|
currentPath: string,
|
||||||
createProjectFolder = true,
|
createProjectFolder = true,
|
||||||
|
fs: IFileSystem = systemFs,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const { name, files, dirs } = folder;
|
const { name, files, dirs } = folder;
|
||||||
|
|
||||||
const folderPath = createProjectFolder ? join(currentPath, name) : currentPath;
|
const folderPath = createProjectFolder ? join(currentPath, name) : currentPath;
|
||||||
|
|
||||||
if (!existsSync(folderPath)) {
|
if (!fs.existsSync(folderPath)) {
|
||||||
await createDirectory(folderPath);
|
await createDirectory(folderPath, fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = [writeFilesToFolder(folderPath, files), writeSubFoldersToFolder(folderPath, dirs)];
|
const promises = [writeFilesToFolder(folderPath, files, fs), writeSubFoldersToFolder(folderPath, dirs, fs)];
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
const writeFilesToFolder = async (folderPath: string, files: ResultFile[]): Promise<void> => {
|
const writeFilesToFolder = async (folderPath: string, files: ResultFile[], fs: IFileSystem): Promise<void> => {
|
||||||
const promises = files.map((file) => {
|
const promises = files.map((file) => {
|
||||||
const fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
|
const fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
|
||||||
const filePath = join(folderPath, fileName);
|
const filePath = join(folderPath, fileName);
|
||||||
return writeContentToFile(filePath, file.content);
|
return writeContentToFile(filePath, file.content, 'utf8', fs);
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
const writeSubFoldersToFolder = async (folderPath: string, subFolders: ResultDir[]): Promise<void> => {
|
const writeSubFoldersToFolder = async (folderPath: string, subFolders: ResultDir[], fs: IFileSystem): Promise<void> => {
|
||||||
const promises = subFolders.map((subFolder) => {
|
const promises = subFolders.map((subFolder) => {
|
||||||
return writeFolder(subFolder, folderPath);
|
return writeFolder(subFolder, folderPath);
|
||||||
});
|
});
|
||||||
@ -38,17 +45,22 @@ const writeSubFoldersToFolder = async (folderPath: string, subFolders: ResultDir
|
|||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createDirectory = (pathToDir: string): Promise<void> => {
|
const createDirectory = (pathToDir: string, fs: IFileSystem): Promise<void> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
mkdir(pathToDir, { recursive: true }, (err) => {
|
fs.mkdir(pathToDir, { recursive: true }, (err) => {
|
||||||
err ? reject(err) : resolve();
|
err ? reject(err) : resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const writeContentToFile = (filePath: string, fileContent: string, encoding = 'utf8'): Promise<void> => {
|
const writeContentToFile = (
|
||||||
|
filePath: string,
|
||||||
|
fileContent: string,
|
||||||
|
encoding = 'utf8',
|
||||||
|
fs: IFileSystem,
|
||||||
|
): Promise<void> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
writeFile(filePath, fileContent, encoding, (err) => {
|
fs.writeFile(filePath, fileContent, encoding, (err) => {
|
||||||
err ? reject(err) : resolve();
|
err ? reject(err) : resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -52,6 +52,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
|||||||
css(),
|
css(),
|
||||||
],
|
],
|
||||||
appConfig: [raxApp.plugins.appConfig()],
|
appConfig: [raxApp.plugins.appConfig()],
|
||||||
|
buildConfig: [raxApp.plugins.buildConfig()],
|
||||||
entry: [raxApp.plugins.entry()],
|
entry: [raxApp.plugins.entry()],
|
||||||
constants: [constants()],
|
constants: [constants()],
|
||||||
utils: [esModule(), utils()],
|
utils: [esModule(), utils()],
|
||||||
|
|||||||
@ -3,8 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rm -f ./dist/miniapp.tar.gz && npm run build:miniapp && cd build/miniapp && tar czf ../../dist/miniapp.tar.gz *",
|
"build": "build-scripts build",
|
||||||
"build:miniapp": "build-scripts build",
|
|
||||||
"start": "build-scripts start",
|
"start": "build-scripts start",
|
||||||
"lint": "eslint --ext .js --ext .jsx ./"
|
"lint": "eslint --ext .js --ext .jsx ./"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
const __$$constants = {};
|
||||||
|
|
||||||
|
export default __$$constants;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
// 例外:rax 框架的导出名和各种组件名除外。
|
// 例外:rax 框架的导出名和各种组件名除外。
|
||||||
import { createElement, Component } from 'rax';
|
import { createElement, Component } from 'rax';
|
||||||
|
import { withRouter as __$$withRouter } from 'rax-app';
|
||||||
|
|
||||||
import Page from 'rax-view';
|
import Page from 'rax-view';
|
||||||
|
|
||||||
@ -10,6 +11,8 @@ import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-en
|
|||||||
|
|
||||||
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
import __$$projectUtils from '../../utils';
|
import __$$projectUtils from '../../utils';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
@ -68,6 +71,9 @@ class Home$$Page extends Component {
|
|||||||
get props() {
|
get props() {
|
||||||
return self.props;
|
return self.props;
|
||||||
},
|
},
|
||||||
|
get constants() {
|
||||||
|
return __$$constants;
|
||||||
|
},
|
||||||
...this._methods,
|
...this._methods,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,7 +115,7 @@ class Home$$Page extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Home$$Page;
|
export default __$$withRouter(Home$$Page);
|
||||||
|
|
||||||
function __$$eval(expr) {
|
function __$$eval(expr) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -3,8 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rm -f ./dist/miniapp.tar.gz && npm run build:miniapp && cd build/miniapp && tar czf ../../dist/miniapp.tar.gz *",
|
"build": "build-scripts build",
|
||||||
"build:miniapp": "build-scripts build",
|
|
||||||
"start": "build-scripts start",
|
"start": "build-scripts start",
|
||||||
"lint": "eslint --ext .js --ext .jsx ./"
|
"lint": "eslint --ext .js --ext .jsx ./"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
const __$$constants = {};
|
||||||
|
|
||||||
|
export default __$$constants;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
// 例外:rax 框架的导出名和各种组件名除外。
|
// 例外:rax 框架的导出名和各种组件名除外。
|
||||||
import { createElement, Component } from 'rax';
|
import { createElement, Component } from 'rax';
|
||||||
|
import { withRouter as __$$withRouter } from 'rax-app';
|
||||||
|
|
||||||
import View from 'rax-view';
|
import View from 'rax-view';
|
||||||
|
|
||||||
@ -8,10 +9,16 @@ import Text from 'rax-text';
|
|||||||
|
|
||||||
import Image from 'rax-image';
|
import Image from 'rax-image';
|
||||||
|
|
||||||
|
import __$$urlParamsRequestHandler from '@ali/lowcode-datasource-engine/handlers/url-params';
|
||||||
|
|
||||||
|
import __$$fetchRequestHandler from '@ali/lowcode-datasource-engine/handlers/fetch';
|
||||||
|
|
||||||
import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine';
|
import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine';
|
||||||
|
|
||||||
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
import __$$projectUtils from '../../utils';
|
import __$$projectUtils from '../../utils';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
@ -39,7 +46,13 @@ class Home$$Page extends Component {
|
|||||||
_context = this._createContext();
|
_context = this._createContext();
|
||||||
|
|
||||||
_dataSourceConfig = this._defineDataSourceConfig();
|
_dataSourceConfig = this._defineDataSourceConfig();
|
||||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });
|
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, {
|
||||||
|
runtimeConfig: true,
|
||||||
|
requestHandlersMap: {
|
||||||
|
urlParams: __$$urlParamsRequestHandler({ search: this.props.location.search }),
|
||||||
|
fetch: __$$fetchRequestHandler,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
_utils = this._defineUtils();
|
_utils = this._defineUtils();
|
||||||
|
|
||||||
@ -155,6 +168,9 @@ class Home$$Page extends Component {
|
|||||||
get props() {
|
get props() {
|
||||||
return self.props;
|
return self.props;
|
||||||
},
|
},
|
||||||
|
get constants() {
|
||||||
|
return __$$constants;
|
||||||
|
},
|
||||||
...this._methods,
|
...this._methods,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -182,6 +198,7 @@ class Home$$Page extends Component {
|
|||||||
return {
|
return {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
uri: 'https://shs.alibaba-inc.com/mock/1458/demo/user',
|
uri: 'https://shs.alibaba-inc.com/mock/1458/demo/user',
|
||||||
|
isSync: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
dataHandler: function (response) {
|
dataHandler: function (response) {
|
||||||
@ -202,6 +219,7 @@ class Home$$Page extends Component {
|
|||||||
return {
|
return {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
uri: __$$context.state.user.ordersApiUri,
|
uri: __$$context.state.user.ordersApiUri,
|
||||||
|
isSync: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
dataHandler: function (response) {
|
dataHandler: function (response) {
|
||||||
@ -280,7 +298,7 @@ class Home$$Page extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Home$$Page;
|
export default __$$withRouter(Home$$Page);
|
||||||
|
|
||||||
function __$$eval(expr) {
|
function __$$eval(expr) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -84,6 +84,7 @@
|
|||||||
options: {
|
options: {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
uri: 'https://shs.alibaba-inc.com/mock/1458/demo/user',
|
uri: 'https://shs.alibaba-inc.com/mock/1458/demo/user',
|
||||||
|
isSync: true,
|
||||||
},
|
},
|
||||||
dataHandler: {
|
dataHandler: {
|
||||||
type: 'JSFunction',
|
type: 'JSFunction',
|
||||||
@ -100,6 +101,7 @@
|
|||||||
type: 'JSExpression',
|
type: 'JSExpression',
|
||||||
value: 'this.state.user.ordersApiUri',
|
value: 'this.state.user.ordersApiUri',
|
||||||
},
|
},
|
||||||
|
isSync: true,
|
||||||
},
|
},
|
||||||
dataHandler: {
|
dataHandler: {
|
||||||
type: 'JSFunction',
|
type: 'JSFunction',
|
||||||
|
|||||||
@ -3,8 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rm -f ./dist/miniapp.tar.gz && npm run build:miniapp && cd build/miniapp && tar czf ../../dist/miniapp.tar.gz *",
|
"build": "build-scripts build",
|
||||||
"build:miniapp": "build-scripts build",
|
|
||||||
"start": "build-scripts start",
|
"start": "build-scripts start",
|
||||||
"lint": "eslint --ext .js --ext .jsx ./"
|
"lint": "eslint --ext .js --ext .jsx ./"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
const __$$constants = {};
|
||||||
|
|
||||||
|
export default __$$constants;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
// 例外:rax 框架的导出名和各种组件名除外。
|
// 例外:rax 框架的导出名和各种组件名除外。
|
||||||
import { createElement, Component } from 'rax';
|
import { createElement, Component } from 'rax';
|
||||||
|
import { withRouter as __$$withRouter } from 'rax-app';
|
||||||
|
|
||||||
import View from 'rax-view';
|
import View from 'rax-view';
|
||||||
|
|
||||||
@ -14,6 +15,8 @@ import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-en
|
|||||||
|
|
||||||
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
import __$$projectUtils from '../../utils';
|
import __$$projectUtils from '../../utils';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
@ -79,6 +82,9 @@ class Detail$$Page extends Component {
|
|||||||
get props() {
|
get props() {
|
||||||
return self.props;
|
return self.props;
|
||||||
},
|
},
|
||||||
|
get constants() {
|
||||||
|
return __$$constants;
|
||||||
|
},
|
||||||
...this._methods,
|
...this._methods,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,7 +126,7 @@ class Detail$$Page extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Detail$$Page;
|
export default __$$withRouter(Detail$$Page);
|
||||||
|
|
||||||
function __$$eval(expr) {
|
function __$$eval(expr) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
// 例外:rax 框架的导出名和各种组件名除外。
|
// 例外:rax 框架的导出名和各种组件名除外。
|
||||||
import { createElement, Component } from 'rax';
|
import { createElement, Component } from 'rax';
|
||||||
|
import { withRouter as __$$withRouter } from 'rax-app';
|
||||||
|
|
||||||
import View from 'rax-view';
|
import View from 'rax-view';
|
||||||
|
|
||||||
@ -14,6 +15,8 @@ import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-en
|
|||||||
|
|
||||||
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
import __$$projectUtils from '../../utils';
|
import __$$projectUtils from '../../utils';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
@ -79,6 +82,9 @@ class Home$$Page extends Component {
|
|||||||
get props() {
|
get props() {
|
||||||
return self.props;
|
return self.props;
|
||||||
},
|
},
|
||||||
|
get constants() {
|
||||||
|
return __$$constants;
|
||||||
|
},
|
||||||
...this._methods,
|
...this._methods,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,7 +126,7 @@ class Home$$Page extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Home$$Page;
|
export default __$$withRouter(Home$$Page);
|
||||||
|
|
||||||
function __$$eval(expr) {
|
function __$$eval(expr) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
// 例外:rax 框架的导出名和各种组件名除外。
|
// 例外:rax 框架的导出名和各种组件名除外。
|
||||||
import { createElement, Component } from 'rax';
|
import { createElement, Component } from 'rax';
|
||||||
|
import { withRouter as __$$withRouter } from 'rax-app';
|
||||||
|
|
||||||
import View from 'rax-view';
|
import View from 'rax-view';
|
||||||
|
|
||||||
@ -14,6 +15,8 @@ import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-en
|
|||||||
|
|
||||||
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
import __$$projectUtils from '../../utils';
|
import __$$projectUtils from '../../utils';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
@ -82,6 +85,9 @@ class List$$Page extends Component {
|
|||||||
get props() {
|
get props() {
|
||||||
return self.props;
|
return self.props;
|
||||||
},
|
},
|
||||||
|
get constants() {
|
||||||
|
return __$$constants;
|
||||||
|
},
|
||||||
...this._methods,
|
...this._methods,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -123,7 +129,7 @@ class List$$Page extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default List$$Page;
|
export default __$$withRouter(List$$Page);
|
||||||
|
|
||||||
function __$$eval(expr) {
|
function __$$eval(expr) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
# 这个 demo 是用来演示运行时的方案的。
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
# http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
# 忽略目录
|
||||||
|
build/
|
||||||
|
tests/
|
||||||
|
demo/
|
||||||
|
|
||||||
|
# node 覆盖率文件
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# 忽略文件
|
||||||
|
**/*-min.js
|
||||||
|
**/*.min.js
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['rax'],
|
||||||
|
};
|
||||||
17
packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.gitignore
vendored
Normal file
17
packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.swp
|
||||||
|
*.log
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
.idea/
|
||||||
|
.temp/
|
||||||
|
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
coverage/
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
template.yml
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
# @ali/rax-component-demo
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### `npm run start`
|
||||||
|
|
||||||
|
Runs the app in development mode.
|
||||||
|
|
||||||
|
Open [http://localhost:9999](http://localhost:9999) to view it in the browser.
|
||||||
|
|
||||||
|
The page will reload if you make edits.
|
||||||
|
|
||||||
|
### `npm run build`
|
||||||
|
|
||||||
|
Builds the app for production to the `build` folder.
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"type": "rax",
|
||||||
|
"builder": "@ali/builder-rax-v1",
|
||||||
|
"info": {
|
||||||
|
"raxVersion": "1.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"inlineStyle": false,
|
||||||
|
"plugins": [
|
||||||
|
[
|
||||||
|
"build-plugin-rax-app",
|
||||||
|
{
|
||||||
|
"targets": ["web", "miniapp"],
|
||||||
|
"miniapp": {
|
||||||
|
"buildType": "runtime"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@ali/build-plugin-rax-app-def"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "@ali/rax-app-demo",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"build": "build-scripts build",
|
||||||
|
"start": "build-scripts start",
|
||||||
|
"lint": "eslint --ext .js --ext .jsx ./"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ali/lowcode-datasource-engine": "^0.1.0",
|
||||||
|
"universal-env": "^3.2.0",
|
||||||
|
"rax": "^1.1.0",
|
||||||
|
"rax-app": "^2.0.0",
|
||||||
|
"rax-document": "^0.1.0",
|
||||||
|
"@alife/right-design-card": "*",
|
||||||
|
"rax-view": "^1.0.0",
|
||||||
|
"rax-text": "^1.0.0",
|
||||||
|
"rax-image": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"build-plugin-rax-app": "^5.0.0",
|
||||||
|
"@alib/build-scripts": "^0.1.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^2.11.0",
|
||||||
|
"@typescript-eslint/parser": "^2.11.0",
|
||||||
|
"babel-eslint": "^10.0.3",
|
||||||
|
"eslint": "^6.8.0",
|
||||||
|
"eslint-config-rax": "^0.1.0",
|
||||||
|
"eslint-plugin-import": "^2.20.0",
|
||||||
|
"eslint-plugin-module": "^0.1.0",
|
||||||
|
"eslint-plugin-react": "^7.18.0",
|
||||||
|
"@ali/build-plugin-rax-app-def": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { runApp } from 'rax-app';
|
||||||
|
import appConfig from './app.json';
|
||||||
|
|
||||||
|
import './global.scss';
|
||||||
|
|
||||||
|
runApp(appConfig);
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"source": "pages/Home/index"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"window": {
|
||||||
|
"title": "Rax App Demo"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
const __$$constants = {};
|
||||||
|
|
||||||
|
export default __$$constants;
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import { createElement } from 'rax';
|
||||||
|
import { Root, Style, Script } from 'rax-document';
|
||||||
|
|
||||||
|
function Document() {
|
||||||
|
return (
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
|
||||||
|
/>
|
||||||
|
<title>Rax App Demo</title>
|
||||||
|
<Style />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{/* root container */}
|
||||||
|
<Root />
|
||||||
|
<Script />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Document;
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
page,
|
||||||
|
body {
|
||||||
|
width: 750rpx;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
@ -0,0 +1,139 @@
|
|||||||
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
|
// 例外:rax 框架的导出名和各种组件名除外。
|
||||||
|
import { createElement, Component } from 'rax';
|
||||||
|
import { withRouter as __$$withRouter } from 'rax-app';
|
||||||
|
|
||||||
|
import Card from '@alife/right-design-card';
|
||||||
|
|
||||||
|
import View from 'rax-view';
|
||||||
|
|
||||||
|
import Text from 'rax-text';
|
||||||
|
|
||||||
|
import Image from 'rax-image';
|
||||||
|
|
||||||
|
import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine';
|
||||||
|
|
||||||
|
import { isMiniApp as __$$isMiniApp } from 'universal-env';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
|
import __$$projectUtils from '../../utils';
|
||||||
|
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
class Home$$Page extends Component {
|
||||||
|
state = {};
|
||||||
|
|
||||||
|
_methods = this._defineMethods();
|
||||||
|
|
||||||
|
_context = this._createContext();
|
||||||
|
|
||||||
|
_dataSourceConfig = this._defineDataSourceConfig();
|
||||||
|
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });
|
||||||
|
|
||||||
|
_utils = this._defineUtils();
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this._dataSourceEngine.reloadDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const __$$context = this._context;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Card>
|
||||||
|
<Text>This is a demo card.</Text>
|
||||||
|
</Card>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_createContext() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
get state() {
|
||||||
|
return self.state;
|
||||||
|
},
|
||||||
|
setState(newState) {
|
||||||
|
self.setState(newState);
|
||||||
|
},
|
||||||
|
get dataSourceMap() {
|
||||||
|
return self._dataSourceEngine.dataSourceMap || {};
|
||||||
|
},
|
||||||
|
async reloadDataSource() {
|
||||||
|
await self._dataSourceEngine.reloadDataSource();
|
||||||
|
},
|
||||||
|
get utils() {
|
||||||
|
return self._utils;
|
||||||
|
},
|
||||||
|
get page() {
|
||||||
|
return context;
|
||||||
|
},
|
||||||
|
get component() {
|
||||||
|
return context;
|
||||||
|
},
|
||||||
|
get props() {
|
||||||
|
return self.props;
|
||||||
|
},
|
||||||
|
get constants() {
|
||||||
|
return __$$constants;
|
||||||
|
},
|
||||||
|
...this._methods,
|
||||||
|
};
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
_defineDataSourceConfig() {
|
||||||
|
const __$$context = this._context;
|
||||||
|
return { list: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
_defineUtils() {
|
||||||
|
const utils = {
|
||||||
|
...__$$projectUtils,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.entries(utils).forEach(([name, util]) => {
|
||||||
|
if (typeof util === 'function') {
|
||||||
|
utils[name] = util.bind(this._context);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return utils;
|
||||||
|
}
|
||||||
|
|
||||||
|
_defineMethods() {
|
||||||
|
const __$$methods = {};
|
||||||
|
|
||||||
|
// 为所有的方法绑定上下文
|
||||||
|
Object.entries(__$$methods).forEach(([methodName, method]) => {
|
||||||
|
if (typeof method === 'function') {
|
||||||
|
__$$methods[methodName] = (...args) => {
|
||||||
|
return method.apply(this._context, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return __$$methods;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default __$$withRouter(Home$$Page);
|
||||||
|
|
||||||
|
function __$$eval(expr) {
|
||||||
|
try {
|
||||||
|
return expr();
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Failed to evaluate: ', expr, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function __$$evalArray(expr) {
|
||||||
|
const res = __$$eval(expr);
|
||||||
|
return Array.isArray(res) ? res : [];
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export default {};
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
{
|
||||||
|
version: '1.0.0',
|
||||||
|
componentsMap: [
|
||||||
|
{
|
||||||
|
componentName: 'Card',
|
||||||
|
package: '@alife/right-design-card',
|
||||||
|
version: '*',
|
||||||
|
destructuring: false,
|
||||||
|
exportName: 'Card',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'View',
|
||||||
|
package: 'rax-view',
|
||||||
|
version: '^1.0.0',
|
||||||
|
destructuring: false,
|
||||||
|
exportName: 'View',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Text',
|
||||||
|
package: 'rax-text',
|
||||||
|
version: '^1.0.0',
|
||||||
|
destructuring: false,
|
||||||
|
exportName: 'Text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Image',
|
||||||
|
package: 'rax-image',
|
||||||
|
version: '^1.0.0',
|
||||||
|
destructuring: false,
|
||||||
|
exportName: 'Image',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Page',
|
||||||
|
package: 'rax-view',
|
||||||
|
version: '^1.0.0',
|
||||||
|
destructuring: false,
|
||||||
|
exportName: 'Page',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
componentsTree: [
|
||||||
|
{
|
||||||
|
componentName: 'Page',
|
||||||
|
fileName: 'home',
|
||||||
|
meta: {
|
||||||
|
router: '/',
|
||||||
|
},
|
||||||
|
state: {},
|
||||||
|
props: {},
|
||||||
|
lifeCycles: {},
|
||||||
|
methods: {},
|
||||||
|
dataSource: {
|
||||||
|
list: [],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Card',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Text',
|
||||||
|
props: {},
|
||||||
|
children: 'This is a demo card.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
utils: [],
|
||||||
|
css: 'page,body{\n width: 750rpx;\n overflow-x: hidden;\n}',
|
||||||
|
config: {
|
||||||
|
sdkVersion: '1.0.3',
|
||||||
|
historyMode: 'hash',
|
||||||
|
targetRootID: 'root',
|
||||||
|
miniAppBuildType: 'runtime',
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
name: 'Rax App Demo',
|
||||||
|
git_group: 'demo-group',
|
||||||
|
project_name: 'demo-project',
|
||||||
|
description: '这是一个示例应用',
|
||||||
|
spma: 'spmademo',
|
||||||
|
creator: '张三',
|
||||||
|
},
|
||||||
|
}
|
||||||
5
packages/datasource-engine/.gitignore
vendored
Normal file
5
packages/datasource-engine/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/node_modules/
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
|
/es/
|
||||||
|
/lib/
|
||||||
1
packages/datasource-engine/handlers/fetch/index.d.ts
vendored
Normal file
1
packages/datasource-engine/handlers/fetch/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type * from '../../es/handlers/fetch';
|
||||||
1
packages/datasource-engine/handlers/fetch/index.js
Normal file
1
packages/datasource-engine/handlers/fetch/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('../../lib/handlers/fetch').default;
|
||||||
1
packages/datasource-engine/handlers/mtop/index.d.ts
vendored
Normal file
1
packages/datasource-engine/handlers/mtop/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type * from '../../es/handlers/mtop';
|
||||||
1
packages/datasource-engine/handlers/mtop/index.js
Normal file
1
packages/datasource-engine/handlers/mtop/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('../../lib/handlers/mtop').default;
|
||||||
1
packages/datasource-engine/handlers/url-params/index.d.ts
vendored
Normal file
1
packages/datasource-engine/handlers/url-params/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type * from '../../es/handlers/url-params';
|
||||||
1
packages/datasource-engine/handlers/url-params/index.js
Normal file
1
packages/datasource-engine/handlers/url-params/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('../../lib/handlers/url-params').default;
|
||||||
34
packages/datasource-engine/package.json
Normal file
34
packages/datasource-engine/package.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "@ali/lowcode-datasource-engine",
|
||||||
|
"version": "0.1.11",
|
||||||
|
"description": "DataSource Engine for lowcode",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"module": "es/index.js",
|
||||||
|
"typings": "es/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"handlers",
|
||||||
|
"src",
|
||||||
|
"lib",
|
||||||
|
"es"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"start": "tsc --watch",
|
||||||
|
"clean": "rm -rf es lib",
|
||||||
|
"build": "rm -rf es lib && tsc --module esnext --target es6 && mv lib es && tsc",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npm.alibaba-inc.com"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^3.9.7"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ali/universal-mtop": "^5.1.9",
|
||||||
|
"query-string": "^6.13.1",
|
||||||
|
"tslib": "^2.0.1",
|
||||||
|
"universal-request": "^2.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
134
packages/datasource-engine/src/core/DataSourceEngine.ts
Normal file
134
packages/datasource-engine/src/core/DataSourceEngine.ts
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import {
|
||||||
|
DataSourceConfig,
|
||||||
|
DataSourceEngineOptions,
|
||||||
|
IDataSourceEngine,
|
||||||
|
IDataSourceEngineFactory,
|
||||||
|
IRuntimeContext,
|
||||||
|
} from '../types';
|
||||||
|
import { RuntimeDataSource } from './RuntimeDataSource';
|
||||||
|
|
||||||
|
export class DataSourceEngine implements IDataSourceEngine {
|
||||||
|
private _dataSourceMap: Record<string, RuntimeDataSource> = {};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _dataSourceConfig: DataSourceConfig,
|
||||||
|
private _runtimeContext: IRuntimeContext,
|
||||||
|
private _options?: DataSourceEngineOptions,
|
||||||
|
) {
|
||||||
|
_dataSourceConfig.list?.forEach((ds) => {
|
||||||
|
// 确保数据源都有处理器
|
||||||
|
const requestHandler =
|
||||||
|
ds.requestHandler || _options?.requestHandlersMap?.[ds.type];
|
||||||
|
if (!requestHandler) {
|
||||||
|
throw new Error(`No request handler for "${ds.type}" data source`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._dataSourceMap[ds.id] = new RuntimeDataSource(
|
||||||
|
ds.id,
|
||||||
|
ds.type,
|
||||||
|
getValue(ds.options) || {},
|
||||||
|
requestHandler.bind(_runtimeContext),
|
||||||
|
ds.dataHandler ? ds.dataHandler.bind(_runtimeContext) : undefined,
|
||||||
|
(data) => {
|
||||||
|
_runtimeContext.setState({ [ds.id]: data });
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public get dataSourceMap() {
|
||||||
|
return this._dataSourceMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async reloadDataSource() {
|
||||||
|
try {
|
||||||
|
const allDataSourceConfigList = this._dataSourceConfig.list || [];
|
||||||
|
|
||||||
|
// urlParams 类型的优先加载
|
||||||
|
for (const ds of allDataSourceConfigList) {
|
||||||
|
if (ds.type === 'urlParams' && (getValue(ds.isInit) ?? true)) {
|
||||||
|
await this._dataSourceMap[ds.id].load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await sleep(0); // TODO: 如何优雅地解决 setState 的异步问题?
|
||||||
|
|
||||||
|
// 然后是所有其他的
|
||||||
|
const remainDataSourceConfigList = allDataSourceConfigList.filter(
|
||||||
|
(x) => x.type !== 'urlParams',
|
||||||
|
);
|
||||||
|
|
||||||
|
// 先发起异步的
|
||||||
|
const asyncLoadings: Array<Promise<unknown>> = [];
|
||||||
|
for (const ds of remainDataSourceConfigList) {
|
||||||
|
if (getValue(ds.isInit) ?? true) {
|
||||||
|
const options = getValue(ds.options);
|
||||||
|
if (options && !options.isSync) {
|
||||||
|
this._dataSourceMap[ds.id].setOptions(options);
|
||||||
|
asyncLoadings.push(
|
||||||
|
this._dataSourceMap[ds.id].load(options?.params).catch(() => {}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 再按先后顺序发起同步请求
|
||||||
|
for (const ds of remainDataSourceConfigList) {
|
||||||
|
if (getValue(ds.isInit) ?? true) {
|
||||||
|
const options = getValue(ds.options);
|
||||||
|
if (options && options.isSync) {
|
||||||
|
this._dataSourceMap[ds.id].setOptions(options);
|
||||||
|
await this._dataSourceMap[ds.id].load(options?.params);
|
||||||
|
await sleep(0); // TODO: 如何优雅地解决 setState 的异步问题?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
await Promise.all(asyncLoadings);
|
||||||
|
} finally {
|
||||||
|
const allDataHandler = this._dataSourceConfig.dataHandler;
|
||||||
|
if (allDataHandler) {
|
||||||
|
await allDataHandler(this._getDataMapOfAll());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getDataMapOfAll(): Record<string, unknown> {
|
||||||
|
const dataMap: Record<string, unknown> = {};
|
||||||
|
|
||||||
|
Object.entries(this._dataSourceMap).forEach(([dsId, ds]) => {
|
||||||
|
dataMap[dsId] = ds.data;
|
||||||
|
});
|
||||||
|
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const create: IDataSourceEngineFactory['create'] = (
|
||||||
|
dataSourceConfig,
|
||||||
|
runtimeContext,
|
||||||
|
options,
|
||||||
|
) => {
|
||||||
|
return new DataSourceEngine(dataSourceConfig, runtimeContext, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
function getValue<T>(valueOrValueGetter: T | (() => T)): T;
|
||||||
|
function getValue<T extends boolean>(
|
||||||
|
valueOrValueGetter: T | (() => T),
|
||||||
|
): T | undefined {
|
||||||
|
if (typeof valueOrValueGetter === 'function') {
|
||||||
|
try {
|
||||||
|
return valueOrValueGetter();
|
||||||
|
} catch (e) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return valueOrValueGetter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleep(ms: number = 0) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
98
packages/datasource-engine/src/core/RuntimeDataSource.ts
Normal file
98
packages/datasource-engine/src/core/RuntimeDataSource.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import {
|
||||||
|
DataSourceOptions,
|
||||||
|
IRuntimeDataSource,
|
||||||
|
RequestHandler,
|
||||||
|
RuntimeDataSourceStatus,
|
||||||
|
} from '../types';
|
||||||
|
|
||||||
|
export class RuntimeDataSource<
|
||||||
|
TParams extends Record<string, unknown> = Record<string, unknown>,
|
||||||
|
TRequestResult = unknown,
|
||||||
|
TResultData = unknown
|
||||||
|
> implements IRuntimeDataSource<TParams, TResultData> {
|
||||||
|
private _status: RuntimeDataSourceStatus = RuntimeDataSourceStatus.Initial;
|
||||||
|
private _data?: TResultData;
|
||||||
|
private _error?: Error;
|
||||||
|
private _latestOptions: DataSourceOptions<TParams>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _id: string,
|
||||||
|
private _type: string,
|
||||||
|
private _initialOptions: DataSourceOptions<TParams>,
|
||||||
|
private _requestHandler: RequestHandler<
|
||||||
|
DataSourceOptions<TParams>,
|
||||||
|
TRequestResult
|
||||||
|
>,
|
||||||
|
private _dataHandler:
|
||||||
|
| ((
|
||||||
|
data: TRequestResult | undefined,
|
||||||
|
error: unknown | undefined,
|
||||||
|
) => TResultData | Promise<TResultData>)
|
||||||
|
| undefined,
|
||||||
|
private _onLoaded: (data: TResultData) => void,
|
||||||
|
) {
|
||||||
|
this._latestOptions = _initialOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get status() {
|
||||||
|
return this._status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get data() {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get error() {
|
||||||
|
return this._error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async load(params?: TParams): Promise<TResultData> {
|
||||||
|
try {
|
||||||
|
this._latestOptions = {
|
||||||
|
...this._latestOptions,
|
||||||
|
params: {
|
||||||
|
...this._latestOptions.params,
|
||||||
|
...params,
|
||||||
|
} as TParams,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._status = RuntimeDataSourceStatus.Loading;
|
||||||
|
|
||||||
|
const data = await this._request(this._latestOptions);
|
||||||
|
|
||||||
|
this._status = RuntimeDataSourceStatus.Loaded;
|
||||||
|
|
||||||
|
this._onLoaded(data);
|
||||||
|
|
||||||
|
this._data = data;
|
||||||
|
return data;
|
||||||
|
} catch (err) {
|
||||||
|
this._error = err;
|
||||||
|
this._status = RuntimeDataSourceStatus.Error;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public setOptions(options: DataSourceOptions<TParams>) {
|
||||||
|
this._latestOptions = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _request(options: DataSourceOptions<TParams>) {
|
||||||
|
try {
|
||||||
|
const reqResult = await this._requestHandler(options);
|
||||||
|
|
||||||
|
const data = this._dataHandler
|
||||||
|
? await this._dataHandler(reqResult, undefined)
|
||||||
|
: ((reqResult as unknown) as TResultData);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
} catch (err) {
|
||||||
|
if (this._dataHandler) {
|
||||||
|
const data = await this._dataHandler(undefined, err);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
packages/datasource-engine/src/core/index.ts
Normal file
1
packages/datasource-engine/src/core/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { create } from './DataSourceEngine';
|
||||||
24
packages/datasource-engine/src/handlers/fetch.ts
Normal file
24
packages/datasource-engine/src/handlers/fetch.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import request from 'universal-request';
|
||||||
|
import type { AsObject, RequestOptions } from 'universal-request/lib/types';
|
||||||
|
|
||||||
|
import { DataSourceOptions, RequestHandler } from '../types';
|
||||||
|
|
||||||
|
const fetchHandler: RequestHandler = async ({
|
||||||
|
url,
|
||||||
|
uri,
|
||||||
|
data,
|
||||||
|
params,
|
||||||
|
...otherOptions
|
||||||
|
}: DataSourceOptions) => {
|
||||||
|
const reqOptions = {
|
||||||
|
url: ((url || uri) as unknown) as string,
|
||||||
|
data: ((data || params) as unknown) as AsObject,
|
||||||
|
...otherOptions,
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await request(reqOptions as RequestOptions);
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default fetchHandler;
|
||||||
15
packages/datasource-engine/src/handlers/mtop.ts
Normal file
15
packages/datasource-engine/src/handlers/mtop.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import mtop from '@ali/universal-mtop';
|
||||||
|
import { RequestHandler } from '../types';
|
||||||
|
|
||||||
|
const mtopHandler: RequestHandler = async ({ data, params, ...options }) => {
|
||||||
|
const reqOptions = {
|
||||||
|
...options,
|
||||||
|
data: data || params,
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await mtop(reqOptions);
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default mtopHandler;
|
||||||
14
packages/datasource-engine/src/handlers/url-params.ts
Normal file
14
packages/datasource-engine/src/handlers/url-params.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import qs from 'query-string';
|
||||||
|
import { RequestHandler } from '../types';
|
||||||
|
|
||||||
|
export default function urlParamsHandler({
|
||||||
|
search,
|
||||||
|
}: {
|
||||||
|
search: string | Record<string, unknown>;
|
||||||
|
}): RequestHandler {
|
||||||
|
const urlParams = typeof search === 'string' ? qs.parse(search) : search;
|
||||||
|
|
||||||
|
return async () => {
|
||||||
|
return urlParams;
|
||||||
|
};
|
||||||
|
}
|
||||||
2
packages/datasource-engine/src/index.ts
Normal file
2
packages/datasource-engine/src/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './core';
|
||||||
|
export * from './types';
|
||||||
6
packages/datasource-engine/src/types/DataSourceConfig.ts
Normal file
6
packages/datasource-engine/src/types/DataSourceConfig.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { DataSourceConfigItem } from './DataSourceConfigItem';
|
||||||
|
|
||||||
|
export type DataSourceConfig = {
|
||||||
|
list?: DataSourceConfigItem[];
|
||||||
|
dataHandler?: (dataMap: Record<string, unknown>) => void | Promise<void>;
|
||||||
|
};
|
||||||
17
packages/datasource-engine/src/types/DataSourceConfigItem.ts
Normal file
17
packages/datasource-engine/src/types/DataSourceConfigItem.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { DataSourceOptions } from './DataSourceOptions';
|
||||||
|
import { RequestHandler } from './RequestHandler';
|
||||||
|
|
||||||
|
export type DataSourceConfigItem = {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
isInit?: boolean | (() => boolean | undefined);
|
||||||
|
|
||||||
|
options?: DataSourceOptions | (() => DataSourceOptions | undefined);
|
||||||
|
|
||||||
|
requestHandler?: RequestHandler;
|
||||||
|
|
||||||
|
dataHandler?: (
|
||||||
|
data: unknown | undefined,
|
||||||
|
error: unknown | undefined,
|
||||||
|
) => unknown;
|
||||||
|
};
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { RequestHandler } from './RequestHandler';
|
||||||
|
|
||||||
|
export type DataSourceEngineOptions = {
|
||||||
|
requestHandlersMap?: {
|
||||||
|
[dataSourceType: string]: RequestHandler;
|
||||||
|
};
|
||||||
|
};
|
||||||
10
packages/datasource-engine/src/types/DataSourceOptions.ts
Normal file
10
packages/datasource-engine/src/types/DataSourceOptions.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export type DataSourceOptions<TParams = Record<string, unknown>> = {
|
||||||
|
uri?: string;
|
||||||
|
params?: TParams;
|
||||||
|
method?: string;
|
||||||
|
isCors?: boolean;
|
||||||
|
timeout?: number;
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
isSync?: boolean;
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
import { IRuntimeDataSource } from './IRuntimeDataSource';
|
||||||
|
|
||||||
|
export interface IDataSourceEngine {
|
||||||
|
/** 数据源, key 是数据源的 ID */
|
||||||
|
readonly dataSourceMap: Record<string, IRuntimeDataSource>;
|
||||||
|
|
||||||
|
/** 重新加载所有的数据源 */
|
||||||
|
reloadDataSource(): Promise<void>;
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { DataSourceConfig } from './DataSourceConfig';
|
||||||
|
import { DataSourceEngineOptions } from './DataSourceEngineOptions';
|
||||||
|
import { IDataSourceEngine } from './IDataSourceEngine';
|
||||||
|
import { IRuntimeContext } from './IRuntimeContext';
|
||||||
|
|
||||||
|
export interface IDataSourceEngineFactory {
|
||||||
|
create(
|
||||||
|
dataSourceConfig: DataSourceConfig,
|
||||||
|
runtimeContext: IRuntimeContext,
|
||||||
|
options?: DataSourceEngineOptions,
|
||||||
|
): IDataSourceEngine;
|
||||||
|
}
|
||||||
24
packages/datasource-engine/src/types/IRuntimeContext.ts
Normal file
24
packages/datasource-engine/src/types/IRuntimeContext.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { IRuntimeDataSource } from './IRuntimeDataSource';
|
||||||
|
|
||||||
|
/** 运行时上下文 */
|
||||||
|
export interface IRuntimeContext<
|
||||||
|
TState extends object = Record<string, unknown>
|
||||||
|
> {
|
||||||
|
/** 当前容器的状态 */
|
||||||
|
readonly state: TState;
|
||||||
|
|
||||||
|
/** 设置状态(浅合并) */
|
||||||
|
setState(state: Partial<TState>): void;
|
||||||
|
|
||||||
|
/** 数据源, key 是数据源的 ID */
|
||||||
|
dataSourceMap: Record<string, IRuntimeDataSource>;
|
||||||
|
|
||||||
|
/** 重新加载所有的数据源 */
|
||||||
|
reloadDataSource(): Promise<void>;
|
||||||
|
|
||||||
|
/** 页面容器 */
|
||||||
|
readonly page: IRuntimeContext & { props: Record<string, unknown> };
|
||||||
|
|
||||||
|
/** 低代码业务组件容器 */
|
||||||
|
readonly component: IRuntimeContext & { props: Record<string, unknown> };
|
||||||
|
}
|
||||||
22
packages/datasource-engine/src/types/IRuntimeDataSource.ts
Normal file
22
packages/datasource-engine/src/types/IRuntimeDataSource.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { RuntimeDataSourceStatus } from './RuntimeDataSourceStatus';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行时的数据源(对外暴露的接口)
|
||||||
|
* @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#Jwgj5
|
||||||
|
*/
|
||||||
|
export interface IRuntimeDataSource<TParams = unknown, TResultData = unknown> {
|
||||||
|
/** 当前状态(initial/loading/loaded/error) */
|
||||||
|
readonly status: RuntimeDataSourceStatus;
|
||||||
|
|
||||||
|
/** 加载成功时的数据 */
|
||||||
|
readonly data?: TResultData;
|
||||||
|
|
||||||
|
/** 加载出错的时候的错误信息 */
|
||||||
|
readonly error?: Error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载数据 (无论是否曾经加载过)
|
||||||
|
* 注意:若提供 params,则会和默认配置的参数做浅合并;否则会使用默认配置的参数。
|
||||||
|
*/
|
||||||
|
load(params?: TParams): Promise<TResultData>;
|
||||||
|
}
|
||||||
6
packages/datasource-engine/src/types/RequestHandler.ts
Normal file
6
packages/datasource-engine/src/types/RequestHandler.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { DataSourceOptions } from './DataSourceOptions';
|
||||||
|
|
||||||
|
export type RequestHandler<
|
||||||
|
TOptions extends DataSourceOptions = DataSourceOptions,
|
||||||
|
TResult = unknown
|
||||||
|
> = (options: TOptions) => Promise<TResult>;
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
/** 数据源的状态 */
|
||||||
|
export enum RuntimeDataSourceStatus {
|
||||||
|
/** 初始状态,尚未加载 */
|
||||||
|
Initial = 'init',
|
||||||
|
|
||||||
|
/** 正在加载 */
|
||||||
|
Loading = 'loading',
|
||||||
|
|
||||||
|
/** 已加载(无错误) */
|
||||||
|
Loaded = 'loaded',
|
||||||
|
|
||||||
|
/** 加载出错了 */
|
||||||
|
Error = 'error',
|
||||||
|
}
|
||||||
1
packages/datasource-engine/src/types/index.ts
Normal file
1
packages/datasource-engine/src/types/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './DataSourceConfig';
export * from './DataSourceConfigItem';
export * from './DataSourceEngineOptions';
export * from './DataSourceOptions';
export * from './IDataSourceEngine';
export * from './IDataSourceEngineFactory';
export * from './IRuntimeContext';
export * from './IRuntimeDataSource';
export * from './RequestHandler';
export * from './RuntimeDataSourceStatus';
|
||||||
1
packages/datasource-engine/src/typing.d.ts
vendored
Normal file
1
packages/datasource-engine/src/typing.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare module '@ali/universal-mtop';
|
||||||
80
packages/datasource-engine/tsconfig.json
Normal file
80
packages/datasource-engine/tsconfig.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||||
|
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
"target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
||||||
|
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
||||||
|
"lib": [
|
||||||
|
"DOM",
|
||||||
|
"ES2015",
|
||||||
|
"ES2016",
|
||||||
|
"ES2017",
|
||||||
|
"ES2018",
|
||||||
|
"ES2019"
|
||||||
|
] /* Specify library files to be included in the compilation. */,
|
||||||
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
|
"declaration": true /* Generates corresponding '.d.ts' file. */,
|
||||||
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
|
"sourceMap": true /* Generates corresponding '.map' file. */,
|
||||||
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
|
"outDir": "./lib" /* Redirect output structure to the directory. */,
|
||||||
|
"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
|
||||||
|
// "composite": true, /* Enable project compilation */
|
||||||
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
|
"removeComments": false /* Do not emit comments to output. */,
|
||||||
|
// "noEmit": true, /* Do not emit outputs. */
|
||||||
|
"importHelpers": true /* Import emit helpers from 'tslib'. */,
|
||||||
|
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||||
|
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||||
|
|
||||||
|
/* Strict Type-Checking Options */
|
||||||
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
|
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||||
|
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
|
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||||
|
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||||
|
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||||
|
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
|
|
||||||
|
/* Additional Checks */
|
||||||
|
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
|
|
||||||
|
/* Module Resolution Options */
|
||||||
|
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
||||||
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||||
|
"rootDirs": [
|
||||||
|
"src"
|
||||||
|
] /* List of root folders whose combined content represents the structure of the project at runtime. */,
|
||||||
|
"typeRoots": [
|
||||||
|
"./node_modules/@types"
|
||||||
|
] /* List of folders to include type definitions from. */,
|
||||||
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||||
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
||||||
|
/* Source Map Options */
|
||||||
|
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||||
|
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||||
|
|
||||||
|
/* Experimental Options */
|
||||||
|
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
|
|
||||||
|
/* Advanced Options */
|
||||||
|
"skipLibCheck": true /* Skip type checking of declaration files. */,
|
||||||
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user