@webresto/graphql 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/.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
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/// <reference path="../../core/libs/globalTypes.ts"/>
|
|
3
|
+
var _a;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.setWhiteList = exports.addModelResolver = exports.addDirResolvers = exports.addAllSailsModels = exports.addToReplaceList = exports.addCustomField = exports.addToBlackList = exports.getSchema = exports.addResolvers = exports.addType = exports.addModel = void 0;
|
|
6
|
+
const _ = require("lodash");
|
|
7
|
+
const worktime_1 = require("@webresto/worktime");
|
|
8
|
+
const getEmitter_1 = require("@webresto/core/libs/getEmitter");
|
|
9
|
+
const WLCriteria = require("waterline-criteria");
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const scalarTypes = {
|
|
13
|
+
string: "String",
|
|
14
|
+
text: "String",
|
|
15
|
+
date: "String",
|
|
16
|
+
datetime: "String",
|
|
17
|
+
integer: "Int",
|
|
18
|
+
float: "Float",
|
|
19
|
+
boolean: "Boolean",
|
|
20
|
+
};
|
|
21
|
+
/*
|
|
22
|
+
const typeDefsExample = {
|
|
23
|
+
types: [
|
|
24
|
+
`type Example{
|
|
25
|
+
id: ID!
|
|
26
|
+
label: String
|
|
27
|
+
text: String
|
|
28
|
+
}`,
|
|
29
|
+
`type Dish{
|
|
30
|
+
name: String
|
|
31
|
+
description: String
|
|
32
|
+
}`
|
|
33
|
+
],
|
|
34
|
+
resolvers: {
|
|
35
|
+
Query: {
|
|
36
|
+
example: {
|
|
37
|
+
def: 'example(id: ID!): Example',
|
|
38
|
+
fn: async function (parent, args, context){
|
|
39
|
+
const example = await Example.find({id: args.id});
|
|
40
|
+
return example[0];
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
dish: {
|
|
44
|
+
def: 'dish(id: ID!): Dish',
|
|
45
|
+
fn: async function (parent, args, context){
|
|
46
|
+
return {
|
|
47
|
+
id: 1,
|
|
48
|
+
name: "test name",
|
|
49
|
+
price: "150"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
*/
|
|
57
|
+
const schemaResolvers = {};
|
|
58
|
+
const schemaTypes = [];
|
|
59
|
+
const schemaUnions = {};
|
|
60
|
+
const schemaScalars = new Set();
|
|
61
|
+
const blackList = [];
|
|
62
|
+
const customFields = {};
|
|
63
|
+
const replaceList = {};
|
|
64
|
+
const models = new Set();
|
|
65
|
+
/**
|
|
66
|
+
* Добавляет модель в список моделей для создания типов схемы graphql
|
|
67
|
+
*
|
|
68
|
+
*
|
|
69
|
+
* @param modelName string
|
|
70
|
+
* @returns void
|
|
71
|
+
*/
|
|
72
|
+
function addModel(modelName) {
|
|
73
|
+
modelName = firstLetterToUpperCase(modelName);
|
|
74
|
+
if (blackList.includes(modelName)) {
|
|
75
|
+
// schemaScalars.add(modelName);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
models.add(modelName.toLowerCase());
|
|
79
|
+
}
|
|
80
|
+
exports.addModel = addModel;
|
|
81
|
+
function addType(typeString) {
|
|
82
|
+
schemaTypes.push(typeString);
|
|
83
|
+
}
|
|
84
|
+
exports.addType = addType;
|
|
85
|
+
/**
|
|
86
|
+
* Мержит новый резолвер с объектом резолверов. Новый резолвер заменит старый при совпадении имен
|
|
87
|
+
*
|
|
88
|
+
* @param resolvers
|
|
89
|
+
* resolverExample = {
|
|
90
|
+
* def: "user(id: String)",
|
|
91
|
+
* fn: function (parent, args, context) {
|
|
92
|
+
* return User.find({id: args.id})
|
|
93
|
+
* }
|
|
94
|
+
* }
|
|
95
|
+
*/
|
|
96
|
+
function addResolvers(resolvers) {
|
|
97
|
+
_.merge(schemaResolvers, resolvers);
|
|
98
|
+
}
|
|
99
|
+
exports.addResolvers = addResolvers;
|
|
100
|
+
/**
|
|
101
|
+
* Сканирует все модели sails и добавляет их в список моделей для создания типов схемы graphql
|
|
102
|
+
*/
|
|
103
|
+
function addAllSailsModels() {
|
|
104
|
+
Object.keys(sails.models).forEach((key) => {
|
|
105
|
+
if (key.includes("__"))
|
|
106
|
+
return;
|
|
107
|
+
if (sails.models[key].graphql && sails.models[key].graphql.public === false) {
|
|
108
|
+
addToBlackList([key]);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
addModel(key);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
exports.addAllSailsModels = addAllSailsModels;
|
|
115
|
+
/**
|
|
116
|
+
* Добавляет массив с исключениями к текущему списку
|
|
117
|
+
* Варианты:
|
|
118
|
+
* 1. ["Order.field"] - исключает поле field в модели Order
|
|
119
|
+
* 2. ["Order"] - исключает модель Order полностью
|
|
120
|
+
* 3. ["field] - исключает поле field из всех моделей
|
|
121
|
+
*
|
|
122
|
+
* @param list array<string>
|
|
123
|
+
*/
|
|
124
|
+
function addToBlackList(list) {
|
|
125
|
+
blackList.push(...list);
|
|
126
|
+
}
|
|
127
|
+
exports.addToBlackList = addToBlackList;
|
|
128
|
+
/**
|
|
129
|
+
* Добавляет в указаную модель новое поле
|
|
130
|
+
* Пример: addCustomField("Order", "customField: String")
|
|
131
|
+
*
|
|
132
|
+
* @param model string
|
|
133
|
+
* @param field string
|
|
134
|
+
*/
|
|
135
|
+
function addCustomField(model, field) {
|
|
136
|
+
customFields[model] = customFields[model] === undefined ? "" : customFields[model];
|
|
137
|
+
customFields[model] += `${field}\n`;
|
|
138
|
+
}
|
|
139
|
+
exports.addCustomField = addCustomField;
|
|
140
|
+
/**
|
|
141
|
+
* Добавляет в список автозамены поле.
|
|
142
|
+
* Пример: addToReplaceList("Dish.image", "image: [Image]");
|
|
143
|
+
*
|
|
144
|
+
* @param model string
|
|
145
|
+
* @param field string
|
|
146
|
+
*/
|
|
147
|
+
function addToReplaceList(model, field) {
|
|
148
|
+
replaceList[model] = field;
|
|
149
|
+
}
|
|
150
|
+
exports.addToReplaceList = addToReplaceList;
|
|
151
|
+
/**
|
|
152
|
+
* Сканирует указанную директорию и добавляет найденные резолверсы в схему graphql
|
|
153
|
+
*
|
|
154
|
+
* @param dir
|
|
155
|
+
*/
|
|
156
|
+
function addDirResolvers(dir) {
|
|
157
|
+
let files = fs.readdirSync(dir);
|
|
158
|
+
for (let file of files) {
|
|
159
|
+
if (file.substr(-3) == ".js") {
|
|
160
|
+
const resolver = require(path.join(dir, file)).default;
|
|
161
|
+
if (resolver) {
|
|
162
|
+
addResolvers(resolver);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.addDirResolvers = addDirResolvers;
|
|
168
|
+
/**
|
|
169
|
+
* Запускает генерацию схемы и резолверсов
|
|
170
|
+
* Возвращает готовые данные для использования при инициализации apollo server
|
|
171
|
+
*
|
|
172
|
+
* @returns {schemaTypes, schemaResolvers}
|
|
173
|
+
*/
|
|
174
|
+
function getSchema() {
|
|
175
|
+
Object.keys(whiteList).forEach(modelname => {
|
|
176
|
+
var _a, _b;
|
|
177
|
+
if (((_b = (_a = sails.models[modelname]) === null || _a === void 0 ? void 0 : _a.graphql) === null || _b === void 0 ? void 0 : _b.public) !== false) {
|
|
178
|
+
addModelResolver(modelname);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
addResolvers(modelsResolvers);
|
|
182
|
+
return createSchema({ types: schemaTypes, resolvers: schemaResolvers });
|
|
183
|
+
}
|
|
184
|
+
exports.getSchema = getSchema;
|
|
185
|
+
function firstLetterToUpperCase(string) {
|
|
186
|
+
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
187
|
+
}
|
|
188
|
+
function firstLetterToLowerCase(string) {
|
|
189
|
+
return string.charAt(0).toLowerCase() + string.slice(1);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Перебирает все поля модели и генерирует тип для схемы graphql
|
|
193
|
+
*
|
|
194
|
+
* @param model sails.model
|
|
195
|
+
* @returns string
|
|
196
|
+
*/
|
|
197
|
+
function createType(model) {
|
|
198
|
+
const modelName = model.globalId;
|
|
199
|
+
const attributes = model._attributes || model.attributes;
|
|
200
|
+
let type = 'type ' + modelName + '{\n';
|
|
201
|
+
for (let prop in attributes) {
|
|
202
|
+
if (blackList.includes(`${modelName}.${prop}`) || blackList.includes(prop))
|
|
203
|
+
continue;
|
|
204
|
+
if (replaceList[`${modelName}.${prop}`] || replaceList[prop]) {
|
|
205
|
+
const newField = replaceList[`${modelName}.${prop}`] || replaceList[prop];
|
|
206
|
+
type += ` ${newField}\n`;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
let scalarType;
|
|
210
|
+
if (attributes[prop].type) {
|
|
211
|
+
if (scalarTypes[attributes[prop].type.toLowerCase()]) {
|
|
212
|
+
scalarType = scalarTypes[attributes[prop].type.toLowerCase()];
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
scalarType = firstLetterToUpperCase(attributes[prop].type);
|
|
216
|
+
schemaScalars.add(scalarType);
|
|
217
|
+
}
|
|
218
|
+
type += ' ' + prop + ': ' + scalarType + '\n';
|
|
219
|
+
}
|
|
220
|
+
// MODEL SCHEMA GENERATION
|
|
221
|
+
if (attributes[prop].model) {
|
|
222
|
+
let relationModel = sails.models[attributes[prop].model.toLowerCase()];
|
|
223
|
+
scalarType = scalarTypes[relationModel.attributes[relationModel.primaryKey].type];
|
|
224
|
+
const name = sails.models[attributes[prop].model.toLowerCase()].globalId;
|
|
225
|
+
type += ` ${prop}: ${name}\n`;
|
|
226
|
+
// todelete
|
|
227
|
+
type += ` ${prop}Id: ${scalarType}\n`;
|
|
228
|
+
}
|
|
229
|
+
// COLLECTION SCHEMA GENERATION
|
|
230
|
+
if (attributes[prop].collection) {
|
|
231
|
+
scalarType = scalarTypes[attributes[sails.models[attributes[prop].collection.toLowerCase()].primaryKey].type.toLowerCase()];
|
|
232
|
+
const name = sails.models[attributes[prop].collection.toLowerCase()].globalId;
|
|
233
|
+
console.log(1, scalarType);
|
|
234
|
+
type += ` ${prop}: [${name}]\n`;
|
|
235
|
+
// todelete
|
|
236
|
+
type += ` ${prop}Ids: ${scalarType}\n`;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (customFields[modelName]) {
|
|
240
|
+
type += ` ${customFields[modelName]}\n`;
|
|
241
|
+
}
|
|
242
|
+
if (!attributes.customData) {
|
|
243
|
+
type += '""" autogenerated """ customData: Json';
|
|
244
|
+
}
|
|
245
|
+
type += '}\n';
|
|
246
|
+
return type;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Соеденяет резолверсы и типы. Отделяет от резолверсов описание запросов.
|
|
250
|
+
* Возвращает готовую схему и резолверсы для использования в apollo server
|
|
251
|
+
*
|
|
252
|
+
* @param typeDefsObj
|
|
253
|
+
* @returns
|
|
254
|
+
*/
|
|
255
|
+
function createSchema(typeDefsObj) {
|
|
256
|
+
let schema = '';
|
|
257
|
+
const resolvers = {};
|
|
258
|
+
if (Array.isArray(typeDefsObj.types)) {
|
|
259
|
+
schema += typeDefsObj.types.join('\n');
|
|
260
|
+
}
|
|
261
|
+
// add types from models
|
|
262
|
+
for (let model of models) {
|
|
263
|
+
schema += createType(sails.models[model]);
|
|
264
|
+
}
|
|
265
|
+
// add union
|
|
266
|
+
for (let prop in schemaUnions) {
|
|
267
|
+
schema += `scalar ${prop}\n`;
|
|
268
|
+
}
|
|
269
|
+
// add scalar
|
|
270
|
+
for (let scalar of schemaScalars) {
|
|
271
|
+
schema += `scalar ${scalar}\n`;
|
|
272
|
+
}
|
|
273
|
+
// add resolver and type definition
|
|
274
|
+
if (typeDefsObj.resolvers) {
|
|
275
|
+
Object.keys(typeDefsObj.resolvers).forEach(key => {
|
|
276
|
+
resolvers[key] = {};
|
|
277
|
+
const res = typeDefsObj.resolvers[key];
|
|
278
|
+
if (['Query', 'Mutation', 'Subscription'].includes(key)) {
|
|
279
|
+
let typeString = `extend type ${key}{\n`;
|
|
280
|
+
for (let prop in res) {
|
|
281
|
+
typeString += ' ' + res[prop].def + '\n';
|
|
282
|
+
resolvers[key][prop] = res[prop].fn;
|
|
283
|
+
}
|
|
284
|
+
typeString += '}\n';
|
|
285
|
+
schema += '\n' + typeString;
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
if (res.def) {
|
|
289
|
+
schema += '\n' + res.def + '\n';
|
|
290
|
+
}
|
|
291
|
+
if (res.fn) {
|
|
292
|
+
resolvers[key] = res.fn;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
resolvers[key] = res;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return { typeDefs: schema, resolvers };
|
|
301
|
+
}
|
|
302
|
+
// AUTOGENERATE RESOLVERS -----------------------------------------------
|
|
303
|
+
// генерация резолверсов по списку моделей. Список моделей автоматически добавляется в схему.
|
|
304
|
+
const whiteList = {
|
|
305
|
+
// group: ['subscription', 'query'] // order - modelname , 'subscription' - resolver type
|
|
306
|
+
};
|
|
307
|
+
const userAuth = typeof ((_a = sails.config.restographql) === null || _a === void 0 ? void 0 : _a.authService) === 'function' ? sails.config.restographql.authService : null;
|
|
308
|
+
let modelsResolvers = { Query: {} };
|
|
309
|
+
const { withFilter } = require("apollo-server");
|
|
310
|
+
/**
|
|
311
|
+
* Патчит waterline criteria во время автогенерации
|
|
312
|
+
*
|
|
313
|
+
* @param modelname
|
|
314
|
+
* @param criteria
|
|
315
|
+
* @returns
|
|
316
|
+
*/
|
|
317
|
+
function sanitizeCriteria(modelname, criteria) {
|
|
318
|
+
if (sails.models[modelname].attributes.enable) {
|
|
319
|
+
criteria.enable = true;
|
|
320
|
+
}
|
|
321
|
+
if (sails.models[modelname].attributes.isDeleted) {
|
|
322
|
+
criteria.isDeleted = false;
|
|
323
|
+
}
|
|
324
|
+
switch (modelname) {
|
|
325
|
+
case 'dish':
|
|
326
|
+
criteria.balance = { '!=': 0 };
|
|
327
|
+
criteria.isDeleted = false;
|
|
328
|
+
break;
|
|
329
|
+
case 'group':
|
|
330
|
+
criteria.isDeleted = false;
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
return criteria;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Добавляет whiteList
|
|
337
|
+
* Пример: setWhiteList({
|
|
338
|
+
page: ['query'],
|
|
339
|
+
promotion: ['query'],
|
|
340
|
+
maintenance: ['query', 'subscription']
|
|
341
|
+
})
|
|
342
|
+
*
|
|
343
|
+
* @param list
|
|
344
|
+
*/
|
|
345
|
+
function setWhiteList(list) {
|
|
346
|
+
_.merge(whiteList, list);
|
|
347
|
+
}
|
|
348
|
+
exports.setWhiteList = setWhiteList;
|
|
349
|
+
/**
|
|
350
|
+
* Генерирует резолвер для модели. Учитывает список исключений и whiteList
|
|
351
|
+
*
|
|
352
|
+
* @param modelname string
|
|
353
|
+
* @returns void
|
|
354
|
+
*/
|
|
355
|
+
function addModelResolver(modelname) {
|
|
356
|
+
if (!sails.models[modelname])
|
|
357
|
+
return;
|
|
358
|
+
let modelName = sails.models[modelname].globalId;
|
|
359
|
+
if (!modelName) {
|
|
360
|
+
sails.log.error('graphql >>> Wrong Model Name :' + modelname);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
// Query resolver
|
|
364
|
+
if (whiteList[modelname].includes('query') && !blackList.includes(`${modelName}`)) {
|
|
365
|
+
models.add(modelname); // make schema Type for Model
|
|
366
|
+
const methodName = firstLetterToLowerCase(modelName);
|
|
367
|
+
let resolverQuery = {
|
|
368
|
+
def: `""" autogenerated """ ${methodName}(criteria: Json): [${modelName}]`,
|
|
369
|
+
fn: async function (parent, args, context) {
|
|
370
|
+
let criteria = args.criteria || {};
|
|
371
|
+
criteria = sanitizeCriteria(modelname, criteria);
|
|
372
|
+
// If model has User field need auth
|
|
373
|
+
if (sails.models[modelname].attributes.user) {
|
|
374
|
+
if (userAuth) {
|
|
375
|
+
let user = await userAuth(context.connectionParams.authorization);
|
|
376
|
+
if (user.id) {
|
|
377
|
+
criteria.user = user.id;
|
|
378
|
+
}
|
|
379
|
+
else
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
let query = { where: criteria };
|
|
387
|
+
//sorting
|
|
388
|
+
if (sails.models[modelname].attributes.order) {
|
|
389
|
+
query.sort = 'order ASC';
|
|
390
|
+
}
|
|
391
|
+
let result = await sails.models[modelname].find(query);
|
|
392
|
+
getEmitter_1.default().emit(`graphql-query-${modelname}`, result);
|
|
393
|
+
//workTime filter
|
|
394
|
+
if (sails.models[modelname].attributes.workTime) {
|
|
395
|
+
result = result.filter(record => {
|
|
396
|
+
if (!record.workTime)
|
|
397
|
+
return true;
|
|
398
|
+
try {
|
|
399
|
+
return (worktime_1.WorkTimeValidator.isWorkNow({ workTime: record.workTime })).workNow;
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
sails.log.error("Graphql > helper > error: ", error);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
result.forEach(item => {
|
|
407
|
+
getEmitter_1.default().emit(`http-api:before-send-${modelname.toLowerCase()}`, item);
|
|
408
|
+
});
|
|
409
|
+
return result;
|
|
410
|
+
},
|
|
411
|
+
};
|
|
412
|
+
modelsResolvers.Query[methodName] = resolverQuery;
|
|
413
|
+
}
|
|
414
|
+
// Model fields resolvers
|
|
415
|
+
let resolvers = {};
|
|
416
|
+
// iterate separate resolvers in model (type])
|
|
417
|
+
Object.keys(sails.models[modelname].attributes).forEach((key) => {
|
|
418
|
+
if (key.includes("__"))
|
|
419
|
+
return;
|
|
420
|
+
if (blackList.includes(`${modelName}.${key}`) || blackList.includes(`${key}`))
|
|
421
|
+
return;
|
|
422
|
+
if (typeof sails.models[modelname].attributes[key] === 'function')
|
|
423
|
+
return;
|
|
424
|
+
if (sails.models[modelname].attributes[key].graphql) {
|
|
425
|
+
if (sails.models[modelname].attributes[key].graphql.public === false)
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
let modelAttribute = sails.models[modelname].attributes[key];
|
|
429
|
+
if (modelAttribute.collection || modelAttribute.model) {
|
|
430
|
+
let modelRelationType = modelAttribute.collection
|
|
431
|
+
? "collection"
|
|
432
|
+
: "model";
|
|
433
|
+
let relationKey = modelAttribute.via !== undefined
|
|
434
|
+
? modelAttribute.via
|
|
435
|
+
: "id";
|
|
436
|
+
let criteria = {};
|
|
437
|
+
criteria = sanitizeCriteria(modelAttribute[modelRelationType], criteria);
|
|
438
|
+
switch (modelRelationType) {
|
|
439
|
+
case "model":
|
|
440
|
+
resolvers[key] = async (parent, args, context) => {
|
|
441
|
+
criteria[relationKey] = parent[key];
|
|
442
|
+
let result = await sails.models[modelAttribute[modelRelationType]].findOne(criteria);
|
|
443
|
+
// TODO: this need only for support legacy patching (discount)
|
|
444
|
+
getEmitter_1.default().emit(`http-api:before-send-${modelAttribute.model.toLowerCase()}`, result);
|
|
445
|
+
// celan if not work time
|
|
446
|
+
if (result && result.workTime && !worktime_1.WorkTimeValidator.isWorkNow({ workTime: result.workTime }).workNow) {
|
|
447
|
+
result = null;
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
return;
|
|
451
|
+
case "collection":
|
|
452
|
+
resolvers[key] = async (parent, args, context) => {
|
|
453
|
+
let subcriteria = {};
|
|
454
|
+
let subquery = { where: criteria };
|
|
455
|
+
//sorting
|
|
456
|
+
if (sails.models[modelname].attributes.order) {
|
|
457
|
+
subquery.sort = 'order ASC';
|
|
458
|
+
}
|
|
459
|
+
let result = (await sails.models[modelname].findOne({ id: parent.id }).populate(key, subquery));
|
|
460
|
+
result = result ? result[key] : null;
|
|
461
|
+
// TODO: this need only for support legacy patching (discount)
|
|
462
|
+
if (result && result.length) {
|
|
463
|
+
result.forEach(item => {
|
|
464
|
+
getEmitter_1.default().emit(`http-api:before-send-${modelAttribute.collection.toLowerCase()}`, item);
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
if (sails.models[modelname].attributes.workTime && Array.isArray(result)) {
|
|
468
|
+
result = result.filter(record => {
|
|
469
|
+
if (!record.workTime)
|
|
470
|
+
return true;
|
|
471
|
+
try {
|
|
472
|
+
return (worktime_1.WorkTimeValidator.isWorkNow({ workTime: record.workTime })).workNow;
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
sails.log.error("Graphql > helper > error: ", error);
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
return result;
|
|
480
|
+
};
|
|
481
|
+
return;
|
|
482
|
+
default:
|
|
483
|
+
// empty
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
resolvers[key] = async (parent, args, context) => {
|
|
488
|
+
return parent && parent[key];
|
|
489
|
+
};
|
|
490
|
+
});
|
|
491
|
+
console.log(modelName, resolvers);
|
|
492
|
+
modelsResolvers[modelName] = resolvers;
|
|
493
|
+
// Subscription resolver
|
|
494
|
+
if (!blackList.includes(`${modelName}`) && whiteList[modelname].includes('subscription')) {
|
|
495
|
+
models.add(modelname);
|
|
496
|
+
const methodName = `${firstLetterToLowerCase(modelName)}`;
|
|
497
|
+
let subscription = {
|
|
498
|
+
def: `""" Generated """ ${methodName}(criteria: Json): ${modelName}`,
|
|
499
|
+
fn: {
|
|
500
|
+
subscribe: withFilter((rootValue, args, context, info) => context.pubsub.asyncIterator(modelName), async (payload, args, context, info) => {
|
|
501
|
+
// For User models
|
|
502
|
+
if (sails.models[modelname].attributes.user) {
|
|
503
|
+
if (userAuth) {
|
|
504
|
+
let user = await userAuth(context.connectionParams.authorization);
|
|
505
|
+
if (user.id === payload.user) {
|
|
506
|
+
if (args.criteria) {
|
|
507
|
+
checkCriteria(payload, args.criteria);
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
return true;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
;
|
|
514
|
+
}
|
|
515
|
+
else {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return checkCriteria(payload, args.criteria);
|
|
520
|
+
// Filter by waterline criteria
|
|
521
|
+
function checkCriteria(payload, criteria) {
|
|
522
|
+
// For id's array
|
|
523
|
+
if (Array.isArray(criteria) || typeof criteria === "string") {
|
|
524
|
+
return (WLCriteria(payload, { where: { id: criteria } }).results).length > 0;
|
|
525
|
+
}
|
|
526
|
+
// Where cause
|
|
527
|
+
if (typeof criteria === 'object' && !Array.isArray(criteria) && criteria !== null) {
|
|
528
|
+
return (WLCriteria(payload, { where: criteria }).results).length > 0;
|
|
529
|
+
}
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
}),
|
|
533
|
+
resolve: (payload) => {
|
|
534
|
+
return payload;
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
};
|
|
538
|
+
// add publish in model
|
|
539
|
+
modelPublishExtend(modelname);
|
|
540
|
+
if (!modelsResolvers.Subscription)
|
|
541
|
+
modelsResolvers.Subscription = {};
|
|
542
|
+
modelsResolvers.Subscription[methodName] = subscription;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
exports.addModelResolver = addModelResolver;
|
|
546
|
+
/**
|
|
547
|
+
* Внутренняя функция используется при автогенерации резолверов
|
|
548
|
+
* Модифицирует модель. Добавляет рассылку сообщений при afterUpdate & afterCreate
|
|
549
|
+
*
|
|
550
|
+
* @param modelname
|
|
551
|
+
*/
|
|
552
|
+
function modelPublishExtend(modelname) {
|
|
553
|
+
let modelName = sails.models[modelname].globalId;
|
|
554
|
+
let afterCreate = sails.models[modelname].afterCreate;
|
|
555
|
+
sails.models[modelname].afterCreate = async function (values, cb) {
|
|
556
|
+
await sails.models[modelname].publish(values.id);
|
|
557
|
+
if (afterCreate) {
|
|
558
|
+
afterCreate(values, cb);
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
cb();
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
let afterUpdate = sails.models[modelname].afterUpdate;
|
|
565
|
+
sails.models[modelname].afterUpdate = async function (values, cb) {
|
|
566
|
+
await sails.models[modelname].publish(values.id);
|
|
567
|
+
if (afterUpdate) {
|
|
568
|
+
afterUpdate(values, cb);
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
cb();
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
let modelPublishExtendObj = {
|
|
575
|
+
publish: async function (id) {
|
|
576
|
+
let data = await sails.models[modelname].findOne(id);
|
|
577
|
+
// `http-api:request-${modelAttribute.collection.toLowerCase()}model-list`,
|
|
578
|
+
getEmitter_1.default().emit(`http-api:before-send-${modelname.toLowerCase()}`, data);
|
|
579
|
+
sails.graphql.pubsub.publish(modelName, data);
|
|
580
|
+
},
|
|
581
|
+
};
|
|
582
|
+
_.merge(sails.models[modelname], modelPublishExtendObj);
|
|
583
|
+
}
|
|
584
|
+
exports.default = {
|
|
585
|
+
addModel,
|
|
586
|
+
addType,
|
|
587
|
+
addResolvers,
|
|
588
|
+
getSchema,
|
|
589
|
+
addToBlackList,
|
|
590
|
+
addCustomField,
|
|
591
|
+
addToReplaceList,
|
|
592
|
+
addAllSailsModels,
|
|
593
|
+
addDirResolvers,
|
|
594
|
+
addModelResolver,
|
|
595
|
+
setWhiteList
|
|
596
|
+
};
|