支持es编译

This commit is contained in:
Wang Kejun 2023-09-05 17:18:37 +08:00
parent be381fbb8b
commit dbf6034b16
23 changed files with 834 additions and 100 deletions

74
es/AspectDict.d.ts vendored Normal file
View File

@ -0,0 +1,74 @@
import { EntityDict, OperateOption, SelectOption, OperationResult, AggregationResult } from "oak-domain/lib/types";
import { AmapInstance } from "oak-external-sdk";
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { AsyncContext } from "oak-domain/lib/store/AsyncRowStore";
export declare type CommonAspectDict<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> = {
operate: <T extends keyof ED, OP extends OperateOption>(params: {
entity: T;
operation: ED[T]['Operation'] | ED[T]['Operation'][];
option?: OP;
}, context: Cxt) => Promise<OperationResult<ED>[] | OperationResult<ED>>;
select: <T extends keyof ED, OP extends SelectOption>(params: {
entity: T;
selection: ED[T]['Selection'];
option?: OP;
getCount?: true;
}, context: Cxt) => Promise<{
ids: string[];
count?: number;
aggr?: (Partial<ED[T]['Schema']> | undefined)[];
}>;
aggregate: <T extends keyof ED, OP extends SelectOption>(params: {
entity: T;
aggregation: ED[T]['Aggregation'];
option?: OP;
}, context: Cxt) => Promise<AggregationResult<ED[T]['Schema']>>;
count: <T extends keyof ED, OP extends SelectOption>(params: {
entity: T;
selection: Pick<ED[T]['Selection'], 'filter'>;
option?: OP;
}, context: Cxt) => Promise<number>;
fetchRows: <OP extends SelectOption>(params: Array<{
entity: keyof ED;
selection: ED[keyof ED]['Selection'];
option?: OP;
}>, context: Cxt) => Promise<void>;
amap: <T extends 'getDrivingPath' | 'regeo' | 'ipLoc' | 'getDistrict' | 'geocode'>(params: {
key: string;
method: T;
data: Parameters<AmapInstance[T]>[0];
}) => Promise<any>;
getTranslations: (params: {
namespace: string | string[];
locale: string;
}) => Promise<any>;
importEntity: (params: FormData, context: Cxt) => Promise<void | ArrayBuffer>;
exportEntity: <T extends keyof ED>(params: {
entity: T;
id: string;
filter?: ED[T]['Selection']['filter'];
properties?: Record<string, any>;
}, context: Cxt) => Promise<ArrayBuffer>;
getImportationTemplate: (params: {
id: string;
}, context: Cxt) => Promise<ArrayBuffer>;
searchPoi: (options: {
value: string;
areaCode?: string;
indexFrom?: number;
count?: number;
typeCode?: string;
}) => Promise<{
id: string;
areaId: string;
poiName: string;
detail: string;
coordinate: [number, number];
}[]>;
loadRelations: (params: {
entities: (keyof ED)[];
}, context: Cxt) => Promise<ED['userRelation']['OpSchema'][]>;
crossBridge: (params: {
url: string;
}) => Promise<ReadableStream<Uint8Array>>;
};

1
es/AspectDict.js Normal file
View File

@ -0,0 +1 @@
export {};

6
es/amap.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
import { AmapInstance } from 'oak-external-sdk';
export declare function amap<T extends 'getDrivingPath' | 'regeo' | 'ipLoc' | 'getDistrict' | 'geocode'>(options: {
key: string;
method: T;
data: Parameters<AmapInstance[T]>[0];
}): Promise<any>;

11
es/amap.js Normal file
View File

@ -0,0 +1,11 @@
import { AmapSDK } from 'oak-external-sdk';
export async function amap(options) {
const { key, method, data } = options;
const instance = AmapSDK.getInstance(key);
const fn = instance[method];
if (!fn) {
throw new Error('method not implemented');
}
// data any后面再改
return fn(data);
}

34
es/crud.d.ts vendored Normal file
View File

