create-entity-server 0.0.27 → 0.2.2

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.
Files changed (100) hide show
  1. package/package.json +1 -1
  2. package/template/configs/cache.json +2 -1
  3. package/template/configs/database.json +18 -7
  4. package/template/entities/README.md +3 -3
  5. package/template/entities/System/Address/addr_dong.json +10115 -0
  6. package/template/entities/System/Address/addr_sido.json +39 -0
  7. package/template/entities/System/Address/addr_sigungu.json +1398 -0
  8. package/template/entities/System/Auth/account.json +94 -18
  9. package/template/entities/System/Auth/account_audit.json +11 -3
  10. package/template/entities/System/Auth/account_device.json +13 -27
  11. package/template/entities/System/Auth/account_login_log.json +17 -7
  12. package/template/entities/System/Auth/anon_device.json +56 -0
  13. package/template/entities/System/Auth/api_keys.json +18 -9
  14. package/template/entities/System/Auth/license.json +41 -20
  15. package/template/entities/System/Auth/rbac_roles.json +10 -7
  16. package/template/entities/System/Backup/backup_log.json +11 -7
  17. package/template/entities/System/Email/smtp_log.json +9 -5
  18. package/template/entities/System/Email/smtp_msg.json +5 -5
  19. package/template/entities/System/Storage/file_backup_log.json +11 -6
  20. package/template/entities/System/Storage/file_download_log.json +7 -5
  21. package/template/entities/System/Storage/file_meta.json +20 -7
  22. package/template/entities/System/system_audit_log.json +38 -34
  23. package/template/entities/company.json +5 -2
  24. package/template/entities/goods.json +10 -3
  25. package/template/entities/todo.json +4 -2
  26. package/template/samples/entities/01_basic_fields.json +15 -2
  27. package/template/samples/entities/02_types_and_defaults.json +15 -5
  28. package/template/samples/entities/03_hash_and_unique.json +18 -3
  29. package/template/samples/entities/04_fk_and_composite_unique.json +18 -3
  30. package/template/samples/entities/05_cache.json +15 -9
  31. package/template/samples/entities/06_history_and_hard_delete.json +19 -6
  32. package/template/samples/entities/07_license_scope.json +18 -3
  33. package/template/samples/entities/08_hook_sql.json +24 -5
  34. package/template/samples/entities/09_hook_entity.json +12 -2
  35. package/template/samples/entities/10_hook_submit_delete.json +14 -5
  36. package/template/samples/entities/11_hook_webhook.json +20 -6
  37. package/template/samples/entities/12_hook_push.json +15 -2
  38. package/template/samples/entities/13_read_only.json +8 -4
  39. package/template/samples/entities/14_optimistic_lock.json +13 -2
  40. package/template/samples/entities/15_reset_defaults.json +7 -1
  41. package/template/samples/entities/16_isolated_license.json +19 -6
  42. package/template/scripts/reset-all.sh +130 -3
  43. package/template/scripts/run.sh +129 -33
  44. package/template/templates/ocr/business_reg.json +145 -0
  45. package/template/templates/ocr/career_cert.json +93 -0
  46. package/template/templates/ocr/driver_license.json +89 -0
  47. package/template/templates/ocr/facility_card.json +82 -0
  48. package/template/templates/ocr/id_card.json +55 -0
  49. package/template/templates/ocr/invoice.json +92 -0
  50. package/template/templates/ocr/namecard.json +116 -0
  51. package/template/templates/ocr/prompts/business_reg.json +14 -0
  52. package/template/templates/ocr/prompts/career_cert.json +16 -0
  53. package/template/templates/ocr/prompts/driver_license.json +14 -0
  54. package/template/templates/ocr/prompts/facility_card.json +15 -0
  55. package/template/templates/ocr/prompts/general.json +13 -0
  56. package/template/templates/ocr/prompts/id_card.json +11 -0
  57. package/template/templates/ocr/prompts/invoice.json +17 -0
  58. package/template/templates/ocr/prompts/namecard.json +15 -0
  59. package/template/templates/ocr/prompts/receipt.json +14 -0
  60. package/template/templates/ocr/receipt.json +79 -0
  61. package/template/configs/auth/identity.json +0 -27
  62. package/template/configs/auth/oauth.json +0 -40
  63. package/template/configs/auth/password.json +0 -33
  64. package/template/configs/auth/privacy_policy.json +0 -28
  65. package/template/configs/auth/two_factor.json +0 -12
  66. package/template/configs/extensions/pg.json +0 -37
  67. package/template/configs/extensions/tax-invoice.json +0 -59
  68. package/template/configs/keys/apns.p8.example +0 -7
  69. package/template/configs/keys/firebase.pem.example +0 -7
  70. package/template/configs/notification/alimtalk.json +0 -75
  71. package/template/configs/notification/push.json +0 -25
  72. package/template/configs/notification/sms.json +0 -54
  73. package/template/entities/System/Auth/account_oauth.json +0 -45
  74. package/template/entities/System/Auth/identity_verification.json +0 -95
  75. package/template/entities/System/Auth/password_history.json +0 -20
  76. package/template/entities/System/Notification/alimtalk_log.json +0 -45
  77. package/template/entities/System/Notification/alimtalk_msg.json +0 -39
  78. package/template/entities/System/Notification/friendtalk_log.json +0 -48
  79. package/template/entities/System/Notification/friendtalk_msg.json +0 -63
  80. package/template/entities/System/Notification/sms_log.json +0 -26
  81. package/template/entities/System/Notification/sms_msg.json +0 -52
  82. package/template/entities/System/Notification/sms_verification.json +0 -40
  83. package/template/entities/System/Payment/pg_cancel.json +0 -45
  84. package/template/entities/System/Payment/pg_order.json +0 -88
  85. package/template/entities/System/Payment/pg_webhook_log.json +0 -37
  86. package/template/entities/System/Push/push_log.json +0 -71
  87. package/template/entities/System/Push/push_msg.json +0 -55
  88. package/template/templates/email/account/dormancy_warning.html +0 -20
  89. package/template/templates/email/account/password_expiry_warning.html +0 -21
  90. package/template/templates/email/auth/2fa_disabled.html +0 -23
  91. package/template/templates/email/auth/2fa_recovery_regenerated.html +0 -31
  92. package/template/templates/email/auth/2fa_setup_complete.html +0 -43
  93. package/template/templates/email/auth/email_verification.html +0 -18
  94. package/template/templates/email/auth/force_reset.html +0 -18
  95. package/template/templates/email/auth/password_reset.html +0 -19
  96. package/template/templates/email/auth/verification.html +0 -15
  97. package/template/templates/email/auth/verification_link.html +0 -25
  98. package/template/templates/email/auth/welcome.html +0 -18
  99. package/template/templates/email/order/order_confirmation.html +0 -30
  100. /package/template/configs/{notification/smtp.json → smtp.json} +0 -0
