mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-07 02:47:12 +00:00
feat: 调整 datasource-handlers
This commit is contained in:
parent
d115ce0bdc
commit
2b9bcb5174
@ -1 +1,3 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
|
/es
|
||||||
|
/lib
|
||||||
@ -1,7 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: '../../.eslintrc.js',
|
extends: '../../.eslintrc',
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/no-parameter-properties': 1,
|
'@typescript-eslint/no-parameter-properties': 1,
|
||||||
'no-param-reassign': 0
|
'no-param-reassign': 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
trailingComma: 'always',
|
trailingComma: 'all',
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,15 +15,10 @@
|
|||||||
},
|
},
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/build-success-types": "^0.1.2-alpha.35",
|
"@ali/lowcode-types": "^0.8.13",
|
||||||
"typescript": "^3.9.7"
|
"typescript": "^3.9.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ali/datasource-engine-universal-mtop-handler": "1.0.0-alpha.2",
|
|
||||||
"@ali/datasource-engine-url-params-handler": "^1.0.0-alpha.3",
|
|
||||||
"@ali/lowcode-datasource-http-handler": "^1.0.0-alpha.1",
|
|
||||||
"@ali/lowcode-datasource-url-params-handler": "^1.0.0-alpha.3",
|
|
||||||
"@ali/ng-lc-types": "^1.0.0-r2009222d5o6k8r8",
|
|
||||||
"@ava/babel": "^1.0.1",
|
"@ava/babel": "^1.0.1",
|
||||||
"@types/sinon": "^9.0.5",
|
"@types/sinon": "^9.0.5",
|
||||||
"ava": "3.11.1",
|
"ava": "3.11.1",
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/indent */
|
||||||
import {
|
import {
|
||||||
|
IDataSourceRuntimeContext,
|
||||||
IRuntimeDataSource,
|
IRuntimeDataSource,
|
||||||
|
RequestHandler,
|
||||||
RuntimeDataSourceConfig,
|
RuntimeDataSourceConfig,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
IRuntimeContext,
|
|
||||||
RequestHandler,
|
|
||||||
RuntimeOptionsConfig,
|
RuntimeOptionsConfig,
|
||||||
UrlParamsHandler,
|
UrlParamsHandler,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
|
|
||||||
class RuntimeDataSourceItem<
|
class RuntimeDataSourceItem<
|
||||||
TParams extends Record<string, unknown> = Record<string, unknown>,
|
TParams extends Record<string, unknown> = Record<string, unknown>,
|
||||||
@ -21,19 +22,19 @@ class RuntimeDataSourceItem<
|
|||||||
private _dataSourceConfig: RuntimeDataSourceConfig;
|
private _dataSourceConfig: RuntimeDataSourceConfig;
|
||||||
|
|
||||||
private _request:
|
private _request:
|
||||||
| RequestHandler<{ data: TResultData }>
|
| RequestHandler<{ data: TResultData }>
|
||||||
| UrlParamsHandler<TResultData>;
|
| UrlParamsHandler<TResultData>;
|
||||||
|
|
||||||
private _context: IRuntimeContext;
|
private _context: IDataSourceRuntimeContext;
|
||||||
|
|
||||||
private _options?: RuntimeOptionsConfig;
|
private _options?: RuntimeOptionsConfig;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
dataSourceConfig: RuntimeDataSourceConfig,
|
dataSourceConfig: RuntimeDataSourceConfig,
|
||||||
request:
|
request:
|
||||||
| RequestHandler<{ data: TResultData }>
|
| RequestHandler<{ data: TResultData }>
|
||||||
| UrlParamsHandler<TResultData>,
|
| UrlParamsHandler<TResultData>,
|
||||||
context: IRuntimeContext,
|
context: IDataSourceRuntimeContext,
|
||||||
) {
|
) {
|
||||||
this._dataSourceConfig = dataSourceConfig;
|
this._dataSourceConfig = dataSourceConfig;
|
||||||
this._request = request;
|
this._request = request;
|
||||||
@ -52,7 +53,7 @@ class RuntimeDataSourceItem<
|
|||||||
return this._status;
|
return this._status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async load(params?: TParams) {
|
async load(params?: TParams) {
|
||||||
if (!this._dataSourceConfig) return;
|
if (!this._dataSourceConfig) return;
|
||||||
// 考虑没有绑定对应的 handler 的情况
|
// 考虑没有绑定对应的 handler 的情况
|
||||||
if (!this._request) {
|
if (!this._request) {
|
||||||
|
|||||||
@ -7,16 +7,19 @@ import {
|
|||||||
} from './../utils';
|
} from './../utils';
|
||||||
// 将不同渠道给的 schema 转为 runtime 需要的类型
|
// 将不同渠道给的 schema 转为 runtime 需要的类型
|
||||||
|
|
||||||
import {
|
|
||||||
DataSource,
|
|
||||||
IPageContext,
|
|
||||||
DataSourceConfig,
|
|
||||||
RuntimeDataSourceConfig,
|
|
||||||
DataSourceMap,
|
|
||||||
} from '@ali/build-success-types';
|
|
||||||
import { defaultDataHandler, defaultWillFetch } from '../helpers';
|
import { defaultDataHandler, defaultWillFetch } from '../helpers';
|
||||||
|
import {
|
||||||
|
DataSourceMap,
|
||||||
|
IDataSourceRuntimeContext,
|
||||||
|
InterpretDataSource,
|
||||||
|
InterpretDataSourceConfig,
|
||||||
|
RuntimeDataSourceConfig,
|
||||||
|
} from '@ali/lowcode-types';
|
||||||
|
|
||||||
const adapt2Runtime = (dataSource: DataSource, context: IPageContext) => {
|
const adapt2Runtime = (
|
||||||
|
dataSource: InterpretDataSource,
|
||||||
|
context: IDataSourceRuntimeContext,
|
||||||
|
) => {
|
||||||
const {
|
const {
|
||||||
list: interpretConfigList,
|
list: interpretConfigList,
|
||||||
dataHandler: interpretDataHandler,
|
dataHandler: interpretDataHandler,
|
||||||
@ -34,7 +37,7 @@ const adapt2Runtime = (dataSource: DataSource, context: IPageContext) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
const list: RuntimeDataSourceConfig[] = interpretConfigList.map(
|
const list: RuntimeDataSourceConfig[] = interpretConfigList.map(
|
||||||
(el: DataSourceConfig) => {
|
(el: InterpretDataSourceConfig) => {
|
||||||
return {
|
return {
|
||||||
id: el.id,
|
id: el.id,
|
||||||
isInit:
|
isInit:
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
RuntimeDataSource,
|
|
||||||
DataSourceMap,
|
DataSourceMap,
|
||||||
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceConfig,
|
RuntimeDataSourceConfig,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
|
|
||||||
export const reloadDataSourceFactory = (
|
export const reloadDataSourceFactory = (
|
||||||
dataSource: RuntimeDataSource,
|
dataSource: RuntimeDataSource,
|
||||||
@ -14,7 +14,8 @@ export const reloadDataSourceFactory = (
|
|||||||
// 单独处理 urlParams 类型的
|
// 单独处理 urlParams 类型的
|
||||||
dataSource.list
|
dataSource.list
|
||||||
.filter(
|
.filter(
|
||||||
(el: RuntimeDataSourceConfig) => el.type === 'urlParams' &&
|
(el: RuntimeDataSourceConfig) =>
|
||||||
|
el.type === 'urlParams' &&
|
||||||
(typeof el.isInit === 'boolean' ? el.isInit : true),
|
(typeof el.isInit === 'boolean' ? el.isInit : true),
|
||||||
)
|
)
|
||||||
.forEach((el: RuntimeDataSourceConfig) => {
|
.forEach((el: RuntimeDataSourceConfig) => {
|
||||||
@ -50,13 +51,8 @@ export const reloadDataSourceFactory = (
|
|||||||
ds.isInit &&
|
ds.isInit &&
|
||||||
ds.isSync
|
ds.isSync
|
||||||
) {
|
) {
|
||||||
// TODO: 我理解这个异常也应该吃掉的,待确认
|
// eslint-disable-next-line no-await-in-loop
|
||||||
try {
|
await dataSourceMap[ds.id].load();
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await dataSourceMap[ds.id].load();
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { DataHandler } from '@ali/build-success-types';
|
import { DataHandler } from '@ali/lowcode-types';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
// 默认的 dataSourceItem 的 dataHandler
|
// 默认的 dataSourceItem 的 dataHandler
|
||||||
|
|||||||
@ -1,15 +1,14 @@
|
|||||||
import {
|
|
||||||
IRuntimeContext,
|
|
||||||
IRuntimeDataSource,
|
|
||||||
DataSource,
|
|
||||||
RuntimeDataSourceConfig,
|
|
||||||
RuntimeDataSource,
|
|
||||||
RequestHandlersMap,
|
|
||||||
} from '@ali/build-success-types';
|
|
||||||
|
|
||||||
import { adapt2Runtime } from '../core/adapter';
|
import { adapt2Runtime } from '../core/adapter';
|
||||||
import { RuntimeDataSourceItem } from '../core/RuntimeDataSourceItem';
|
import { RuntimeDataSourceItem } from '../core/RuntimeDataSourceItem';
|
||||||
import { reloadDataSourceFactory } from '../core/reloadDataSourceFactory';
|
import { reloadDataSourceFactory } from '../core/reloadDataSourceFactory';
|
||||||
|
import {
|
||||||
|
IDataSourceRuntimeContext,
|
||||||
|
InterpretDataSource,
|
||||||
|
IRuntimeDataSource,
|
||||||
|
RequestHandlersMap,
|
||||||
|
RuntimeDataSource,
|
||||||
|
RuntimeDataSourceConfig,
|
||||||
|
} from '@ali/lowcode-types';
|
||||||
|
|
||||||
// TODO: requestConfig mtop 默认的请求 config 怎么处理?
|
// TODO: requestConfig mtop 默认的请求 config 怎么处理?
|
||||||
/**
|
/**
|
||||||
@ -18,13 +17,11 @@ import { reloadDataSourceFactory } from '../core/reloadDataSourceFactory';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
dataSource: DataSource,
|
dataSource: InterpretDataSource,
|
||||||
context: IRuntimeContext,
|
context: IDataSourceRuntimeContext,
|
||||||
extraConfig: {
|
extraConfig: {
|
||||||
requestHandlersMap: RequestHandlersMap<{ data: unknown }>;
|
requestHandlersMap: RequestHandlersMap<{ data: unknown }>;
|
||||||
} = {
|
} = { requestHandlersMap: {} },
|
||||||
requestHandlersMap: {},
|
|
||||||
},
|
|
||||||
) => {
|
) => {
|
||||||
const { requestHandlersMap } = extraConfig;
|
const { requestHandlersMap } = extraConfig;
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/indent */
|
||||||
/* eslint-disable no-nested-ternary */
|
/* eslint-disable no-nested-ternary */
|
||||||
import {
|
import {
|
||||||
IRuntimeContext,
|
|
||||||
IRuntimeDataSource,
|
IRuntimeDataSource,
|
||||||
|
IDataSourceRuntimeContext,
|
||||||
|
RequestHandlersMap,
|
||||||
RuntimeDataSourceConfig,
|
RuntimeDataSourceConfig,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RequestHandlersMap,
|
} from '@ali/lowcode-types';
|
||||||
} from '@ali/build-success-types';
|
|
||||||
|
|
||||||
import { RuntimeDataSourceItem } from '../core';
|
import { RuntimeDataSourceItem } from '../core';
|
||||||
import { reloadDataSourceFactory } from '../core/reloadDataSourceFactory';
|
import { reloadDataSourceFactory } from '../core/reloadDataSourceFactory';
|
||||||
@ -22,24 +23,22 @@ import {
|
|||||||
*/
|
*/
|
||||||
export default (
|
export default (
|
||||||
dataSource: RuntimeDataSource,
|
dataSource: RuntimeDataSource,
|
||||||
context: IRuntimeContext,
|
context: IDataSourceRuntimeContext,
|
||||||
extraConfig: {
|
extraConfig: {
|
||||||
requestHandlersMap: RequestHandlersMap<{ data: unknown }>;
|
requestHandlersMap: RequestHandlersMap<{ data: unknown }>;
|
||||||
} = {
|
} = { requestHandlersMap: {} },
|
||||||
requestHandlersMap: {},
|
|
||||||
},
|
|
||||||
) => {
|
) => {
|
||||||
const { requestHandlersMap } = extraConfig;
|
const { requestHandlersMap } = extraConfig;
|
||||||
|
|
||||||
// TODO: 对于出码类型,需要做一层数据兼容,给一些必要的值设置默认值,先兜底几个必要的
|
// TODO: 对于出码类型,需要做一层数据兼容,给一些必要的值设置默认值,先兜底几个必要的
|
||||||
dataSource.list.forEach((ds) => {
|
dataSource.list.forEach(ds => {
|
||||||
ds.isInit = ds.isInit || true;
|
ds.isInit = ds.isInit || true;
|
||||||
ds.isSync = ds.isSync || false;
|
ds.isSync = ds.isSync || false;
|
||||||
ds.shouldFetch = !ds.shouldFetch
|
ds.shouldFetch = !ds.shouldFetch
|
||||||
? defaultShouldFetch
|
? defaultShouldFetch
|
||||||
: typeof ds.shouldFetch === 'function'
|
: typeof ds.shouldFetch === 'function'
|
||||||
? ds.shouldFetch.bind(context)
|
? ds.shouldFetch.bind(context)
|
||||||
: ds.shouldFetch;
|
: ds.shouldFetch;
|
||||||
ds.willFetch = ds.willFetch ? ds.willFetch.bind(context) : defaultWillFetch;
|
ds.willFetch = ds.willFetch ? ds.willFetch.bind(context) : defaultWillFetch;
|
||||||
ds.dataHandler = ds.dataHandler
|
ds.dataHandler = ds.dataHandler
|
||||||
? ds.dataHandler.bind(context)
|
? ds.dataHandler.bind(context)
|
||||||
|
|||||||
@ -1,16 +1,20 @@
|
|||||||
/* eslint-disable no-new-func */
|
/* eslint-disable no-new-func */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
JSExpression,
|
|
||||||
IRuntimeContext,
|
|
||||||
CompositeValue,
|
CompositeValue,
|
||||||
|
IDataSourceRuntimeContext,
|
||||||
|
InterpretDataSourceConfig,
|
||||||
|
isJSExpression,
|
||||||
|
isJSFunction,
|
||||||
|
JSExpression,
|
||||||
JSFunction,
|
JSFunction,
|
||||||
JSONObject,
|
JSONObject,
|
||||||
isJSExpression,
|
} from '@ali/lowcode-types';
|
||||||
DataSourceConfig,
|
|
||||||
isJSFunction,
|
|
||||||
} from '@ali/build-success-types';
|
|
||||||
|
|
||||||
export const transformExpression = (code: string, context: IRuntimeContext) => {
|
export const transformExpression = (
|
||||||
|
code: string,
|
||||||
|
context: IDataSourceRuntimeContext,
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
return new Function(`return (${code})`).call(context);
|
return new Function(`return (${code})`).call(context);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -20,7 +24,10 @@ export const transformExpression = (code: string, context: IRuntimeContext) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformFunction = (code: string, context: IRuntimeContext) => {
|
export const transformFunction = (
|
||||||
|
code: string,
|
||||||
|
context: IDataSourceRuntimeContext,
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
return new Function(`return (${code})`).call(context).bind(context);
|
return new Function(`return (${code})`).call(context).bind(context);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -36,12 +43,13 @@ export const transformBoolStr = (str: string) => {
|
|||||||
|
|
||||||
export const getRuntimeJsValue = (
|
export const getRuntimeJsValue = (
|
||||||
value: JSExpression | JSFunction,
|
value: JSExpression | JSFunction,
|
||||||
context: IRuntimeContext,
|
context: IDataSourceRuntimeContext,
|
||||||
) => {
|
) => {
|
||||||
if (!['JSExpression', 'JSFunction'].includes(value.type)) {
|
if (!['JSExpression', 'JSFunction'].includes(value.type)) {
|
||||||
console.error(`translate error, value is ${JSON.stringify(value)}`);
|
console.error(`translate error, value is ${JSON.stringify(value)}`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
// TODO: 类型修复
|
||||||
const code = value.compiled || value.value;
|
const code = value.compiled || value.value;
|
||||||
return value.type === 'JSFunction'
|
return value.type === 'JSFunction'
|
||||||
? transformFunction(code, context)
|
? transformFunction(code, context)
|
||||||
@ -66,7 +74,7 @@ export const getRuntimeBaseValue = (type: string, value: any) => {
|
|||||||
export const getRuntimeValueFromConfig = (
|
export const getRuntimeValueFromConfig = (
|
||||||
type: string,
|
type: string,
|
||||||
value: CompositeValue,
|
value: CompositeValue,
|
||||||
context: IRuntimeContext,
|
context: IDataSourceRuntimeContext,
|
||||||
) => {
|
) => {
|
||||||
if (!value) return undefined;
|
if (!value) return undefined;
|
||||||
if (isJSExpression(value) || isJSFunction(value)) {
|
if (isJSExpression(value) || isJSFunction(value)) {
|
||||||
@ -77,7 +85,7 @@ export const getRuntimeValueFromConfig = (
|
|||||||
|
|
||||||
export const buildJsonObj = (
|
export const buildJsonObj = (
|
||||||
params: JSONObject | JSExpression,
|
params: JSONObject | JSExpression,
|
||||||
context: IRuntimeContext,
|
context: IDataSourceRuntimeContext,
|
||||||
) => {
|
) => {
|
||||||
const result: Record<string, any> = {};
|
const result: Record<string, any> = {};
|
||||||
if (isJSExpression(params)) {
|
if (isJSExpression(params)) {
|
||||||
@ -96,8 +104,8 @@ export const buildJsonObj = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const buildShouldFetch = (
|
export const buildShouldFetch = (
|
||||||
ds: DataSourceConfig,
|
ds: InterpretDataSourceConfig,
|
||||||
context: IRuntimeContext,
|
context: IDataSourceRuntimeContext,
|
||||||
) => {
|
) => {
|
||||||
if (!ds.options || !ds.shouldFetch) {
|
if (!ds.options || !ds.shouldFetch) {
|
||||||
return true; // 默认为 true
|
return true; // 默认为 true
|
||||||
@ -110,12 +118,12 @@ export const buildShouldFetch = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const buildOptions = (
|
export const buildOptions = (
|
||||||
ds: DataSourceConfig,
|
ds: InterpretDataSourceConfig,
|
||||||
context: IRuntimeContext,
|
context: IDataSourceRuntimeContext,
|
||||||
) => {
|
) => {
|
||||||
const { options } = ds;
|
const { options } = ds;
|
||||||
if (!options) return undefined;
|
if (!options) return undefined;
|
||||||
return function () {
|
return function() {
|
||||||
return {
|
return {
|
||||||
uri: getRuntimeValueFromConfig('string', options.uri, context),
|
uri: getRuntimeValueFromConfig('string', options.uri, context),
|
||||||
params: options.params ? buildJsonObj(options.params, context) : {},
|
params: options.params ? buildJsonObj(options.params, context) : {},
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
import { IDataSourceEngine, IRuntimeContext } from '@ali/build-success-types';
|
import {
|
||||||
|
IDataSourceRuntimeContext,
|
||||||
|
IDataSourceEngine
|
||||||
|
} from '@ali/lowcode-types';
|
||||||
|
|
||||||
export class MockContext<TState extends object = Record<string, unknown>>
|
export class MockContext<TState extends Record<string, unknown> = Record<string, unknown>>
|
||||||
implements IRuntimeContext<TState> {
|
implements IDataSourceRuntimeContext<TState> {
|
||||||
private _dataSourceEngine: IDataSourceEngine;
|
private _dataSourceEngine: IDataSourceEngine;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private _state: TState,
|
private _state: TState,
|
||||||
private _createDataSourceEngine: (
|
private _createDataSourceEngine: (
|
||||||
context: IRuntimeContext<TState>
|
context: IDataSourceRuntimeContext<TState>
|
||||||
) => IDataSourceEngine,
|
) => IDataSourceEngine,
|
||||||
private _customMethods: Record<string, () => any> = {}
|
private _customMethods: Record<string, () => any> = {}
|
||||||
) {
|
) {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RuntimeDataSource } from '@ali/build-success-types';
|
import { RuntimeDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的:
|
// 这里仅仅是数据源部分的:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { DataSource } from '@ali/build-success-types';
|
import { InterpretDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的 schema:
|
// 这里仅仅是数据源部分的 schema:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
export const DATA_SOURCE_SCHEMA: DataSource = {
|
export const DATA_SOURCE_SCHEMA: InterpretDataSource = {
|
||||||
list: [
|
list: [
|
||||||
{
|
{
|
||||||
id: 'user',
|
id: 'user',
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { delay, MockContext } from '../../_helpers';
|
import { delay, MockContext } from '../../_helpers';
|
||||||
@ -17,56 +17,56 @@ export const abnormalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
const ERROR_MSG = 'test error';
|
const ERROR_MSG = 'test error';
|
||||||
const fetchHandler = sinon.fake(async () => {
|
const fetchHandler = sinon.fake(async () => {
|
||||||
await delay(100);
|
await delay(100);
|
||||||
throw new Error(ERROR_MSG);
|
throw new Error(ERROR_MSG);
|
||||||
});
|
});
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
||||||
requestHandlersMap: {
|
requestHandlersMap: {
|
||||||
fetch: fetchHandler,
|
fetch: fetchHandler,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
// 一开始应该是初始状态
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
// 中间应该有 loading 态
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
// 最后应该失败了,error 状态
|
// 最后应该失败了,error 状态
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Error);
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Error);
|
||||||
|
|
||||||
// 检查数据源的数据
|
// 检查数据源的数据
|
||||||
t.deepEqual(context.dataSourceMap.user.data, undefined);
|
t.deepEqual(context.dataSourceMap.user.data, undefined);
|
||||||
t.not(context.dataSourceMap.user.error, undefined);
|
t.not(context.dataSourceMap.user.error, undefined);
|
||||||
t.regex(context.dataSourceMap.user.error!.message, new RegExp(ERROR_MSG));
|
t.regex(context.dataSourceMap.user.error!.message, new RegExp(ERROR_MSG));
|
||||||
|
|
||||||
// 检查状态数据
|
// 检查状态数据
|
||||||
t.assert(setState.notCalled);
|
t.assert(setState.notCalled);
|
||||||
t.deepEqual(context.state.user, undefined);
|
t.deepEqual(context.state.user, undefined);
|
||||||
|
|
||||||
// fetchHandler 不应该被调
|
// fetchHandler 不应该被调
|
||||||
t.assert(fetchHandler.calledOnce);
|
t.assert(fetchHandler.calledOnce);
|
||||||
};
|
};
|
||||||
|
|
||||||
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { delay, MockContext } from '../../_helpers';
|
import { delay, MockContext } from '../../_helpers';
|
||||||
@ -17,65 +17,65 @@ export const normalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
|
|
||||||
const USER_DATA = {
|
const USER_DATA = {
|
||||||
name: 'Alice',
|
name: 'Alice',
|
||||||
age: 18,
|
age: 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchHandler = sinon.fake(async () => {
|
||||||
|
await delay(100);
|
||||||
|
return { data: USER_DATA };
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
|
||||||
|
// 一开始应该是初始状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
|
// 最后应该成功了,loaded 状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
|
||||||
|
// 检查数据源的数据
|
||||||
|
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
||||||
|
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
||||||
|
|
||||||
|
// 检查状态数据
|
||||||
|
t.assert(setState.calledOnce);
|
||||||
|
t.deepEqual(context.state.user, USER_DATA);
|
||||||
|
|
||||||
|
// fetchHandler 应该被调用了一次
|
||||||
|
t.assert(fetchHandler.calledOnce);
|
||||||
|
|
||||||
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
// 检查调用参数
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchHandler = sinon.fake(async () => {
|
|
||||||
await delay(100);
|
|
||||||
return { data: USER_DATA };
|
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
|
||||||
|
|
||||||
// 最后应该成功了,loaded 状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
|
|
||||||
// 检查数据源的数据
|
|
||||||
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
|
||||||
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
|
||||||
|
|
||||||
// 检查状态数据
|
|
||||||
t.assert(setState.calledOnce);
|
|
||||||
t.deepEqual(context.state.user, USER_DATA);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了一次
|
|
||||||
t.assert(fetchHandler.calledOnce);
|
|
||||||
|
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
|
||||||
// 检查调用参数
|
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
|
||||||
};
|
|
||||||
|
|
||||||
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RuntimeDataSource } from '@ali/build-success-types';
|
import { RuntimeDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的:
|
// 这里仅仅是数据源部分的:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { DataSource } from '@ali/build-success-types';
|
import { InterpretDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的 schema:
|
// 这里仅仅是数据源部分的 schema:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
export const DATA_SOURCE_SCHEMA: DataSource = {
|
export const DATA_SOURCE_SCHEMA: InterpretDataSource = {
|
||||||
list: [
|
list: [
|
||||||
{
|
{
|
||||||
id: 'user',
|
id: 'user',
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
||||||
@ -17,80 +17,80 @@ export const abnormalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
|
|
||||||
const USER_DATA = {
|
const USER_DATA = {
|
||||||
id: 9527,
|
id: 9527,
|
||||||
name: 'Alice',
|
name: 'Alice',
|
||||||
|
};
|
||||||
|
const ERROR_MSG = 'test error';
|
||||||
|
const fetchHandler = sinon.fake(async ({ uri }) => {
|
||||||
|
await delay(100);
|
||||||
|
if (/user/.test(uri)) {
|
||||||
|
return { data: USER_DATA };
|
||||||
|
} else {
|
||||||
|
throw new Error(ERROR_MSG);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
|
||||||
|
// 一开始应该是初始状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
|
// 最后 user 应该成功了,loaded
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
// 最后 orders 应该失败了,error 状态
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Error);
|
||||||
|
|
||||||
|
// 检查数据源的数据
|
||||||
|
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
||||||
|
t.is(context.dataSourceMap.user.error, undefined);
|
||||||
|
t.deepEqual(context.dataSourceMap.orders.data, undefined);
|
||||||
|
t.not(context.dataSourceMap.orders.error, undefined);
|
||||||
|
t.regex(context.dataSourceMap.orders.error!.message, new RegExp(ERROR_MSG));
|
||||||
|
|
||||||
|
// 检查状态数据
|
||||||
|
t.assert(setState.calledOnce);
|
||||||
|
t.deepEqual(context.state.user, USER_DATA);
|
||||||
|
t.is(context.state.orders, undefined);
|
||||||
|
|
||||||
|
// fetchHandler 应该被调用了2次
|
||||||
|
t.assert(fetchHandler.calledTwice);
|
||||||
|
|
||||||
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
// 检查调用参数
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
};
|
};
|
||||||
const ERROR_MSG = 'test error';
|
|
||||||
const fetchHandler = sinon.fake(async ({ uri }) => {
|
|
||||||
await delay(100);
|
|
||||||
if (/user/.test(uri)) {
|
|
||||||
return { data: USER_DATA };
|
|
||||||
} else {
|
|
||||||
throw new Error(ERROR_MSG);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
|
||||||
|
|
||||||
// 最后 user 应该成功了,loaded
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
// 最后 orders 应该失败了,error 状态
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Error);
|
|
||||||
|
|
||||||
// 检查数据源的数据
|
|
||||||
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
|
||||||
t.is(context.dataSourceMap.user.error, undefined);
|
|
||||||
t.deepEqual(context.dataSourceMap.orders.data, undefined);
|
|
||||||
t.not(context.dataSourceMap.orders.error, undefined);
|
|
||||||
t.regex(context.dataSourceMap.orders.error!.message, new RegExp(ERROR_MSG));
|
|
||||||
|
|
||||||
// 检查状态数据
|
|
||||||
t.assert(setState.calledOnce);
|
|
||||||
t.deepEqual(context.state.user, USER_DATA);
|
|
||||||
t.is(context.state.orders, undefined);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了2次
|
|
||||||
t.assert(fetchHandler.calledTwice);
|
|
||||||
|
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
|
||||||
// 检查调用参数
|
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
|
||||||
};
|
|
||||||
|
|
||||||
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
||||||
@ -17,76 +17,76 @@ export const normalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
|
|
||||||
const USER_DATA = {
|
const USER_DATA = {
|
||||||
id: 9527,
|
id: 9527,
|
||||||
name: 'Alice',
|
name: 'Alice',
|
||||||
|
};
|
||||||
|
|
||||||
|
const ORDERS_DATA = [{ id: 123 }, { id: 456 }];
|
||||||
|
|
||||||
|
const fetchHandler = sinon.fake(async ({ uri }) => {
|
||||||
|
await delay(100);
|
||||||
|
return { data: /user/.test(uri) ? USER_DATA : ORDERS_DATA };
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
|
||||||
|
// 一开始应该是初始状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
|
// 最后应该成功了,loaded 状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
|
||||||
|
// 检查数据源的数据
|
||||||
|
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
||||||
|
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
||||||
|
t.deepEqual(context.dataSourceMap.orders.data, ORDERS_DATA);
|
||||||
|
t.deepEqual(context.dataSourceMap.orders.error, undefined);
|
||||||
|
|
||||||
|
// 检查状态数据
|
||||||
|
t.assert(setState.calledTwice);
|
||||||
|
t.deepEqual(context.state.user, USER_DATA);
|
||||||
|
t.deepEqual(context.state.orders, ORDERS_DATA);
|
||||||
|
|
||||||
|
// fetchHandler 应该被调用了2次
|
||||||
|
t.assert(fetchHandler.calledTwice);
|
||||||
|
|
||||||
|
// 检查调用参数
|
||||||
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ORDERS_DATA = [{ id: 123 }, { id: 456 }];
|
|
||||||
|
|
||||||
const fetchHandler = sinon.fake(async ({ uri }) => {
|
|
||||||
await delay(100);
|
|
||||||
return { data: /user/.test(uri) ? USER_DATA : ORDERS_DATA };
|
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
|
||||||
|
|
||||||
// 最后应该成功了,loaded 状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
|
|
||||||
// 检查数据源的数据
|
|
||||||
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
|
||||||
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
|
||||||
t.deepEqual(context.dataSourceMap.orders.data, ORDERS_DATA);
|
|
||||||
t.deepEqual(context.dataSourceMap.orders.error, undefined);
|
|
||||||
|
|
||||||
// 检查状态数据
|
|
||||||
t.assert(setState.calledTwice);
|
|
||||||
t.deepEqual(context.state.user, USER_DATA);
|
|
||||||
t.deepEqual(context.state.orders, ORDERS_DATA);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了2次
|
|
||||||
t.assert(fetchHandler.calledTwice);
|
|
||||||
|
|
||||||
// 检查调用参数
|
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
|
||||||
};
|
|
||||||
|
|
||||||
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RuntimeDataSource } from '@ali/build-success-types';
|
import { RuntimeDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的:
|
// 这里仅仅是数据源部分的:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { DataSource } from '@ali/build-success-types';
|
import { InterpretDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的 schema:
|
// 这里仅仅是数据源部分的 schema:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
export const DATA_SOURCE_SCHEMA: DataSource = {
|
export const DATA_SOURCE_SCHEMA: InterpretDataSource = {
|
||||||
list: [
|
list: [
|
||||||
{
|
{
|
||||||
id: 'urlParams',
|
id: 'urlParams',
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { MockContext } from '../../_helpers';
|
import { MockContext } from '../../_helpers';
|
||||||
@ -16,57 +16,57 @@ export const normalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
|
|
||||||
const URL_PARAMS = {
|
const URL_PARAMS = {
|
||||||
name: 'Alice',
|
name: 'Alice',
|
||||||
age: '18',
|
age: '18',
|
||||||
|
};
|
||||||
|
|
||||||
|
const urlParamsHandler = sinon.fake(async () => {
|
||||||
|
return URL_PARAMS; // TODO: 别的都是返回的套了一层 data 的,但是 urlParams 的为啥不一样?
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
urlParams: urlParamsHandler,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
|
||||||
|
// 一开始应该是初始状态
|
||||||
|
t.is(context.dataSourceMap.urlParams.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
|
// 最后应该成功了,loaded 状态
|
||||||
|
t.is(context.dataSourceMap.urlParams.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
|
||||||
|
// 检查数据源的数据
|
||||||
|
t.deepEqual(context.dataSourceMap.urlParams.data, URL_PARAMS);
|
||||||
|
t.deepEqual(context.dataSourceMap.urlParams.error, undefined);
|
||||||
|
|
||||||
|
// 检查状态数据
|
||||||
|
t.assert(setState.calledOnce);
|
||||||
|
t.deepEqual(context.state.urlParams, URL_PARAMS);
|
||||||
|
|
||||||
|
// fetchHandler 应该被调用了一次
|
||||||
|
t.assert(urlParamsHandler.calledOnce);
|
||||||
|
|
||||||
|
// 检查调用参数 url 没有 options
|
||||||
|
t.deepEqual(urlParamsHandler.firstCall.args, [context]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const urlParamsHandler = sinon.fake(async () => {
|
|
||||||
return URL_PARAMS; // TODO: 别的都是返回的套了一层 data 的,但是 urlParams 的为啥不一样?
|
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
urlParams: urlParamsHandler,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
|
||||||
t.is(context.dataSourceMap.urlParams.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
|
||||||
|
|
||||||
// 最后应该成功了,loaded 状态
|
|
||||||
t.is(context.dataSourceMap.urlParams.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
|
|
||||||
// 检查数据源的数据
|
|
||||||
t.deepEqual(context.dataSourceMap.urlParams.data, URL_PARAMS);
|
|
||||||
t.deepEqual(context.dataSourceMap.urlParams.error, undefined);
|
|
||||||
|
|
||||||
// 检查状态数据
|
|
||||||
t.assert(setState.calledOnce);
|
|
||||||
t.deepEqual(context.state.urlParams, URL_PARAMS);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了一次
|
|
||||||
t.assert(urlParamsHandler.calledOnce);
|
|
||||||
|
|
||||||
// 检查调用参数 url 没有 options
|
|
||||||
t.deepEqual(urlParamsHandler.firstCall.args, [context]);
|
|
||||||
};
|
|
||||||
|
|
||||||
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RuntimeDataSource } from '@ali/build-success-types';
|
import { RuntimeDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的:
|
// 这里仅仅是数据源部分的:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { DataSource } from '@ali/build-success-types';
|
import { InterpretDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的 schema:
|
// 这里仅仅是数据源部分的 schema:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
export const DATA_SOURCE_SCHEMA: DataSource = {
|
export const DATA_SOURCE_SCHEMA: InterpretDataSource = {
|
||||||
list: [
|
list: [
|
||||||
{
|
{
|
||||||
id: 'user',
|
id: 'user',
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
||||||
@ -17,79 +17,79 @@ export const abnormalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
const ERROR_MSG = 'test error';
|
const ERROR_MSG = 'test error';
|
||||||
const fetchHandler = sinon.fake(async () => {
|
const fetchHandler = sinon.fake(async () => {
|
||||||
await delay(100);
|
await delay(100);
|
||||||
return {
|
return {
|
||||||
data: {
|
data: {
|
||||||
success: false,
|
success: false,
|
||||||
message: ERROR_MSG,
|
message: ERROR_MSG,
|
||||||
code: 'E_FOO',
|
code: 'E_FOO',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>(
|
||||||
|
{},
|
||||||
|
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
recordError() { },
|
||||||
},
|
},
|
||||||
};
|
);
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>(
|
const setState = sinon.spy(context, 'setState');
|
||||||
{},
|
const recordError = sinon.spy(context, 'recordError');
|
||||||
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
recordError() {},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
// 一开始应该是初始状态
|
||||||
const recordError = sinon.spy(context, 'recordError');
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
const loading = context.reloadDataSource();
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
// 最后应该失败了,error 状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Error);
|
||||||
|
|
||||||
// 最后应该失败了,error 状态
|
// 检查数据源的数据
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Error);
|
t.deepEqual(context.dataSourceMap.user.data, undefined);
|
||||||
|
t.not(context.dataSourceMap.user.error, undefined);
|
||||||
|
|
||||||
// 检查数据源的数据
|
t.regex(context.dataSourceMap.user.error!.message, new RegExp(ERROR_MSG));
|
||||||
t.deepEqual(context.dataSourceMap.user.data, undefined);
|
|
||||||
t.not(context.dataSourceMap.user.error, undefined);
|
|
||||||
|
|
||||||
t.regex(context.dataSourceMap.user.error!.message, new RegExp(ERROR_MSG));
|
// 检查状态数据
|
||||||
|
t.assert(setState.notCalled);
|
||||||
|
t.deepEqual(context.state.user, undefined);
|
||||||
|
|
||||||
// 检查状态数据
|
// fetchHandler 应该被调用了一次
|
||||||
t.assert(setState.notCalled);
|
t.assert(fetchHandler.calledOnce);
|
||||||
t.deepEqual(context.state.user, undefined);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了一次
|
// 检查调用参数
|
||||||
t.assert(fetchHandler.calledOnce);
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
|
|
||||||
// 检查调用参数
|
// 埋点应该也会被调用
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
t.assert(recordError.calledOnce);
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
t.snapshot(recordError.firstCall.args);
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
};
|
||||||
|
|
||||||
// 埋点应该也会被调用
|
|
||||||
t.assert(recordError.calledOnce);
|
|
||||||
t.snapshot(recordError.firstCall.args);
|
|
||||||
};
|
|
||||||
|
|
||||||
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
||||||
@ -17,80 +17,80 @@ export const normalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
|
|
||||||
const USER_DATA = {
|
const USER_DATA = {
|
||||||
name: 'Alice',
|
name: 'Alice',
|
||||||
age: 18,
|
age: 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchHandler = sinon.fake(async () => {
|
||||||
|
await delay(100);
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
success: true,
|
||||||
|
data: USER_DATA,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>(
|
||||||
|
{},
|
||||||
|
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
recordError() { },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
const recordError = sinon.spy(context, 'recordError');
|
||||||
|
|
||||||
|
// 一开始应该是初始状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
|
// 最后应该成功了,loaded 状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
|
||||||
|
// 检查数据源的数据
|
||||||
|
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
||||||
|
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
||||||
|
|
||||||
|
// 检查状态数据
|
||||||
|
t.assert(setState.calledOnce);
|
||||||
|
t.deepEqual(context.state.user, USER_DATA);
|
||||||
|
|
||||||
|
// fetchHandler 应该被调用了一次
|
||||||
|
t.assert(fetchHandler.calledOnce);
|
||||||
|
|
||||||
|
// 检查调用参数
|
||||||
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
|
|
||||||
|
// 埋点不应该被调用
|
||||||
|
t.assert(recordError.notCalled);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchHandler = sinon.fake(async () => {
|
|
||||||
await delay(100);
|
|
||||||
return {
|
|
||||||
data: {
|
|
||||||
success: true,
|
|
||||||
data: USER_DATA,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>(
|
|
||||||
{},
|
|
||||||
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
recordError() {},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
|
||||||
const recordError = sinon.spy(context, 'recordError');
|
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
|
||||||
|
|
||||||
// 最后应该成功了,loaded 状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
|
|
||||||
// 检查数据源的数据
|
|
||||||
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
|
||||||
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
|
||||||
|
|
||||||
// 检查状态数据
|
|
||||||
t.assert(setState.calledOnce);
|
|
||||||
t.deepEqual(context.state.user, USER_DATA);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了一次
|
|
||||||
t.assert(fetchHandler.calledOnce);
|
|
||||||
|
|
||||||
// 检查调用参数
|
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
|
||||||
|
|
||||||
// 埋点不应该被调用
|
|
||||||
t.assert(recordError.notCalled);
|
|
||||||
};
|
|
||||||
|
|
||||||
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RuntimeDataSource } from '@ali/build-success-types';
|
import { RuntimeDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
export const DEFAULT_USER_DATA = { id: 0, name: 'guest' }; // 返回一个兜底的数据
|
export const DEFAULT_USER_DATA = { id: 0, name: 'guest' }; // 返回一个兜底的数据
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { DataSource } from '@ali/build-success-types';
|
import { InterpretDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的 schema:
|
// 这里仅仅是数据源部分的 schema:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
export const DATA_SOURCE_SCHEMA: DataSource = {
|
export const DATA_SOURCE_SCHEMA: InterpretDataSource = {
|
||||||
list: [
|
list: [
|
||||||
{
|
{
|
||||||
id: 'user',
|
id: 'user',
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { delay, MockContext } from '../../_helpers';
|
import { delay, MockContext } from '../../_helpers';
|
||||||
@ -17,62 +17,62 @@ export const abnormalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
const ERROR_MSG = 'test error';
|
const ERROR_MSG = 'test error';
|
||||||
const fetchHandler = sinon.fake(async () => {
|
const fetchHandler = sinon.fake(async () => {
|
||||||
await delay(100);
|
await delay(100);
|
||||||
throw new Error(ERROR_MSG);
|
throw new Error(ERROR_MSG);
|
||||||
});
|
});
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
||||||
requestHandlersMap: {
|
requestHandlersMap: {
|
||||||
fetch: fetchHandler,
|
fetch: fetchHandler,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
// 一开始应该是初始状态
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
// 中间应该有 loading 态
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
// 注意 error 是会被吃掉了,还是 loaded 状态
|
// 注意 error 是会被吃掉了,还是 loaded 状态
|
||||||
// FIXME: 根据协议内容,dataHandler 返回的结果是需要抛出错误的,那么 fetchHandler 的错误难道不需要处理?
|
// FIXME: 根据协议内容,dataHandler 返回的结果是需要抛出错误的,那么 fetchHandler 的错误难道不需要处理?
|
||||||
// TODO: 提案:request 如果挂了,不应该需要走 dataHandler 了,没有意义
|
// TODO: 提案:request 如果挂了,不应该需要走 dataHandler 了,没有意义
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Error);
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Error);
|
||||||
|
|
||||||
// 检查数据源的数据
|
// 检查数据源的数据
|
||||||
t.deepEqual(context.dataSourceMap.user.data, undefined);
|
t.deepEqual(context.dataSourceMap.user.data, undefined);
|
||||||
t.not(context.dataSourceMap.user.error, undefined);
|
t.not(context.dataSourceMap.user.error, undefined);
|
||||||
t.regex(context.dataSourceMap.user.error!.message, new RegExp(ERROR_MSG));
|
t.regex(context.dataSourceMap.user.error!.message, new RegExp(ERROR_MSG));
|
||||||
|
|
||||||
// 检查状态数据
|
// 检查状态数据
|
||||||
t.assert(setState.notCalled);
|
t.assert(setState.notCalled);
|
||||||
|
|
||||||
// fetchHandler 应该没调
|
// fetchHandler 应该没调
|
||||||
t.assert.skip(fetchHandler.notCalled);
|
t.assert.skip(fetchHandler.notCalled);
|
||||||
|
|
||||||
// 检查调用参数
|
// 检查调用参数
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { delay, MockContext } from '../../_helpers';
|
import { delay, MockContext } from '../../_helpers';
|
||||||
@ -17,65 +17,65 @@ export const normalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
|
|
||||||
const USER_DATA = {
|
const USER_DATA = {
|
||||||
name: 'Alice',
|
name: 'Alice',
|
||||||
age: 18,
|
age: 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchHandler = sinon.fake(async () => {
|
||||||
|
await delay(100);
|
||||||
|
return { data: USER_DATA };
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
|
||||||
|
// 一开始应该是初始状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
|
// 最后应该成功了,loaded 状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
|
||||||
|
// 检查数据源的数据
|
||||||
|
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
||||||
|
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
||||||
|
|
||||||
|
// 检查状态数据
|
||||||
|
t.assert(setState.calledOnce);
|
||||||
|
t.deepEqual(context.state.user, USER_DATA);
|
||||||
|
|
||||||
|
// fetchHandler 应该被调用了一次
|
||||||
|
t.assert(fetchHandler.calledOnce);
|
||||||
|
|
||||||
|
// 检查调用参数
|
||||||
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchHandler = sinon.fake(async () => {
|
|
||||||
await delay(100);
|
|
||||||
return { data: USER_DATA };
|
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>({}, (ctx) => create(dataSource, ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
|
||||||
|
|
||||||
// 最后应该成功了,loaded 状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
|
|
||||||
// 检查数据源的数据
|
|
||||||
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
|
||||||
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
|
||||||
|
|
||||||
// 检查状态数据
|
|
||||||
t.assert(setState.calledOnce);
|
|
||||||
t.deepEqual(context.state.user, USER_DATA);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了一次
|
|
||||||
t.assert(fetchHandler.calledOnce);
|
|
||||||
|
|
||||||
// 检查调用参数
|
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
|
||||||
};
|
|
||||||
|
|
||||||
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RuntimeDataSource } from '@ali/build-success-types';
|
import { RuntimeDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的:
|
// 这里仅仅是数据源部分的:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { DataSource } from '@ali/build-success-types';
|
import { InterpretDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的 schema:
|
// 这里仅仅是数据源部分的 schema:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
export const DATA_SOURCE_SCHEMA: DataSource = {
|
export const DATA_SOURCE_SCHEMA: InterpretDataSource = {
|
||||||
list: [
|
list: [
|
||||||
{
|
{
|
||||||
id: 'user',
|
id: 'user',
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
||||||
@ -17,79 +17,79 @@ export const abnormalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
const ERROR_MSG = 'test error';
|
const ERROR_MSG = 'test error';
|
||||||
const fetchHandler = sinon.fake(async () => {
|
const fetchHandler = sinon.fake(async () => {
|
||||||
await delay(100);
|
await delay(100);
|
||||||
return {
|
return {
|
||||||
data: {
|
data: {
|
||||||
success: false,
|
success: false,
|
||||||
message: ERROR_MSG,
|
message: ERROR_MSG,
|
||||||
code: 'E_FOO',
|
code: 'E_FOO',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>(
|
||||||
|
{},
|
||||||
|
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
recordError() { },
|
||||||
},
|
},
|
||||||
};
|
);
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>(
|
const setState = sinon.spy(context, 'setState');
|
||||||
{},
|
const recordError = sinon.spy(context, 'recordError');
|
||||||
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
recordError() {},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
// 一开始应该是初始状态
|
||||||
const recordError = sinon.spy(context, 'recordError');
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
const loading = context.reloadDataSource();
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
// 最后应该失败了,error 状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Error);
|
||||||
|
|
||||||
// 最后应该失败了,error 状态
|
// 检查数据源的数据
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Error);
|
t.deepEqual(context.dataSourceMap.user.data, undefined);
|
||||||
|
t.not(context.dataSourceMap.user.error, undefined);
|
||||||
|
|
||||||
// 检查数据源的数据
|
t.regex(context.dataSourceMap.user.error!.message, new RegExp(ERROR_MSG));
|
||||||
t.deepEqual(context.dataSourceMap.user.data, undefined);
|
|
||||||
t.not(context.dataSourceMap.user.error, undefined);
|
|
||||||
|
|
||||||
t.regex(context.dataSourceMap.user.error!.message, new RegExp(ERROR_MSG));
|
// 检查状态数据
|
||||||
|
t.assert(setState.notCalled);
|
||||||
|
t.deepEqual(context.state.user, undefined);
|
||||||
|
|
||||||
// 检查状态数据
|
// fetchHandler 应该被调用了一次
|
||||||
t.assert(setState.notCalled);
|
t.assert(fetchHandler.calledOnce);
|
||||||
t.deepEqual(context.state.user, undefined);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了一次
|
// 检查调用参数
|
||||||
t.assert(fetchHandler.calledOnce);
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
|
|
||||||
// 检查调用参数
|
// 埋点应该也会被调用
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
t.assert(recordError.calledOnce);
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
t.snapshot(recordError.firstCall.args);
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
};
|
||||||
|
|
||||||
// 埋点应该也会被调用
|
|
||||||
t.assert(recordError.calledOnce);
|
|
||||||
t.snapshot(recordError.firstCall.args);
|
|
||||||
};
|
|
||||||
|
|
||||||
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
abnormalScene.title = (providedTitle) => providedTitle || 'abnormal scene';
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
||||||
@ -17,80 +17,80 @@ export const normalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
|
|
||||||
const USER_DATA = {
|
const USER_DATA = {
|
||||||
name: 'Alice',
|
name: 'Alice',
|
||||||
age: 18,
|
age: 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchHandler = sinon.fake(async () => {
|
||||||
|
await delay(100);
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
success: true,
|
||||||
|
data: USER_DATA,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>(
|
||||||
|
{},
|
||||||
|
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
recordError() { },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
const recordError = sinon.spy(context, 'recordError');
|
||||||
|
|
||||||
|
// 一开始应该是初始状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
|
// 最后应该成功了,loaded 状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
|
||||||
|
// 检查数据源的数据
|
||||||
|
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
||||||
|
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
||||||
|
|
||||||
|
// 检查状态数据
|
||||||
|
t.assert(setState.calledOnce);
|
||||||
|
t.deepEqual(context.state.user, USER_DATA);
|
||||||
|
|
||||||
|
// fetchHandler 应该被调用了一次
|
||||||
|
t.assert(fetchHandler.calledOnce);
|
||||||
|
|
||||||
|
// 检查调用参数
|
||||||
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
|
|
||||||
|
// 埋点不应该被调用
|
||||||
|
t.assert(recordError.notCalled);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchHandler = sinon.fake(async () => {
|
|
||||||
await delay(100);
|
|
||||||
return {
|
|
||||||
data: {
|
|
||||||
success: true,
|
|
||||||
data: USER_DATA,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>(
|
|
||||||
{},
|
|
||||||
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
recordError() {},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
|
||||||
const recordError = sinon.spy(context, 'recordError');
|
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
|
||||||
|
|
||||||
// 最后应该成功了,loaded 状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
|
|
||||||
// 检查数据源的数据
|
|
||||||
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
|
||||||
t.deepEqual(context.dataSourceMap.user.error, undefined);
|
|
||||||
|
|
||||||
// 检查状态数据
|
|
||||||
t.assert(setState.calledOnce);
|
|
||||||
t.deepEqual(context.state.user, USER_DATA);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了一次
|
|
||||||
t.assert(fetchHandler.calledOnce);
|
|
||||||
|
|
||||||
// 检查调用参数
|
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
|
||||||
|
|
||||||
// 埋点不应该被调用
|
|
||||||
t.assert(recordError.notCalled);
|
|
||||||
};
|
|
||||||
|
|
||||||
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RuntimeDataSource } from '@ali/build-success-types';
|
import { RuntimeDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的:
|
// 这里仅仅是数据源部分的:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { DataSource } from '@ali/build-success-types';
|
import { InterpretDataSource } from '@ali/lowcode-types';
|
||||||
|
|
||||||
// 这里仅仅是数据源部分的 schema:
|
// 这里仅仅是数据源部分的 schema:
|
||||||
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
// @see: https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
export const DATA_SOURCE_SCHEMA: DataSource = {
|
export const DATA_SOURCE_SCHEMA: InterpretDataSource = {
|
||||||
list: [
|
list: [
|
||||||
{
|
{
|
||||||
id: 'user',
|
id: 'user',
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DataSource,
|
InterpretDataSource,
|
||||||
IDataSourceEngine,
|
IDataSourceEngine,
|
||||||
IRuntimeContext,
|
IDataSourceRuntimeContext,
|
||||||
RuntimeDataSource,
|
RuntimeDataSource,
|
||||||
RuntimeDataSourceStatus,
|
RuntimeDataSourceStatus,
|
||||||
} from '@ali/build-success-types';
|
} from '@ali/lowcode-types';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
import { bindRuntimeContext, delay, MockContext } from '../../_helpers';
|
||||||
@ -17,92 +17,92 @@ export const normalScene: Macro<[
|
|||||||
{
|
{
|
||||||
create: (
|
create: (
|
||||||
dataSource: any,
|
dataSource: any,
|
||||||
ctx: IRuntimeContext,
|
ctx: IDataSourceRuntimeContext,
|
||||||
options: any
|
options: any
|
||||||
) => IDataSourceEngine;
|
) => IDataSourceEngine;
|
||||||
dataSource: RuntimeDataSource | DataSource;
|
dataSource: RuntimeDataSource | InterpretDataSource;
|
||||||
}
|
}
|
||||||
]> = async (
|
]> = async (
|
||||||
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
t: ExecutionContext<{ clock: SinonFakeTimers }>,
|
||||||
{ create, dataSource },
|
{ create, dataSource },
|
||||||
) => {
|
) => {
|
||||||
const { clock } = t.context;
|
const { clock } = t.context;
|
||||||
const ORDERS_ERROR_MSG =
|
const ORDERS_ERROR_MSG =
|
||||||
'the orders request should not fetch, please check the condition';
|
'the orders request should not fetch, please check the condition';
|
||||||
|
|
||||||
const USER_DATA = {
|
const USER_DATA = {
|
||||||
name: 'Alice',
|
name: 'Alice',
|
||||||
age: 18,
|
age: 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchHandler = sinon.fake(async () => {
|
||||||
|
await delay(100);
|
||||||
|
return {
|
||||||
|
data: USER_DATA,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = new MockContext<Record<string, unknown>>(
|
||||||
|
{},
|
||||||
|
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
||||||
|
requestHandlersMap: {
|
||||||
|
fetch: fetchHandler,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
recordError() { },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const setState = sinon.spy(context, 'setState');
|
||||||
|
// const recordError = sinon.spy(context, 'recordError');
|
||||||
|
|
||||||
|
// 一开始应该是初始状态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Initial);
|
||||||
|
|
||||||
|
const loading = context.reloadDataSource();
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
||||||
|
|
||||||
|
await clock.tickAsync(50);
|
||||||
|
|
||||||
|
// 中间应该有 loading 态
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Error);
|
||||||
|
|
||||||
|
await Promise.all([clock.runAllAsync(), loading]);
|
||||||
|
|
||||||
|
// 最后 user 成功, orders 失败
|
||||||
|
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
||||||
|
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Error);
|
||||||
|
|
||||||
|
// 检查数据源的数据
|
||||||
|
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
||||||
|
t.is(context.dataSourceMap.user.error, undefined);
|
||||||
|
t.regex(
|
||||||
|
context.dataSourceMap.orders.error!.message,
|
||||||
|
new RegExp(ORDERS_ERROR_MSG),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 检查状态数据
|
||||||
|
t.assert(setState.calledOnce);
|
||||||
|
t.deepEqual(context.state.user, USER_DATA);
|
||||||
|
|
||||||
|
// fetchHandler 应该被调用了 1 次
|
||||||
|
t.assert(fetchHandler.calledOnce);
|
||||||
|
|
||||||
|
// 检查调用参数
|
||||||
|
|
||||||
|
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
||||||
|
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
||||||
|
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
||||||
|
|
||||||
|
// // 埋点应该也会被调用
|
||||||
|
// t.assert(recordError.calledOnce);
|
||||||
|
// t.snapshot(recordError.firstCall.args);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchHandler = sinon.fake(async () => {
|
|
||||||
await delay(100);
|
|
||||||
return {
|
|
||||||
data: USER_DATA,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const context = new MockContext<Record<string, unknown>>(
|
|
||||||
{},
|
|
||||||
(ctx) => create(bindRuntimeContext(dataSource, ctx), ctx, {
|
|
||||||
requestHandlersMap: {
|
|
||||||
fetch: fetchHandler,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
recordError() {},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const setState = sinon.spy(context, 'setState');
|
|
||||||
// const recordError = sinon.spy(context, 'recordError');
|
|
||||||
|
|
||||||
// 一开始应该是初始状态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Initial);
|
|
||||||
|
|
||||||
const loading = context.reloadDataSource();
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loading);
|
|
||||||
|
|
||||||
await clock.tickAsync(50);
|
|
||||||
|
|
||||||
// 中间应该有 loading 态
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Error);
|
|
||||||
|
|
||||||
await Promise.all([clock.runAllAsync(), loading]);
|
|
||||||
|
|
||||||
// 最后 user 成功, orders 失败
|
|
||||||
t.is(context.dataSourceMap.user.status, RuntimeDataSourceStatus.Loaded);
|
|
||||||
t.is(context.dataSourceMap.orders.status, RuntimeDataSourceStatus.Error);
|
|
||||||
|
|
||||||
// 检查数据源的数据
|
|
||||||
t.deepEqual(context.dataSourceMap.user.data, USER_DATA);
|
|
||||||
t.is(context.dataSourceMap.user.error, undefined);
|
|
||||||
t.regex(
|
|
||||||
context.dataSourceMap.orders.error!.message,
|
|
||||||
new RegExp(ORDERS_ERROR_MSG),
|
|
||||||
);
|
|
||||||
|
|
||||||
// 检查状态数据
|
|
||||||
t.assert(setState.calledOnce);
|
|
||||||
t.deepEqual(context.state.user, USER_DATA);
|
|
||||||
|
|
||||||
// fetchHandler 应该被调用了 1 次
|
|
||||||
t.assert(fetchHandler.calledOnce);
|
|
||||||
|
|
||||||
// 检查调用参数
|
|
||||||
|
|
||||||
const firstListItemOptions = DATA_SOURCE_SCHEMA.list[0].options;
|
|
||||||
const fetchHandlerCallArgs = fetchHandler.firstCall.args[0];
|
|
||||||
t.is(firstListItemOptions.uri, fetchHandlerCallArgs.uri);
|
|
||||||
|
|
||||||
// // 埋点应该也会被调用
|
|
||||||
// t.assert(recordError.calledOnce);
|
|
||||||
// t.snapshot(recordError.firstCall.args);
|
|
||||||
};
|
|
||||||
|
|
||||||
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
normalScene.title = (providedTitle) => providedTitle || 'normal scene';
|
||||||
|
|||||||
3
packages/datasource-fetch-handler/.eslintignore
Normal file
3
packages/datasource-fetch-handler/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/node_modules
|
||||||
|
/es
|
||||||
|
/lib
|
||||||
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: '../../.eslintrc.js',
|
extends: '../../.eslintrc',
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/no-parameter-properties': 1,
|
'@typescript-eslint/no-parameter-properties': 1,
|
||||||
'no-param-reassign': 0,
|
'no-param-reassign': 0,
|
||||||
@ -1,4 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
trailingComma: 'always',
|
trailingComma: 'all',
|
||||||
};
|
};
|
||||||
@ -16,12 +16,10 @@
|
|||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ali/lowcode-types": "^1.0.10",
|
||||||
"typescript": "^3.9.7",
|
"typescript": "^3.9.7",
|
||||||
"universal-request": "^2.2.0"
|
"universal-request": "^2.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
|
||||||
"@ali/build-success-types": "^0.1.2-alpha.35"
|
|
||||||
},
|
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://registry.npm.alibaba-inc.com"
|
"registry": "https://registry.npm.alibaba-inc.com"
|
||||||
},
|
},
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { RuntimeOptionsConfig } from '@ali/build-success-types';
|
import { RuntimeOptionsConfig } from '@ali/lowcode-types';
|
||||||
|
|
||||||
import request from 'universal-request';
|
import request from 'universal-request';
|
||||||
import { RequestOptions, AsObject } from 'universal-request/lib/types';
|
import { RequestOptions, AsObject } from 'universal-request/lib/types';
|
||||||
@ -1,10 +1,16 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"outDir": "es",
|
||||||
|
"target": "es6",
|
||||||
|
"module": "esnext",
|
||||||
/* Basic Options */
|
/* Basic Options */
|
||||||
// "incremental": true, /* Enable incremental compilation */
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
// "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
// "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
||||||
// "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
// "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
||||||
"lib": ["ESNext", "DOM"] /* Specify library files to be included in the compilation. */,
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"DOM"
|
||||||
|
] /* Specify library files to be included in the compilation. */,
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
@ -21,7 +27,6 @@
|
|||||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
// "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'. */
|
// "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'). */
|
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
/* Strict Type-Checking Options */
|
||||||
"strict": true /* Enable all 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. */
|
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
@ -31,13 +36,11 @@
|
|||||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
// "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. */
|
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
|
|
||||||
/* Additional Checks */
|
/* Additional Checks */
|
||||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
|
|
||||||
/* Module Resolution Options */
|
/* Module Resolution Options */
|
||||||
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
||||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
@ -49,19 +52,19 @@
|
|||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
"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. */
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
||||||
/* Source Map Options */
|
/* Source Map Options */
|
||||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
// "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. */
|
// "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. */
|
// "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. */
|
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||||
|
|
||||||
/* Experimental Options */
|
/* Experimental Options */
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
|
|
||||||
/* Advanced Options */
|
/* Advanced Options */
|
||||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true,
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
/node_modules/
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"packages": ["packages/*"],
|
|
||||||
"version": "independent",
|
|
||||||
"npmClient": "yarn"
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@ali/lowcode-datasource-handlers",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "index.js",
|
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"lerna": "^3.22.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
import { RuntimeOptionsConfig } from '@ali/build-success-types';
|
|
||||||
export declare function createFetchHandler(config?: unknown): (options: RuntimeOptionsConfig) => Promise<any>;
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
import request from 'universal-request';
|
|
||||||
// config 留着扩展
|
|
||||||
export function createFetchHandler(config) {
|
|
||||||
return function (options) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
const requestConfig = Object.assign(Object.assign({}, options), { url: options.uri, method: options.method, data: options.params, headers: options.headers });
|
|
||||||
try {
|
|
||||||
const response = yield request(requestConfig);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "es",
|
|
||||||
"target": "es6",
|
|
||||||
"module": "esnext"
|
|
||||||
},
|
|
||||||
|
|
||||||
"include": ["src/**/*"]
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import { MopenClientConfig } from '@ali/mirror-io-client-mopen';
|
|
||||||
import { RuntimeOptionsConfig } from '@ali/build-success-types';
|
|
||||||
export declare function createMopenHandler<T = unknown>(config?: MopenClientConfig): (options: RuntimeOptionsConfig) => Promise<{
|
|
||||||
data: T;
|
|
||||||
}>;
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
import { MopenClient, MOPEN_APPKEY_XSPACE_PRE_ONLINE, MOPEN_DOMAIN_TAOBAO_PRE_ONLINE, } from '@ali/mirror-io-client-mopen';
|
|
||||||
export function createMopenHandler(config = {
|
|
||||||
mtopDomain: MOPEN_DOMAIN_TAOBAO_PRE_ONLINE,
|
|
||||||
appKey: MOPEN_APPKEY_XSPACE_PRE_ONLINE,
|
|
||||||
}) {
|
|
||||||
return function (options) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
try {
|
|
||||||
const { data, response } = yield MopenClient.request(Object.assign(Object.assign({ config }, options), { api: options.uri, v: options.v, data: options.params, type: options.method || 'get', dataType: options.dataType || 'json', timeout: options.timeout, headers: options.headers }));
|
|
||||||
return Object.assign(Object.assign({}, response), { data });
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "es",
|
|
||||||
"target": "es6",
|
|
||||||
"module": "esnext"
|
|
||||||
},
|
|
||||||
|
|
||||||
"include": ["src/**/*"]
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
import { RuntimeOptionsConfig } from '@ali/build-success-types';
|
|
||||||
export declare type Method = 'get' | 'post' | 'GET' | 'POST';
|
|
||||||
export declare type DataType = 'jsonp' | 'json' | 'originaljsonp';
|
|
||||||
export declare function createMtopHandler<T = unknown>(config?: MTopConfig): (options: RuntimeOptionsConfig) => Promise<{
|
|
||||||
data: T;
|
|
||||||
}>;
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
import mtopRequest from '@ali/universal-mtop';
|
|
||||||
// 考虑一下 mtop 类型的问题,官方没有提供 ts 文件
|
|
||||||
export function createMtopHandler(config) {
|
|
||||||
if (config && Object.keys(config).length > 0) {
|
|
||||||
Object.keys(config).forEach((key) => mtopRequest.config(key, config[key]));
|
|
||||||
}
|
|
||||||
return function (options) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
try {
|
|
||||||
const response = yield mtopRequest.request({
|
|
||||||
api: options.uri,
|
|
||||||
v: options.v || '1.0',
|
|
||||||
data: options.params,
|
|
||||||
type: options.method || 'get',
|
|
||||||
dataType: options.dataType || 'json',
|
|
||||||
timeout: options.timeout,
|
|
||||||
headers: options.headers,
|
|
||||||
});
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "es",
|
|
||||||
"target": "es6",
|
|
||||||
"module": "esnext"
|
|
||||||
},
|
|
||||||
|
|
||||||
"include": ["src/**/*"]
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import { UniversalMtopClientConfig } from '@ali/mirror-io-client-universal-mtop';
|
|
||||||
import { RuntimeOptionsConfig } from '@ali/build-success-types';
|
|
||||||
export declare function createMopenHandler<T = unknown>(config?: UniversalMtopClientConfig): (options: RuntimeOptionsConfig) => Promise<{
|
|
||||||
data: T;
|
|
||||||
}>;
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
import { UniversalMtopClient, } from '@ali/mirror-io-client-universal-mtop';
|
|
||||||
export function createMopenHandler(config) {
|
|
||||||
return function (options) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
try {
|
|
||||||
const { data, response } = yield UniversalMtopClient.request(Object.assign(Object.assign({ config }, options), { api: options.uri, v: options.v, data: options.params, type: options.method || 'get', dataType: options.dataType || 'json', timeout: options.timeout, headers: options.headers }));
|
|
||||||
return Object.assign(Object.assign({}, response), { data });
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "es",
|
|
||||||
"target": "es6",
|
|
||||||
"module": "esnext"
|
|
||||||
},
|
|
||||||
|
|
||||||
"include": ["src/**/*"]
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
import { UrlParamsHandler } from '@ali/build-success-types';
|
|
||||||
export declare function createUrlParamsHandler<T = unknown>(searchString?: string | T): UrlParamsHandler<T>;
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
import qs from 'query-string';
|
|
||||||
export function createUrlParamsHandler(searchString = '') {
|
|
||||||
return function () {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
if (typeof searchString === 'string') {
|
|
||||||
const params = qs.parse(searchString);
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
return searchString;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "es",
|
|
||||||
"target": "es6",
|
|
||||||
"module": "esnext"
|
|
||||||
},
|
|
||||||
|
|
||||||
"include": ["src/**/*"]
|
|
||||||
}
|
|
||||||
3
packages/datasource-mopen-handler/.eslintignore
Normal file
3
packages/datasource-mopen-handler/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/node_modules
|
||||||
|
/es
|
||||||
|
/lib
|
||||||
7
packages/datasource-mopen-handler/.eslintrc.js
Normal file
7
packages/datasource-mopen-handler/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-parameter-properties': 1,
|
||||||
|
'no-param-reassign': 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
4
packages/datasource-mopen-handler/.prettierrc.js
Normal file
4
packages/datasource-mopen-handler/.prettierrc.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: 'all',
|
||||||
|
};
|
||||||
@ -15,10 +15,8 @@
|
|||||||
"build": "npm run clean && tsc && tsc --outDir ./lib --module commonjs ",
|
"build": "npm run clean && tsc && tsc --outDir ./lib --module commonjs ",
|
||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
|
||||||
"@ali/build-success-types": "^0.1.2-alpha.35"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ali/lowcode-types": "^1.0.10",
|
||||||
"@ali/mirror-io-client-mopen": "1.0.0-beta.16",
|
"@ali/mirror-io-client-mopen": "1.0.0-beta.16",
|
||||||
"typescript": "^3.9.7"
|
"typescript": "^3.9.7"
|
||||||
},
|
},
|
||||||
@ -4,7 +4,7 @@ import {
|
|||||||
MOPEN_APPKEY_XSPACE_PRE_ONLINE,
|
MOPEN_APPKEY_XSPACE_PRE_ONLINE,
|
||||||
MOPEN_DOMAIN_TAOBAO_PRE_ONLINE,
|
MOPEN_DOMAIN_TAOBAO_PRE_ONLINE,
|
||||||
} from '@ali/mirror-io-client-mopen';
|
} from '@ali/mirror-io-client-mopen';
|
||||||
import { RuntimeOptionsConfig } from '@ali/build-success-types';
|
import { RuntimeOptionsConfig } from '@ali/lowcode-types';
|
||||||
|
|
||||||
type Method = 'get' | 'post' | 'GET' | 'POST';
|
type Method = 'get' | 'post' | 'GET' | 'POST';
|
||||||
|
|
||||||
70
packages/datasource-mopen-handler/tsconfig.json
Normal file
70
packages/datasource-mopen-handler/tsconfig.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "es",
|
||||||
|
"target": "es6",
|
||||||
|
"module": "esnext",
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
// "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
||||||
|
// "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
||||||
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"DOM"
|
||||||
|
] /* 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": "es" /* Redirect output structure to the directory. */,
|
||||||
|
// "rootDir": "./", /* 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": true, /* 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": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
|
// "typeRoots": [], /* 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 */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/datasource-mtop-handler/.eslintignore
Normal file
3
packages/datasource-mtop-handler/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/node_modules
|
||||||
|
/es
|
||||||
|
/lib
|
||||||
7
packages/datasource-mtop-handler/.eslintrc.js
Normal file
7
packages/datasource-mtop-handler/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-parameter-properties': 1,
|
||||||
|
'no-param-reassign': 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
4
packages/datasource-mtop-handler/.prettierrc.js
Normal file
4
packages/datasource-mtop-handler/.prettierrc.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: 'all',
|
||||||
|
};
|
||||||
@ -15,10 +15,8 @@
|
|||||||
"build": "npm run clean && tsc && tsc --outDir ./lib --module commonjs ",
|
"build": "npm run clean && tsc && tsc --outDir ./lib --module commonjs ",
|
||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
|
||||||
"@ali/build-success-types": "^0.1.2-alpha.35"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ali/lowcode-types": "^1.0.10",
|
||||||
"@ali/universal-mtop": "^5.1.9",
|
"@ali/universal-mtop": "^5.1.9",
|
||||||
"typescript": "^3.9.7"
|
"typescript": "^3.9.7"
|
||||||
},
|
},
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import mtopRequest from '@ali/universal-mtop';
|
import mtopRequest from '@ali/universal-mtop';
|
||||||
|
|
||||||
import { RuntimeOptionsConfig } from '@ali/build-success-types';
|
import { RuntimeOptionsConfig } from '@ali/lowcode-types';
|
||||||
|
|
||||||
export type Method = 'get' | 'post' | 'GET' | 'POST';
|
export type Method = 'get' | 'post' | 'GET' | 'POST';
|
||||||
|
|
||||||
70
packages/datasource-mtop-handler/tsconfig.json
Normal file
70
packages/datasource-mtop-handler/tsconfig.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "es",
|
||||||
|
"target": "es6",
|
||||||
|
"module": "esnext",
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
// "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
||||||
|
// "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
||||||
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"DOM"
|
||||||
|
] /* 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": "es" /* Redirect output structure to the directory. */,
|
||||||
|
// "rootDir": "./", /* 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": true, /* 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": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
|
// "typeRoots": [], /* 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 */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/datasource-universal-mtop-handler/.eslintignore
Normal file
3
packages/datasource-universal-mtop-handler/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/node_modules
|
||||||
|
/es
|
||||||
|
/lib
|
||||||
7
packages/datasource-universal-mtop-handler/.eslintrc.js
Normal file
7
packages/datasource-universal-mtop-handler/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-parameter-properties': 1,
|
||||||
|
'no-param-reassign': 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: 'all',
|
||||||
|
};
|
||||||
@ -15,10 +15,8 @@
|
|||||||
"build": "npm run clean && tsc && tsc --outDir ./lib --module commonjs ",
|
"build": "npm run clean && tsc && tsc --outDir ./lib --module commonjs ",
|
||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
|
||||||
"@ali/build-success-types": "^0.1.2-alpha.27"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ali/lowcode-types": "^1.0.10",
|
||||||
"@ali/mirror-io-client-universal-mtop": "1.0.0-beta.16",
|
"@ali/mirror-io-client-universal-mtop": "1.0.0-beta.16",
|
||||||
"typescript": "^3.9.7"
|
"typescript": "^3.9.7"
|
||||||
},
|
},
|
||||||
@ -3,7 +3,7 @@ import {
|
|||||||
UniversalMtopClientConfig,
|
UniversalMtopClientConfig,
|
||||||
} from '@ali/mirror-io-client-universal-mtop';
|
} from '@ali/mirror-io-client-universal-mtop';
|
||||||
|
|
||||||
import { RuntimeOptionsConfig } from '@ali/build-success-types';
|
import { RuntimeOptionsConfig } from '@ali/lowcode-types';
|
||||||
|
|
||||||
type Method = 'get' | 'post' | 'GET' | 'POST';
|
type Method = 'get' | 'post' | 'GET' | 'POST';
|
||||||
|
|
||||||
70
packages/datasource-universal-mtop-handler/tsconfig.json
Normal file
70
packages/datasource-universal-mtop-handler/tsconfig.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "es",
|
||||||
|
"target": "es6",
|
||||||
|
"module": "esnext",
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
// "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
||||||
|
// "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
||||||
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"DOM"
|
||||||
|
] /* 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": "es" /* Redirect output structure to the directory. */,
|
||||||
|
// "rootDir": "./", /* 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": true, /* 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": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
|
// "typeRoots": [], /* 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 */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/datasource-url-params-handler/.eslintignore
Normal file
3
packages/datasource-url-params-handler/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/node_modules
|
||||||
|
/es
|
||||||
|
/lib
|
||||||
7
packages/datasource-url-params-handler/.eslintrc.js
Normal file
7
packages/datasource-url-params-handler/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-parameter-properties': 1,
|
||||||
|
'no-param-reassign': 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -15,10 +15,8 @@
|
|||||||
"build": "npm run clean && tsc && tsc --outDir ./lib --module commonjs ",
|
"build": "npm run clean && tsc && tsc --outDir ./lib --module commonjs ",
|
||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
|
||||||
"@ali/build-success-types": "^0.1.2-alpha.31"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ali/lowcode-types": "^1.0.10",
|
||||||
"query-string": "^6.13.1",
|
"query-string": "^6.13.1",
|
||||||
"typescript": "^3.9.7"
|
"typescript": "^3.9.7"
|
||||||
},
|
},
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import qs from 'query-string';
|
import qs from 'query-string';
|
||||||
import { UrlParamsHandler } from '@ali/build-success-types';
|
import { UrlParamsHandler } from '@ali/lowcode-types';
|
||||||
|
|
||||||
export function createUrlParamsHandler<T = unknown>(
|
export function createUrlParamsHandler<T = unknown>(
|
||||||
searchString: string | T = '',
|
searchString: string | T = '',
|
||||||
70
packages/datasource-url-params-handler/tsconfig.json
Normal file
70
packages/datasource-url-params-handler/tsconfig.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "es",
|
||||||
|
"target": "es6",
|
||||||
|
"module": "esnext",
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
// "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
||||||
|
// "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
||||||
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"DOM"
|
||||||
|
] /* 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": "es" /* Redirect output structure to the directory. */,
|
||||||
|
// "rootDir": "./", /* 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": true, /* 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": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
|
// "typeRoots": [], /* 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 */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/types/.eslintignore
Normal file
3
packages/types/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
lib
|
||||||
|
es
|
||||||
|
node_modules
|
||||||
9
packages/types/.eslintrc.js
Normal file
9
packages/types/.eslintrc.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-parameter-properties': 1,
|
||||||
|
'no-param-reassign': 0,
|
||||||
|
'@typescript-eslint/member-ordering': 0,
|
||||||
|
indent: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
6
packages/types/.prettierrc.js
Normal file
6
packages/types/.prettierrc.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
printWidth: 80,
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: 'all',
|
||||||
|
tabSize: 2,
|
||||||
|
};
|
||||||
15
packages/types/src/data-source-handlers.ts
Normal file
15
packages/types/src/data-source-handlers.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import {
|
||||||
|
IDataSourceRuntimeContext,
|
||||||
|
RuntimeOptionsConfig,
|
||||||
|
} from './data-source-runtime';
|
||||||
|
|
||||||
|
export type RequestHandler<T = unknown> = (
|
||||||
|
options: RuntimeOptionsConfig,
|
||||||
|
context: IDataSourceRuntimeContext
|
||||||
|
) => Promise<T>;
|
||||||
|
|
||||||
|
export type UrlParamsHandler<T = unknown> = (
|
||||||
|
context?: IDataSourceRuntimeContext
|
||||||
|
) => Promise<T>;
|
||||||
|
|
||||||
|
export type RequestHandlersMap<T = unknown> = Record<string, RequestHandler<T>>;
|
||||||
41
packages/types/src/data-source-interpret.ts
Normal file
41
packages/types/src/data-source-interpret.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import {
|
||||||
|
CompositeValue,
|
||||||
|
JSExpression,
|
||||||
|
JSFunction,
|
||||||
|
JSONObject,
|
||||||
|
} from './value-type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源对象
|
||||||
|
* @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
|
*/
|
||||||
|
export interface InterpretDataSource {
|
||||||
|
list: InterpretDataSourceConfig[];
|
||||||
|
dataHandler?: JSFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源对象
|
||||||
|
* @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
|
||||||
|
*/
|
||||||
|
export interface InterpretDataSourceConfig {
|
||||||
|
id: string;
|
||||||
|
isInit?: boolean | JSExpression;
|
||||||
|
isSync?: boolean | JSExpression;
|
||||||
|
type?: string;
|
||||||
|
requestHandler?: JSFunction;
|
||||||
|
dataHandler?: JSFunction;
|
||||||
|
errorHandler?: JSFunction;
|
||||||
|
willFetch?: JSFunction;
|
||||||
|
shouldFetch?: JSFunction;
|
||||||
|
options?: {
|
||||||
|
uri: string | JSExpression;
|
||||||
|
params?: JSONObject | JSExpression;
|
||||||
|
method?: string | JSExpression;
|
||||||
|
isCors?: boolean | JSExpression;
|
||||||
|
timeout?: number | JSExpression;
|
||||||
|
headers?: JSONObject | JSExpression;
|
||||||
|
[option: string]: CompositeValue;
|
||||||
|
};
|
||||||
|
[otherKey: string]: CompositeValue;
|
||||||
|
}
|
||||||
53
packages/types/src/data-source-runtime.ts
Normal file
53
packages/types/src/data-source-runtime.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { IRuntimeDataSource } from './data-source';
|
||||||
|
|
||||||
|
// 先定义运行模式的类型
|
||||||
|
export interface RuntimeDataSource {
|
||||||
|
list: RuntimeDataSourceConfig[];
|
||||||
|
// TODO: dataMap 格式不对要处理
|
||||||
|
dataHandler?: (dataMap: DataSourceMap) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DataSourceMap = Record<string, IRuntimeDataSource>;
|
||||||
|
|
||||||
|
export interface RuntimeDataSourceConfig {
|
||||||
|
id: string;
|
||||||
|
isInit?: boolean;
|
||||||
|
isSync?: boolean;
|
||||||
|
type?: string;
|
||||||
|
willFetch?: () => void;
|
||||||
|
shouldFetch?: () => boolean;
|
||||||
|
requestHandler?: () => void; // TODO: 待定
|
||||||
|
dataHandler?: DataHandler;
|
||||||
|
errorHandler?: ErrorHandler;
|
||||||
|
options?: RuntimeOptions;
|
||||||
|
[otherKey: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DataHandler = <T>(response: {
|
||||||
|
data: T;
|
||||||
|
[index: string]: unknown;
|
||||||
|
}) => Promise<T | undefined>;
|
||||||
|
|
||||||
|
export type ErrorHandler = (err: unknown) => Promise<any>;
|
||||||
|
|
||||||
|
export type RuntimeOptions = () => RuntimeOptionsConfig;
|
||||||
|
|
||||||
|
export interface RuntimeOptionsConfig {
|
||||||
|
uri: string;
|
||||||
|
params?: Record<string, unknown>;
|
||||||
|
method?: string;
|
||||||
|
isCors?: boolean;
|
||||||
|
timeout?: number;
|
||||||
|
headers?: Record<string, unknown>;
|
||||||
|
[option: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可以采用 react 的 state,但是需要注意必须提供同步的 setState 功能
|
||||||
|
export interface IDataSourceRuntimeContext<
|
||||||
|
TState extends Record<string, unknown> = Record<string, unknown>
|
||||||
|
> {
|
||||||
|
/** 当前数据源的内容 */
|
||||||
|
state: TState;
|
||||||
|
/** 设置状态(浅合并) */
|
||||||
|
setState(state: Partial<TState>): void;
|
||||||
|
}
|
||||||
@ -1,16 +1,65 @@
|
|||||||
import { CompositeValue } from './value-type';
|
import { RequestHandlersMap } from './data-source-handlers';
|
||||||
|
import {
|
||||||
|
IDataSourceRuntimeContext,
|
||||||
|
RuntimeDataSource,
|
||||||
|
} from './data-source-runtime';
|
||||||
|
|
||||||
export interface DataSourceConfig {
|
/** 数据源的状态 */
|
||||||
id: string;
|
export enum RuntimeDataSourceStatus {
|
||||||
isInit: boolean;
|
/** 初始状态,尚未加载 */
|
||||||
type: string;
|
Initial = 'init',
|
||||||
options: {
|
|
||||||
uri: string;
|
/** 正在加载 */
|
||||||
[option: string]: CompositeValue;
|
Loading = 'loading',
|
||||||
};
|
|
||||||
[otherKey: string]: CompositeValue;
|
/** 已加载(无错误) */
|
||||||
|
Loaded = 'loaded',
|
||||||
|
|
||||||
|
/** 加载出错了 */
|
||||||
|
Error = 'error',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataSource {
|
/**
|
||||||
items: DataSourceConfig[];
|
* 运行时的数据源(对外暴露的接口)
|
||||||
|
* @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 | void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataSourceEngineFactory
|
||||||
|
* 用来定义 engine 的工厂函数类型
|
||||||
|
*/
|
||||||
|
export interface IRuntimeDataSourceEngineFactory {
|
||||||
|
create(
|
||||||
|
dataSource: RuntimeDataSource,
|
||||||
|
context: IDataSourceRuntimeContext,
|
||||||
|
extraConfig?: {
|
||||||
|
requestHandlersMap: RequestHandlersMap;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
): IDataSourceEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create 返回的 DataSourceEngine 定义
|
||||||
|
export interface IDataSourceEngine {
|
||||||
|
/** 数据源, key 是数据源的 ID */
|
||||||
|
dataSourceMap: Record<string, IRuntimeDataSource>;
|
||||||
|
|
||||||
|
/** 重新加载所有的数据源 */
|
||||||
|
reloadDataSource(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
export * from './data-source';
|
export * from './data-source';
|
||||||
|
export * from './data-source-handlers';
|
||||||
|
export * from './data-source-interpret';
|
||||||
|
export * from './data-source-runtime';
|
||||||
export * from './editor';
|
export * from './editor';
|
||||||
export * from './field-config';
|
export * from './field-config';
|
||||||
export * from './i18n';
|
export * from './i18n';
|
||||||
|
|||||||
@ -11,6 +11,44 @@ export interface JSExpression {
|
|||||||
* 模拟值
|
* 模拟值
|
||||||
*/
|
*/
|
||||||
mock?: any;
|
mock?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 函数
|
||||||
|
export interface JSFunction {
|
||||||
|
type: 'JSFunction';
|
||||||
|
/**
|
||||||
|
* 表达式字符串
|
||||||
|
*/
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件函数类型
|
||||||
|
* @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#feHTW
|
||||||
|
*/
|
||||||
|
export interface JSFunction {
|
||||||
|
type: 'JSFunction';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 函数定义,或直接函数表达式
|
||||||
|
*/
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
/** 源码 */
|
||||||
|
compiled?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 函数
|
||||||
|
export interface JSFunction {
|
||||||
|
type: 'JSFunction';
|
||||||
|
/**
|
||||||
|
* 函数字符串
|
||||||
|
*/
|
||||||
|
value: string;
|
||||||
|
/**
|
||||||
|
* 模拟值
|
||||||
|
*/
|
||||||
|
mock?: any;
|
||||||
/**
|
/**
|
||||||
* 额外扩展属性,如 extType、events
|
* 额外扩展属性,如 extType、events
|
||||||
*/
|
*/
|
||||||
@ -18,7 +56,6 @@ export interface JSExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface JSSlot {
|
export interface JSSlot {
|
||||||
name?: string;
|
|
||||||
type: 'JSSlot';
|
type: 'JSSlot';
|
||||||
title?: string;
|
title?: string;
|
||||||
// 函数的入参
|
// 函数的入参
|
||||||
@ -32,28 +69,44 @@ export interface JSBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// JSON 基本类型
|
// JSON 基本类型
|
||||||
export type JSONValue = boolean | string | number | null | undefined | JSONArray | JSONObject;
|
export type JSONValue =
|
||||||
|
| boolean
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| null
|
||||||
|
| undefined
|
||||||
|
| JSONArray
|
||||||
|
| JSONObject;
|
||||||
export type JSONArray = JSONValue[];
|
export type JSONArray = JSONValue[];
|
||||||
export interface JSONObject {
|
export interface JSONObject {
|
||||||
[key: string]: JSONValue;
|
[key: string]: JSONValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 复合类型
|
// 复合类型
|
||||||
export type CompositeValue = JSONValue | JSExpression | JSSlot | CompositeArray | CompositeObject;
|
export type CompositeValue =
|
||||||
|
| JSONValue
|
||||||
|
| JSExpression
|
||||||
|
| JSFunction
|
||||||
|
| JSSlot
|
||||||
|
| CompositeArray
|
||||||
|
| CompositeObject;
|
||||||
export type CompositeArray = CompositeValue[];
|
export type CompositeArray = CompositeValue[];
|
||||||
export interface CompositeObject {
|
export interface CompositeObject {
|
||||||
[key: string]: CompositeValue;
|
[key: string]: CompositeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function isJSExpression(data: any): data is JSExpression {
|
export function isJSExpression(data: any): data is JSExpression {
|
||||||
return data && data.type === 'JSExpression';
|
return data && data.type === 'JSExpression';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isJSFunction(x: any): x is JSFunction {
|
||||||
|
return typeof x === 'object' && x && x.type === 'JSFunction';
|
||||||
|
}
|
||||||
|
|
||||||
export function isJSSlot(data: any): data is JSSlot {
|
export function isJSSlot(data: any): data is JSSlot {
|
||||||
return data && data.type === 'JSSlot';
|
return data && data.type === 'JSSlot';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isJSBlock(data: any): data is JSBlock {
|
export function isJSBlock(data: any): data is JSBlock {
|
||||||
return data && data.type === 'JSBlock'
|
return data && data.type === 'JSBlock';
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user