@ -0,0 +1,34 @@
import { OperateOption, EntityDict, SelectOption } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
export declare function operate<ED extends BaseEntityDict & EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends OperateOption>(params: {
entity: T;
operation: ED[T]['Operation'] | ED[T]['Operation'][];
option?: OP;
}, context: Cxt): Promise<import("oak-domain/lib/types").OperationResult<ED> | Awaited<import("oak-domain/lib/types").OperationResult<ED>>[]>;
export declare function select<ED extends BaseEntityDict & EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends SelectOption>(params: {
entity: T;
selection: ED[T]['Selection'];
option?: OP;
getCount?: true;
maxCount?: number;
}, context: Cxt): Promise<{
ids: string[];
count?: number | undefined;
aggr?: (Partial<ED[T]["Schema"]> | undefined)[] | undefined;
}>;
export declare function aggregate<ED extends BaseEntityDict & EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends SelectOption>(params: {
entity: T;
aggregation: ED[T]['Aggregation'];
option?: OP;
}, context: Cxt): Promise<import("oak-domain/lib/types").AggregationResult<ED[T]["Schema"]>>;
export declare function fetchRows<ED extends EntityDict & BaseEntityDict, OP extends SelectOption, Cxt extends AsyncContext<ED>>(params: Array<{
entity: keyof ED;
selection: ED[keyof ED]['Selection'];
option?: OP;
}>, context: Cxt): Promise<void>;
export declare function count<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends SelectOption>(params: {
entity: T;
selection: Pick<ED[T]['Selection'], 'filter'>;
option?: OP;
}, context: Cxt): Promise<number>;

136
es/crud.js Normal file
View File

@ -0,0 +1,136 @@
import { OakUserUnpermittedException, } from 'oak-domain/lib/types';
import { judgeRelation } from 'oak-domain/lib/store/relation';
import { assert } from 'oak-domain/lib/utils/assert';
export async function operate(params, context) {
const { entity, operation, option } = params;
/* const userId = context.getCurrentUserId();
if (!userId) {
// operate默认必须用户登录
throw new OakUnloggedInException();
} */
if (!context.allowUserUpdate()) {
throw new OakUserUnpermittedException('您被禁更新');
}
if (operation instanceof Array) {
const result = [];
for (const oper of operation) {
const r = await context.operate(entity, oper, option || {});
result.push(r);
}
return result;
}
return await context.operate(entity, operation, option || {});
}
function pruneAggrResult(schema, entity, result) {
const pruneInner = (e, r) => {
const r2 = {};
let hasAggr = false;
for (const attr in r) {
if (attr.endsWith('$$aggr')) {
hasAggr = true;
Object.assign(r2, {
[attr]: r[attr],
});
}
else if (typeof r[attr] === 'object') {
const rel = judgeRelation(schema, e, attr);
if (rel === 2 || typeof rel === 'string') {
const rr = pruneInner(rel === 2 ? attr : rel, r[attr]);
if (rr) {
hasAggr = true;
Object.assign(r2, {
[attr]: rr,
});
}
}
else if (rel instanceof Array) {
assert(r[attr] instanceof Array);
const rr = r[attr].map((ele) => pruneInner(rel[0], ele));
if (rr.find((ele) => !ele)) {
hasAggr = true;
Object.assign(r2, {
[attr]: rr,
});
}
}
}
}
if (hasAggr) {
return r2;
}
return;
};
const result2 = result.map((row) => pruneInner(entity, row));
if (result2.find(ele => !!ele)) {
return result2;
}
}
export async function select(params, context) {
const { entity, selection, option, getCount, maxCount } = params;
const { randomRange, count } = selection;
let selection2 = selection;
if (randomRange) {
// 如果是随机取值这里就从randomRange的ids中随机取
const idSelection = Object.assign({}, selection, {
indexFrom: 0,
count: randomRange,
data: {
id: 1,
},
});
const idResults = await context.select(entity, idSelection, option || {});
const possibility = count / idResults.length;
let reduced = idResults.length - count;
const ids2 = idResults.map(ele => ele.id).filter((id) => {
const rand = Math.random();
if (rand > possibility && reduced) {
reduced--;
return false;
}
return true;
});
selection2.filter = {
id: {
$in: ids2,
},
};
}
const data = await context.select(entity, selection2, option || {});
const result = {
ids: data.map(ele => ele.id),
};
if (getCount && !randomRange) {
const { filter } = selection;
const count = await context.count(entity, Object.assign({}, { filter, count: maxCount || 1000 }), option || {});
Object.assign(result, {
count,
});
}
if (data.length === 0) {
}
else {
const aggrData = pruneAggrResult(context.getSchema(), entity, data);
if (aggrData) {
result.aggr = aggrData;
}
}
return result;
}
export async function aggregate(params, context) {
const { entity, aggregation, option } = params;
return context.aggregate(entity, aggregation, option || {});
}
export async function fetchRows(params, context) {
await Promise.all(params.map((ele) => context.select(ele.entity, ele.selection, ele.option || {})));
}
export async function count(params, context) {
const { entity, selection, option } = params;
const { filter } = selection;
const count = await context.count(entity, Object.assign({}, { filter }), option || {});
return count;
}
/*
export type AspectDict<ED extends EntityDict> = {
operation: <T extends keyof ED>(options: { entity: T, operation: ED[T]['Operation'], params?: OperateParams }, context: Context<ED>) => Promise<OperationResult>;
select: <T extends keyof ED, S extends ED[T]['Selection']>( options: { entity: T, selection: S, params?: object }, context: Context<ED>) => Promise<SelectionResult2<ED[T]['Schema'], S>>;
}; */

