oak-domain 4.2.1 → 4.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/store/CascadeStore.d.ts +2 -2
- package/lib/store/CascadeStore.js +12 -8
- package/lib/store/RelationAuth.js +49 -19
- package/lib/store/checker.js +2 -2
- package/lib/store/relation.d.ts +1 -1
- package/lib/store/relation.js +10 -3
- package/lib/types/Connector.d.ts +2 -1
- package/lib/types/Sync.d.ts +25 -5
- package/lib/types/Sync.js +1 -0
- package/lib/utils/SimpleConnector.d.ts +18 -1
- package/lib/utils/SimpleConnector.js +44 -33
- package/lib/utils/relationPath.d.ts +2 -2
- package/lib/utils/relationPath.js +13 -13
- package/package.json +1 -1
|
@@ -61,14 +61,14 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
|
|
|
61
61
|
* @param filter
|
|
62
62
|
* @returns
|
|
63
63
|
*/
|
|
64
|
-
protected destructCascadeUpdate<T extends keyof ED, Cxt extends SyncContext<ED> | AsyncContext<ED>, OP extends OperateOption, R>(entity: T, action: ED[T]['Action'], data: ED[T]['CreateSingle']['data'] | ED[T]['Update']['data'] | ED[T]['Remove']['data'], context: Cxt, option: OP, cascadeUpdate: <T2 extends keyof ED>(entity: T2, operation: ED[T2]['Operation'], context: Cxt, option: OP) => R, filter?: ED[T]['Update']['filter']): {
|
|
64
|
+
protected destructCascadeUpdate<T extends keyof ED, Cxt extends SyncContext<ED> | AsyncContext<ED>, OP extends OperateOption, R>(entity: T, action: ED[T]['Action'], data: ED[T]['CreateSingle']['data'] | ED[T]['Update']['data'] | ED[T]['Remove']['data'], context: Cxt, option: OP, cascadeUpdate: <T2 extends keyof ED>(entity: T2, operation: ED[T2]['Operation'], context: Cxt, option: OP) => R, filter?: ED[T]['Update']['filter'], bornAt?: number): {
|
|
65
65
|
data: Record<string, any>;
|
|
66
66
|
beforeFns: (() => R)[];
|
|
67
67
|
afterFns: (() => R)[];
|
|
68
68
|
};
|
|
69
69
|
protected preProcessDataCreated<T extends keyof ED>(entity: T, data: ED[T]['Create']['data']): void;
|
|
70
70
|
protected preProcessDataUpdated(data: Record<string, any>): void;
|
|
71
|
-
judgeRelation(entity: keyof ED, attr: string): string | 1 | 2 | string[] | 0;
|
|
71
|
+
judgeRelation(entity: keyof ED, attr: string): string | 1 | 2 | string[] | 0 | -1;
|
|
72
72
|
/**
|
|
73
73
|
* 和具体的update过程无关的例程放在这里,包括对later动作的处理、对oper的记录以及对record的收集等
|
|
74
74
|
* @param entity
|
|
@@ -674,7 +674,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|
|
674
674
|
* @param filter
|
|
675
675
|
* @returns
|
|
676
676
|
*/
|
|
677
|
-
destructCascadeUpdate(entity, action, data, context, option, cascadeUpdate, filter) {
|
|
677
|
+
destructCascadeUpdate(entity, action, data, context, option, cascadeUpdate, filter, bornAt) {
|
|
678
678
|
const modiAttr = this.getSchema()[entity].toModi;
|
|
679
679
|
const option2 = Object.assign({}, option);
|
|
680
680
|
const opData = {};
|
|
@@ -696,7 +696,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|
|
696
696
|
}
|
|
697
697
|
}
|
|
698
698
|
for (const attr in data) {
|
|
699
|
-
const relation = (0, relation_1.judgeRelation)(this.storageSchema, entity, attr);
|
|
699
|
+
const relation = (0, relation_1.judgeRelation)(this.storageSchema, entity, attr, !!bornAt);
|
|
700
700
|
if (relation === 1) {
|
|
701
701
|
Object.assign(opData, {
|
|
702
702
|
[attr]: data[attr],
|
|
@@ -814,8 +814,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|
|
814
814
|
}
|
|
815
815
|
beforeFns.push(() => cascadeUpdate.call(this, relation, operationMto, context, option2));
|
|
816
816
|
}
|
|
817
|
-
else {
|
|
818
|
-
(0, assert_1.default)(relation instanceof Array);
|
|
817
|
+
else if (relation instanceof Array) {
|
|
819
818
|
const [entityOtm, foreignKey] = relation;
|
|
820
819
|
const otmOperations = data[attr];
|
|
821
820
|
const dealWithOneToMany = (otm) => {
|
|
@@ -969,6 +968,9 @@ class CascadeStore extends RowStore_1.RowStore {
|
|
|
969
968
|
dealWithOneToMany(otmOperations);
|
|
970
969
|
}
|
|
971
970
|
}
|
|
971
|
+
else {
|
|
972
|
+
console.warn(`接收到不合法的属性「${attr}」`);
|
|
973
|
+
}
|
|
972
974
|
}
|
|
973
975
|
return {
|
|
974
976
|
data: opData,
|
|
@@ -1306,6 +1308,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|
|
1306
1308
|
if (!option.dontCreateOper && !['oper', 'operEntity', 'modiEntity', 'modi'].includes(entity) && ids.length > 0) {
|
|
1307
1309
|
// 按照框架要求生成Oper和OperEntity这两个内置的对象
|
|
1308
1310
|
(0, assert_1.default)(operId);
|
|
1311
|
+
const operatorId = context.getCurrentUserId(true);
|
|
1309
1312
|
const createOper = {
|
|
1310
1313
|
id: 'dummy',
|
|
1311
1314
|
action: 'create',
|
|
@@ -1315,6 +1318,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|
|
1315
1318
|
data,
|
|
1316
1319
|
targetEntity: entity,
|
|
1317
1320
|
bornAt,
|
|
1321
|
+
operatorId,
|
|
1318
1322
|
operEntity$oper: {
|
|
1319
1323
|
id: 'dummy',
|
|
1320
1324
|
action: 'create',
|
|
@@ -1444,7 +1448,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|
|
1444
1448
|
}
|
|
1445
1449
|
}
|
|
1446
1450
|
cascadeUpdate(entity, operation, context, option) {
|
|
1447
|
-
const { action, data, filter, id } = operation;
|
|
1451
|
+
const { action, data, filter, id, bornAt } = operation;
|
|
1448
1452
|
let opData;
|
|
1449
1453
|
const wholeBeforeFns = [];
|
|
1450
1454
|
const wholeAfterFns = [];
|
|
@@ -1484,21 +1488,21 @@ class CascadeStore extends RowStore_1.RowStore {
|
|
|
1484
1488
|
* @param option
|
|
1485
1489
|
*/
|
|
1486
1490
|
async cascadeUpdateAsync(entity, operation, context, option) {
|
|
1487
|
-
const { action, data, filter, id } = operation;
|
|
1491
|
+
const { action, data, filter, id, bornAt } = operation;
|
|
1488
1492
|
let opData;
|
|
1489
1493
|
const wholeBeforeFns = [];
|
|
1490
1494
|
const wholeAfterFns = [];
|
|
1491
1495
|
if (['create', 'create-l'].includes(action) && data instanceof Array) {
|
|
1492
1496
|
opData = [];
|
|
1493
1497
|
for (const d of data) {
|
|
1494
|
-
const { data: od, beforeFns, afterFns } = this.destructCascadeUpdate(entity, action, d, context, option, this.cascadeUpdateAsync);
|
|
1498
|
+
const { data: od, beforeFns, afterFns } = this.destructCascadeUpdate(entity, action, d, context, option, this.cascadeUpdateAsync, undefined, bornAt);
|
|
1495
1499
|
opData.push(od);
|
|
1496
1500
|
wholeBeforeFns.push(...beforeFns);
|
|
1497
1501
|
wholeAfterFns.push(...afterFns);
|
|
1498
1502
|
}
|
|
1499
1503
|
}
|
|
1500
1504
|
else {
|
|
1501
|
-
const { data: od, beforeFns, afterFns } = this.destructCascadeUpdate(entity, action, data, context, option, this.cascadeUpdateAsync, filter);
|
|
1505
|
+
const { data: od, beforeFns, afterFns } = this.destructCascadeUpdate(entity, action, data, context, option, this.cascadeUpdateAsync, filter, bornAt);
|
|
1502
1506
|
opData = od;
|
|
1503
1507
|
wholeBeforeFns.push(...beforeFns);
|
|
1504
1508
|
wholeAfterFns.push(...afterFns);
|
|
@@ -53,7 +53,7 @@ class RelationAuth {
|
|
|
53
53
|
* @param destRelationId
|
|
54
54
|
* @returns
|
|
55
55
|
*/
|
|
56
|
-
const checkOnRelationId = (
|
|
56
|
+
const checkOnRelationId = (entity, destRelationId, filter) => {
|
|
57
57
|
/**
|
|
58
58
|
* 找到能创建此relation的所有父级relation,只要user和其中一个有关联即可以通过
|
|
59
59
|
*/
|
|
@@ -114,20 +114,48 @@ class RelationAuth {
|
|
|
114
114
|
* @param relationFilter 限定relationId的条件
|
|
115
115
|
* @param intersection 是否交集(对每个relationId都得有权限)
|
|
116
116
|
* @param entityFilter 限定entity的条件
|
|
117
|
+
* @param entity 对应的entity
|
|
118
|
+
* @attention 这里为了代码复用,有可能是要通过本函数内部来查询确定entity;所以要保证,如果传入的relationFilter就可以确定relationId,则这里的entity参数必传。
|
|
117
119
|
* @returns
|
|
118
120
|
*/
|
|
119
|
-
const checkOnMultipleRelations = (relationFilter, intersection, entityFilter) => {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
121
|
+
const checkOnMultipleRelations = (relationFilter, intersection, entityFilter, entity) => {
|
|
122
|
+
let entity2 = entity;
|
|
123
|
+
const getRelationIds = () => {
|
|
124
|
+
const relevantIds = (0, filter_1.getRelevantIds)(relationFilter);
|
|
125
|
+
if (relevantIds.length > 0) {
|
|
126
|
+
return relevantIds;
|
|
127
|
+
}
|
|
128
|
+
const relations = context.select('relation', {
|
|
129
|
+
data: {
|
|
130
|
+
id: 1,
|
|
131
|
+
entity: 1,
|
|
132
|
+
entityId: 1,
|
|
133
|
+
},
|
|
134
|
+
filter: relationFilter
|
|
135
|
+
}, { dontCollect: true });
|
|
136
|
+
if (relations instanceof Promise) {
|
|
137
|
+
return relations.then((rs) => {
|
|
138
|
+
if (!entity2) {
|
|
139
|
+
entity2 = rs[0]?.entity;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
(0, assert_1.default)(entity2 === rs[0]?.entity);
|
|
143
|
+
}
|
|
144
|
+
return rs.map(ele => ele.id);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (!entity2) {
|
|
148
|
+
entity2 = relations[0]?.entity;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
(0, assert_1.default)(entity2 === relations[0]?.entity);
|
|
152
|
+
}
|
|
153
|
+
return relations.map(ele => ele.id);
|
|
154
|
+
};
|
|
155
|
+
const relationIds = getRelationIds();
|
|
156
|
+
if (relationIds instanceof Promise) {
|
|
157
|
+
return relationIds.then((ids) => {
|
|
158
|
+
return Promise.all(ids.map(ele => checkOnRelationId(entity2, ele, entityFilter))).then((value) => {
|
|
131
159
|
if (intersection) {
|
|
132
160
|
return !(value.includes(false));
|
|
133
161
|
}
|
|
@@ -135,7 +163,7 @@ class RelationAuth {
|
|
|
135
163
|
});
|
|
136
164
|
});
|
|
137
165
|
}
|
|
138
|
-
const value =
|
|
166
|
+
const value = relationIds.map(ele => checkOnRelationId(entity2, ele, entityFilter));
|
|
139
167
|
if (intersection) {
|
|
140
168
|
return !(value.includes(false));
|
|
141
169
|
}
|
|
@@ -156,12 +184,14 @@ class RelationAuth {
|
|
|
156
184
|
}
|
|
157
185
|
if (relationId) {
|
|
158
186
|
// 如果指定relation,则测试该relation上是否可行
|
|
159
|
-
|
|
160
|
-
return
|
|
187
|
+
// 目前可能会有多个relationIds传入(userEntityGrant做测试),但一定是可以确定的relationId集合
|
|
188
|
+
return checkOnMultipleRelations({ id: relationId }, true, entityFilter, entity);
|
|
161
189
|
}
|
|
162
190
|
else {
|
|
163
191
|
// 否则为测试“能否”有权限管理的资格,此时只要有一个就可以
|
|
164
192
|
// 这是为上层的menu所有,真正的创建不可能走到这里
|
|
193
|
+
// bug fixed,目前框架不支持entityId为null,所以这里暂时只支持entityId一种方式的测试
|
|
194
|
+
(0, assert_1.default)(entityId);
|
|
165
195
|
return checkOnMultipleRelations({
|
|
166
196
|
entity,
|
|
167
197
|
$or: [
|
|
@@ -171,10 +201,10 @@ class RelationAuth {
|
|
|
171
201
|
},
|
|
172
202
|
},
|
|
173
203
|
{
|
|
174
|
-
|
|
204
|
+
entityId,
|
|
175
205
|
}
|
|
176
206
|
]
|
|
177
|
-
}, false, entityFilter);
|
|
207
|
+
}, false, entityFilter, entity);
|
|
178
208
|
}
|
|
179
209
|
}
|
|
180
210
|
else {
|
|
@@ -184,7 +214,7 @@ class RelationAuth {
|
|
|
184
214
|
userRelation$relation: filter,
|
|
185
215
|
}, false, {
|
|
186
216
|
userRelation$entity: filter,
|
|
187
|
-
});
|
|
217
|
+
}, filter.entity);
|
|
188
218
|
}
|
|
189
219
|
}
|
|
190
220
|
checkOperateSpecialEntities2(entity2, action, filter, context) {
|
package/lib/store/checker.js
CHANGED
|
@@ -152,7 +152,7 @@ function translateCheckerInSyncContext(checker) {
|
|
|
152
152
|
if ((0, filter_1.checkFilterContains)(entity, context, filter2, operationFilter, true)) {
|
|
153
153
|
return;
|
|
154
154
|
}
|
|
155
|
-
const e = new Exception_1.OakRowInconsistencyException(undefined, errMsg);
|
|
155
|
+
const e = new Exception_1.OakRowInconsistencyException(undefined, errMsg || 'row checker condition illegal');
|
|
156
156
|
throw e;
|
|
157
157
|
};
|
|
158
158
|
return {
|
|
@@ -402,7 +402,7 @@ function checkAttributeLegal(schema, entity, data) {
|
|
|
402
402
|
case 'enum': {
|
|
403
403
|
(0, assert_1.default)(enumeration);
|
|
404
404
|
if (!enumeration.includes(data[attr])) {
|
|
405
|
-
throw new Exception_1.OakInputIllegalException(entity, [attr], 'not in
|
|
405
|
+
throw new Exception_1.OakInputIllegalException(entity, [attr], 'not in enumeration');
|
|
406
406
|
}
|
|
407
407
|
break;
|
|
408
408
|
}
|
package/lib/store/relation.d.ts
CHANGED
|
@@ -9,4 +9,4 @@ import { StorageSchema } from "../types/Storage";
|
|
|
9
9
|
* @param row
|
|
10
10
|
* @returns
|
|
11
11
|
*/
|
|
12
|
-
export declare function judgeRelation<ED extends EntityDict & BaseEntityDict>(schema: StorageSchema<ED>, entity: keyof ED, attr: string): string | 1 | 2 | string[] | 0;
|
|
12
|
+
export declare function judgeRelation<ED extends EntityDict & BaseEntityDict>(schema: StorageSchema<ED>, entity: keyof ED, attr: string, allowUnrecoganized?: boolean): string | 1 | 2 | string[] | 0 | -1;
|
package/lib/store/relation.js
CHANGED
|
@@ -13,7 +13,7 @@ const Entity_1 = require("../types/Entity");
|
|
|
13
13
|
* @param row
|
|
14
14
|
* @returns
|
|
15
15
|
*/
|
|
16
|
-
function judgeRelation(schema, entity, attr) {
|
|
16
|
+
function judgeRelation(schema, entity, attr, allowUnrecoganized) {
|
|
17
17
|
const { [entity]: { attributes } } = schema;
|
|
18
18
|
if (attr.startsWith(Demand_1.EXPRESSION_PREFIX) || attr.startsWith('#')) {
|
|
19
19
|
// 表达式属性或者metadata
|
|
@@ -60,8 +60,15 @@ function judgeRelation(schema, entity, attr) {
|
|
|
60
60
|
return 2;
|
|
61
61
|
}
|
|
62
62
|
else {
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
if (Entity_1.initinctiveAttributes.includes(attr)) {
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
else if (allowUnrecoganized) {
|
|
67
|
+
return -1;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
throw new Error(`${entity}对象中的${attr}属性找不到`);
|
|
71
|
+
}
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
exports.judgeRelation = judgeRelation;
|
package/lib/types/Connector.d.ts
CHANGED
|
@@ -10,9 +10,10 @@ export interface Connector<ED extends EntityDict, FrontCxt extends SyncContext<E
|
|
|
10
10
|
message?: string | null;
|
|
11
11
|
}>;
|
|
12
12
|
getRouter: () => string;
|
|
13
|
-
|
|
13
|
+
parseRequest: (headers: IncomingHttpHeaders, body?: any, files?: any) => {
|
|
14
14
|
contextString?: string;
|
|
15
15
|
aspectName: string;
|
|
16
|
+
data?: any;
|
|
16
17
|
};
|
|
17
18
|
serializeResult: (result: any, opRecords: OpRecord<ED>[], headers: IncomingHttpHeaders, body: any, message?: string) => Promise<{
|
|
18
19
|
body: any;
|
package/lib/types/Sync.d.ts
CHANGED
|
@@ -17,26 +17,46 @@ export type SelfEncryptInfo = {
|
|
|
17
17
|
privateKey: string;
|
|
18
18
|
algorithm: Algorithm;
|
|
19
19
|
};
|
|
20
|
-
export interface
|
|
20
|
+
export interface PullEntityDef<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>> {
|
|
21
|
+
direction: 'pull';
|
|
21
22
|
entity: T;
|
|
22
23
|
path: string;
|
|
23
24
|
recursive?: boolean;
|
|
24
25
|
relationName?: string;
|
|
25
|
-
|
|
26
|
+
process?: <A extends ED[T]['Action']>(action: A, data: ED[T]['Operation']['data'], context: Cxt) => Promise<void>;
|
|
26
27
|
}
|
|
27
|
-
export interface
|
|
28
|
+
export interface PushEntityDef<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>> {
|
|
29
|
+
direction: 'push';
|
|
30
|
+
entity: T;
|
|
31
|
+
path: string;
|
|
32
|
+
recursive?: boolean;
|
|
33
|
+
relationName?: string;
|
|
34
|
+
actions?: ED[T]['Action'][];
|
|
35
|
+
/**
|
|
36
|
+
* 同步结果回调,根据接口的幂等原理,同步一定要完全成功再回调
|
|
37
|
+
*/
|
|
38
|
+
onSynchronized?: (result: {
|
|
39
|
+
action: ED[T]['Action'];
|
|
40
|
+
data: ED[T]['Operation']['data'];
|
|
41
|
+
rowIds: string[];
|
|
42
|
+
}, context: Cxt) => Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
export interface SyncRemoteConfigBase<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> {
|
|
28
45
|
entity: keyof ED;
|
|
46
|
+
entitySelf?: keyof ED;
|
|
29
47
|
endpoint?: string;
|
|
30
48
|
pathToUser?: string;
|
|
31
49
|
relationName?: string;
|
|
32
|
-
|
|
50
|
+
pushEntities?: Array<PushEntityDef<ED, keyof ED, Cxt>>;
|
|
51
|
+
pullEntities?: Array<PullEntityDef<ED, keyof ED, Cxt>>;
|
|
33
52
|
}
|
|
34
|
-
interface SyncRemoteConfig<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends SyncRemoteConfigBase<ED> {
|
|
53
|
+
interface SyncRemoteConfig<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends SyncRemoteConfigBase<ED, Cxt> {
|
|
35
54
|
getPushInfo: (userId: string, context: Cxt) => Promise<RemotePushInfo>;
|
|
36
55
|
getPullInfo: (id: string, context: Cxt) => Promise<RemotePullInfo>;
|
|
37
56
|
}
|
|
38
57
|
export interface SyncSelfConfigBase<ED extends EntityDict & BaseEntityDict> {
|
|
39
58
|
endpoint?: string;
|
|
59
|
+
entitySelf: keyof ED;
|
|
40
60
|
}
|
|
41
61
|
interface SyncSelfConfig<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends SyncSelfConfigBase<ED> {
|
|
42
62
|
getSelfEncryptInfo: (context: Cxt) => Promise<SelfEncryptInfo>;
|
package/lib/types/Sync.js
CHANGED
|
@@ -20,6 +20,22 @@ export declare class SimpleConnector<ED extends EntityDict, FrontCxt extends Syn
|
|
|
20
20
|
private option;
|
|
21
21
|
private makeException;
|
|
22
22
|
constructor(option: ServerOption, makeException: (exceptionData: any) => OakException<ED>);
|
|
23
|
+
protected makeHeadersAndBody(name: string, data: any, context?: FrontCxt): Promise<{
|
|
24
|
+
headers: Record<string, string>;
|
|
25
|
+
body: FormData;
|
|
26
|
+
} | {
|
|
27
|
+
headers: HeadersInit;
|
|
28
|
+
body: string;
|
|
29
|
+
}>;
|
|
30
|
+
protected parseAspectResult(response: Response): Promise<{
|
|
31
|
+
result: any;
|
|
32
|
+
opRecords: any;
|
|
33
|
+
message: string | null;
|
|
34
|
+
} | {
|
|
35
|
+
result: ArrayBuffer;
|
|
36
|
+
message: string | null;
|
|
37
|
+
opRecords?: undefined;
|
|
38
|
+
}>;
|
|
23
39
|
callAspect(name: string, params: any, context?: FrontCxt): Promise<{
|
|
24
40
|
result: any;
|
|
25
41
|
opRecords: any;
|
|
@@ -37,9 +53,10 @@ export declare class SimpleConnector<ED extends EntityDict, FrontCxt extends Syn
|
|
|
37
53
|
path: any;
|
|
38
54
|
}>;
|
|
39
55
|
getEndpointRouter(): string;
|
|
40
|
-
|
|
56
|
+
parseRequest(headers: IncomingHttpHeaders, body?: any, files?: any): {
|
|
41
57
|
contextString: string | undefined;
|
|
42
58
|
aspectName: string;
|
|
59
|
+
data: any;
|
|
43
60
|
};
|
|
44
61
|
serializeResult(result: any, opRecords: OpRecord<ED>[], headers: IncomingHttpHeaders, body: any, message?: string): Promise<{
|
|
45
62
|
body: any;
|
|
@@ -6,20 +6,6 @@ const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
|
6
6
|
const stream_1 = require("stream");
|
|
7
7
|
const url_1 = tslib_1.__importDefault(require("url"));
|
|
8
8
|
const types_1 = require("../types");
|
|
9
|
-
function makeContentTypeAndBody(data) {
|
|
10
|
-
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
|
11
|
-
if (data instanceof FormData) {
|
|
12
|
-
return {
|
|
13
|
-
// contentType: 'multipart/form-data',
|
|
14
|
-
body: data,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
contentType: 'application/json',
|
|
20
|
-
body: JSON.stringify(data),
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
9
|
class SimpleConnector {
|
|
24
10
|
static ASPECT_ROUTER = '/aspect';
|
|
25
11
|
static BRIDGE_ROUTER = '/bridge';
|
|
@@ -47,26 +33,30 @@ class SimpleConnector {
|
|
|
47
33
|
this.serverSubscribePointUrl = `${serverUrl}${SimpleConnector.SUBSCRIBE_POINT_ROUTER}`;
|
|
48
34
|
this.makeException = makeException;
|
|
49
35
|
}
|
|
50
|
-
async
|
|
36
|
+
async makeHeadersAndBody(name, data, context) {
|
|
51
37
|
const cxtStr = context ? await context.toString() : '{}';
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
body,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
catch (err) {
|
|
67
|
-
// fetch返回异常一定是网络异常
|
|
68
|
-
throw new types_1.OakNetworkException(`请求[${this.serverAspectUrl}],发生网络异常`);
|
|
38
|
+
const headers = {
|
|
39
|
+
'oak-cxt': cxtStr,
|
|
40
|
+
'oak-aspect': name,
|
|
41
|
+
};
|
|
42
|
+
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
|
43
|
+
if (data instanceof FormData) {
|
|
44
|
+
return {
|
|
45
|
+
headers,
|
|
46
|
+
body: data,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
69
49
|
}
|
|
50
|
+
return {
|
|
51
|
+
headers: {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
...headers,
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify(data),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
;
|
|
59
|
+
async parseAspectResult(response) {
|
|
70
60
|
if (response.status > 299) {
|
|
71
61
|
const err = new types_1.OakServerProxyException(`网络请求返回status是${response.status}`);
|
|
72
62
|
throw err;
|
|
@@ -98,6 +88,22 @@ class SimpleConnector {
|
|
|
98
88
|
throw new Error(`尚不支持的content-type类型${responseType}`);
|
|
99
89
|
}
|
|
100
90
|
}
|
|
91
|
+
async callAspect(name, params, context) {
|
|
92
|
+
const { headers, body } = await this.makeHeadersAndBody(name, params, context);
|
|
93
|
+
let response;
|
|
94
|
+
try {
|
|
95
|
+
response = await global.fetch(this.serverAspectUrl, {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers,
|
|
98
|
+
body,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
// fetch返回异常一定是网络异常
|
|
103
|
+
throw new types_1.OakNetworkException(`请求[${this.serverAspectUrl}],发生网络异常`);
|
|
104
|
+
}
|
|
105
|
+
return this.parseAspectResult(response);
|
|
106
|
+
}
|
|
101
107
|
getRouter() {
|
|
102
108
|
return SimpleConnector.ASPECT_ROUTER;
|
|
103
109
|
}
|
|
@@ -142,13 +148,18 @@ class SimpleConnector {
|
|
|
142
148
|
getEndpointRouter() {
|
|
143
149
|
return SimpleConnector.ENDPOINT_ROUTER;
|
|
144
150
|
}
|
|
145
|
-
|
|
151
|
+
parseRequest(headers, body, files) {
|
|
146
152
|
const { 'oak-cxt': oakCxtStr, 'oak-aspect': aspectName } = headers;
|
|
147
153
|
(0, assert_1.default)(typeof oakCxtStr === 'string' || oakCxtStr === undefined);
|
|
148
154
|
(0, assert_1.default)(typeof aspectName === 'string');
|
|
149
155
|
return {
|
|
150
156
|
contextString: oakCxtStr,
|
|
151
157
|
aspectName,
|
|
158
|
+
/* data: !files ? body : {
|
|
159
|
+
data: body,
|
|
160
|
+
files,
|
|
161
|
+
}, */ // 下个版本再改
|
|
162
|
+
data: files ? Object.assign({}, body, files) : body,
|
|
152
163
|
};
|
|
153
164
|
}
|
|
154
165
|
async serializeResult(result, opRecords, headers, body, message) {
|
|
@@ -11,7 +11,7 @@ import { EntityDict } from "../types/Entity";
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function destructRelationPath<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(schema: StorageSchema<ED>, entity: T, path: string, relationFilter: ED['userRelation']['Selection']['filter'], recursive?: boolean): {
|
|
13
13
|
projection: ED[T]['Selection']['data'];
|
|
14
|
-
getData: (d: Partial<ED[T]['Schema']>) => ED['userRelation']['Schema'][];
|
|
14
|
+
getData: (d: Partial<ED[T]['Schema']>) => ED['userRelation']['Schema'][] | undefined;
|
|
15
15
|
};
|
|
16
16
|
/**
|
|
17
17
|
* 根据entity的相对path,找到对应的根结点对象上的直接userId
|
|
@@ -27,5 +27,5 @@ export declare function destructDirectPath<ED extends EntityDict & BaseEntityDic
|
|
|
27
27
|
entity: keyof ED;
|
|
28
28
|
entityId: string;
|
|
29
29
|
userId: string;
|
|
30
|
-
}[];
|
|
30
|
+
}[] | undefined;
|
|
31
31
|
};
|
|
@@ -59,7 +59,7 @@ function destructRelationPath(schema, entity, path, relationFilter, recursive) {
|
|
|
59
59
|
userId: 1,
|
|
60
60
|
},
|
|
61
61
|
filter: relationFilter,
|
|
62
|
-
}
|
|
62
|
+
} // as ED['userRelation']['Selection']
|
|
63
63
|
},
|
|
64
64
|
getData: (d) => {
|
|
65
65
|
return d.userRelation$entity;
|
|
@@ -100,7 +100,7 @@ function destructRelationPath(schema, entity, path, relationFilter, recursive) {
|
|
|
100
100
|
data: projection,
|
|
101
101
|
},
|
|
102
102
|
},
|
|
103
|
-
getData: (d) => d[attr] && d[attr].map(
|
|
103
|
+
getData: (d) => d[attr] && d[attr].map(ele => getData(ele)).flat().filter(ele => !!ele),
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
106
|
};
|
|
@@ -133,11 +133,11 @@ function destructDirectPath(schema, entity, path, recursive) {
|
|
|
133
133
|
},
|
|
134
134
|
getData: (d) => {
|
|
135
135
|
if (d) {
|
|
136
|
-
return {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
return [{
|
|
137
|
+
entity: e,
|
|
138
|
+
entityId: d.id,
|
|
139
|
+
userId: d.entityId,
|
|
140
|
+
}];
|
|
141
141
|
}
|
|
142
142
|
},
|
|
143
143
|
};
|
|
@@ -151,11 +151,11 @@ function destructDirectPath(schema, entity, path, recursive) {
|
|
|
151
151
|
},
|
|
152
152
|
getData: (d) => {
|
|
153
153
|
if (d) {
|
|
154
|
-
return {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
return [{
|
|
155
|
+
entity: e,
|
|
156
|
+
entityId: d.id,
|
|
157
|
+
userId: d[`${attr}Id`],
|
|
158
|
+
}];
|
|
159
159
|
}
|
|
160
160
|
},
|
|
161
161
|
};
|
|
@@ -193,7 +193,7 @@ function destructDirectPath(schema, entity, path, recursive) {
|
|
|
193
193
|
data: projection,
|
|
194
194
|
},
|
|
195
195
|
},
|
|
196
|
-
getData: (d) => d[attr] && d[attr].map(
|
|
196
|
+
getData: (d) => d[attr] && d[attr].map(ele => getData(ele)).flat().filter(ele => !!ele),
|
|
197
197
|
};
|
|
198
198
|
}
|
|
199
199
|
};
|