@websolutespa/bom-mixer-store 1.2.2 → 1.3.0
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/CHANGELOG.md +7 -0
- package/dist/index.d.ts +17 -10
- package/dist/index.js +569 -282
- package/dist/index.mjs +545 -266
- package/package.json +1 -1
- package/src/mock/mock-menu.service.ts +63 -28
- package/src/mock/mock-page.service.ts +133 -54
- package/src/mock/mock.service.ts +120 -45
- package/src/remote/remote.service.ts +14 -9
- package/src/static/static.service.ts +67 -50
- package/src/store/store.handler.ts +140 -8
- package/src/store/store.ts +3 -2
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ICategorized, ICategory, IEntity,
|
|
2
|
+
ICategorized, ICategory, IEntity,
|
|
3
|
+
IMenu, IMenuCategory, IMenuGroup, IMenuItem,
|
|
3
4
|
IMenuLink, IMenuPage, IMenuRoute, IRoute, IStore,
|
|
4
5
|
IUndecoratedMenu, IUndecoratedMenuCategory, IUndecoratedMenuGroup, IUndecoratedMenuItem,
|
|
5
|
-
IUndecoratedMenuLink, IUndecoratedMenuPage,
|
|
6
|
+
IUndecoratedMenuLink, IUndecoratedMenuPage,
|
|
7
|
+
QueryParams
|
|
6
8
|
} from '@websolutespa/bom-core';
|
|
7
|
-
import { MockService } from './mock.service';
|
|
9
|
+
import { MockService, localizeItem_, localizeItems_ } from './mock.service';
|
|
8
10
|
|
|
9
11
|
export const MAX_INT = 1000000000000; // 9007199254740991
|
|
10
12
|
|
|
@@ -12,11 +14,15 @@ let UID = 0;
|
|
|
12
14
|
|
|
13
15
|
export class MockMenuService<T extends IEntity = IEntity> extends MockService<T> {
|
|
14
16
|
|
|
17
|
+
/*
|
|
15
18
|
async findOne<B extends T = T>(id: IEquatable, params: QueryParams = {}): Promise<B | undefined> {
|
|
16
19
|
// console.log('MockMenuService.findOne', id, params);
|
|
17
20
|
let item = await super.findOne<B>(id, params);
|
|
18
21
|
if (item && params.market && params.locale) {
|
|
19
|
-
item = await
|
|
22
|
+
item = await decorateMenu_(this.store, (item as any), {
|
|
23
|
+
market: params.market,
|
|
24
|
+
locale: params.locale,
|
|
25
|
+
}) as any;
|
|
20
26
|
}
|
|
21
27
|
return item;
|
|
22
28
|
}
|
|
@@ -25,7 +31,10 @@ export class MockMenuService<T extends IEntity = IEntity> extends MockService<T>
|
|
|
25
31
|
// console.log('MockMenuService.findMany', params);
|
|
26
32
|
let items = await super.findMany<B>(params);
|
|
27
33
|
if (params.market && params.locale) {
|
|
28
|
-
items = await
|
|
34
|
+
items = await decorateMenus_(this.store, (items as any[]), {
|
|
35
|
+
market: params.market,
|
|
36
|
+
locale: params.locale,
|
|
37
|
+
}) as any[];
|
|
29
38
|
}
|
|
30
39
|
return items;
|
|
31
40
|
}
|
|
@@ -34,20 +43,40 @@ export class MockMenuService<T extends IEntity = IEntity> extends MockService<T>
|
|
|
34
43
|
// console.log('MockMenuService.findPaged', params);
|
|
35
44
|
const pagination = await super.findPaged<B>(params);
|
|
36
45
|
if (params.market && params.locale) {
|
|
37
|
-
pagination.docs = await
|
|
46
|
+
pagination.docs = await decorateMenus_(this.store, (pagination.docs as any[]), {
|
|
47
|
+
market: params.market,
|
|
48
|
+
locale: params.locale,
|
|
49
|
+
}) as any[];
|
|
38
50
|
}
|
|
39
51
|
return pagination;
|
|
40
52
|
}
|
|
53
|
+
*/
|
|
41
54
|
|
|
42
|
-
protected override
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
55
|
+
protected override async decorateOne_<B extends T = T>(item: B, params: QueryParams = {}): Promise<B> {
|
|
56
|
+
let decoratedItem = await localizeItem_(item, params);
|
|
57
|
+
// decoratedItem = await decorateHref_<B>(this.store, decoratedItem, params);
|
|
58
|
+
if (params.market && params.locale) {
|
|
59
|
+
decoratedItem = await decorateMenu_(this.store, decoratedItem as any as IUndecoratedMenu, {
|
|
60
|
+
market: params.market,
|
|
61
|
+
locale: params.locale,
|
|
62
|
+
}) as any;
|
|
47
63
|
}
|
|
64
|
+
return decoratedItem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
protected override async decorateMany_<B extends T = T>(items: B[], params: QueryParams = {}): Promise<B[]> {
|
|
68
|
+
let decoratedItems = await localizeItems_(items, params);
|
|
69
|
+
// decoratedItems = await decorateHrefs_<B>(this.store, decoratedItems, params);
|
|
70
|
+
if (params.market && params.locale) {
|
|
71
|
+
decoratedItems = await decorateMenus_(this.store, decoratedItems as any as IUndecoratedMenu[], {
|
|
72
|
+
market: params.market,
|
|
73
|
+
locale: params.locale,
|
|
74
|
+
}) as any[];
|
|
75
|
+
}
|
|
76
|
+
return decoratedItems;
|
|
48
77
|
}
|
|
49
|
-
}
|
|
50
78
|
|
|
79
|
+
}
|
|
51
80
|
|
|
52
81
|
async function collectPages(store: IStore, items?: IUndecoratedMenuItem[], params: QueryParams = {}) {
|
|
53
82
|
if (!items) {
|
|
@@ -65,6 +94,8 @@ async function collectPages(store: IStore, items?: IUndecoratedMenuItem[], param
|
|
|
65
94
|
if (value) {
|
|
66
95
|
const routes = await store.route.findMany<IRoute>({
|
|
67
96
|
where: {
|
|
97
|
+
...(params.market ? { market: { equals: params.market } } : {}),
|
|
98
|
+
...(params.locale ? { locale: { equals: params.locale } } : {}),
|
|
68
99
|
page: {
|
|
69
100
|
equals: item.page.value,
|
|
70
101
|
},
|
|
@@ -72,8 +103,6 @@ async function collectPages(store: IStore, items?: IUndecoratedMenuItem[], param
|
|
|
72
103
|
equals: item.page.relationTo,
|
|
73
104
|
},
|
|
74
105
|
},
|
|
75
|
-
market: params.market,
|
|
76
|
-
locale: params.locale,
|
|
77
106
|
});
|
|
78
107
|
const page = {
|
|
79
108
|
...value,
|
|
@@ -92,31 +121,34 @@ async function collectPages(store: IStore, items?: IUndecoratedMenuItem[], param
|
|
|
92
121
|
}
|
|
93
122
|
}
|
|
94
123
|
|
|
95
|
-
export async function
|
|
124
|
+
export async function decorateMenu_(store: IStore, item: IUndecoratedMenu, params: { market: string, locale: string }): Promise<IMenu> {
|
|
96
125
|
const items = item.items || [];
|
|
97
126
|
const decoratedItem: IMenu = {
|
|
98
127
|
id: item.id,
|
|
99
128
|
items: [],
|
|
100
129
|
};
|
|
101
|
-
const categories = await store.category.findMany<ICategory>(
|
|
130
|
+
const categories = await store.category.findMany<ICategory>(params);
|
|
102
131
|
const routes = await store.route.findMany<IRoute>({
|
|
132
|
+
...params,
|
|
103
133
|
where: {
|
|
104
|
-
market: {
|
|
105
|
-
|
|
106
|
-
},
|
|
107
|
-
locale: {
|
|
108
|
-
equals: locale,
|
|
109
|
-
},
|
|
134
|
+
...(params.market ? { market: { equals: params.market } } : {}),
|
|
135
|
+
...(params.locale ? { locale: { equals: params.locale } } : {}),
|
|
110
136
|
},
|
|
111
|
-
market, locale,
|
|
112
137
|
});
|
|
113
|
-
await collectPages(store, items,
|
|
114
|
-
decoratedItem.items = items
|
|
138
|
+
await collectPages(store, items, params);
|
|
139
|
+
decoratedItem.items = items
|
|
140
|
+
.filter(x => hasMarket(x, params.market))
|
|
141
|
+
.map(x => decorateMenuItem(x, categories, routes, params.market));
|
|
115
142
|
return decoratedItem;
|
|
116
143
|
}
|
|
117
144
|
|
|
118
|
-
export async function
|
|
119
|
-
|
|
145
|
+
export async function decorateMenus_(store: IStore, items: IUndecoratedMenu[], params: { market: string, locale: string }): Promise<IMenu[]> {
|
|
146
|
+
const decoratedItems: IMenu[] = [];
|
|
147
|
+
for (const item of items) {
|
|
148
|
+
const decoratedItem = await decorateMenu_(store, item, params);
|
|
149
|
+
decoratedItems.push(decoratedItem);
|
|
150
|
+
}
|
|
151
|
+
return decoratedItems;
|
|
120
152
|
}
|
|
121
153
|
|
|
122
154
|
export function decorateMenuCategory(
|
|
@@ -251,7 +283,10 @@ export function decorateMenuPage(
|
|
|
251
283
|
market: string
|
|
252
284
|
): IMenuItem {
|
|
253
285
|
const items = item.items || [];
|
|
254
|
-
const route = routes.find(x =>
|
|
286
|
+
const route = routes.find(x =>
|
|
287
|
+
x.schema === item.page.relationTo &&
|
|
288
|
+
x.page === item.page.value.id
|
|
289
|
+
);
|
|
255
290
|
const decoratedItem: IMenuPage = {
|
|
256
291
|
id: item.id || '',
|
|
257
292
|
type: item.type,
|
|
@@ -1,75 +1,154 @@
|
|
|
1
|
-
import { IEntity, IEquatable, IRoute, ISchema, IStore,
|
|
2
|
-
import { MockService } from './mock.service';
|
|
1
|
+
import { IDecoratedNav, IEntity, IEquatable, IMenuPage, IRoute, ISchema, IStore, IUndecoratedNav, QueryParams, isArray, isObject, isUndecoratedNav } from '@websolutespa/bom-core';
|
|
2
|
+
import { MockService, decorateRelation_, decorateRelations_, localizeItem_, localizeItems_ } from './mock.service';
|
|
3
3
|
|
|
4
4
|
export class MockPageService<T extends IEntity = IEntity> extends MockService<T> {
|
|
5
5
|
|
|
6
|
-
async
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
protected override async decorateOne_<B extends T = T>(item: B, params: QueryParams = {}): Promise<B> {
|
|
7
|
+
let decoratedItem = await localizeItem_(item, params);
|
|
8
|
+
decoratedItem = await decorateHref_<B>(this.store, decoratedItem, params);
|
|
9
|
+
decoratedItem = await decorateNav_<B>(this.store, decoratedItem, params);
|
|
10
|
+
decoratedItem = await decorateRelation_<B>(this.store, decoratedItem, {
|
|
11
|
+
market: params.market,
|
|
12
|
+
locale: params.locale,
|
|
13
|
+
depth: params.depth,
|
|
14
|
+
});
|
|
15
|
+
return decoratedItem;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
protected override async decorateMany_<B extends T = T>(items: B[], params: QueryParams = {}): Promise<B[]> {
|
|
19
|
+
let decoratedItems = await localizeItems_(items, params);
|
|
20
|
+
decoratedItems = await decorateHrefs_<B>(this.store, decoratedItems, params);
|
|
21
|
+
decoratedItems = await decorateNavs_<B>(this.store, decoratedItems, params);
|
|
22
|
+
decoratedItems = await decorateRelations_<B>(this.store, decoratedItems, {
|
|
23
|
+
market: params.market,
|
|
24
|
+
locale: params.locale,
|
|
25
|
+
depth: params.depth,
|
|
26
|
+
});
|
|
27
|
+
return decoratedItems;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function decorateHref_<T extends ISchema = ISchema>(store: IStore, item: T, params: QueryParams = {}): Promise<T | T & { href: string | null }> {
|
|
33
|
+
if (params.market && params.locale) {
|
|
34
|
+
const routes = await store.route.findMany<IRoute>({
|
|
35
|
+
where: {
|
|
36
|
+
market: {
|
|
37
|
+
equals: params.market,
|
|
38
|
+
},
|
|
39
|
+
locale: {
|
|
40
|
+
equals: params.locale,
|
|
41
|
+
},
|
|
42
|
+
schema: {
|
|
43
|
+
equals: item.schema,
|
|
44
|
+
},
|
|
45
|
+
page: {
|
|
46
|
+
equals: item.id,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
const href = routes.length ? routes[0].id : null;
|
|
51
|
+
return { ...item, href };
|
|
52
|
+
} else {
|
|
12
53
|
return item;
|
|
13
54
|
}
|
|
55
|
+
}
|
|
14
56
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
57
|
+
export async function decorateHrefs_<T extends ISchema = ISchema>(store: IStore, items: T[], params: QueryParams = {}): Promise<T[] | (T & { href: string | null })[]> {
|
|
58
|
+
if (params.market && params.locale) {
|
|
59
|
+
const routes = await store.route.findMany<IRoute>({
|
|
60
|
+
where: {
|
|
61
|
+
market: {
|
|
62
|
+
equals: params.market,
|
|
63
|
+
},
|
|
64
|
+
locale: {
|
|
65
|
+
equals: params.locale,
|
|
66
|
+
},
|
|
67
|
+
/*
|
|
68
|
+
...(params.market ? { market: { equals: params.market } } : {}),
|
|
69
|
+
...(params.locale ? { locale: { equals: params.locale } } : {}),
|
|
70
|
+
*/
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
return items.map(item => {
|
|
74
|
+
const route = routes.find(x =>
|
|
75
|
+
x.schema === item.schema &&
|
|
76
|
+
x.page === item.id
|
|
77
|
+
);
|
|
78
|
+
const href = route ? route.id : null;
|
|
79
|
+
return { ...item, href };
|
|
80
|
+
});
|
|
81
|
+
} else {
|
|
21
82
|
return items;
|
|
22
83
|
}
|
|
84
|
+
}
|
|
23
85
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
86
|
+
export async function decorateNav_<T extends ISchema = ISchema>(store: IStore, item: T, params: QueryParams = {}, routes?: IRoute[]): Promise<T> {
|
|
87
|
+
if (!routes) {
|
|
88
|
+
routes = await store.route.findMany<IRoute>({
|
|
89
|
+
where: {
|
|
90
|
+
...(params.market ? { market: { equals: params.market } } : {}),
|
|
91
|
+
...(params.locale ? { locale: { equals: params.locale } } : {}),
|
|
92
|
+
},
|
|
93
|
+
});
|
|
31
94
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
} else {
|
|
37
|
-
return item;
|
|
38
|
-
}
|
|
95
|
+
const navs = collectNavs_(item);
|
|
96
|
+
for (const nav of navs) {
|
|
97
|
+
const decoratedNav = decorateNav__(nav, routes);
|
|
98
|
+
(nav as IDecoratedNav<T>).nav = decoratedNav.nav;
|
|
39
99
|
}
|
|
100
|
+
return item;
|
|
40
101
|
}
|
|
41
102
|
|
|
42
|
-
export async function
|
|
103
|
+
export async function decorateNavs_<T extends ISchema = ISchema>(store: IStore, items: T[], params: QueryParams = {}): Promise<T[]> {
|
|
43
104
|
const routes = await store.route.findMany<IRoute>({
|
|
105
|
+
...params,
|
|
44
106
|
where: {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
page: {
|
|
49
|
-
equals: item.id
|
|
50
|
-
},
|
|
51
|
-
market: {
|
|
52
|
-
equals: market
|
|
53
|
-
},
|
|
54
|
-
locale: {
|
|
55
|
-
equals: locale
|
|
56
|
-
},
|
|
57
|
-
}
|
|
107
|
+
...(params.market ? { market: { equals: params.market } } : {}),
|
|
108
|
+
...(params.locale ? { locale: { equals: params.locale } } : {}),
|
|
109
|
+
},
|
|
58
110
|
});
|
|
59
|
-
const
|
|
60
|
-
|
|
111
|
+
for (const item of items) {
|
|
112
|
+
await decorateNav_<T>(store, item, params, routes);
|
|
113
|
+
}
|
|
114
|
+
return items;
|
|
61
115
|
}
|
|
62
116
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
117
|
+
// collecting navs recursively
|
|
118
|
+
function collectNavs_<T>(item: unknown, navs: IUndecoratedNav<T>[] = []): IUndecoratedNav<T>[] {
|
|
119
|
+
if (isUndecoratedNav<T>(item)) {
|
|
120
|
+
navs.push(item);
|
|
121
|
+
}
|
|
122
|
+
// console.log(item, isUndecoratedNav<T>(item));
|
|
123
|
+
if (isArray(item)) {
|
|
124
|
+
item.forEach(x => collectNavs_(x, navs));
|
|
125
|
+
} else if (isObject(item)) {
|
|
126
|
+
Object.values(item).forEach(value => {
|
|
127
|
+
collectNavs_(value, navs);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return navs;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function decorateNav__<T>(item: IUndecoratedNav<T>, routes: IRoute[]): IDecoratedNav<T> {
|
|
134
|
+
const { nav, ...undecorated } = item;
|
|
135
|
+
if (nav !== undefined) {
|
|
136
|
+
const decorated = { ...undecorated } as { nav?: IMenuPage };
|
|
66
137
|
const route = routes.find(x =>
|
|
67
|
-
x.
|
|
68
|
-
x.
|
|
69
|
-
x.market === market &&
|
|
70
|
-
x.locale === locale
|
|
138
|
+
x.page === (nav.page.value as unknown as IEquatable) &&
|
|
139
|
+
x.schema === nav.page.relationTo
|
|
71
140
|
);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
141
|
+
if (route) {
|
|
142
|
+
decorated.nav = {
|
|
143
|
+
type: 'page',
|
|
144
|
+
id: route.id,
|
|
145
|
+
href: route.id,
|
|
146
|
+
title: route.title,
|
|
147
|
+
page: (nav.page.value as unknown as IEquatable),
|
|
148
|
+
schema: nav.page.relationTo,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return decorated as IDecoratedNav<T>;
|
|
152
|
+
}
|
|
153
|
+
return undecorated as IDecoratedNav<T>;
|
|
75
154
|
}
|
package/src/mock/mock.service.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { IEntity,
|
|
1
|
+
import { cloneItem, IEntity, IPageUnresolvedRelation, isArray, ISchema, isObject, IStore, isUnresolvedRelation, JsonService, localizeItem, QueryParams } from '@websolutespa/bom-core';
|
|
2
|
+
|
|
3
|
+
export const MOCK_SERVICE_DEFAULT_DEPTH = 2;
|
|
2
4
|
|
|
3
5
|
export class MockService<T extends IEntity = IEntity> extends JsonService<T> {
|
|
4
6
|
store: IStore;
|
|
@@ -8,66 +10,139 @@ export class MockService<T extends IEntity = IEntity> extends JsonService<T> {
|
|
|
8
10
|
this.store = store;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
protected override async decorateOne_<B extends T = T>(item: B, params: QueryParams = {}): Promise<B> {
|
|
14
|
+
let decoratedItem = await localizeItem_(item, params);
|
|
15
|
+
decoratedItem = await decorateRelation_<B>(this.store, decoratedItem, {
|
|
16
|
+
market: params.market,
|
|
17
|
+
locale: params.locale,
|
|
18
|
+
depth: params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH,
|
|
19
|
+
});
|
|
20
|
+
return decoratedItem;
|
|
21
|
+
}
|
|
12
22
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return item;
|
|
23
|
+
protected override async decorateMany_<B extends T = T>(items: B[], params: QueryParams = {}): Promise<B[]> {
|
|
24
|
+
let decoratedItems = await localizeItems_(items, params);
|
|
25
|
+
decoratedItems = await decorateRelations_<B>(this.store, decoratedItems, {
|
|
26
|
+
market: params.market,
|
|
27
|
+
locale: params.locale,
|
|
28
|
+
depth: params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH,
|
|
29
|
+
});
|
|
30
|
+
return decoratedItems;
|
|
24
31
|
}
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return items;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function localizeItem_<B>(item: B, params: QueryParams = {}): Promise<B> {
|
|
36
|
+
if (params.locale) {
|
|
37
|
+
return localizeItem(item, params.locale);
|
|
38
|
+
} else {
|
|
39
|
+
return cloneItem(item);
|
|
34
40
|
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function localizeItems_<B>(items: B[], params: QueryParams = {}): Promise<B[]> {
|
|
44
|
+
const decoratedItems: B[] = [];
|
|
45
|
+
for (const item of items) {
|
|
46
|
+
const decoratedItem = params.locale ?
|
|
47
|
+
localizeItem(item, params.locale) :
|
|
48
|
+
cloneItem(item);
|
|
49
|
+
decoratedItems.push(decoratedItem);
|
|
50
|
+
}
|
|
51
|
+
return decoratedItems;
|
|
52
|
+
}
|
|
53
|
+
|
|
35
54
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (
|
|
41
|
-
|
|
55
|
+
// getting item relation !!!unused
|
|
56
|
+
function getRelations_(item: Record<string, any>): IPageUnresolvedRelation[] {
|
|
57
|
+
const relations: IPageUnresolvedRelation[] = [];
|
|
58
|
+
if (isObject(item)) {
|
|
59
|
+
if (item.relation && isUnresolvedRelation(item.relation)) {
|
|
60
|
+
relations.push(item.relation);
|
|
42
61
|
}
|
|
43
|
-
return pagination;
|
|
44
62
|
}
|
|
63
|
+
return relations;
|
|
64
|
+
}
|
|
45
65
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
66
|
+
// collecting relations recursively
|
|
67
|
+
function collectRelations_(item: unknown, relations: IPageUnresolvedRelation[] = []): IPageUnresolvedRelation[] {
|
|
68
|
+
if (isObject(item)) {
|
|
69
|
+
Object.entries(item).forEach(([key, value]) => {
|
|
70
|
+
if (key === 'relation' && isUnresolvedRelation(value)) {
|
|
71
|
+
// skip circular reference
|
|
72
|
+
if (value.relationTo !== item.schema || value.value !== item.id) {
|
|
73
|
+
relations.push(value);
|
|
74
|
+
}
|
|
75
|
+
} else if (isArray(value)) {
|
|
76
|
+
value.forEach(x => collectRelations_(x, relations));
|
|
77
|
+
} else if (isObject(value)) {
|
|
78
|
+
collectRelations_(value, relations);
|
|
51
79
|
}
|
|
52
80
|
});
|
|
53
|
-
return x;
|
|
54
81
|
}
|
|
55
|
-
|
|
82
|
+
return relations;
|
|
83
|
+
}
|
|
56
84
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
85
|
+
/*
|
|
86
|
+
const RELATION_CACHE = new Map<IEquatable, IEntity>();
|
|
87
|
+
|
|
88
|
+
export async function decorateRelation_<T extends ISchema = ISchema>(store: IStore, item: T, params: QueryParams = {}): Promise<T> {
|
|
89
|
+
const depth = params.depth != null ? params.depth : 0;
|
|
90
|
+
if (depth === 0) {
|
|
91
|
+
return item;
|
|
92
|
+
}
|
|
93
|
+
if (RELATION_CACHE.has(item.id)) {
|
|
94
|
+
return RELATION_CACHE.get(item.id) as T;
|
|
95
|
+
} else {
|
|
96
|
+
// item = await decorateRelation_<B>(this.store, item, params.market, params.locale);
|
|
97
|
+
const relations = collectRelations_(item);
|
|
98
|
+
for (const relation of relations) {
|
|
99
|
+
const isMany = Array.isArray(relation.value);
|
|
100
|
+
const items = await store[relation.relationTo].findMany({
|
|
101
|
+
...params,
|
|
102
|
+
where: {
|
|
103
|
+
id: { in: isMany ? relation.value : [relation.value] },
|
|
104
|
+
},
|
|
105
|
+
depth: depth - 1,
|
|
106
|
+
});
|
|
107
|
+
if (isMany) {
|
|
108
|
+
relation.value = items as any; // !!!
|
|
109
|
+
} else {
|
|
110
|
+
relation.value = (items.length ? items[0] : undefined) as any; // !!!
|
|
111
|
+
}
|
|
62
112
|
}
|
|
113
|
+
RELATION_CACHE.set(item.id, item);
|
|
63
114
|
}
|
|
64
|
-
|
|
115
|
+
return item;
|
|
65
116
|
}
|
|
117
|
+
*/
|
|
66
118
|
|
|
67
|
-
export function
|
|
68
|
-
|
|
119
|
+
export async function decorateRelation_<T extends ISchema = ISchema>(store: IStore, item: T, params: QueryParams = {}): Promise<T> {
|
|
120
|
+
const depth = params.depth != null ? params.depth : MOCK_SERVICE_DEFAULT_DEPTH;
|
|
121
|
+
if (depth === 0) {
|
|
122
|
+
return item;
|
|
123
|
+
}
|
|
124
|
+
const relations = collectRelations_(item);
|
|
125
|
+
for (const relation of relations) {
|
|
126
|
+
const isMany = Array.isArray(relation.value);
|
|
127
|
+
const items = await store[relation.relationTo].findMany({
|
|
128
|
+
...params,
|
|
129
|
+
where: {
|
|
130
|
+
id: { in: isMany ? relation.value : [relation.value] },
|
|
131
|
+
},
|
|
132
|
+
depth: depth - 1,
|
|
133
|
+
});
|
|
134
|
+
if (isMany) {
|
|
135
|
+
relation.value = items as any; // !!!
|
|
136
|
+
} else {
|
|
137
|
+
relation.value = (items.length ? items[0] : undefined) as any; // !!!
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return item;
|
|
69
141
|
}
|
|
70
142
|
|
|
71
|
-
export function
|
|
72
|
-
|
|
143
|
+
export async function decorateRelations_<T extends ISchema = ISchema>(store: IStore, items: T[], params: QueryParams = {}): Promise<T[]> {
|
|
144
|
+
for (const item of items) {
|
|
145
|
+
await decorateRelation_<T>(store, item, params);
|
|
146
|
+
}
|
|
147
|
+
return items;
|
|
73
148
|
}
|
|
@@ -23,7 +23,7 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
|
|
|
23
23
|
// console.log('RemoteService', this.key, 'findOne', url);
|
|
24
24
|
const item = await remoteApiGet<B>(url);
|
|
25
25
|
if (item) {
|
|
26
|
-
return this.
|
|
26
|
+
return await this.decorateOne_(item, params);
|
|
27
27
|
}
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
@@ -37,7 +37,7 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
|
|
|
37
37
|
// console.log('RemoteService', this.key, 'findMany', url);
|
|
38
38
|
const response = await remoteApiGet(url) as any; // !!! todo pagination<B[]> | B[]
|
|
39
39
|
const items: B[] = Array.isArray(response.docs) ? response.docs : response;
|
|
40
|
-
return
|
|
40
|
+
return await this.decorateMany_(items, params);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
async findPaged<B extends T = T>(params: QueryParams = {}): Promise<{ docs: B[]; } & Pagination> {
|
|
@@ -49,30 +49,33 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
|
|
|
49
49
|
// console.log('RemoteService', this.key, 'findPaged', url);
|
|
50
50
|
const response = await remoteApiGet<{ docs: B[]; } & Pagination>(url);
|
|
51
51
|
let items: B[] = response.docs;
|
|
52
|
-
items =
|
|
52
|
+
items = await this.decorateMany_(items, params);
|
|
53
53
|
return { ...response, docs: items };
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// !!! todo params
|
|
56
57
|
async create<B extends T = T>(payload: Omit<B, 'id'>): Promise<B> {
|
|
57
58
|
const url = `/${this.key}`;
|
|
58
59
|
// console.log('RemoteService', this.key, 'create', url);
|
|
59
60
|
const item = await remoteApiPost<B>(url, payload);
|
|
60
|
-
return this.
|
|
61
|
+
return await this.decorateOne_(item, {});
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
// !!! todo params
|
|
63
65
|
async update<B extends T = T>(payload: Partial<B>): Promise<B> {
|
|
64
66
|
const url = `/${this.key}`;
|
|
65
67
|
// console.log('RemoteService', this.key, 'update', url);
|
|
66
68
|
const item = await remoteApiPut<B>(url, payload);
|
|
67
|
-
return this.
|
|
69
|
+
return await this.decorateOne_(item, {});
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
// !!! todo params
|
|
70
73
|
async delete<B extends T = T>(id: IEquatable): Promise<B | undefined> {
|
|
71
74
|
const params = {
|
|
72
75
|
where: {
|
|
73
76
|
id: {
|
|
74
77
|
equals: id,
|
|
75
|
-
}
|
|
78
|
+
},
|
|
76
79
|
},
|
|
77
80
|
};
|
|
78
81
|
const query = qsSerialize(params);
|
|
@@ -80,12 +83,14 @@ export class RemoteService<T extends IEntity = IEntity> implements IQuerable<T>
|
|
|
80
83
|
const url = `/${this.key}${search}`;
|
|
81
84
|
// console.log('RemoteService', this.key, 'delete', url);
|
|
82
85
|
const item = await remoteApiDelete<B>(url);
|
|
83
|
-
return this.
|
|
86
|
+
return await this.decorateOne_(item, {});
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
protected decorator_<B extends T = T>(item: B, params: QueryParams = {}): B {
|
|
89
|
+
protected async decorateOne_<B extends T = T>(item: B, params: QueryParams = {}): Promise<B> {
|
|
88
90
|
return item;
|
|
89
91
|
}
|
|
90
92
|
|
|
93
|
+
protected async decorateMany_<B extends T = T>(items: B[], params: QueryParams = {}): Promise<B[]> {
|
|
94
|
+
return items;
|
|
95
|
+
}
|
|
91
96
|
}
|