12
es/geo.d.ts vendored Normal file
View File

@ -0,0 +1,12 @@
export declare function searchPoi(options: {
value: string;
areaCode?: string;
indexFrom?: number;
count?: number;
typeCode?: string;
}): Promise<{
id: string;
areaId: string;
poiName: string;
coordinate: [number, number];
}[]>;

38
es/geo.js Normal file
View File

@ -0,0 +1,38 @@
export async function searchPoi(options) {
const { value, areaCode, indexFrom, count } = options;
const form = new FormData();
form.set('stName', value);
if (areaCode) {
form.set('code', areaCode);
}
if (indexFrom && count) {
form.set('page', `${indexFrom / count}`);
form.set('size', `${count}`);
}
const result = await fetch('https://dmfw.mca.gov.cn/9095/stname/listPub', {
method: 'post',
body: form,
});
const { records } = await result.json();
const pois = await Promise.all(records.map(async (ele) => {
let { area, standard_name, gdm, id, province_name, city_name, area_name, place_type, } = ele;
// 对返回的area数据进行一些清洗不规范
if (area.length === 9) {
if (area.endsWith('999')) {
area = area.slice(0, 6);
}
}
if (area === '000000') {
// 搜索如长江这样的地理名称时会返回这样的数据,过滤掉
return undefined;
}
return {
id,
areaId: area,
poiName: standard_name,
coordinate: gdm.coordinates[0],
detail: `${province_name}${city_name}${area_name}${standard_name}(${place_type})`,
};
}));
return pois.filter((poi) => !!poi);
}

25
es/index.d.ts vendored Normal file
View File

@ -0,0 +1,25 @@
import { operate, select, fetchRows, count, aggregate } from './crud';
import { amap } from './amap';
import { getTranslations } from './locales';
import { registerPorts, clearPorts, importEntity, exportEntity, getImportationTemplate } from './port';
import { searchPoi } from './geo';
import { loadRelations } from './relation';
import { crossBridge } from './utils';
declare const aspectDict: {
operate: typeof operate;
select: typeof select;
count: typeof count;
aggregate: typeof aggregate;
fetchRows: typeof fetchRows;
amap: typeof amap;
getTranslations: typeof getTranslations;
importEntity: typeof importEntity;
exportEntity: typeof exportEntity;
getImportationTemplate: typeof getImportationTemplate;
searchPoi: typeof searchPoi;
loadRelations: typeof loadRelations;
crossBridge: typeof crossBridge;
};
export default aspectDict;
export * from './AspectDict';
export { registerPorts, clearPorts, };

25
es/index.js Normal file
View File

