@webresto/graphql 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- package/.editorconfig +10 -0
- package/index.d.ts +3 -0
- package/index.js +22 -0
- package/index.ts +14 -0
- package/lib/afterHook.d.ts +1 -0
- package/lib/afterHook.js +24 -0
- package/lib/afterHook.ts +26 -0
- package/lib/afterHook.ts___graphql-transport-ws +138 -0
- package/lib/afterHook.ts___graphql-ws +133 -0
- package/lib/defaults.js +12 -0
- package/lib/errorWrapper.d.ts +4 -0
- package/lib/errorWrapper.js +13 -0
- package/lib/errorWrapper.ts +12 -0
- package/lib/eventHelper.d.ts +21 -0
- package/lib/eventHelper.js +32 -0
- package/lib/eventHelper.ts +35 -0
- package/lib/graphqlHelper.d.ts +115 -0
- package/lib/graphqlHelper.js +596 -0
- package/lib/graphqlHelper.ts +692 -0
- package/lib/initialize.d.ts +1 -0
- package/lib/initialize.js +22 -0
- package/lib/initialize.ts +21 -0
- package/notes.md +1976 -0
- package/package.json +47 -0
- package/readme.md +258 -0
- package/restApi.http +11 -0
- package/src/additionalResolvers.d.ts +19 -0
- package/src/additionalResolvers.js +114 -0
- package/src/additionalResolvers.ts +111 -0
- package/src/graphql.d.ts +7 -0
- package/src/graphql.js +144 -0
- package/src/graphql.ts +160 -0
- package/src/resolvers/cart.d.ts +123 -0
- package/src/resolvers/cart.js +176 -0
- package/src/resolvers/cart.ts +256 -0
- package/src/resolvers/checkout.d.ts +30 -0
- package/src/resolvers/checkout.js +226 -0
- package/src/resolvers/checkout.ts +242 -0
- package/src/resolvers/dishAndModifier.d.ts +2 -0
- package/src/resolvers/dishAndModifier.js +35 -0
- package/src/resolvers/dishAndModifier.ts +38 -0
- package/src/resolvers/maintenance.d.ts +9 -0
- package/src/resolvers/maintenance.js +12 -0
- package/src/resolvers/maintenance.ts +11 -0
- package/src/resolvers/paymentMethod.d.ts +9 -0
- package/src/resolvers/paymentMethod.js +22 -0
- package/src/resolvers/paymentMethod.ts +20 -0
- package/src/resolvers/restrictions.d.ts +9 -0
- package/src/resolvers/restrictions.js +24 -0
- package/src/resolvers/restrictions.ts +22 -0
- package/src/resolvers/streets.d.ts +9 -0
- package/src/resolvers/streets.js +16 -0
- package/src/resolvers/streets.ts +13 -0
- package/src/resolvers/subscriptions.d.ts +33 -0
- package/src/resolvers/subscriptions.js +52 -0
- package/src/resolvers/subscriptions.ts +63 -0
- package/test/.eslintrc +8 -0
- package/test/_bootstrap.js +29 -0
- package/test/fixtures/v0.12-app/.gitignore +11 -0
- package/test/fixtures/v0.12-app/.sailsrc +11 -0
- package/test/fixtures/v0.12-app/api/controllers/.gitkeep +0 -0
- package/test/fixtures/v0.12-app/api/models/.gitkeep +0 -0
- package/test/fixtures/v0.12-app/api/models/TestModel.js +22 -0
- package/test/fixtures/v0.12-app/api/responses/badRequest.js +76 -0
- package/test/fixtures/v0.12-app/api/responses/created.js +60 -0
- package/test/fixtures/v0.12-app/api/responses/forbidden.js +89 -0
- package/test/fixtures/v0.12-app/api/responses/notFound.js +94 -0
- package/test/fixtures/v0.12-app/api/responses/ok.js +60 -0
- package/test/fixtures/v0.12-app/api/responses/serverError.js +89 -0
- package/test/fixtures/v0.12-app/api/services/.gitkeep +0 -0
- package/test/fixtures/v0.12-app/app.js +73 -0
- package/test/fixtures/v0.12-app/config/bootstrap.js +6 -0
- package/test/fixtures/v0.12-app/config/connections.js +5 -0
- package/test/fixtures/v0.12-app/config/cors.js +78 -0
- package/test/fixtures/v0.12-app/config/csrf.js +64 -0
- package/test/fixtures/v0.12-app/config/env/development.js +10 -0
- package/test/fixtures/v0.12-app/config/env/production.js +16 -0
- package/test/fixtures/v0.12-app/config/globals.js +63 -0
- package/test/fixtures/v0.12-app/config/hookTimeout.js +8 -0
- package/test/fixtures/v0.12-app/config/http.js +93 -0
- package/test/fixtures/v0.12-app/config/i18n.js +57 -0
- package/test/fixtures/v0.12-app/config/log.js +29 -0
- package/test/fixtures/v0.12-app/config/models.js +3 -0
- package/test/fixtures/v0.12-app/config/policies.js +51 -0
- package/test/fixtures/v0.12-app/config/restoapi.js +3 -0
- package/test/fixtures/v0.12-app/config/restocore.js +39 -0
- package/test/fixtures/v0.12-app/config/routes.js +49 -0
- package/test/fixtures/v0.12-app/config/session.js +100 -0
- package/test/fixtures/v0.12-app/config/sockets.js +141 -0
- package/test/fixtures/v0.12-app/config/stateflow.js +4 -0
- package/test/fixtures/v0.12-app/config/views.js +95 -0
- package/test/fixtures/v0.12-app/package.json +34 -0
- package/test/fixtures/v0.12-app/views/403.ejs +68 -0
- package/test/fixtures/v0.12-app/views/404.ejs +68 -0
- package/test/fixtures/v0.12-app/views/500.ejs +73 -0
- package/test/fixtures/v0.12-app/views/homepage.ejs +74 -0
- package/test/fixtures/v0.12-app/views/layout.ejs +91 -0
- package/test/mocha.opts +2 -0
- package/test/readme.md +0 -0
- package/test/todo +0 -0
- package/test/tslint.json +18 -0
- package/test/unit/first.test.js +11 -0
- package/test/unit/sails_not_crash.test.js +3 -0
- package/todo.md +1 -0
- package/tsconfig.json +10 -0
package/package.json
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
{
|
2
|
+
"author": {
|
3
|
+
"name": "Webresto"
|
4
|
+
},
|
5
|
+
"bundleDependencies": false,
|
6
|
+
"dependencies": {
|
7
|
+
"apollo-fetch": "^0.7.0",
|
8
|
+
"apollo-server": "^2.25.2",
|
9
|
+
"dataloader": "^2.0.0",
|
10
|
+
"graphql": "^15.5.0",
|
11
|
+
"waterline-criteria": "^2.0.0"
|
12
|
+
},
|
13
|
+
"deprecated": false,
|
14
|
+
"description": "Webresto graphql api",
|
15
|
+
"directories": {
|
16
|
+
"doc": "docs",
|
17
|
+
"lib": "lib"
|
18
|
+
},
|
19
|
+
"keywords": [
|
20
|
+
"iiko",
|
21
|
+
"sails",
|
22
|
+
"resto",
|
23
|
+
"graphql"
|
24
|
+
],
|
25
|
+
"license": "ISC",
|
26
|
+
"main": "index.js",
|
27
|
+
"name": "@webresto/graphql",
|
28
|
+
"repository": {
|
29
|
+
"type": "git",
|
30
|
+
"url": "http://git.42team.org/webresto/graphql.git"
|
31
|
+
},
|
32
|
+
"sails": {
|
33
|
+
"isHook": true,
|
34
|
+
"hookName": "restographql"
|
35
|
+
},
|
36
|
+
"scripts": {
|
37
|
+
"gendoc": "apidoc -o apidoc/ && apidoc-markdown2 -p apidoc -o docs/api.md",
|
38
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
39
|
+
"test:js": "mocha test/_bootstrap.js test/**/*.test.js",
|
40
|
+
"test:init": "cd ./test/fixtures/v0.12-app && npm i --no-package-lock --prefix ./ && cd -"
|
41
|
+
},
|
42
|
+
"version": "1.3.0",
|
43
|
+
"devDependencies": {
|
44
|
+
"@types/node": "^14.14.35",
|
45
|
+
"@webresto/core": "^1.0.0"
|
46
|
+
}
|
47
|
+
}
|
package/readme.md
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
# Order
|
2
|
+
Корзина
|
3
|
+
- Запросить новую корзину getNewOrder
|
4
|
+
- Подписатся на изменения корзины order(id: String)
|
5
|
+
- Добавить блюдо addToOrder
|
6
|
+
- Изменить количество orderSetAmount
|
7
|
+
- Удалить блюдо removeFromOrder
|
8
|
+
|
9
|
+
# Menu
|
10
|
+
- Получение блюд dish, dishes (без параметров вернет все блюда)
|
11
|
+
- Получение групп group, groups (без параметров вернет корневые группы)
|
12
|
+
|
13
|
+
# Checkout
|
14
|
+
- Проверка checkOrder
|
15
|
+
- Заказ sendOrder
|
16
|
+
|
17
|
+
# Subscription
|
18
|
+
- сообщения и ошибки - message
|
19
|
+
- переходы и экшены - action
|
20
|
+
- измененная корзина - order
|
21
|
+
|
22
|
+
# criteria: Json
|
23
|
+
query запросы waterline ORM
|
24
|
+
https://0.12.sailsjs.com/documentation/concepts/models-and-orm/query-language#?criteria-modifiers
|
25
|
+
```js
|
26
|
+
// поиск по полю id
|
27
|
+
criteria = {id: "some-unique-id"}
|
28
|
+
// можно перечислить массив (условие OR), вернутся записи имеющие slug1 или slug2
|
29
|
+
criteria = {slug: ["slag1", "slag2"]}
|
30
|
+
// перечисление полей равносильно условию AND, вернутся записи с id = "some-unique-id" AND slug = "slug1"
|
31
|
+
criteria = {id: "some-unique-id", slug: "slug1"}
|
32
|
+
|
33
|
+
|
34
|
+
// дополнительный условия
|
35
|
+
'lessThan'
|
36
|
+
'lessThanOrEqual'
|
37
|
+
'greaterThan'
|
38
|
+
'greaterThanOrEqual'
|
39
|
+
'not'
|
40
|
+
'like'
|
41
|
+
'contains'
|
42
|
+
'startsWith'
|
43
|
+
'endsWith'
|
44
|
+
// пример
|
45
|
+
criteria = {price: {lessThan: 100}}
|
46
|
+
|
47
|
+
// сортировка и пагинация. Чтобы использовать сортировку или лимиты основной запрос нужно поместить в where: {}
|
48
|
+
criteria = {
|
49
|
+
where: {price: {lessThan: 100}},
|
50
|
+
skip: 20,
|
51
|
+
limit: 10,
|
52
|
+
sort: 'price DESC'
|
53
|
+
}
|
54
|
+
|
55
|
+
// graphql аналоги запросов для LF :
|
56
|
+
/*
|
57
|
+
1. https://api.lifenadym.com/navigation
|
58
|
+
query{
|
59
|
+
navigation{
|
60
|
+
...
|
61
|
+
}
|
62
|
+
}
|
63
|
+
2. https://api.lifenadym.com/page/kafe
|
64
|
+
query{
|
65
|
+
pages(criteria: {path: "kafe"}}){
|
66
|
+
...
|
67
|
+
}
|
68
|
+
}
|
69
|
+
3. https://api.lifenadym.com/api/0.5/menu?groupSlug=dostavka
|
70
|
+
query{
|
71
|
+
groups(criteria: {slug: "dostavka"}){
|
72
|
+
...
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
4. Запрос по поду с json
|
77
|
+
promotions(criteria: {section: {contains:"dostavka"}})
|
78
|
+
*/
|
79
|
+
```
|
80
|
+
|
81
|
+
|
82
|
+
# Backend helpers
|
83
|
+
- sendMessage(orderId, message) - отправление собщения через подписку PubSub
|
84
|
+
- sendAction(orderId, action)
|
85
|
+
- addModel(modelName) - генерирует тип из модели. Не использовать! при автоматической генерации всех моделей через addAllSailsModels
|
86
|
+
- addType(string) - добавить тип в виде готовой схемы
|
87
|
+
- addResolvers - добавить resolvers
|
88
|
+
- getSchema - возвращает сгенерированную схему и соедененные резолверсы
|
89
|
+
- addToBlackList
|
90
|
+
- addCustomField
|
91
|
+
- addToReplaceList
|
92
|
+
- addAllSailsModels - Генерирует схему по sails моделям.
|
93
|
+
|
94
|
+
# Пример использования
|
95
|
+
## Использование хука
|
96
|
+
Хук должен находиться в папке node_modules.
|
97
|
+
|
98
|
+
Код можно вставить в config/bootstrap.js или в afterHook при оспользовании в друших хуках. Главное чтобы код был выполнен до sails lifted, т.к. генерация GraphQL схемы происходит на этом событии.
|
99
|
+
|
100
|
+
Хук автоматически сканирует и добавляет в схему все модели проекта, находящиеся в sails.models
|
101
|
+
|
102
|
+
Автоматически добавляются резолверсы в папке проекта api/resolvers
|
103
|
+
|
104
|
+
|
105
|
+
```typescript
|
106
|
+
// импортируем хелпер
|
107
|
+
import * as helper from '@webresto/graphql'
|
108
|
+
// доп импорты
|
109
|
+
const path = require('path');
|
110
|
+
|
111
|
+
// добавляем resolvers из указанной папки
|
112
|
+
helper.addDirResolvers(path.resolve(__dirname, './resolvers'));
|
113
|
+
// все модели sails будут автоматически занесены в схему GraphQL
|
114
|
+
|
115
|
+
// Игнорируем при генерации поле dontShow модели Picture
|
116
|
+
helper.addToBlackList(["Picture.dontShow"]);
|
117
|
+
|
118
|
+
// для простых задач выше перечисленного достаточно. Ниже описанны дополнительные возможности.
|
119
|
+
|
120
|
+
// Добавляем резолверс вручную
|
121
|
+
helper.addResolvers(
|
122
|
+
// структура резолверса
|
123
|
+
{
|
124
|
+
// Название основного элемента, обычно Query, Mutation, Subscription
|
125
|
+
Query: {
|
126
|
+
// имя должно совпадать с именем метода в GraphQL схеме ниже
|
127
|
+
sayHi: {
|
128
|
+
// описание метода в GraphQL схеме. При генерации будет полностью перенесено в неизменном виде
|
129
|
+
def: 'sayHi: String',
|
130
|
+
// функция резолвер. Стандартный резолвер GraphQL, после генерации схемы будет расположен в переменной sayHi. Для подписок может быть объектом, а не функцией
|
131
|
+
fn: function (parent, args, context){
|
132
|
+
return "Hi there! Welcome to GraphQL!";
|
133
|
+
},
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
);
|
138
|
+
|
139
|
+
// пример добавления типов в схему. Для существующих типов обязательно расширять тип, то есть писать extend type. Такие типы как Query, Mutation, Subscription определены поумолчанию, их обязательно расширять. Если добавляется метод, к нему обязательно нужно добавить резолвер.
|
140
|
+
helper.addType(`extend type Query {
|
141
|
+
sayAnotherWord: String
|
142
|
+
}
|
143
|
+
`);
|
144
|
+
|
145
|
+
```
|
146
|
+
|
147
|
+
пример резолверса
|
148
|
+
|
149
|
+
```typescript
|
150
|
+
export default {
|
151
|
+
// основные типы Query, Mutation, Subscription будут записаны в соответствующий тип
|
152
|
+
Query: {
|
153
|
+
dish: {
|
154
|
+
def: 'dish(id: String): Dish',
|
155
|
+
fn: async function (parent, args, context, info) {
|
156
|
+
return await Dish.findOne({id: args.id});
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
Subscription: {
|
161
|
+
dish: {
|
162
|
+
def: 'dish: Dish',
|
163
|
+
// для типа Subscription резолвер должен содержать функции subscribe & resolve
|
164
|
+
fn: {
|
165
|
+
subscribe: function (parent, args, context, info) {
|
166
|
+
return context.pubsub.asyncIterator("dish-changed");
|
167
|
+
},
|
168
|
+
resolve: payload => {
|
169
|
+
return payload;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
173
|
+
},
|
174
|
+
|
175
|
+
// пример резолверса полей типа Dish
|
176
|
+
Dish: {
|
177
|
+
// функция по умолчанию, можно не писать. Можно заменить любой логикой, главное что бы возвращаемый тип соответствовал схеме
|
178
|
+
filed1: (parent, args, context, info) => parent.field1
|
179
|
+
}
|
180
|
+
}
|
181
|
+
```
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
## Black List
|
187
|
+
Варианты:
|
188
|
+
1. ["Order.field"] - исключает поле field в модели Order
|
189
|
+
2. ["Order"] - исключает модель Order полностью
|
190
|
+
3. ["field] - исключает поле field из всех моделей
|
191
|
+
|
192
|
+
### example
|
193
|
+
```
|
194
|
+
grqlHelper.addToBlackList(["createdAt", "updatedAt"]);
|
195
|
+
```
|
196
|
+
исключает поля "createdAt", "updatedAt" из автоматической генерации
|
197
|
+
|
198
|
+
## addResolvers
|
199
|
+
Пример добавления:
|
200
|
+
- def - описание метода для graphQl schema. Попадет в основные типы Query, Mutation, Subscription. Для примера ниже будет "type Query { orderDish(id: Int!): OrderDish }"
|
201
|
+
- fn - метод или объект. Попадет в Resolvers согласно структуре, для примера ниже будет - Resolvers = {Query:{orderDish: fn}}
|
202
|
+
- При вызове соеденяет объекты: _.merge(oldResolvers, newResolvers);
|
203
|
+
```
|
204
|
+
const resolvers = {
|
205
|
+
Query: {
|
206
|
+
orderDish: {
|
207
|
+
def: 'orderDish(id: Int!): OrderDish',
|
208
|
+
fn: async function (parent, args, context) {
|
209
|
+
return await OrderDish.findOne({id: args.id});
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
}
|
214
|
+
```
|
215
|
+
|
216
|
+
## addToReplaceList
|
217
|
+
addToReplaceList(path, field)
|
218
|
+
### example
|
219
|
+
Замена поля и его типизация. Если добавляется новый тип, его необходимо описать, иначе вылетит исключение graphql
|
220
|
+
```
|
221
|
+
grqlHelper.addToReplaceList("Dish.image", "image: [Image]");
|
222
|
+
grqlHelper.addType("scalar Image");
|
223
|
+
```
|
224
|
+
|
225
|
+
## addCustomField
|
226
|
+
Добавляет поле в указанную модель. Нет проверки на совпадение полей. Если поля совпадут graphql не запустится.
|
227
|
+
```
|
228
|
+
grqlHelper.addCustomField("Order", "customField: String")
|
229
|
+
```
|
230
|
+
Результат:
|
231
|
+
type Order {
|
232
|
+
...
|
233
|
+
customField: String
|
234
|
+
...
|
235
|
+
}
|
236
|
+
|
237
|
+
## setWhiteList
|
238
|
+
Добавляет модели в белый лист автогенератора. Можно установить генерацию для query запросов и подписок
|
239
|
+
```ts
|
240
|
+
/**
|
241
|
+
* Добавляет whiteList
|
242
|
+
* Пример: setWhiteList({
|
243
|
+
page: ['query'],
|
244
|
+
promotion: ['query'],
|
245
|
+
maintenance: ['query', 'subscription']
|
246
|
+
})
|
247
|
+
*
|
248
|
+
* @param list
|
249
|
+
*/
|
250
|
+
// Пример использования в хуках или проекте
|
251
|
+
import * as helper from '@webresto/graphql'
|
252
|
+
|
253
|
+
helper.setWhiteList({
|
254
|
+
page: ['query'],
|
255
|
+
promotion: ['query'],
|
256
|
+
maintenance: ['query', 'subscription']
|
257
|
+
})
|
258
|
+
```
|
package/restApi.http
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
export declare const additionalResolver: {
|
2
|
+
GroupModifier: {
|
3
|
+
group: (parent: any, args: any, context: any, info: any) => Promise<any>;
|
4
|
+
};
|
5
|
+
Modifier: {
|
6
|
+
dish: (parent: any, args: any, context: any, info: any) => Promise<any>;
|
7
|
+
};
|
8
|
+
OrderModifier: {
|
9
|
+
dish: (parent: any, args: any, context: any, info: any) => Promise<any>;
|
10
|
+
group: (parent: any, args: any) => Promise<any>;
|
11
|
+
};
|
12
|
+
Dish: {
|
13
|
+
parentGroup: (parent: any, args: any, context: any, info: any) => Promise<any>;
|
14
|
+
images: (parent: any, args: any, context: any, info: any) => Promise<any>;
|
15
|
+
};
|
16
|
+
Group: {
|
17
|
+
parentGroup: (parent: any, args: any, context: any, info: any) => Promise<any>;
|
18
|
+
};
|
19
|
+
};
|
@@ -0,0 +1,114 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.additionalResolver = void 0;
|
4
|
+
const DataLoader = require('dataloader');
|
5
|
+
exports.additionalResolver = {
|
6
|
+
GroupModifier: {
|
7
|
+
group: async (parent, args, context, info) => {
|
8
|
+
if (!parent.modifierId)
|
9
|
+
return;
|
10
|
+
if (!context.dataloaders)
|
11
|
+
context.dataloaders = new WeakMap();
|
12
|
+
const dataloaders = context.dataloaders;
|
13
|
+
let dl = dataloaders.get(info.fieldNodes);
|
14
|
+
if (!dl) {
|
15
|
+
dl = new DataLoader(async (ids) => {
|
16
|
+
const rows = await Group.find({ id: ids });
|
17
|
+
const sortedInIdsOrder = ids.map(id => rows.find(x => x.id === id));
|
18
|
+
return sortedInIdsOrder;
|
19
|
+
});
|
20
|
+
dataloaders.set(info.fieldNodes, dl);
|
21
|
+
}
|
22
|
+
return dl.load(parent.modifierId);
|
23
|
+
},
|
24
|
+
},
|
25
|
+
Modifier: {
|
26
|
+
dish: async (parent, args, context, info) => {
|
27
|
+
if (!parent.modifierId)
|
28
|
+
return;
|
29
|
+
if (!context.dataloaders)
|
30
|
+
context.dataloaders = new WeakMap();
|
31
|
+
const dataloaders = context.dataloaders;
|
32
|
+
let dl = dataloaders.get(info.fieldNodes);
|
33
|
+
if (!dl) {
|
34
|
+
dl = new DataLoader(async (ids) => {
|
35
|
+
const rows = await Dish.find({ id: ids, balance: { "!=": 0 }, isDeleted: false });
|
36
|
+
const sortedInIdsOrder = ids.map(id => rows.find(x => x.id === id));
|
37
|
+
return sortedInIdsOrder;
|
38
|
+
});
|
39
|
+
// ложим инстанс дата-лоадера в WeakMap для повторного использования
|
40
|
+
dataloaders.set(info.fieldNodes, dl);
|
41
|
+
}
|
42
|
+
// юзаем метод `load` из нашего дата-лоадера
|
43
|
+
return dl.load(parent.modifierId);
|
44
|
+
// return await Dish.findOne({id: parent.modifierId}).populateAll();
|
45
|
+
}
|
46
|
+
},
|
47
|
+
OrderModifier: {
|
48
|
+
dish: async (parent, args, context, info) => {
|
49
|
+
return (await Dish.find({ id: parent.id, balance: { "!": 0 }, isDeleted: false }).populateAll())[0];
|
50
|
+
},
|
51
|
+
group: async (parent, args) => {
|
52
|
+
return (await Group.find({ id: parent.groupId, isDeleted: false }).populateAll())[0];
|
53
|
+
}
|
54
|
+
},
|
55
|
+
Dish: {
|
56
|
+
parentGroup: async (parent, args, context, info) => {
|
57
|
+
if (!parent.parentGroup)
|
58
|
+
return;
|
59
|
+
if (!context.dataloaders)
|
60
|
+
context.dataloaders = new WeakMap();
|
61
|
+
const dataloaders = context.dataloaders;
|
62
|
+
// need to investigate why getting object instead of string
|
63
|
+
if (typeof parent.parentGroup === "object") {
|
64
|
+
return parent.parentGroup;
|
65
|
+
}
|
66
|
+
let dl = dataloaders.get(info.fieldNodes);
|
67
|
+
if (!dl) {
|
68
|
+
dl = new DataLoader(async (id) => {
|
69
|
+
return await Group.find(id);
|
70
|
+
});
|
71
|
+
dataloaders.set(info.fieldNodes, dl);
|
72
|
+
}
|
73
|
+
return dl.load(parent.parentGroup);
|
74
|
+
},
|
75
|
+
images: async (parent, args, context, info) => {
|
76
|
+
if (!parent.id)
|
77
|
+
return;
|
78
|
+
if (!context.dataloaders)
|
79
|
+
context.dataloaders = new WeakMap();
|
80
|
+
const dataloaders = context.dataloaders;
|
81
|
+
let dl = dataloaders.get(info.fieldNodes);
|
82
|
+
if (!dl) {
|
83
|
+
dl = new DataLoader(async (ids) => {
|
84
|
+
const rows = await Dish.find({ id: ids }).populate('images');
|
85
|
+
const images = ids.map(id => { var _a; return (_a = rows.find(x => x.id === id)) === null || _a === void 0 ? void 0 : _a.images; });
|
86
|
+
return images;
|
87
|
+
});
|
88
|
+
dataloaders.set(info.fieldNodes, dl);
|
89
|
+
}
|
90
|
+
return dl.load(parent.id);
|
91
|
+
}
|
92
|
+
},
|
93
|
+
Group: {
|
94
|
+
parentGroup: async (parent, args, context, info) => {
|
95
|
+
if (!parent.parentGroup)
|
96
|
+
return;
|
97
|
+
if (!context.dataloaders)
|
98
|
+
context.dataloaders = new WeakMap();
|
99
|
+
const dataloaders = context.dataloaders;
|
100
|
+
// need to investigate why getting object instead of string
|
101
|
+
if (typeof parent.parentGroup === "object") {
|
102
|
+
return parent.parentGroup;
|
103
|
+
}
|
104
|
+
let dl = dataloaders.get(info.fieldNodes);
|
105
|
+
if (!dl) {
|
106
|
+
dl = new DataLoader(async (id) => {
|
107
|
+
return await Group.find(id);
|
108
|
+
});
|
109
|
+
dataloaders.set(info.fieldNodes, dl);
|
110
|
+
}
|
111
|
+
return dl.load(parent.parentGroup);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
};
|
@@ -0,0 +1,111 @@
|
|
1
|
+
const DataLoader = require('dataloader');
|
2
|
+
|
3
|
+
export const additionalResolver = {
|
4
|
+
GroupModifier: {
|
5
|
+
group: async (parent, args, context, info) => {
|
6
|
+
if (!parent.modifierId) return;
|
7
|
+
if (!context.dataloaders) context.dataloaders = new WeakMap();
|
8
|
+
const dataloaders = context.dataloaders;
|
9
|
+
|
10
|
+
let dl = dataloaders.get(info.fieldNodes);
|
11
|
+
if (!dl) {
|
12
|
+
dl = new DataLoader(async (ids: any) => {
|
13
|
+
const rows = await Group.find({id: ids});
|
14
|
+
const sortedInIdsOrder = ids.map(id => rows.find(x => x.id === id));
|
15
|
+
return sortedInIdsOrder;
|
16
|
+
});
|
17
|
+
dataloaders.set(info.fieldNodes, dl);
|
18
|
+
}
|
19
|
+
return dl.load(parent.modifierId);
|
20
|
+
},
|
21
|
+
},
|
22
|
+
Modifier: {
|
23
|
+
dish: async (parent, args, context, info) => {
|
24
|
+
if (!parent.modifierId) return;
|
25
|
+
if (!context.dataloaders) context.dataloaders = new WeakMap();
|
26
|
+
const dataloaders = context.dataloaders;
|
27
|
+
|
28
|
+
let dl = dataloaders.get(info.fieldNodes);
|
29
|
+
if (!dl) {
|
30
|
+
dl = new DataLoader(async (ids: any) => {
|
31
|
+
const rows = await Dish.find({id: ids, balance: { "!=": 0 }, isDeleted: false});
|
32
|
+
const sortedInIdsOrder = ids.map(id => rows.find(x => x.id === id));
|
33
|
+
return sortedInIdsOrder;
|
34
|
+
});
|
35
|
+
// ложим инстанс дата-лоадера в WeakMap для повторного использования
|
36
|
+
dataloaders.set(info.fieldNodes, dl);
|
37
|
+
}
|
38
|
+
// юзаем метод `load` из нашего дата-лоадера
|
39
|
+
return dl.load(parent.modifierId);
|
40
|
+
// return await Dish.findOne({id: parent.modifierId}).populateAll();
|
41
|
+
}
|
42
|
+
},
|
43
|
+
|
44
|
+
OrderModifier: {
|
45
|
+
dish: async (parent, args, context, info) => {
|
46
|
+
return (await Dish.find({id: parent.id, balance: { "!": 0 }, isDeleted: false}).populateAll())[0];
|
47
|
+
},
|
48
|
+
group: async (parent, args) => {
|
49
|
+
return (await Group.find({id: parent.groupId, isDeleted: false}).populateAll())[0];
|
50
|
+
}
|
51
|
+
},
|
52
|
+
|
53
|
+
Dish: {
|
54
|
+
parentGroup: async (parent, args, context, info) => {
|
55
|
+
if (!parent.parentGroup) return;
|
56
|
+
if (!context.dataloaders) context.dataloaders = new WeakMap();
|
57
|
+
const dataloaders = context.dataloaders;
|
58
|
+
|
59
|
+
// need to investigate why getting object instead of string
|
60
|
+
if (typeof parent.parentGroup === "object") {
|
61
|
+
return parent.parentGroup;
|
62
|
+
}
|
63
|
+
|
64
|
+
let dl = dataloaders.get(info.fieldNodes);
|
65
|
+
if (!dl) {
|
66
|
+
dl = new DataLoader(async (id: any) => {
|
67
|
+
return await Group.find(id);
|
68
|
+
});
|
69
|
+
dataloaders.set(info.fieldNodes, dl);
|
70
|
+
}
|
71
|
+
return dl.load(parent.parentGroup);
|
72
|
+
},
|
73
|
+
images: async (parent, args, context, info) => {
|
74
|
+
if (!parent.id) return;
|
75
|
+
if (!context.dataloaders) context.dataloaders = new WeakMap();
|
76
|
+
const dataloaders = context.dataloaders;
|
77
|
+
|
78
|
+
let dl = dataloaders.get(info.fieldNodes);
|
79
|
+
if (!dl) {
|
80
|
+
dl = new DataLoader(async (ids: any) => {
|
81
|
+
const rows = await Dish.find({id: ids}).populate('images');
|
82
|
+
const images = ids.map(id => rows.find(x => x.id === id)?.images);
|
83
|
+
return images;
|
84
|
+
});
|
85
|
+
dataloaders.set(info.fieldNodes, dl);
|
86
|
+
}
|
87
|
+
return dl.load(parent.id);
|
88
|
+
}
|
89
|
+
},
|
90
|
+
Group: {
|
91
|
+
parentGroup: async (parent, args, context, info) => {
|
92
|
+
if (!parent.parentGroup) return;
|
93
|
+
if (!context.dataloaders) context.dataloaders = new WeakMap();
|
94
|
+
const dataloaders = context.dataloaders;
|
95
|
+
|
96
|
+
// need to investigate why getting object instead of string
|
97
|
+
if (typeof parent.parentGroup === "object") {
|
98
|
+
return parent.parentGroup;
|
99
|
+
}
|
100
|
+
|
101
|
+
let dl = dataloaders.get(info.fieldNodes);
|
102
|
+
if (!dl) {
|
103
|
+
dl = new DataLoader(async (id: any) => {
|
104
|
+
return await Group.find(id);
|
105
|
+
});
|
106
|
+
dataloaders.set(info.fieldNodes, dl);
|
107
|
+
}
|
108
|
+
return dl.load(parent.parentGroup);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|