yaml-admin-api 0.0.77 → 0.0.79

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.79",
4
4
  "license": "MIT",
5
5
  "description": "YAML Admin API package",
6
6
  "type": "commonjs",
@@ -89,12 +89,52 @@ 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')
95
121
  return { $ne: null }
96
122
  else if(value == 'null')
97
123
  return null
124
+ if(value?.startsWith('$')) {
125
+ const [op, val] = value.split(' ')
126
+ if(op == '$lte')
127
+ return { $lte: parseFloat(val) }
128
+ else if(op == '$gte')
129
+ return { $gte: val }
130
+ else if(op == '$lt')
131
+ return { $lt: val }
132
+ else if(op == '$gt')
133
+ return { $gt: val }
134
+ else
135
+ return value
136
+ }
137
+
98
138
  if (type == 'boolean') {
99
139
  if(value == 'true')
100
140
  return true
@@ -262,9 +302,6 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
262
302
  //Custom f list End
263
303
 
264
304
  const projection = (key_field.name == '_id' ? {} : { _id: false })
265
- if(yml.debug)
266
- console.log('list', entity_name, f)
267
-
268
305
  let list, count;
269
306
  let aggregate = await makeApiGenerateAggregate(db, entity_name, yml_entity, yml, options)
270
307
 
@@ -274,9 +311,12 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
274
311
  count = countResult.length > 0 ? countResult[0].count : 0
275
312
 
276
313
  aggregate = [...aggregate, { $sort: s }, { $skip: parseInt(_start) }, { $limit: l }]
314
+ if(yml.debug)
315
+ console.log('list', entity_name, JSON.stringify(aggregate, null, 2))
277
316
  list = await db.collection(collection_name).aggregate(aggregate).toArray()
278
- } else
279
- {
317
+ } else {
318
+ if(yml.debug)
319
+ console.log('list', entity_name, f)
280
320
  count = await db.collection(collection_name).find(f).project(projection).sort(s).count()
281
321
  list = await db.collection(collection_name).find(f).project(projection).sort(s).skip(parseInt(_start)).limit(l).toArray()
282
322
  }
@@ -362,6 +402,9 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
362
402
  // default_filter 값을 entity에 자동 적용
363
403
  Object.assign(entity, default_filter)
364
404
 
405
+ // unique 검사
406
+ await checkUnique(entity)
407
+
365
408
  //Custom Create Start
366
409
 
367
410
  //Custom Create End
@@ -408,6 +451,9 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
408
451
  }
409
452
  }
410
453
 
454
+ // unique 검사 (자기 자신 제외)
455
+ await checkUnique(entity, entityId)
456
+
411
457
  await db.collection(collection_name).updateOne(f, { $set: entity });
412
458
 
413
459
  //Custom Create Tail Start
@@ -726,6 +772,15 @@ const makeApiGenerateAggregate = async (db, entity_name, yml_entity, yml, option
726
772
  { $match: { $expr: { $eq: ['$' + match, '$$local_key'] } } }
727
773
  ]
728
774
 
775
+ // filter 처리
776
+ if (Array.isArray(apiGenerateItem.filter)) {
777
+ let filterMatch = {}
778
+ apiGenerateItem.filter.forEach(f => {
779
+ filterMatch[f.name] = f.value
780
+ })
781
+ innerPipeline.push({ $match: filterMatch })
782
+ }
783
+
729
784
  // single일 때 max _id로 하나만 선택 ($match 바로 다음에)
730
785
  if(single) {
731
786
  innerPipeline.push({ $sort: { _id: -1 } })
@@ -785,84 +840,6 @@ const makeApiGenerateAggregate = async (db, entity_name, yml_entity, yml, option
785
840
  return aggregate
786
841
  }
787
842
 
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
843
  const generateEntityApi = async ({ app, db, entity_name, entity, yml, options }) => {
867
844
  await generateCrud({ app, db, entity_name, yml_entity: entity, yml, options })
868
845
  }