@@ -1,22 +1,31 @@
1
1
  {
2
2
  "name": "user_point",
3
3
  "description": "SQL 훅 예제 — INSERT/UPDATE 시 자동 감사 로그 기록 (실행형) + SELECT 결과 주입 (조회형)",
4
- "index": {
4
+ "fields": {
5
5
  "user_seq": {
6
+ "index": true,
6
7
  "comment": "사용자 seq",
7
8
  "required": true,
8
9
  "unique": true
9
10
  },
10
11
  "point": {
12
+ "index": true,
11
13
  "comment": "보유 포인트",
12
14
  "type": "uint"
13
15
  },
14
16
  "grade": {
17
+ "index": true,
15
18
  "comment": "등급",
16
- "type": ["bronze", "silver", "gold", "platinum"],
19
+ "type": [
20
+ "bronze",
21
+ "silver",
22
+ "gold",
23
+ "platinum"
24
+ ],
17
25
  "default": "bronze"
18
26
  },
19
27
  "updated_at": {
28
+ "index": true,
20
29
  "comment": "마지막 포인트 변경일시 (*_at → DATETIME 자동 추론)"
21
30
  }
22
31
  },
@@ -26,7 +35,11 @@
26
35
  "comment": "포인트 생성 이력 기록 (실행형 SQL 훅)",
27
36
  "type": "sql",
28
37
  "query": "INSERT INTO point_history (user_seq, delta, reason, created_time) VALUES (?, ?, ?, NOW())",
29
- "params": ["${new.user_seq}", "${new.point}", "initial_grant"],
38
+ "params": [
39
+ "${new.user_seq}",
40
+ "${new.point}",
41
+ "initial_grant"
42
+ ],
30
43
  "async": false
31
44
  }
32
45
  ],
