mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-13 17:48:13 +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?
|
||||
if (parseResult.project && builders.constants && this.template.slots.constants) {
|
||||
const { files } = await builders.constants.generateModule(parseResult.project);
|
||||
@ -187,6 +197,8 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: 更多 slots 的处理??是不是可以考虑把 template 中所有的 slots 都处理下?
|
||||
|
||||
// Post Process
|
||||
|
||||
// Combine Modules
|
||||
|
||||
@ -22,6 +22,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:rax 框架的导出名和各种组件名除外。
|
||||
import { createElement, Component } from 'rax';
|
||||
import { withRouter as __$$withRouter } from 'rax-app';
|
||||
`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
@ -125,7 +125,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `export default ${componentClassName};`,
|
||||
content: `export default __$$withRouter(${componentClassName});`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
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 {
|
||||
BuilderComponentPlugin,
|
||||
@ -24,6 +24,14 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
...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({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
@ -67,6 +75,9 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
get props() {
|
||||
return self.props;
|
||||
},
|
||||
get constants() {
|
||||
return __$$constants;
|
||||
},
|
||||
...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';
|
||||
|
||||
@ -30,6 +31,36 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
...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({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
@ -45,8 +76,12 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
content: `
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });`,
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(
|
||||
this._dataSourceConfig,
|
||||
this._context,
|
||||
${generateCompositeType(dataSourceEngineOptions)}
|
||||
);`,
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||
});
|
||||
|
||||
@ -60,9 +95,6 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin],
|
||||
});
|
||||
|
||||
const dataSourceConfig = isContainerSchema(pre.ir) ? pre.ir.dataSource : null;
|
||||
const dataSourceItems: DataSourceConfig[] = (dataSourceConfig && dataSourceConfig.list) || [];
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
|
||||
@ -16,40 +16,38 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
};
|
||||
|
||||
const ir = next.ir as IProjectInfo;
|
||||
if (ir.constants) {
|
||||
const constantStr = generateCompositeType(ir.constants);
|
||||
const constantStr = generateCompositeType(ir.constants || {});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `
|
||||
const constantConfig = ${constantStr};
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||
],
|
||||
});
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileVarDefine,
|
||||
content: `
|
||||
const __$$constants = (${constantStr});
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export default constantConfig;
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
}
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileExport,
|
||||
content: `
|
||||
export default __$$constants;
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
COMMON_CHUNK_NAME.ImportAliasDefine,
|
||||
COMMON_CHUNK_NAME.FileVarDefine,
|
||||
COMMON_CHUNK_NAME.FileUtilDefine,
|
||||
COMMON_CHUNK_NAME.FileMainContent,
|
||||
],
|
||||
});
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import template from './template';
|
||||
import entry from './plugins/entry';
|
||||
import appConfig from './plugins/appConfig';
|
||||
import buildConfig from './plugins/buildConfig';
|
||||
import entryDocument from './plugins/entryDocument';
|
||||
import globalStyle from './plugins/globalStyle';
|
||||
import packageJSON from './plugins/packageJSON';
|
||||
@ -9,6 +10,7 @@ export default {
|
||||
template,
|
||||
plugins: {
|
||||
appConfig,
|
||||
buildConfig,
|
||||
entry,
|
||||
entryDocument,
|
||||
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,
|
||||
version: '1.0.0',
|
||||
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',
|
||||
build: 'build-scripts build',
|
||||
start: 'build-scripts start',
|
||||
lint: 'eslint --ext .js --ext .jsx ./',
|
||||
},
|
||||
|
||||
@ -4,13 +4,12 @@ import { IProjectTemplate } from '../../../../../types';
|
||||
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
||||
import { createResultDir } from '../../../../../utils/resultHelper';
|
||||
|
||||
import file0 from './files/.editorconfig';
|
||||
import file1 from './files/.eslintignore';
|
||||
import file2 from './files/.eslintrc.js';
|
||||
import file3 from './files/.gitignore';
|
||||
import file0 from './files/editorconfig';
|
||||
import file1 from './files/eslintignore';
|
||||
import file2 from './files/eslintrc.js';
|
||||
import file3 from './files/gitignore';
|
||||
import file4 from './files/README.md';
|
||||
import file5 from './files/abc.json';
|
||||
import file6 from './files/build.json';
|
||||
|
||||
const raxAppTemplate: IProjectTemplate = {
|
||||
slots: {
|
||||
@ -32,6 +31,10 @@ const raxAppTemplate: IProjectTemplate = {
|
||||
path: ['src'],
|
||||
fileName: 'app',
|
||||
},
|
||||
buildConfig: {
|
||||
path: [],
|
||||
fileName: 'build',
|
||||
},
|
||||
constants: {
|
||||
path: ['src'],
|
||||
fileName: 'constants',
|
||||
@ -67,7 +70,6 @@ const raxAppTemplate: IProjectTemplate = {
|
||||
runFileGenerator(root, file3);
|
||||
runFileGenerator(root, file4);
|
||||
runFileGenerator(root, file5);
|
||||
runFileGenerator(root, file6);
|
||||
|
||||
return root;
|
||||
},
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
import * as defaultFs from 'fs';
|
||||
|
||||
import { ResultDir } from '@ali/lowcode-types';
|
||||
import { PublisherFactory, IPublisher, IPublisherFactoryParams, PublisherError } from '../../types';
|
||||
import { writeFolder } from './utils';
|
||||
import { writeFolder, IFileSystem } from './utils';
|
||||
|
||||
export interface IDiskFactoryParams extends IPublisherFactoryParams {
|
||||
outputPath?: string;
|
||||
projectSlug?: string;
|
||||
createProjectFolder?: boolean;
|
||||
fs?: IFileSystem;
|
||||
}
|
||||
|
||||
export interface IDiskPublisher extends IPublisher<IDiskFactoryParams, string> {
|
||||
@ -17,6 +20,7 @@ export const createDiskPublisher: PublisherFactory<IDiskFactoryParams, IDiskPubl
|
||||
params: IDiskFactoryParams = {},
|
||||
): IDiskPublisher => {
|
||||
let { project, outputPath = './' } = params;
|
||||
const { fs = defaultFs } = params;
|
||||
|
||||
const getProject = (): ResultDir => {
|
||||
if (!project) {
|
||||
@ -50,7 +54,7 @@ export const createDiskPublisher: PublisherFactory<IDiskFactoryParams, IDiskPubl
|
||||
}
|
||||
|
||||
try {
|
||||
await writeFolder(projectToPublish, projectOutputPath, createProjectFolder);
|
||||
await writeFolder(projectToPublish, projectOutputPath, createProjectFolder, fs);
|
||||
return { success: true, payload: projectOutputPath };
|
||||
} catch (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 { 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 (
|
||||
folder: ResultDir,
|
||||
currentPath: string,
|
||||
createProjectFolder = true,
|
||||
fs: IFileSystem = systemFs,
|
||||
): Promise<void> => {
|
||||
const { name, files, dirs } = folder;
|
||||
|
||||
const folderPath = createProjectFolder ? join(currentPath, name) : currentPath;
|
||||
|
||||
if (!existsSync(folderPath)) {
|
||||
await createDirectory(folderPath);
|
||||
if (!fs.existsSync(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);
|
||||
};
|
||||
|
||||
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 fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
|
||||
const filePath = join(folderPath, fileName);
|
||||
return writeContentToFile(filePath, file.content);
|
||||
return writeContentToFile(filePath, file.content, 'utf8', fs);
|
||||
});
|
||||
|
||||
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) => {
|
||||
return writeFolder(subFolder, folderPath);
|
||||
});
|
||||
@ -38,17 +45,22 @@ const writeSubFoldersToFolder = async (folderPath: string, subFolders: ResultDir
|
||||
await Promise.all(promises);
|
||||
};
|
||||
|
||||
const createDirectory = (pathToDir: string): Promise<void> => {
|
||||
const createDirectory = (pathToDir: string, fs: IFileSystem): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
mkdir(pathToDir, { recursive: true }, (err) => {
|
||||
fs.mkdir(pathToDir, { recursive: true }, (err) => {
|
||||
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) => {
|
||||
writeFile(filePath, fileContent, encoding, (err) => {
|
||||
fs.writeFile(filePath, fileContent, encoding, (err) => {
|
||||
err ? reject(err) : resolve();
|
||||
});
|
||||
});
|
||||
|
||||
@ -52,6 +52,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
css(),
|
||||
],
|
||||
appConfig: [raxApp.plugins.appConfig()],
|
||||
buildConfig: [raxApp.plugins.buildConfig()],
|
||||
entry: [raxApp.plugins.entry()],
|
||||
constants: [constants()],
|
||||
utils: [esModule(), utils()],
|
||||
|
||||
@ -3,8 +3,7 @@
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"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",
|
||||
"build": "build-scripts build",
|
||||
"start": "build-scripts start",
|
||||
"lint": "eslint --ext .js --ext .jsx ./"
|
||||
},
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
const __$$constants = {};
|
||||
|
||||
export default __$$constants;
|
||||
@ -1,6 +1,7 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:rax 框架的导出名和各种组件名除外。
|
||||
import { createElement, Component } from 'rax';
|
||||
import { withRouter as __$$withRouter } from 'rax-app';
|
||||
|
||||
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 __$$constants from '../../constants';
|
||||
|
||||
import __$$projectUtils from '../../utils';
|
||||
|
||||
import './index.css';
|
||||
@ -68,6 +71,9 @@ class Home$$Page extends Component {
|
||||
get props() {
|
||||
return self.props;
|
||||
},
|
||||
get constants() {
|
||||
return __$$constants;
|
||||
},
|
||||
...this._methods,
|
||||
};
|
||||
|
||||
@ -109,7 +115,7 @@ class Home$$Page extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default Home$$Page;
|
||||
export default __$$withRouter(Home$$Page);
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
|
||||
@ -3,8 +3,7 @@
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"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",
|
||||
"build": "build-scripts build",
|
||||
"start": "build-scripts start",
|
||||
"lint": "eslint --ext .js --ext .jsx ./"
|
||||
},
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
const __$$constants = {};
|
||||
|
||||
export default __$$constants;
|
||||
@ -1,6 +1,7 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:rax 框架的导出名和各种组件名除外。
|
||||
import { createElement, Component } from 'rax';
|
||||
import { withRouter as __$$withRouter } from 'rax-app';
|
||||
|
||||
import View from 'rax-view';
|
||||
|
||||
@ -8,10 +9,16 @@ import Text from 'rax-text';
|
||||
|
||||
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 { isMiniApp as __$$isMiniApp } from 'universal-env';
|
||||
|
||||
import __$$constants from '../../constants';
|
||||
|
||||
import __$$projectUtils from '../../utils';
|
||||
|
||||
import './index.css';
|
||||
@ -39,7 +46,13 @@ class Home$$Page extends Component {
|
||||
_context = this._createContext();
|
||||
|
||||
_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();
|
||||
|
||||
@ -155,6 +168,9 @@ class Home$$Page extends Component {
|
||||
get props() {
|
||||
return self.props;
|
||||
},
|
||||
get constants() {
|
||||
return __$$constants;
|
||||
},
|
||||
...this._methods,
|
||||
};
|
||||
|
||||
@ -182,6 +198,7 @@ class Home$$Page extends Component {
|
||||
return {
|
||||
method: 'GET',
|
||||
uri: 'https://shs.alibaba-inc.com/mock/1458/demo/user',
|
||||
isSync: true,
|
||||
};
|
||||
},
|
||||
dataHandler: function (response) {
|
||||
@ -202,6 +219,7 @@ class Home$$Page extends Component {
|
||||
return {
|
||||
method: 'GET',
|
||||
uri: __$$context.state.user.ordersApiUri,
|
||||
isSync: true,
|
||||
};
|
||||
},
|
||||
dataHandler: function (response) {
|
||||
@ -280,7 +298,7 @@ class Home$$Page extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default Home$$Page;
|
||||
export default __$$withRouter(Home$$Page);
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
|
||||
@ -84,6 +84,7 @@
|
||||
options: {
|
||||
method: 'GET',
|
||||
uri: 'https://shs.alibaba-inc.com/mock/1458/demo/user',
|
||||
isSync: true,
|
||||
},
|
||||
dataHandler: {
|
||||
type: 'JSFunction',
|
||||
@ -100,6 +101,7 @@
|
||||
type: 'JSExpression',
|
||||
value: 'this.state.user.ordersApiUri',
|
||||
},
|
||||
isSync: true,
|
||||
},
|
||||
dataHandler: {
|
||||
type: 'JSFunction',
|
||||
|
||||
@ -3,8 +3,7 @@
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"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",
|
||||
"build": "build-scripts build",
|
||||
"start": "build-scripts start",
|
||||
"lint": "eslint --ext .js --ext .jsx ./"
|
||||
},
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
const __$$constants = {};
|
||||
|
||||
export default __$$constants;
|
||||
@ -1,6 +1,7 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:rax 框架的导出名和各种组件名除外。
|
||||
import { createElement, Component } from 'rax';
|
||||
import { withRouter as __$$withRouter } from 'rax-app';
|
||||
|
||||
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 __$$constants from '../../constants';
|
||||
|
||||
import __$$projectUtils from '../../utils';
|
||||
|
||||
import './index.css';
|
||||
@ -79,6 +82,9 @@ class Detail$$Page extends Component {
|
||||
get props() {
|
||||
return self.props;
|
||||
},
|
||||
get constants() {
|
||||
return __$$constants;
|
||||
},
|
||||
...this._methods,
|
||||
};
|
||||
|
||||
@ -120,7 +126,7 @@ class Detail$$Page extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default Detail$$Page;
|
||||
export default __$$withRouter(Detail$$Page);
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:rax 框架的导出名和各种组件名除外。
|
||||
import { createElement, Component } from 'rax';
|
||||
import { withRouter as __$$withRouter } from 'rax-app';
|
||||
|
||||
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 __$$constants from '../../constants';
|
||||
|
||||
import __$$projectUtils from '../../utils';
|
||||
|
||||
import './index.css';
|
||||
@ -79,6 +82,9 @@ class Home$$Page extends Component {
|
||||
get props() {
|
||||
return self.props;
|
||||
},
|
||||
get constants() {
|
||||
return __$$constants;
|
||||
},
|
||||
...this._methods,
|
||||
};
|
||||
|
||||
@ -120,7 +126,7 @@ class Home$$Page extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default Home$$Page;
|
||||
export default __$$withRouter(Home$$Page);
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:rax 框架的导出名和各种组件名除外。
|
||||
import { createElement, Component } from 'rax';
|
||||
import { withRouter as __$$withRouter } from 'rax-app';
|
||||
|
||||
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 __$$constants from '../../constants';
|
||||
|
||||
import __$$projectUtils from '../../utils';
|
||||
|
||||
import './index.css';
|
||||
@ -82,6 +85,9 @@ class List$$Page extends Component {
|
||||
get props() {
|
||||
return self.props;
|
||||
},
|
||||
get constants() {
|
||||
return __$$constants;
|
||||
},
|
||||
...this._methods,
|
||||
};
|
||||
|
||||
@ -123,7 +129,7 @@ class List$$Page extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default List$$Page;
|
||||
export default __$$withRouter(List$$Page);
|
||||
|
||||
function __$$eval(expr) {
|
||||
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