yaml-admin-api 0.0.69 → 0.0.71
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/package.json +1 -1
- package/src/crud/entity-api-generator.js +166 -8
package/package.json
CHANGED
|
@@ -82,7 +82,15 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
82
82
|
return { $ne: null }
|
|
83
83
|
else if(value == 'null')
|
|
84
84
|
return null
|
|
85
|
-
if (type == '
|
|
85
|
+
if (type == 'boolean') {
|
|
86
|
+
if(value == 'true')
|
|
87
|
+
return true
|
|
88
|
+
else if(value == 'false')
|
|
89
|
+
return false
|
|
90
|
+
else
|
|
91
|
+
return null
|
|
92
|
+
}
|
|
93
|
+
else if (type == 'reference') {
|
|
86
94
|
const referenceEntity = yml.entity[reference_entity]
|
|
87
95
|
const referenceField = referenceEntity.fields.find(f => f.name == reference_match)
|
|
88
96
|
if(!referenceField)
|
|
@@ -131,7 +139,7 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
131
139
|
}
|
|
132
140
|
}
|
|
133
141
|
|
|
134
|
-
|
|
142
|
+
//await makeApiGenerateFields(db, entity_name, yml_entity, yml, options, list)
|
|
135
143
|
}
|
|
136
144
|
|
|
137
145
|
const mediaKeyToFullUrl = async (key, private) => {
|
|
@@ -189,10 +197,12 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
189
197
|
var _order = req.query._order;
|
|
190
198
|
if (_sort != null)
|
|
191
199
|
s[_sort] = (_order == 'ASC' ? 1 : -1);
|
|
200
|
+
else
|
|
201
|
+
s._id = -1
|
|
192
202
|
|
|
193
203
|
var _end = req.query._end;
|
|
194
|
-
var _start = req.query._start;
|
|
195
|
-
var l = _end - _start;
|
|
204
|
+
var _start = req.query._start || 0;
|
|
205
|
+
var l = _end - _start || 50;
|
|
196
206
|
|
|
197
207
|
//검색 파라미터
|
|
198
208
|
const f = {};
|
|
@@ -238,13 +248,36 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
238
248
|
const projection = (key_field.name == '_id' ? {} : { _id: false })
|
|
239
249
|
if(yml.debug)
|
|
240
250
|
console.log('list', entity_name, f)
|
|
241
|
-
|
|
242
|
-
let list
|
|
251
|
+
|
|
252
|
+
let list, count;
|
|
253
|
+
let aggregate = await makeApiGenerateAggregate(db, entity_name, yml_entity, yml, options)
|
|
254
|
+
|
|
255
|
+
if(aggregate?.length > 0) {
|
|
256
|
+
aggregate = [{$match: f}, ...aggregate]
|
|
257
|
+
|
|
258
|
+
const countResult = await db.collection(entity_name).aggregate([...aggregate, { $count: 'count' }]).toArray()
|
|
259
|
+
count = countResult.length > 0 ? countResult[0].count : 0
|
|
260
|
+
|
|
261
|
+
list = await db.collection(entity_name).aggregate(aggregate)
|
|
262
|
+
.sort(s)
|
|
263
|
+
.skip(parseInt(_start))
|
|
264
|
+
.limit(l).toArray()
|
|
265
|
+
} else
|
|
266
|
+
{
|
|
267
|
+
count = await db.collection(entity_name).find(f).project(projection).sort(s).count()
|
|
268
|
+
list = await db.collection(entity_name).find(f).project(projection).sort(s).skip(parseInt(_start)).limit(l).toArray()
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if(yml.debug)
|
|
272
|
+
console.log('list', entity_name, 'count', count, 'list length', list.length)
|
|
273
|
+
|
|
243
274
|
list.map(m => {
|
|
244
275
|
m.id = getKeyFromEntity(m)
|
|
245
276
|
})
|
|
246
277
|
|
|
247
278
|
await addInfo(db, list)
|
|
279
|
+
//await makeApiGenerateFields(db, entity_name, yml_entity, yml, options, list)
|
|
280
|
+
|
|
248
281
|
if(options?.listener?.entityListed)
|
|
249
282
|
await options.listener.entityListed(db, entity_name, list)
|
|
250
283
|
|
|
@@ -375,7 +408,18 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
375
408
|
app.get(`${api_prefix}/${entity_name}/:id`, auth.isAuthenticated, asyncErrorHandler(async (req, res) => {
|
|
376
409
|
let f = {}
|
|
377
410
|
f[key_field.name] = parseKey(req.params.id)
|
|
378
|
-
|
|
411
|
+
|
|
412
|
+
let aggregate = await makeApiGenerateAggregate(db, entity_name, yml_entity, yml, options)
|
|
413
|
+
|
|
414
|
+
let m
|
|
415
|
+
if(aggregate?.length > 0) {
|
|
416
|
+
aggregate = [{$match: f}, ...aggregate, { $limit: 1 }]
|
|
417
|
+
const result = await db.collection(entity_name).aggregate(aggregate).toArray()
|
|
418
|
+
m = result.length > 0 ? result[0] : null
|
|
419
|
+
} else {
|
|
420
|
+
m = await db.collection(entity_name).findOne(f);
|
|
421
|
+
}
|
|
422
|
+
|
|
379
423
|
if (!m)
|
|
380
424
|
return res.status(404).send('Not found');
|
|
381
425
|
|
|
@@ -384,7 +428,7 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
384
428
|
|
|
385
429
|
if(yml.debug)
|
|
386
430
|
console.log('show', entity_name, m)
|
|
387
|
-
|
|
431
|
+
|
|
388
432
|
res.json(m);
|
|
389
433
|
}))
|
|
390
434
|
|
|
@@ -602,6 +646,120 @@ const matchPathInObject = (obj, path) => {
|
|
|
602
646
|
return r
|
|
603
647
|
}
|
|
604
648
|
|
|
649
|
+
const makeApiGenerateAggregate = async (db, entity_name, yml_entity, yml, options) => {
|
|
650
|
+
const apiGenerate = yml_entity.api_generate
|
|
651
|
+
if(!apiGenerate)
|
|
652
|
+
return;
|
|
653
|
+
|
|
654
|
+
// reference 필드를 위한 중첩 pipeline 생성 함수
|
|
655
|
+
const buildReferencePipeline = (refField) => {
|
|
656
|
+
const pipeline = []
|
|
657
|
+
let project = { _id: 0 }
|
|
658
|
+
|
|
659
|
+
if(refField.field)
|
|
660
|
+
project[refField.field] = 1
|
|
661
|
+
else if(refField.fields) {
|
|
662
|
+
refField.fields.forEach(f => {
|
|
663
|
+
project[f.name] = 1
|
|
664
|
+
})
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
pipeline.push({
|
|
668
|
+
$lookup: {
|
|
669
|
+
from: refField.reference_entity,
|
|
670
|
+
localField: refField.reference_from,
|
|
671
|
+
foreignField: refField.reference_match,
|
|
672
|
+
pipeline: [{ $project: project }],
|
|
673
|
+
as: refField.name
|
|
674
|
+
}
|
|
675
|
+
})
|
|
676
|
+
|
|
677
|
+
if(refField.single) {
|
|
678
|
+
pipeline.push({
|
|
679
|
+
$unwind: {
|
|
680
|
+
path: `$${refField.name}`,
|
|
681
|
+
preserveNullAndEmptyArrays: true
|
|
682
|
+
}
|
|
683
|
+
})
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
if(refField.field) {
|
|
687
|
+
pipeline.push({
|
|
688
|
+
$addFields: { [refField.name]: `$${refField.name}.${refField.field}` }
|
|
689
|
+
})
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
return pipeline
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
const aggregate = []
|
|
696
|
+
for(let key in apiGenerate) {
|
|
697
|
+
|
|
698
|
+
const apiGenerateItem = apiGenerate[key]
|
|
699
|
+
let { entity, field, fields, match, sort, limit, single, match_from } = apiGenerateItem
|
|
700
|
+
|
|
701
|
+
sort = sort || []
|
|
702
|
+
sort = makeMongoSortFromYml(sort)
|
|
703
|
+
limit = limit || 1000
|
|
704
|
+
|
|
705
|
+
// lookup 내부 pipeline 구성
|
|
706
|
+
const innerPipeline = [
|
|
707
|
+
{ $match: { $expr: { $eq: ['$' + match, '$$local_key'] } } }
|
|
708
|
+
]
|
|
709
|
+
|
|
710
|
+
// projection 구성
|
|
711
|
+
const projection = { _id: 0, [match]: 1 }
|
|
712
|
+
if(field) {
|
|
713
|
+
projection[field] = 1
|
|
714
|
+
} else if(fields) {
|
|
715
|
+
fields.forEach(m => {
|
|
716
|
+
if(m.type !== 'reference') {
|
|
717
|
+
projection[m.name] = 1
|
|
718
|
+
}
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
// reference 필드는 중첩 lookup으로 처리
|
|
722
|
+
fields.filter(m => m.type === 'reference').forEach(refField => {
|
|
723
|
+
projection[refField.reference_from] = 1
|
|
724
|
+
const refPipeline = buildReferencePipeline(refField)
|
|
725
|
+
innerPipeline.push(...refPipeline)
|
|
726
|
+
})
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// projection을 innerPipeline 맨 앞에 추가 (match 다음)
|
|
730
|
+
innerPipeline.splice(1, 0, { $project: projection })
|
|
731
|
+
|
|
732
|
+
// 기본 $lookup 추가
|
|
733
|
+
aggregate.push({
|
|
734
|
+
$lookup: {
|
|
735
|
+
from: entity,
|
|
736
|
+
let: { local_key: '$' + match_from },
|
|
737
|
+
pipeline: innerPipeline,
|
|
738
|
+
as: key
|
|
739
|
+
}
|
|
740
|
+
})
|
|
741
|
+
|
|
742
|
+
if(single) {
|
|
743
|
+
aggregate.push({
|
|
744
|
+
$unwind: {
|
|
745
|
+
path: `$${key}`,
|
|
746
|
+
preserveNullAndEmptyArrays: true
|
|
747
|
+
}
|
|
748
|
+
})
|
|
749
|
+
|
|
750
|
+
// field만 있는 경우 값만 추출
|
|
751
|
+
if(field) {
|
|
752
|
+
aggregate.push({
|
|
753
|
+
$addFields: { [key]: `$${key}.${field}` }
|
|
754
|
+
})
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
//console.log('aggregate', JSON.stringify(aggregate, null, 2))
|
|
760
|
+
return aggregate
|
|
761
|
+
}
|
|
762
|
+
|
|
605
763
|
const makeApiGenerateFields = async (db, entity_name, yml_entity, yml, options, data_list) => {
|
|
606
764
|
const apiGenerate = yml_entity.api_generate
|
|
607
765
|
if(!apiGenerate)
|