@ -0,0 +1,25 @@
import { operate, select, fetchRows, count, aggregate } from './crud';
import { amap } from './amap';
import { getTranslations } from './locales';
import { registerPorts, clearPorts, importEntity, exportEntity, getImportationTemplate } from './port';
import { searchPoi } from './geo';
import { loadRelations } from './relation';
import { crossBridge } from './utils';
const aspectDict = {
operate,
select,
count,
aggregate,
fetchRows,
amap,
getTranslations,
importEntity,
exportEntity,
getImportationTemplate,
searchPoi,
loadRelations,
crossBridge,
};
export default aspectDict;
export * from './AspectDict';
export { registerPorts, clearPorts, };

10
es/locales.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
export declare function getTranslations(options: {
namespace: string | string[];
locale: string;
}): Promise<{
common: {
action: {
confirm: string;
};
};
}>;

34
es/locales.js Normal file
View File

@ -0,0 +1,34 @@
export async function getTranslations(options) {
const { namespace, locale } = options;
// 表示entity locale表示zh_CN
let translations = {};
return {
common: {
action: {
confirm: '确定2',
},
},
};
// const getTranslations = (ns: string) => {
// const entityName = ns.substring(0, 1).toUpperCase() + ns.substring(1);
// const entityName2 = ns.toLowerCase();
// try {
// const data = require(`${entityName}/locales/${locale}.ts`).default;
// assign(translations, {
// [entityName2]: data,
// });
// }
// catch (err) {
// throw err
// }
// };
// if (namespace instanceof Array) {
// namespace.forEach((ns) => {
// getTranslations(ns);
// })
// }
// else {
// getTranslations(namespace);
// }
// return translations;
}

20
es/port.d.ts vendored Normal file
View File

@ -0,0 +1,20 @@
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { Importation, Exportation } from 'oak-domain/lib/types/Port';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
export declare function registerPorts<ED extends EntityDict>(importations: Importation<ED, keyof ED, any>[], exportations: Exportation<ED, keyof ED, any>[]): void;
export declare function clearPorts(): void;
export declare function importEntity<ED extends EntityDict, Cxt extends AsyncContext<ED>>(params: {
entity: string;
id: string;
file: any;
option: string;
}, context: Cxt): Promise<ArrayBuffer | void>;
export declare function exportEntity<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>>(params: {
entity: T;
id: string;
filter?: ED[T]['Selection']['filter'];
properties?: Record<string, any>;
}, context: Cxt): Promise<ArrayBuffer>;
export declare function getImportationTemplate<ED extends EntityDict, Cxt extends AsyncContext<ED>>(params: {
id: string;
}, context: Cxt): Promise<ArrayBuffer>;

114
es/port.js Normal file
View File