@@ -35,7 +48,11 @@
35
48
  "comment": "포인트 변경 이력 기록 (실행형 SQL 훅)",
36
49
  "type": "sql",
37
50
  "query": "INSERT INTO point_history (user_seq, delta, reason, created_time) VALUES (?, ?, ?, NOW())",
38
- "params": ["${new.user_seq}", "${new.point}", "update"],
51
+ "params": [
52
+ "${new.user_seq}",
53
+ "${new.point}",
54
+ "update"
55
+ ],
39
56
  "async": true
40
57
  }
41
58
  ],
@@ -44,7 +61,9 @@
44
61
  "comment": "최근 포인트 변경 이력 5건 주입 (조회형 SQL 훅)",
45
62
  "type": "sql",
46
63
  "query": "SELECT delta, reason, created_time FROM point_history WHERE user_seq = ? ORDER BY created_time DESC LIMIT 5",
47
- "params": ["${new.user_seq}"],
64
+ "params": [
65
+ "${new.user_seq}"
66
+ ],
48
67
  "assign_to": "recent_history"
49
68
  }
50
69
  ]
@@ -1,27 +1,37 @@
1
1
  {
2
2
  "name": "post",
3
3
  "description": "entity 훅 예제 — after_get/after_list 시 관련 엔티티 데이터를 자동 주입",
4
- "index": {
4
+ "fields": {
5
5
  "author_seq": {
6
+ "index": true,
6
7
  "comment": "작성자 user seq",
7
8
  "required": true
8
9
  },
9
10
  "title": {
11
+ "index": true,
10
12
  "comment": "제목",
11
13
  "required": true
12
14
  },
13
15
  "status": {
16
+ "index": true,
14
17
  "comment": "상태",
15
- "type": ["draft", "published", "hidden"],
18
+ "type": [
19
+ "draft",
20
+ "published",
21
+ "hidden"
22
+ ],
16
23
  "default": "draft"
17
24
  },
18
25
  "comment_count": {
26
+ "index": true,
19
27
  "comment": "댓글 수 (*_count → INT 자동 추론)"
20
28
  },
21
29
  "like_count": {
30
+ "index": true,
22
31
  "comment": "좋아요 수 (*_count → INT 자동 추론)"
23
32
  },
24
33
  "published_at": {
34
+ "index": true,
25
35
  "comment": "게시일시 (*_at → DATETIME 자동 추론)"
26
36
  }
27
37
  },
@@ -1,28 +1,37 @@
1
1
  {
2
2
  "name": "project",
3
3
  "description": "submit & delete 훅 예제 — 프로젝트 생성 시 기본 태스크 자동 생성, 삭제 시 연관 데이터 정리",
4
- "index": {
4
+ "fields": {
5
5
  "owner_seq": {
6
+ "index": true,
6
7
  "comment": "프로젝트 소유자 user seq",
7
8
  "required": true
8
9
  },
9
10
  "name": {
11
+ "index": true,
10
12
  "comment": "프로젝트명",
11
13
  "required": true
12
14
  },
13
15
  "status": {
16
+ "index": true,
14
17
  "comment": "진행 상태",
15
- "type": ["planning", "active", "on_hold", "completed", "cancelled"],
18
+ "type": [
19
+ "planning",
20
+ "active",
21
+ "on_hold",
22
+ "completed",
23
+ "cancelled"
24
+ ],
16
25
  "default": "planning"
17
26
  },
18
27
  "due_date": {
28
+ "index": true,
19
29
  "comment": "마감일 (*_date → DATE 자동 추론)"
20
30
  },
21
31
  "task_count": {
32
+ "index": true,
22
33
  "comment": "태스크 수 (*_count → INT 자동 추론)"
23
- }
24
- },
25
- "fields": {
34
+ },
26
35
  "description": {
27
36
  "type": "text",
28
37
  "comment": "프로젝트 설명"
@@ -1,34 +1,48 @@
1
1
  {
2
2
  "name": "payment",
3
3
  "description": "webhook 훅 예제 — 결제 완료/환불 시 외부 정산 서비스 실시간 통보",
4
- "index": {
4
+ "fields": {
5
5
  "order_seq": {
6
+ "index": true,
6
7
  "comment": "주문 seq",
7
8
  "required": true
8
9
  },
9
10
  "user_seq": {
11
+ "index": true,
10
12
  "comment": "결제자 user seq",
11
13
  "required": true
12
14
  },
13
15
  "amount": {
16
+ "index": true,
14
17
  "comment": "결제 금액 (*_amount → DECIMAL(15,2) 자동 추론)",
15
18
  "required": true
16
19
  },
17
20
  "method": {
21
+ "index": true,
18
22
  "comment": "결제 수단",
19
- "type": ["card", "bank_transfer", "virtual_account", "point"],
23
+ "type": [
24
+ "card",
25
+ "bank_transfer",
26
+ "virtual_account",
27
+ "point"
28
+ ],
20
29
  "required": true
21
30
  },
22
31
  "status": {
32
+ "index": true,
23
33
  "comment": "결제 상태",
24
- "type": ["pending", "paid", "cancelled", "refunded"],
34
+ "type": [
35
+ "pending",
36
+ "paid",
37
+ "cancelled",
38
+ "refunded"
39
+ ],
25
40
  "default": "pending"
26
41
  },
27
42
  "paid_at": {
43
+ "index": true,
28
44
  "comment": "결제 완료일시 (*_at → DATETIME 자동 추론)"
29
- }
30
- },
31
- "fields": {
45
+ },
32
46
  "pg_transaction_id": {
33
47
  "type": "varchar(100)",
34
48
  "comment": "PG사 거래 ID"
@@ -1,25 +1,36 @@
1
1
  {
2
2
  "name": "delivery",
3
3
  "description": "push 훅 예제 — 배송 상태 변경 시 고객에게 푸시 알림 전송 (FCM / APNs 공통, 다단계 상태 알림)",
4
- "index": {
4
+ "fields": {
5
5
  "order_seq": {
6
+ "index": true,
6
7
  "comment": "주문 seq",
7
8
  "required": true
8
9
  },
9
10
  "customer_seq": {
11
+ "index": true,
10
12
  "comment": "고객 user seq",
11
13
  "required": true
12
14
  },
13
15
  "tracking_number": {
16
+ "index": true,
14
17
  "comment": "운송장 번호",
15
18
  "unique": true
16
19
  },
17
20
  "carrier": {
21
+ "index": true,
18
22
  "comment": "택배사",
19
- "type": ["cj", "lotte", "hanjin", "post", "direct"],
23
+ "type": [
24
+ "cj",
25
+ "lotte",
26
+ "hanjin",
27
+ "post",
28
+ "direct"
29
+ ],
20
30
  "default": "cj"
21
31
  },
22
32
  "status": {
33
+ "index": true,
23
34
  "comment": "배송 상태",
24
35
  "type": [
25
36
  "ready",
@@ -32,9 +43,11 @@
32
43
  "default": "ready"
33
44
  },
34
45
  "estimated_date": {
46
+ "index": true,
35
47
  "comment": "예상 도착일 (*_date → DATE 자동 추론)"
36
48
  },
37
49
  "delivered_at": {
50
+ "index": true,
38
51
  "comment": "배송 완료일시 (*_at → DATETIME 자동 추론)"
39
52
  }
40
53
  },
@@ -4,18 +4,22 @@
4
4
  "read_only": true,
5
5
  "hard_delete": true,
6
6
  "history_ttl": 0,
7
- "index": {
7
+ "fields": {
8
8
  "actor_seq": {
9
+ "index": true,
9
10
  "comment": "행위자 user seq (null = 시스템)"
10
11
  },
11
12
  "entity_name": {
13
+ "index": true,
12
14
  "comment": "대상 엔티티명",
13
15
  "required": true
14
16
  },
15
17
  "entity_seq": {
18
+ "index": true,
16
19
  "comment": "대상 레코드 seq"
17
20
  },
18
21
  "action": {
22
+ "index": true,
19
23
  "comment": "수행된 작업",
20
24
  "type": [
21
25
  "INSERT",
@@ -29,15 +33,15 @@
29
33
  "required": true
30
34
  },
31
35
  "ip_address": {
36
+ "index": true,
32
37
  "comment": "요청 IP",
33
38
  "type": "varchar(45)"
34
39
  },
35
40
  "result_code": {
41
+ "index": true,
36
42
  "comment": "결과 코드 (HTTP 상태)",
37
43
  "type": "int"
38
- }
39
- },
40
- "fields": {
44
+ },
41
45
  "before_snapshot": {
42
46
  "type": "json",
43
47
  "comment": "변경 전 데이터 스냅샷"
@@ -2,28 +2,39 @@
2
2
  "name": "inventory",
3
3
  "description": "optimistic_lock 예제 — 동시 수정 충돌 방지가 필요한 재고 엔티티",
4
4
  "optimistic_lock": true,
5
- "index": {
5
+ "fields": {
6
6
  "product_seq": {
7
+ "index": true,
7
8
  "comment": "상품 seq",
8
9
  "required": true,
9
10
  "unique": true
10
11
  },
11
12
  "warehouse_code": {
13
+ "index": true,
12
14
  "comment": "창고 코드",
13
15
  "required": true
14
16
  },
15
17
  "qty_available": {
18
+ "index": true,
16
19
  "comment": "가용 재고 수량 (*_qty → INT 자동 추론)"
17
20
  },
18
21
  "qty_reserved": {
22
+ "index": true,
19
23
  "comment": "예약된 재고 수량 (*_qty → INT 자동 추론)"
20
24
  },
21
25
  "location": {
26
+ "index": true,
22
27
  "comment": "창고 내 위치 (예: A-01-03)"
23
28
  },
24
29
  "last_stocked_at": {
30
+ "index": true,
25
31
  "comment": "마지막 입고일시 (*_at → DATETIME 자동 추론)"
26
32
  }
27
33
  },
28
- "unique": [["product_seq", "warehouse_code"]]
34
+ "unique": [
35
+ [
36
+ "product_seq",
37
+ "warehouse_code"
38
+ ]
39
+ ]
29
40
  }
@@ -1,19 +1,23 @@
1
1
  {
2
2
  "name": "country",
3
3
  "description": "reset_defaults 예제 — reset-all 실행 시 주요 국가 코드 자동 시딩",
4
- "index": {
4
+ "fields": {
5
5
  "code": {
6
+ "index": true,
6
7
  "comment": "ISO 3166-1 alpha-2 국가 코드 (예: KR, US)",
7
8
  "required": true,
8
9
  "unique": true
9
10
  },
10
11
  "name_ko": {
12
+ "index": true,
11
13
  "comment": "국가명 (한국어)"
12
14
  },
13
15
  "name_en": {
16
+ "index": true,
14
17
  "comment": "국가명 (영어)"
15
18
  },
16
19
  "region": {
20
+ "index": true,
17
21
  "comment": "대륙/지역",
18
22
  "type": [
19
23
  "asia",
@@ -25,9 +29,11 @@
25
29
  ]
26
30
  },
27
31
  "phone_code": {
32
+ "index": true,
28
33
  "comment": "국가 전화 코드 (예: +82)"
29
34
  },
30
35
  "is_active": {
36
+ "index": true,
31
37
  "comment": "서비스 지원 여부 (is_* → TINYINT(1) 자동 추론)",
32
38
  "default": true
33
39
  }
@@ -2,34 +2,43 @@
2
2
  "name": "organization",
3
3
  "description": "isolated: license 예제 — 이 엔티티가 테넌트(라이선스) 경계를 정의하는 루트 엔티티. license_seq FK 없이 license_seq 컬럼을 직접 소유",
4
4
  "isolated": "license",
5
- "index": {
5
+ "fields": {
6
6
  "name": {
7
+ "index": true,
7
8
  "comment": "조직명",
8
9
  "required": true,
9
10
  "unique": true
10
11
  },
11
12
  "plan": {
13
+ "index": true,
12
14
  "comment": "구독 플랜",
13
- "type": ["free", "starter", "pro", "enterprise"],
15
+ "type": [
16
+ "free",
17
+ "starter",
18
+ "pro",
19
+ "enterprise"
20
+ ],
14
21
  "default": "free"
15
22
  },
16
23
  "max_members": {
24
+ "index": true,
17
25
  "comment": "최대 팀원 수",
18
26
  "type": "uint",
19
27
  "default": 5
20
28
  },
21
29
  "owner_seq": {
30
+ "index": true,
22
31
  "comment": "소유자 account seq"
23
32
  },
24
33
  "is_active": {
34
+ "index": true,
25
35
  "comment": "활성 여부 (is_* → TINYINT(1) 자동 추론)",
26
36
  "default": true
27
37
  },
28
38
  "expires_at": {
39
+ "index": true,
29
40
  "comment": "구독 만료일시 (*_at → DATETIME 자동 추론)"
30
- }
31
- },
32
- "fields": {
41
+ },
33
42
  "billing_email": {
34
43
  "type": "varchar(255)",
35
44
  "comment": "청구용 이메일"
@@ -38,7 +47,11 @@
38
47
  "comment": "조직 설정 (중첩 fields 그룹)",
39
48
  "fields": {
40
49
  "theme": {
41
- "type": ["light", "dark", "system"],
50
+ "type": [
51
+ "light",
52
+ "dark",
53
+ "system"
54
+ ],
42
55
  "comment": "기본 UI 테마",
43
56
  "default": "system"
44
57
  },
@@ -1,18 +1,99 @@
1
1
  #!/bin/bash
2
2
 
3
+ set -e
4
+ set -o pipefail
5
+
3
6
  # Reset all entity tables and seed default data
4
7
 
5
8
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
9
  PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
10
+ RESET_LOG=""
11
+
12
+ cleanup() {
13
+ if [ -n "$RESET_LOG" ] && [ -f "$RESET_LOG" ]; then
14
+ rm -f "$RESET_LOG"
15
+ fi
16
+ }
17
+
18
+ trap cleanup EXIT
7
19
 
8
20
  cd "$PROJECT_ROOT"
9
21
 
10
22
  # Load language from .env
11
23
  if [ -f .env ]; then
12
- LANGUAGE=$(grep '^LANGUAGE=' .env | cut -d '=' -f2)
24
+ LANGUAGE=$(grep '^LANGUAGE=' .env | cut -d '=' -f2 || true)
13
25
  fi
14
26
  LANGUAGE=${LANGUAGE:-ko}
15
27
 
28
+ get_env_value() {
29
+ local key="$1"
30
+ local value="${!key}"
31
+
32
+ if [ -n "$value" ]; then
33
+ echo "$value"
34
+ return
35
+ fi
36
+
37
+ if [ -f .env ]; then
38
+ value=$(grep -E "^${key}=" .env | tail -n 1 | cut -d '=' -f2-)
39
+ echo "$value"
40
+ fi
41
+ }
42
+
43
+ get_database_default_group() {
44
+ grep -E '"default"[[:space:]]*:' "$PROJECT_ROOT/configs/database.json" \
45
+ | head -n 1 \
46
+ | sed -E 's/.*:[[:space:]]*"([^"]+)".*/\1/'
47
+ }
48
+
49
+ get_database_group_field() {
50
+ local group="$1"
51
+ local field="$2"
52
+
53
+ awk -v group="$group" -v field="$field" '
54
+ $0 ~ "^[[:space:]]*\"" group "\"[[:space:]]*:[[:space:]]*\\{" { in_group=1; next }
55
+ in_group && $0 ~ "^[[:space:]]*}" { exit }
56
+ in_group && $0 ~ "^[[:space:]]*\"" field "\"[[:space:]]*:" {
57
+ match($0, /"[^"]+"[[:space:]]*:[[:space:]]*"([^"]+)"/, arr)
58
+ if (arr[1] != "") {
59
+ print arr[1]
60
+ }
61
+ exit
62
+ }
63
+ ' "$PROJECT_ROOT/configs/database.json"
64
+ }
65
+
66
+ resolve_database_name() {
67
+ local group="$1"
68
+ local raw_value
69
+ raw_value=$(get_database_group_field "$group" "database")
70
+
71
+ if [[ "$raw_value" =~ ^\$\{([A-Z0-9_]+)\}$ ]]; then
72
+ get_env_value "${BASH_REMATCH[1]}"
73
+ return
74
+ fi
75
+
76
+ echo "$raw_value"
77
+ }
78
+
79
+ print_target_database() {
80
+ local group
81
+ local database_name
82
+
83
+ group=$(get_database_default_group)
84
+ database_name=$(resolve_database_name "$group")
85
+
86
+ echo ""
87
+ if [ "$LANGUAGE" = "en" ]; then
88
+ echo "Target database group: ${group:-<unknown>}"
89
+ echo "Target database name : ${database_name:-<unknown>}"
90
+ else
91
+ echo "대상 DB 그룹 : ${group:-<unknown>}"
92
+ echo "대상 DB 이름 : ${database_name:-<unknown>}"
93
+ fi
94
+ echo ""
95
+ }
96
+
16
97
  # Show usage if no arguments
17
98
  if [ $# -eq 0 ]; then
18
99
  if [ "$LANGUAGE" = "en" ]; then
@@ -66,9 +147,11 @@ fi
66
147
  # Execute based on flag
67
148
  case "$1" in
68
149
  --dry-run)
150
+ print_target_database
69
151
  "$PROJECT_ROOT/bin/entity-cli" reset-all
70
152
  ;;
71
153
  --force|--apply)
154
+ print_target_database
72
155
  # 필수 엔티티 없으면 자동 생성 (api_keys, rbac_roles, account, user)
73
156
  if [ "$LANGUAGE" = "en" ]; then
74
157
  echo "⚙️ Checking required entities..."
@@ -76,10 +159,54 @@ case "$1" in
76
159
  echo "⚙️ 필수 엔티티 확인 중..."
77
160
  fi
78
161
  LANGUAGE="$LANGUAGE" "$SCRIPT_DIR/normalize-entities.sh" --apply
162
+
163
+ RESET_LOG=$(mktemp)
79
164
  if [ "$1" = "--force" ]; then
80
- "$PROJECT_ROOT/bin/entity-cli" reset-all --apply --force
165
+ set +e
166
+ "$PROJECT_ROOT/bin/entity-cli" reset-all --apply --force 2>&1 | tee "$RESET_LOG"
167
+ RESET_STATUS=${PIPESTATUS[0]}
168
+ set -e
81
169
  else
82
- "$PROJECT_ROOT/bin/entity-cli" reset-all --apply
170
+ set +e
171
+ "$PROJECT_ROOT/bin/entity-cli" reset-all --apply 2>&1 | tee "$RESET_LOG"
172
+ RESET_STATUS=${PIPESTATUS[0]}
173
+ set -e
174
+ fi
175
+
176
+ if [ "$RESET_STATUS" -ne 0 ]; then
177
+ exit "$RESET_STATUS"
178
+ fi
179
+
180
+ if ! grep -q "Reset completed successfully!" "$RESET_LOG"; then
181
+ exit 0
182
+ fi
183
+
184
+ # 새로 생성된 API 키 조회 후 .env 업데이트
185
+ NEW_API_KEY=$("$PROJECT_ROOT/bin/entity-cli" api-key show --seq=1 --reveal-secret 2>/dev/null | grep -E '^key_value' | awk '{print $NF}')
186
+ NEW_HMAC=$("$PROJECT_ROOT/bin/entity-cli" api-key show --seq=1 --reveal-secret 2>/dev/null | grep -E '^hmac_secret' | awk '{print $NF}')
187
+
188
+ if [ -n "$NEW_API_KEY" ] && [ -n "$NEW_HMAC" ]; then
189
+ echo ""
190
+ if [ "$LANGUAGE" = "en" ]; then
191
+ echo "🔑 New API Key generated:"
192
+ else
193
+ echo "🔑 새 API 키가 생성되었습니다:"
194
+ fi
195
+ echo " ENTITY_API_KEY = $NEW_API_KEY"
196
+ echo " ENTITY_HMAC_SECRET = $NEW_HMAC"
197
+
198
+ # 게이트웨이 .env 자동 업데이트 (개발 환경: entity-app-server/ 폴더가 같은 레벨에 있을 때만)
199
+ GW_DIR="$(dirname "$PROJECT_ROOT")/entity-app-server"
200
+ GW_ENV="$GW_DIR/.env"
201
+ if [ -d "$GW_DIR" ] && [ -f "$GW_ENV" ]; then
202
+ sed -i "s|^ENTITY_API_KEY=.*|ENTITY_API_KEY=$NEW_API_KEY|" "$GW_ENV"
203
+ sed -i "s|^ENTITY_HMAC_SECRET=.*|ENTITY_HMAC_SECRET=$NEW_HMAC|" "$GW_ENV"
204
+ if [ "$LANGUAGE" = "en" ]; then
205
+ echo " ✓ Updated: entity-app-server/.env"
206
+ else
207
+ echo " ✓ 업데이트 완료: entity-app-server/.env"
208
+ fi
209
+ fi
83
210
  fi
84
211
  ;;
85
212
  *)