yaml-admin-api 0.0.77 → 0.0.78

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaml-admin-api",
3
- "version": "0.0.77",
3
+ "version": "0.0.78",
4
4
  "license": "MIT",
5
5
  "description": "YAML Admin API package",
6
6
  "type": "commonjs",
@@ -89,6 +89,32 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
89
89
  return key
90
90
  }
91
91
 
92
+ // unique 검사 함수
93
+ const checkUnique = async (entity, excludeId = null) => {
94
+ const uniqueFields = yml_entity.unique
95
+ if (!uniqueFields || uniqueFields.length === 0) return
96
+
97
+ const f = {}
98
+ for (const field of uniqueFields) {
99
+ f[field.name] = entity[field.name]
100
+ }
101
+
102
+ // 자기 자신 제외 (update 시)
103
+ if (excludeId !== null) {
104
+ f[key_field.name] = { $ne: excludeId }
105
+ }
106
+
107
+ const existing = await db.collection(collection_name).findOne(f)
108
+ if (existing) {
109
+ const fieldNames = uniqueFields.map(u => {
110
+ const fieldDef = yml_entity.fields?.find(field => field.name === u.name)
111
+ return fieldDef?.label || u.name
112
+ }).join(', ')
113
+ const fieldValues = uniqueFields.map(u => entity[u.name]).join(', ')
114
+ throw new Error("duplicate key of [" + fieldNames + "] - [" + fieldValues + "]")
115
+ }
116
+ }
117
+
92
118
  const parseValueByType = (value, field) => {
93
119
  const { type, reference_entity, reference_match } = field
94
120
  if(value == 'not null')
@@ -262,9 +288,6 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
262
288
  //Custom f list End
263
289
 
264
290
  const projection = (key_field.name == '_id' ? {} : { _id: false })
265
- if(yml.debug)
266
- console.log('list', entity_name, f)
267
-
268
291
  let list, count;
269
292
  let aggregate = await makeApiGenerateAggregate(db, entity_name, yml_entity, yml, options)
270
293
 
@@ -274,9 +297,12 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
274
297
  count = countResult.length > 0 ? countResult[0].count : 0
275
298
 
276
299
  aggregate = [...aggregate, { $sort: s }, { $skip: parseInt(_start) }, { $limit: l }]
300
+ if(yml.debug)
301
+ console.log('list', entity_name, JSON.stringify(aggregate, null, 2))
277
302
  list = await db.collection(collection_name).aggregate(aggregate).toArray()
278
- } else
279
- {
303
+ } else {
304
+ if(yml.debug)
305
+ console.log('list', entity_name, f)
280
306
  count = await db.collection(collection_name).find(f).project(projection).sort(s).count()
281
307
  list = await db.collection(collection_name).find(f).project(projection).sort(s).skip(parseInt(_start)).limit(l).toArray()
282
308
  }
@@ -362,6 +388,9 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
362
388
  // default_filter 값을 entity에 자동 적용
363
389
  Object.assign(entity, default_filter)
364
390
 
391
+ // unique 검사
392
+ await checkUnique(entity)
393
+
365
394
  //Custom Create Start
366
395
 
367
396
  //Custom Create End
@@ -408,6 +437,9 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
408
437
  }
409
438
  }
410
439
 
440
+ // unique 검사 (자기 자신 제외)
441
+ await checkUnique(entity, entityId)
442
+
411
443
  await db.collection(collection_name).updateOne(f, { $set: entity });
412
444
 
413
445
  //Custom Create Tail Start
@@ -726,6 +758,15 @@ const makeApiGenerateAggregate = async (db, entity_name, yml_entity, yml, option
726
758
  { $match: { $expr: { $eq: ['$' + match, '$$local_key'] } } }
727
759
  ]
728
760
 
761
+ // filter 처리
762
+ if (Array.isArray(apiGenerateItem.filter)) {
763
+ let filterMatch = {}
764
+ apiGenerateItem.filter.forEach(f => {
765
+ filterMatch[f.name] = f.value
766
+ })
767
+ innerPipeline.push({ $match: filterMatch })
768
+ }
769
+
729
770
  // single일 때 max _id로 하나만 선택 ($match 바로 다음에)
730
771
  if(single) {
731
772
  innerPipeline.push({ $sort: { _id: -1 } })
@@ -785,84 +826,6 @@ const makeApiGenerateAggregate = async (db, entity_name, yml_entity, yml, option
785
826
  return aggregate
786
827
  }
787
828
 
788
- const makeApiGenerateFields = async (db, entity_name, yml_entity, yml, options, data_list) => {
789
- const apiGenerate = yml_entity.api_generate
790
- if(!apiGenerate)
791
- return;
792
- for(let key in apiGenerate) {
793
-
794
- const apiGenerateItem = apiGenerate[key]
795
- let { entity, field, fields, match, sort, limit, single, match_from } = apiGenerateItem
796
-
797
- sort = sort || []
798
- sort = makeMongoSortFromYml(sort)
799
- limit = limit || 1000
800
-
801
- let match_from_list = data_list.map(m=>matchPathInObject(m, match_from))
802
- match_from_list = match_from_list.filter(m=>m)
803
- const projection = {[match]:1}
804
-
805
- const aggregate = [
806
- { $match: { [match]: {$in:match_from_list} } },
807
- ]
808
-
809
- if(field)
810
- projection[field] = 1
811
- else if(fields){
812
- fields.map(m=>{
813
- projection[m.name] = 1
814
- })
815
-
816
- fields.map(m=>{
817
- if(m.type == 'reference') {
818
- let project = { _id: 0 }
819
-
820
- if(m.field)
821
- project[m.field] = 1
822
- else
823
- m.fields.map(f=>{
824
- project[f.name] = 1
825
- })
826
-
827
- aggregate.push({ $lookup: {
828
- from: m.reference_entity,
829
- let: { local_key: '$'+m.reference_from },
830
- pipeline: [
831
- { $match: { $expr: { $eq: ["$"+m.reference_match, "$$local_key"] } } },
832
- { $project: project }
833
- ],
834
- as: m.name
835
- } })
836
- if(m.single)
837
- aggregate.push({ $unwind: `$${m.name}` })
838
-
839
- if(m.field)
840
- aggregate.push({ $addFields: { [m.field]: `$${m.name}.${m.field}` } })
841
- }
842
- })
843
- }
844
-
845
- const result = await db.collection(entity)
846
- .aggregate(aggregate)
847
- .project(projection)
848
- .toArray()
849
- data_list.map(m=>{
850
- let found = result.filter(f=>matchPathInObject(f, match) === matchPathInObject(m, match_from))
851
- if(single) {
852
- if(field)
853
- m[key] = found.length > 0 ? found[0][field] : null
854
- else
855
- m[key] = found.length > 0 ? found[0] : null
856
- } else {
857
- if(field)
858
- m[key] = found.map(f=>f[field])
859
- else
860
- m[key] = found
861
- }
862
- })
863
- }
864
- }
865
-
866
829
  const generateEntityApi = async ({ app, db, entity_name, entity, yml, options }) => {
867
830
  await generateCrud({ app, db, entity_name, yml_entity: entity, yml, options })
868
831
  }