@ -0,0 +1,114 @@
import { assert } from 'oak-domain/lib/utils/assert';
import { utils, write, readFile } from 'xlsx';
const Importations = {};
const Exportations = {};
export function registerPorts(importations, exportations) {
for (const i of importations) {
assert(!Importations.hasOwnProperty(i.id), `Importation中的id【${i.id}】重复了`);
Object.assign(Importations, {
[i.id]: i,
});
}
for (const e of exportations) {
assert(!Exportations.hasOwnProperty(e.id), `Exportation中的id【${e.id}】重复了`);
Object.assign(Exportations, {
[e.id]: e,
});
}
}
export function clearPorts() {
for (const i in Importations) {
delete Importations[i];
}
for (const e in Exportations) {
delete Exportations[e];
}
}
function getImportation(id) {
assert(Importations.hasOwnProperty(id), `id为[${id}]的importation不存在`);
return Importations[id];
}
function getExportation(id) {
assert(Exportations.hasOwnProperty(id), `id为[${id}]的exportation不存在`);
return Exportations[id];
}
export async function importEntity(params, context) {
const entity = params.entity;
const file = params.file;
const id = params.id;
const option = JSON.parse(params.option);
const importation = getImportation(id);
if (!importation) {
throw new Error('尚不支持此数据的导入');
}
const { fn } = importation;
// const arrayBuffer = await file.arrayBuffer();
const workbook = readFile(file.filepath, { type: 'buffer' });
const { SheetNames, Sheets } = workbook;
const errorSheets = [];
for (const sheetName of SheetNames) {
const sheet = Sheets[sheetName];
const dataList = utils.sheet_to_json(sheet);
const errorMessageList = await fn(dataList, context, option);
if (errorMessageList.length > 0) {
errorSheets.push({
sheetName,
worksheet: utils.json_to_sheet(errorMessageList),
});
}
}
if (errorSheets.length > 0) {
const errorWorkbook = utils.book_new();
for (const sheetData of errorSheets) {
utils.book_append_sheet(errorWorkbook, sheetData.worksheet, sheetData.sheetName);
}
return await write(errorWorkbook, { type: 'buffer' });
}
// throw new Error('not implement yet');
}
export async function exportEntity(params, context) {
const id = params.id;
const filter = params.filter;
const properties = params.properties;
const exportation = getExportation(id);
if (!exportation) {
throw new Error('尚不支持此数据的导出');
}
const { projection, headers, fn, entity, makeHeaders } = exportation;
const dataList = await context.select(entity, {
filter,
data: projection,
}, {});
const headers2 = makeHeaders ? makeHeaders(dataList) : headers;
assert(headers2 && headers2.length > 0, '导出未传入表头');
const fittedDatalist = [];
for (const data of dataList) {
fittedDatalist.push(await fn(data, context, properties));
}
const exportSheet = utils.json_to_sheet(fittedDatalist, {
header: headers2,
});
const exportBook = utils.book_new();
utils.book_append_sheet(exportBook, exportSheet);
return await write(exportBook, { type: 'buffer' });
// throw new Error('export not implement yet');
}
export async function getImportationTemplate(params, context) {
const id = params.id;
const importation = getImportation(id);
const { headers } = importation;
if (!importation) {
throw new Error('未找到对应的模板');
}
const exportSheet = utils.json_to_sheet([], { header: headers });
const widthList = headers.map((ele) => {
return {
width: ele.length * 2.2,
};
});
exportSheet['!cols'] = widthList;
const exportBook = utils.book_new();
utils.book_append_sheet(exportBook, exportSheet);
return await write(exportBook, { type: 'buffer' });
// throw new Error('not implement yet');
}

