@webtypen/webframez-core 0.1.17 → 0.2.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/dist/DataBuilder/DataBuilder.d.ts +82 -0
- package/dist/DataBuilder/DataBuilder.js +420 -0
- package/dist/DataBuilder/DataBuilderController.d.ts +9 -0
- package/dist/DataBuilder/DataBuilderController.js +43 -0
- package/dist/Database/DBConnection.d.ts +4 -0
- package/dist/Database/DBConnection.js +18 -6
- package/dist/Database/Model.d.ts +6 -0
- package/dist/Database/Model.js +11 -0
- package/package.json +1 -1
- package/src/DataBuilder/DataBuilder.ts +505 -0
- package/src/DataBuilder/DataBuilderController.ts +32 -0
- package/src/Database/DBConnection.ts +92 -84
- package/src/Database/Model.ts +13 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Request } from "../Router/Request";
|
|
2
|
+
export type DataBuilderSchema = {
|
|
3
|
+
version: string;
|
|
4
|
+
collection?: string;
|
|
5
|
+
primaryKey?: string;
|
|
6
|
+
primaryKeyPlain?: boolean;
|
|
7
|
+
beforeSave?: any;
|
|
8
|
+
afterSave?: any;
|
|
9
|
+
getAggregation?: any;
|
|
10
|
+
events?: {
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
};
|
|
13
|
+
fields: {
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export type DataBuilderType = {
|
|
18
|
+
key: string;
|
|
19
|
+
singular: string;
|
|
20
|
+
plural: string;
|
|
21
|
+
schema: DataBuilderSchema;
|
|
22
|
+
forms?: {
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export type DataBuilderFieldType = {
|
|
27
|
+
key: string;
|
|
28
|
+
type: "api-autocomplete";
|
|
29
|
+
onSave: (value: any, payload?: any) => void;
|
|
30
|
+
onSearch: (query: string, req: Request) => void;
|
|
31
|
+
} | {
|
|
32
|
+
key: string;
|
|
33
|
+
type: "object";
|
|
34
|
+
onSave: (value: any, payload?: any) => void;
|
|
35
|
+
onSearch?: never;
|
|
36
|
+
};
|
|
37
|
+
export declare class DataBuilder {
|
|
38
|
+
private types;
|
|
39
|
+
private fieldTypes;
|
|
40
|
+
getType(key: string): DataBuilderType | null;
|
|
41
|
+
registerType(typeObj: DataBuilderType): this;
|
|
42
|
+
registerFieldType(key: string, options?: any): this;
|
|
43
|
+
registerModelType(key: string, model: any): this;
|
|
44
|
+
getFieldType(key: string): DataBuilderFieldType | null;
|
|
45
|
+
getFieldTypesFrontend(): any;
|
|
46
|
+
getFieldsFrontend(fields: any, payload?: any): Promise<any>;
|
|
47
|
+
getTypeFromRequest(req: any): DataBuilderType;
|
|
48
|
+
validateFields(fields: any, data: any, errors?: any, path?: string): Promise<any>;
|
|
49
|
+
typeForFrontend(type: any, req: any): Promise<any>;
|
|
50
|
+
loadType(req: Request): Promise<{
|
|
51
|
+
status: string;
|
|
52
|
+
data: any;
|
|
53
|
+
}>;
|
|
54
|
+
applyFields(fields: any, element: any, data: any, payload: any, path?: string): Promise<any>;
|
|
55
|
+
getAggregation(type: any, req: Request): Promise<{
|
|
56
|
+
$match: {
|
|
57
|
+
[x: number]: any;
|
|
58
|
+
};
|
|
59
|
+
}[]>;
|
|
60
|
+
save(db: any, req: any): Promise<{
|
|
61
|
+
status: string;
|
|
62
|
+
errors: any;
|
|
63
|
+
data?: undefined;
|
|
64
|
+
} | {
|
|
65
|
+
status: string;
|
|
66
|
+
data: {
|
|
67
|
+
_id: any;
|
|
68
|
+
redirect: any;
|
|
69
|
+
};
|
|
70
|
+
errors?: undefined;
|
|
71
|
+
}>;
|
|
72
|
+
getField(req: Request, type: DataBuilderType, path: string): Promise<any>;
|
|
73
|
+
removeArrayIndicators(str: string): string;
|
|
74
|
+
details(db: any, req: any): Promise<{
|
|
75
|
+
status: string;
|
|
76
|
+
data: any;
|
|
77
|
+
}>;
|
|
78
|
+
apiAutoComplete(req: any): Promise<{
|
|
79
|
+
status: string;
|
|
80
|
+
data: void;
|
|
81
|
+
}>;
|
|
82
|
+
}
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.DataBuilder = void 0;
|
|
16
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
17
|
+
const Model_1 = require("../Database/Model");
|
|
18
|
+
class DataBuilder {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.types = {};
|
|
21
|
+
this.fieldTypes = {};
|
|
22
|
+
}
|
|
23
|
+
getType(key) {
|
|
24
|
+
return this.types[key] && this.types[key].key ? this.types[key] : null;
|
|
25
|
+
}
|
|
26
|
+
registerType(typeObj) {
|
|
27
|
+
this.types[typeObj.key] = typeObj;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
registerFieldType(key, options) {
|
|
31
|
+
this.fieldTypes[key] = Object.assign(Object.assign({}, options), { key: key });
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
registerModelType(key, model) {
|
|
35
|
+
if (model &&
|
|
36
|
+
typeof model.__schema === "object" &&
|
|
37
|
+
model.__schema.fields &&
|
|
38
|
+
(Object.keys(model.__schema.fields).length > 0 || typeof model.__schema.fields === "function")) {
|
|
39
|
+
this.registerType({
|
|
40
|
+
key: key,
|
|
41
|
+
singular: model.__singular,
|
|
42
|
+
plural: model.__plural,
|
|
43
|
+
schema: Object.assign(Object.assign({}, model.__schema), { collection: key }),
|
|
44
|
+
forms: model.__forms,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
getFieldType(key) {
|
|
50
|
+
return this.fieldTypes[key] && this.fieldTypes[key].key ? this.fieldTypes[key] : null;
|
|
51
|
+
}
|
|
52
|
+
getFieldTypesFrontend() {
|
|
53
|
+
const fieldtypes = {};
|
|
54
|
+
for (let key in this.fieldTypes) {
|
|
55
|
+
fieldtypes[key] = {
|
|
56
|
+
key: key,
|
|
57
|
+
type: this.fieldTypes[key].type,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return fieldtypes;
|
|
61
|
+
}
|
|
62
|
+
getFieldsFrontend(fields, payload) {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const out = {};
|
|
65
|
+
for (let key in fields) {
|
|
66
|
+
if (fields[key].type === "object") {
|
|
67
|
+
out[key] =
|
|
68
|
+
typeof fields[key].schema === "object" && Object.keys(fields[key].schema).length > 0
|
|
69
|
+
? Object.assign({}, (yield this.getFieldsFrontend(fields[key].schema, payload))) : fields[key];
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
out[key] =
|
|
73
|
+
typeof fields[key].schema === "object" && Object.keys(fields[key].schema).length > 0
|
|
74
|
+
? Object.assign(Object.assign({}, fields[key]), { schema: yield this.getFieldsFrontend(fields[key].schema, payload) }) : fields[key];
|
|
75
|
+
}
|
|
76
|
+
if (out[key].type === "option" && typeof fields[key].options === "function") {
|
|
77
|
+
out[key].options = yield fields[key].options(payload);
|
|
78
|
+
}
|
|
79
|
+
if (out[key].disabled && typeof out[key].disabled === "function") {
|
|
80
|
+
out[key].disabled = yield out[key].disabled(payload);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
getTypeFromRequest(req) {
|
|
87
|
+
const type = req.body && req.body.__builder_type
|
|
88
|
+
? this.getType(req.body.__builder_type)
|
|
89
|
+
: req.__builder_type
|
|
90
|
+
? this.getType(req.__builder_type)
|
|
91
|
+
: null;
|
|
92
|
+
if (!type) {
|
|
93
|
+
throw new Error("Missing builder-type '" + (req.body && req.body.__builder_type ? req.body.__builder_type : req.__builder_type) + "' ...");
|
|
94
|
+
}
|
|
95
|
+
return type;
|
|
96
|
+
}
|
|
97
|
+
validateFields(fields, data, errors, path) {
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
if (!errors) {
|
|
100
|
+
errors = {};
|
|
101
|
+
}
|
|
102
|
+
if (!fields || typeof fields !== "object") {
|
|
103
|
+
return errors;
|
|
104
|
+
}
|
|
105
|
+
for (let key in fields) {
|
|
106
|
+
const fieldPath = (path ? path + "." : "") + key;
|
|
107
|
+
const value = lodash_1.default.get(data, fieldPath);
|
|
108
|
+
if (fields[key].required) {
|
|
109
|
+
let check = true;
|
|
110
|
+
if (typeof fields[key].required === "function") {
|
|
111
|
+
check = yield fields[key].required(data);
|
|
112
|
+
}
|
|
113
|
+
if (check) {
|
|
114
|
+
if (value === null ||
|
|
115
|
+
value === false ||
|
|
116
|
+
value === undefined ||
|
|
117
|
+
(Array.isArray(value) && value.length < 1) ||
|
|
118
|
+
(!Array.isArray(value) && value.toString().trim() === "")) {
|
|
119
|
+
errors[fieldPath] = "Dieses Feld muss ausgefüllt werden.";
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (typeof fields[key].schema === "object") {
|
|
125
|
+
if (value && value.length > 0) {
|
|
126
|
+
for (let i in value) {
|
|
127
|
+
const entryPath = fieldPath + "[" + i + "]";
|
|
128
|
+
errors = yield this.validateFields(fields[key].schema, data, errors, entryPath);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (fields[key].validation && fields[key].validation.trim() !== "") {
|
|
133
|
+
// @ToDo
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return errors;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
typeForFrontend(type, req) {
|
|
140
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
141
|
+
const newData = {};
|
|
142
|
+
for (let key in type) {
|
|
143
|
+
if (key === "forms") {
|
|
144
|
+
newData.forms = {};
|
|
145
|
+
if (typeof type.forms === "function") {
|
|
146
|
+
newData.forms = yield type.forms(req);
|
|
147
|
+
}
|
|
148
|
+
for (let form in type.forms) {
|
|
149
|
+
if (!type.forms[form] || !type.forms[form].fields || type.forms[form].fields.length < 1) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
newData.forms[form] = {};
|
|
153
|
+
if (typeof type.forms[form].pageActions === "function") {
|
|
154
|
+
newData.forms[form].pageActions = yield type.forms[form].pageActions(req);
|
|
155
|
+
}
|
|
156
|
+
else if (type.forms[form].pageActions) {
|
|
157
|
+
newData.forms[form].pageActions = JSON.parse(JSON.stringify(type.forms[form].pageActions));
|
|
158
|
+
}
|
|
159
|
+
if (typeof type.forms[form].backLink === "function") {
|
|
160
|
+
newData.forms[form].backLink = yield type.forms[form].backLink(req);
|
|
161
|
+
}
|
|
162
|
+
if (typeof type.forms[form].fields === "function") {
|
|
163
|
+
newData.forms[form].fields = yield type.forms[form].fields(req);
|
|
164
|
+
}
|
|
165
|
+
else if (type.forms[form].fields) {
|
|
166
|
+
newData.forms[form].fields = JSON.parse(JSON.stringify(type.forms[form].fields));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
newData[key] = type[key];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return newData;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
loadType(req) {
|
|
178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
const type = this.getTypeFromRequest(req);
|
|
180
|
+
const data = Object.assign(Object.assign({}, (yield this.typeForFrontend(type, req))), { fieldtypes: this.getFieldTypesFrontend() });
|
|
181
|
+
return {
|
|
182
|
+
status: "success",
|
|
183
|
+
data: Object.assign(Object.assign({}, data), { schema: Object.assign(Object.assign({}, (data.schema ? data.schema : {})), { fields: yield this.getFieldsFrontend(type.schema
|
|
184
|
+
? typeof type.schema.fields === "function"
|
|
185
|
+
? yield type.schema.fields(req)
|
|
186
|
+
: type.schema.fields
|
|
187
|
+
: typeof type.fields === "function"
|
|
188
|
+
? yield type.fields(req)
|
|
189
|
+
: type.fields, req) }) }),
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
applyFields(fields, element, data, payload, path) {
|
|
194
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
195
|
+
if (typeof fields !== "object" || !fields) {
|
|
196
|
+
return element;
|
|
197
|
+
}
|
|
198
|
+
for (let key in fields) {
|
|
199
|
+
if (!fields[key] || fields[key].unmapped) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const fieldPath = (path ? path + "." : "") + key;
|
|
203
|
+
const value = lodash_1.default.get(data, fieldPath);
|
|
204
|
+
const customType = this.getFieldType(fields[key].type);
|
|
205
|
+
if (typeof fields[key].schema === "object" && fields[key].type === "array") {
|
|
206
|
+
lodash_1.default.set(element, fieldPath, []);
|
|
207
|
+
if (value && value.length > 0) {
|
|
208
|
+
for (let i in value) {
|
|
209
|
+
const entryPath = fieldPath + "[" + i + "]";
|
|
210
|
+
this.applyFields(fields[key].schema, element, data, payload, entryPath);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (customType && typeof customType.onSave === "function") {
|
|
214
|
+
lodash_1.default.set(element, fieldPath, yield customType.onSave(lodash_1.default.get(element, fieldPath), Object.assign(Object.assign({}, payload), fields[key].payload)));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
lodash_1.default.set(element, fieldPath, value === undefined || value === null || (typeof value === "string" && value.trim() === "")
|
|
219
|
+
? null
|
|
220
|
+
: customType && typeof customType.onSave === "function"
|
|
221
|
+
? yield customType.onSave(value, Object.assign(Object.assign({}, payload), fields[key].payload))
|
|
222
|
+
: fields[key].type === "currency" || fields[key].type === "float"
|
|
223
|
+
? parseFloat(value.toString().replace(",", "."))
|
|
224
|
+
: fields[key].type === "integer"
|
|
225
|
+
? parseInt(value)
|
|
226
|
+
: value);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return element;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
getAggregation(type, req) {
|
|
233
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
234
|
+
return [
|
|
235
|
+
{
|
|
236
|
+
$match: {
|
|
237
|
+
[type.schema.primaryKey ? type.schema.primaryKey : "_id"]: type.schema.primaryKeyPlain
|
|
238
|
+
? req.body.__builder_id
|
|
239
|
+
: yield Model_1.Model.objectId(req.body.__builder_id),
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
];
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
save(db, req) {
|
|
246
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
247
|
+
if (!req || !req.body || typeof req.body !== "object" || !req.body.__builder_id || req.body.__builder_id.toString().trim() === "") {
|
|
248
|
+
throw new Error("Missing id ...");
|
|
249
|
+
}
|
|
250
|
+
if (typeof req.body.data !== "object") {
|
|
251
|
+
throw new Error("Missing id ...");
|
|
252
|
+
}
|
|
253
|
+
const type = this.getTypeFromRequest(req.body);
|
|
254
|
+
if (!type || !type.schema || !type.schema.fields) {
|
|
255
|
+
throw new Error("Missing schema fields ...");
|
|
256
|
+
}
|
|
257
|
+
const schemaFields = typeof type.schema.fields === "function" ? yield type.schema.fields(req) : type.schema.fields;
|
|
258
|
+
const errors = yield this.validateFields(schemaFields, req.body.data);
|
|
259
|
+
if (errors && Object.keys(errors).length > 0) {
|
|
260
|
+
return {
|
|
261
|
+
status: "error",
|
|
262
|
+
errors: errors,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const collection = type.schema && type.schema.collection ? type.schema.collection : undefined;
|
|
266
|
+
if (!collection || collection.trim() === "") {
|
|
267
|
+
throw new Error("Missing collection ...");
|
|
268
|
+
}
|
|
269
|
+
let element = null;
|
|
270
|
+
let updateId = null;
|
|
271
|
+
if (req.body.__builder_id === "new") {
|
|
272
|
+
element = {};
|
|
273
|
+
if (type.schema.primaryKey && type.schema.primaryKey.trim() !== "" && type.schema.primaryKey !== "_id") {
|
|
274
|
+
element[type.schema.primaryKey] = type.schema.primaryKeyPlain
|
|
275
|
+
? req.body.__builder_id
|
|
276
|
+
: yield Model_1.Model.objectId(req.body.builder_id);
|
|
277
|
+
}
|
|
278
|
+
element.__builder = {
|
|
279
|
+
created_at: new Date(),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
const result = yield db
|
|
284
|
+
.collection(collection)
|
|
285
|
+
.aggregate(type.schema && typeof type.schema.getAggregation === "function"
|
|
286
|
+
? yield type.schema.getAggregation(yield this.getAggregation(type, req), req)
|
|
287
|
+
: yield this.getAggregation(type, req), collection)
|
|
288
|
+
.toArray();
|
|
289
|
+
if (!result || !result[0] || !result[0][type.schema.primaryKey ? type.schema.primaryKey : "_id"]) {
|
|
290
|
+
throw new Error("Element '" + req.body.__builder_id + "' not found ...");
|
|
291
|
+
}
|
|
292
|
+
element = result[0];
|
|
293
|
+
updateId = result[0][type.schema.primaryKey ? type.schema.primaryKey : "_id"];
|
|
294
|
+
}
|
|
295
|
+
element = yield this.applyFields(schemaFields, element, req.body.data, req.body.payload);
|
|
296
|
+
if (!element.__builder) {
|
|
297
|
+
element.__builder = {};
|
|
298
|
+
}
|
|
299
|
+
element.__builder.version = type.schema.version;
|
|
300
|
+
element.__builder.collection = type.schema.collection;
|
|
301
|
+
element.__builder.updated_at = new Date();
|
|
302
|
+
try {
|
|
303
|
+
if (typeof type.schema.beforeSave === "function") {
|
|
304
|
+
yield type.schema.beforeSave(element, req);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch (e) {
|
|
308
|
+
throw e;
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
if (typeof type.schema.afterSave === "function") {
|
|
312
|
+
yield type.schema.afterSave(element, req);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch (e) {
|
|
316
|
+
throw e;
|
|
317
|
+
}
|
|
318
|
+
let changedId = null;
|
|
319
|
+
if (updateId) {
|
|
320
|
+
delete element[type.schema.primaryKey ? type.schema.primaryKey : "_id"];
|
|
321
|
+
const status = yield db.collection(collection).updateOne({
|
|
322
|
+
_id: type.schema.primaryKeyPlain ? updateId.toString() : yield Model_1.Model.objectId(updateId),
|
|
323
|
+
}, { $set: Object.assign({}, element) });
|
|
324
|
+
if (status && status.matchedCount) {
|
|
325
|
+
changedId = updateId;
|
|
326
|
+
element[type.schema.primaryKey ? type.schema.primaryKey : "_id"] = type.schema.primaryKeyPlain
|
|
327
|
+
? changedId.toString()
|
|
328
|
+
: changedId;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
const status = yield db
|
|
333
|
+
.collection(collection)
|
|
334
|
+
.insertOne(Object.assign(Object.assign({}, element), { [type.schema.primaryKey ? type.schema.primaryKey : "_id"]: undefined }));
|
|
335
|
+
if (status && status.insertedId) {
|
|
336
|
+
changedId = status.insertedId;
|
|
337
|
+
element[type.schema.primaryKey ? type.schema.primaryKey : "_id"] = type.schema.primaryKeyPlain
|
|
338
|
+
? changedId.toString()
|
|
339
|
+
: changedId;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
let redirect = undefined;
|
|
343
|
+
if (type.forms && type.forms.main && type.forms.main.onSaveRedirect && typeof type.forms.main.onSaveRedirect === "function") {
|
|
344
|
+
redirect = yield type.forms.main.onSaveRedirect(element, req);
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
status: "success",
|
|
348
|
+
data: {
|
|
349
|
+
_id: changedId,
|
|
350
|
+
redirect: redirect,
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
getField(req, type, path) {
|
|
356
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
357
|
+
if (!path || path.trim() === "") {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
const schemaFields = typeof type.schema.fields === "function" ? yield type.schema.fields(req) : type.schema.fields;
|
|
361
|
+
const field = lodash_1.default.get(schemaFields, this.removeArrayIndicators(path));
|
|
362
|
+
return field && field.type ? field : null;
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
removeArrayIndicators(str) {
|
|
366
|
+
return str.replace(/\[\d+\]/g, ".schema");
|
|
367
|
+
}
|
|
368
|
+
details(db, req) {
|
|
369
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
370
|
+
if (!req.body.__builder_id || req.body.__builder_id.toString().trim() === "") {
|
|
371
|
+
throw new Error("Missing id ...");
|
|
372
|
+
}
|
|
373
|
+
const type = this.getTypeFromRequest(req);
|
|
374
|
+
if (!type || !type.schema || !type.schema.fields) {
|
|
375
|
+
throw new Error("Missing schema fields ...");
|
|
376
|
+
}
|
|
377
|
+
const collection = type.schema && type.schema.collection ? type.schema.collection : undefined;
|
|
378
|
+
let element = null;
|
|
379
|
+
try {
|
|
380
|
+
element = yield db
|
|
381
|
+
.collection(collection)
|
|
382
|
+
.aggregate(type.schema && typeof type.schema.getAggregation === "function"
|
|
383
|
+
? yield type.schema.getAggregation(yield this.getAggregation(type, req), req)
|
|
384
|
+
: yield this.getAggregation(type, req), collection)
|
|
385
|
+
.toArray();
|
|
386
|
+
}
|
|
387
|
+
catch (e) {
|
|
388
|
+
console.error(e);
|
|
389
|
+
throw e;
|
|
390
|
+
}
|
|
391
|
+
if (!element || !element[0] || !element[0][type.schema.primaryKey ? type.schema.primaryKey : "_id"]) {
|
|
392
|
+
throw new Error("Element '" + req.body.__builder_id + "' not found ...");
|
|
393
|
+
}
|
|
394
|
+
return {
|
|
395
|
+
status: "success",
|
|
396
|
+
data: element[0],
|
|
397
|
+
};
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
apiAutoComplete(req) {
|
|
401
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
402
|
+
const type = this.getTypeFromRequest(req);
|
|
403
|
+
const field = req.body.__builder_field ? yield this.getField(req, type, req.body.__builder_field) : null;
|
|
404
|
+
if (!field) {
|
|
405
|
+
throw new Error("Invalid autocomplete field ...");
|
|
406
|
+
}
|
|
407
|
+
const fieldType = this.getFieldType(field.type);
|
|
408
|
+
if (!fieldType || !fieldType.key || fieldType.type !== "api-autocomplete" || !fieldType.onSearch) {
|
|
409
|
+
throw new Error("Invalid autocomplete field type '" + field.type + "' ...");
|
|
410
|
+
}
|
|
411
|
+
req.body.payload = Object.assign(Object.assign({}, req.body.payload), field.payload);
|
|
412
|
+
req.field = field;
|
|
413
|
+
return {
|
|
414
|
+
status: "success",
|
|
415
|
+
data: yield fieldType.onSearch(req.body.query, req),
|
|
416
|
+
};
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
exports.DataBuilder = DataBuilder;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Controller } from "../Controller/Controller";
|
|
2
|
+
import { Request } from "../Router/Request";
|
|
3
|
+
import { Response } from "../Router/Response";
|
|
4
|
+
import { DataBuilder } from "./DataBuilder";
|
|
5
|
+
export declare class DataBuilderController extends Controller {
|
|
6
|
+
builder: DataBuilder;
|
|
7
|
+
constructor(builder?: DataBuilder);
|
|
8
|
+
restApi(req: Request, res: Response): Promise<Response>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DataBuilderController = void 0;
|
|
13
|
+
const Controller_1 = require("../Controller/Controller");
|
|
14
|
+
const DBConnection_1 = require("../Database/DBConnection");
|
|
15
|
+
const DataBuilder_1 = require("./DataBuilder");
|
|
16
|
+
class DataBuilderController extends Controller_1.Controller {
|
|
17
|
+
constructor(builder) {
|
|
18
|
+
super();
|
|
19
|
+
this.builder = builder ? builder : new DataBuilder_1.DataBuilder();
|
|
20
|
+
}
|
|
21
|
+
restApi(req, res) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
const db = yield DBConnection_1.DBConnection.getConnection();
|
|
24
|
+
if (req.body.__builder_rest_api === "api-autocomplete") {
|
|
25
|
+
return res.send(yield this.builder.apiAutoComplete(req));
|
|
26
|
+
}
|
|
27
|
+
else if (req.body.__builder_rest_api === "details") {
|
|
28
|
+
return res.send(yield this.builder.details(db.client.db(null), req));
|
|
29
|
+
}
|
|
30
|
+
else if (req.body.__builder_rest_api === "save") {
|
|
31
|
+
return res.send(yield this.builder.save(db.client.db(null), req));
|
|
32
|
+
}
|
|
33
|
+
else if (req.body.__builder_rest_api === "type") {
|
|
34
|
+
return res.send(yield this.builder.loadType(req));
|
|
35
|
+
}
|
|
36
|
+
return res.status(404).send({
|
|
37
|
+
status: "error",
|
|
38
|
+
message: "Api-Endpoint not found ...",
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.DataBuilderController = DataBuilderController;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { QueryBuilder } from "./QueryBuilder";
|
|
2
|
+
type ObjectIDType = {
|
|
3
|
+
noExceptions?: Boolean;
|
|
4
|
+
};
|
|
2
5
|
declare class DBConnectionFacade {
|
|
3
6
|
connections: {
|
|
4
7
|
[key: string]: any;
|
|
@@ -11,6 +14,7 @@ declare class DBConnectionFacade {
|
|
|
11
14
|
}): Promise<any>;
|
|
12
15
|
execute(data: any, connectionName?: string): Promise<any>;
|
|
13
16
|
getDriver(connectionName?: string): Promise<any>;
|
|
17
|
+
objectId(val?: any, connectionName?: string, options?: ObjectIDType): Promise<any>;
|
|
14
18
|
mapDataToModel(model: any, data: any): any;
|
|
15
19
|
}
|
|
16
20
|
export declare const DBConnection: DBConnectionFacade;
|
|
@@ -25,10 +25,7 @@ class DBConnectionFacade {
|
|
|
25
25
|
if (!connection) {
|
|
26
26
|
connection = dbconfig.defaultConnection;
|
|
27
27
|
}
|
|
28
|
-
if (!connection ||
|
|
29
|
-
!dbconfig ||
|
|
30
|
-
!dbconfig.connections ||
|
|
31
|
-
!dbconfig.connections[connection]) {
|
|
28
|
+
if (!connection || !dbconfig || !dbconfig.connections || !dbconfig.connections[connection]) {
|
|
32
29
|
throw new Error("No connection given ...");
|
|
33
30
|
}
|
|
34
31
|
return dbconfig.connections[connection];
|
|
@@ -55,8 +52,7 @@ class DBConnectionFacade {
|
|
|
55
52
|
if (!connectionName) {
|
|
56
53
|
return null;
|
|
57
54
|
}
|
|
58
|
-
if (this.connections[connectionName] &&
|
|
59
|
-
this.connections[connectionName].driver) {
|
|
55
|
+
if (this.connections[connectionName] && this.connections[connectionName].driver) {
|
|
60
56
|
// Use cached connection
|
|
61
57
|
return this.connections[connectionName];
|
|
62
58
|
}
|
|
@@ -96,6 +92,22 @@ class DBConnectionFacade {
|
|
|
96
92
|
return connection.driver;
|
|
97
93
|
});
|
|
98
94
|
}
|
|
95
|
+
objectId(val, connectionName, options) {
|
|
96
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
if (options && options.noExceptions) {
|
|
98
|
+
try {
|
|
99
|
+
const connection = yield this.getConnection(connectionName);
|
|
100
|
+
return yield connection.driver.objectId(val);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
console.error(e);
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
const connection = yield this.getConnection(connectionName);
|
|
108
|
+
return yield connection.driver.objectId(val);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
99
111
|
mapDataToModel(model, data) {
|
|
100
112
|
const obj = new model();
|
|
101
113
|
if (data) {
|
package/dist/Database/Model.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { QueryBuilder } from "./QueryBuilder";
|
|
2
|
+
type ObjectIDType = {
|
|
3
|
+
noExceptions?: Boolean;
|
|
4
|
+
};
|
|
2
5
|
export declare class Model {
|
|
3
6
|
[key: string]: any | undefined;
|
|
4
7
|
__primaryKey: string;
|
|
@@ -7,6 +10,8 @@ export declare class Model {
|
|
|
7
10
|
__hidden: string[];
|
|
8
11
|
__unmapped: string[];
|
|
9
12
|
__unmappedSystem: string[];
|
|
13
|
+
static objectId(val?: any, options?: ObjectIDType): Promise<any>;
|
|
14
|
+
objectId(val?: any, options?: ObjectIDType): Promise<any>;
|
|
10
15
|
/**
|
|
11
16
|
* Creates a new query-builder object and adds a where-clause
|
|
12
17
|
* @param column
|
|
@@ -68,3 +73,4 @@ export declare class Model {
|
|
|
68
73
|
*/
|
|
69
74
|
delete(): Promise<boolean>;
|
|
70
75
|
}
|
|
76
|
+
export {};
|
package/dist/Database/Model.js
CHANGED
|
@@ -21,6 +21,17 @@ class Model {
|
|
|
21
21
|
this.__unmapped = [];
|
|
22
22
|
this.__unmappedSystem = ["__primaryKey", "__table", "__connection", "__unmapped", "__unmappedSystem", "__is_deleted", "__hidden"];
|
|
23
23
|
}
|
|
24
|
+
static objectId(val, options) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const model = new this();
|
|
27
|
+
return yield DBConnection_1.DBConnection.objectId(val, model.__connection, options);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
objectId(val, options) {
|
|
31
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
return yield DBConnection_1.DBConnection.objectId(val, this.__connection, options);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
24
35
|
/**
|
|
25
36
|
* Creates a new query-builder object and adds a where-clause
|
|
26
37
|
* @param column
|
package/package.json
CHANGED