6
es/relation.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
import { EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
export declare function loadRelations<ED extends BaseEntityDict & EntityDict, Cxt extends AsyncContext<ED>>(params: {
entities: (keyof ED)[];
}, context: Cxt): Promise<ED["userRelation"]["OpSchema"][]>;

58
es/relation.js Normal file
View File

@ -0,0 +1,58 @@
import { OakUnloggedInException, } from 'oak-domain/lib/types';
import { omit } from 'oak-domain/lib/utils/lodash';
export async function loadRelations(params, context) {
const { entities } = params;
const userId = context.getCurrentUserId();
if (!userId) {
throw new OakUnloggedInException();
}
const userRelations = await context.select('userRelation', {
data: {
id: 1,
userId: 1,
relationId: 1,
entity: 1,
entityId: 1,
relation: {
id: 1,
entity: 1,
entityId: 1,
name: 1,
display: 1,
actionAuth$relation: {
$entity: 'actionAuth',
data: {
id: 1,
paths: 1,
destEntity: 1,
deActions: 1,
},
},
relationAuth$sourceRelation: {
$entity: 'relationAuth',
data: {
id: 1,
sourceRelationId: 1,
destRelationId: 1,
destRelation: {
id: 1,
entity: 1,
entityId: 1,
name: 1,
display: 1,
},
path: 1,
},
}
},
},
filter: {
userId,
/* entity: {
$in: entities as string[],
}, */
},
}, {});
const result = userRelations.map((userRelation) => omit(userRelation, 'relation'));
return result;
}

3
es/utils.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
export declare function crossBridge(params: {
url: string;
}): Promise<ReadableStream<Uint8Array> | null>;

5
es/utils.js Normal file
View File

@ -0,0 +1,5 @@
export async function crossBridge(params) {
const { url } = params;
const res = await fetch(url);
return res.body;
}

View File

@ -9,9 +9,13 @@
"lib/**/*"
],
"main": "lib/index",
"module": "es/index",
"types": "es/index.d.ts",
"typings": "es/index.d.ts",
"scripts": {
"test": "test",
"build": "tsc"
"build": "tsc -p tsconfig.json",
"build-es": "tsc -p tsconfig.es.json"
},
"license": "ISC",
"dependencies": {
@ -22,6 +26,7 @@
},
"devDependencies": {
"@types/node": "^18.0.0",
"@types/lodash": "^4.14.182",
"assert": "^2.0.0",
"ts-node": "~10.9.1",
"tslib": "^2.4.0",

View File

@ -9,7 +9,7 @@ import {
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
import { judgeRelation } from 'oak-domain/lib/store/relation';
import assert from 'assert';
import { assert } from 'oak-domain/lib/utils/assert';
export async function operate<
ED extends BaseEntityDict & EntityDict,

View File

@ -1,4 +1,4 @@
import assert from 'assert';
import { assert } from 'oak-domain/lib/utils/assert';
/**
* poiName搜索地理位置
@ -10,14 +10,14 @@ type DmfwPoi = {
area: string;
standard_name: string;
gdm: {
coordinates: [[number, number]],
},
coordinates: [[number, number]];
};
place_type: string;
place_code: string;
area_name: string;
city_name: string;
province_name: string;
}
};
export async function searchPoi(options: {
value: string;
@ -25,7 +25,14 @@ export async function searchPoi(options: {
indexFrom?: number;
count?: number;
typeCode?: string;
}): Promise<{ id: string; areaId: string; poiName: string; coordinate: [number, number] }[]> {
}): Promise<
{
id: string;
areaId: string;
poiName: string;
coordinate: [number, number];
}[]
> {
const { value, areaCode, indexFrom, count } = options;
const form = new FormData();
form.set('stName', value);
@ -43,12 +50,19 @@ export async function searchPoi(options: {
});
const { records } = await result.json();
const pois = await Promise.all(
records.map(
async (ele: DmfwPoi) => {
let { area, standard_name, gdm, id,
province_name, city_name, area_name, place_type } = ele;
records.map(async (ele: DmfwPoi) => {
let {
area,
standard_name,
gdm,
id,
province_name,
city_name,
area_name,
place_type,
} = ele;
// 对返回的area数据进行一些清洗不规范
if(area.length === 9) {
if (area.length === 9) {
if (area.endsWith('999')) {
area = area.slice(0, 6);
}
@ -65,10 +79,12 @@ export async function searchPoi(options: {
coordinate: gdm.coordinates[0],
detail: `${province_name}${city_name}${area_name}${standard_name}(${place_type})`,
};
}
)
})
);
return pois.filter(
poi => !!poi
) as { id: string; areaId: string; poiName: string; coordinate: [number, number] }[];
return pois.filter((poi) => !!poi) as {
id: string;
areaId: string;
poiName: string;
coordinate: [number, number];
}[];
}

View File

@ -1,23 +1,32 @@
import assert from 'assert';
import { assert } from 'oak-domain/lib/utils/assert';
import { EntityDict, SelectOption } from 'oak-domain/lib/types/Entity';
import { Importation, Exportation } from 'oak-domain/lib/types/Port';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
import { read, utils, write, readFile } from 'xlsx';
import { buffer } from 'stream/consumers';
import { Duplex } from 'stream';
const Importations: Record<string, any> = {};
const Exportations: Record<string, any> = {};
export function registerPorts<ED extends EntityDict>(importations: Importation<ED, keyof ED, any>[], exportations: Exportation<ED, keyof ED, any>[]) {
export function registerPorts<ED extends EntityDict>(
importations: Importation<ED, keyof ED, any>[],
exportations: Exportation<ED, keyof ED, any>[]
) {
for (const i of importations) {
assert(!Importations.hasOwnProperty(i.id), `Importation中的id【${i.id}】重复了`);
assert(
!Importations.hasOwnProperty(i.id),
`Importation中的id【${i.id}】重复了`
);
Object.assign(Importations, {
[i.id]: i,
});
}
for (const e of exportations) {
assert(!Exportations.hasOwnProperty(e.id), `Exportation中的id【${e.id}】重复了`);
assert(
!Exportations.hasOwnProperty(e.id),
`Exportation中的id【${e.id}】重复了`
);
Object.assign(Exportations, {
[e.id]: e,
});
@ -46,12 +55,15 @@ function getExportation<ED extends EntityDict, T extends keyof ED>(id: string) {
export async function importEntity<
ED extends EntityDict,
Cxt extends AsyncContext<ED>
>(params: {
entity: string,
id: string,
file: any, // 是否链接后台的file类型不一致暂时无法解决
option: string,
}, context: Cxt): Promise<ArrayBuffer | void> {
>(
params: {
entity: string;
id: string;
file: any; // 是否链接后台的file类型不一致暂时无法解决
option: string;
},
context: Cxt
): Promise<ArrayBuffer | void> {
const entity = params.entity;
const file = params.file;
const id = params.id;
@ -68,23 +80,27 @@ export async function importEntity<
for (const sheetName of SheetNames) {
const sheet = Sheets[sheetName];
const dataList = utils.sheet_to_json(
sheet
const dataList = utils.sheet_to_json(sheet);
const errorMessageList = await fn(
dataList as Record<string, string | number | boolean>[],
context,
option
);
const errorMessageList = await fn(dataList as Record<string, string | number | boolean>[], context, option);
if (errorMessageList.length > 0) {
errorSheets.push(
{
errorSheets.push({
sheetName,
worksheet: utils.json_to_sheet(errorMessageList),
}
);
});
}
}
if (errorSheets.length > 0) {
const errorWorkbook = utils.book_new();
for (const sheetData of errorSheets) {
utils.book_append_sheet(errorWorkbook, sheetData.worksheet, sheetData.sheetName);
utils.book_append_sheet(
errorWorkbook,
sheetData.worksheet,
sheetData.sheetName
);
}
return await write(errorWorkbook, { type: 'buffer' });
}
@ -95,12 +111,15 @@ export async function exportEntity<
ED extends EntityDict,
T extends keyof ED,
Cxt extends AsyncContext<ED>
>(params: {
>(
params: {
entity: T;
id: string;
filter?: ED[T]['Selection']['filter'];
properties?: Record<string, any>;
}, context: Cxt): Promise<ArrayBuffer> {
},
context: Cxt
): Promise<ArrayBuffer> {
const id = params.id;
const filter = params.filter;
const properties = params.properties;
@ -118,12 +137,16 @@ export async function exportEntity<
{}
);
const headers2 = makeHeaders ? makeHeaders(dataList) : headers;
assert(headers2 && headers2.length > 0, '导出未传入表头')
const fittedDatalist = []
assert(headers2 && headers2.length > 0, '导出未传入表头');
const fittedDatalist = [];
for (const data of dataList) {
fittedDatalist.push(await fn(data as ED[keyof ED]['Schema'], context, properties));
fittedDatalist.push(
await fn(data as ED[keyof ED]['Schema'], context, properties)
);
}
const exportSheet = utils.json_to_sheet(fittedDatalist, { header: headers2 });
const exportSheet = utils.json_to_sheet(fittedDatalist, {
header: headers2,
});
const exportBook = utils.book_new();
utils.book_append_sheet(exportBook, exportSheet);
return await write(exportBook, { type: 'buffer' });
@ -141,13 +164,11 @@ export async function getImportationTemplate<
throw new Error('未找到对应的模板');
}
const exportSheet = utils.json_to_sheet([], { header: headers });
const widthList = headers.map(
(ele: string) => {
const widthList = headers.map((ele: string) => {
return {
width: ele.length * 2.2,
};
}
)
});
exportSheet['!cols'] = widthList;
const exportBook = utils.book_new();
utils.book_append_sheet(exportBook, exportSheet);

80
tsconfig.es.json Normal file
View File

@ -0,0 +1,80 @@
{
"compilerOptions": {
"jsx": "preserve",
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "ESNEXT", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"lib": [
"dom",
"dom.iterable",
"esnext"
],
// "lib": [], /* 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. */
"importHelpers": true,
// "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": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": 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. */
"skipLibCheck": true,
// "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 */
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
"resolveJsonModule": true
},
"types": [
"node",
"miniprogram-api-typings"
],
"include": [ "src/**/*.ts" ],
"exclude": [
"node_modules",
"**/*.spec.ts",
"test"
]
}