create-entity-server 0.0.15 → 0.0.25
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/bin/create.js +15 -7
- package/package.json +1 -1
- package/template/.env.example +8 -7
- package/template/configs/database.json +173 -10
- package/template/entities/Account/account_audit.json +4 -5
- package/template/entities/System/system_audit_log.json +14 -8
- package/template/samples/README.md +28 -22
- package/template/samples/browser/entity-server-client.js +453 -0
- package/template/samples/browser/example.html +498 -0
- package/template/samples/entities/02_types_and_defaults.json +15 -16
- package/template/samples/entities/04_fk_and_composite_unique.json +0 -2
- package/template/samples/entities/05_cache.json +9 -8
- package/template/samples/entities/06_history_and_hard_delete.json +27 -9
- package/template/samples/entities/07_license_scope.json +40 -31
- package/template/samples/entities/09_hook_entity.json +0 -6
- package/template/samples/entities/10_hook_submit_delete.json +5 -2
- package/template/samples/entities/11_hook_webhook.json +9 -7
- package/template/samples/entities/12_hook_push.json +3 -3
- package/template/samples/entities/13_read_only.json +13 -10
- package/template/samples/entities/15_reset_defaults.json +0 -1
- package/template/samples/entities/16_isolated_license.json +62 -0
- package/template/samples/entities/README.md +36 -39
- package/template/samples/flutter/lib/entity_server_client.dart +170 -48
- package/template/samples/java/EntityServerClient.java +208 -61
- package/template/samples/java/EntityServerExample.java +4 -3
- package/template/samples/kotlin/EntityServerClient.kt +175 -45
- package/template/samples/node/src/EntityServerClient.js +232 -59
- package/template/samples/node/src/example.js +9 -9
- package/template/samples/php/ci4/Config/EntityServer.php +0 -1
- package/template/samples/php/ci4/Libraries/EntityServer.php +206 -53
- package/template/samples/php/laravel/Services/EntityServerService.php +190 -41
- package/template/samples/python/entity_server.py +181 -68
- package/template/samples/python/example.py +7 -6
- package/template/samples/react/src/example.tsx +41 -25
- package/template/samples/swift/EntityServerClient.swift +143 -37
- package/template/scripts/run.ps1 +12 -3
- package/template/scripts/run.sh +12 -8
- package/template/scripts/update-server.ps1 +68 -2
- package/template/scripts/update-server.sh +59 -2
- package/template/samples/entities/order_notification.json +0 -51
- package/template/samples/react/src/api/entityServerClient.ts +0 -413
- package/template/samples/react/src/hooks/useEntity.ts +0 -173
|
@@ -1,43 +1,52 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
3
|
-
"description": "license_scope 예제 —
|
|
4
|
-
"license_scope":
|
|
2
|
+
"name": "exchange_rate",
|
|
3
|
+
"description": "license_scope: false 예제 — 전 라이선스 공용 기준 데이터 (환율). license_seq 컬럼 없이 모든 테넌트가 동일 데이터 공유",
|
|
4
|
+
"license_scope": false,
|
|
5
5
|
"index": {
|
|
6
|
-
"
|
|
7
|
-
"comment": "
|
|
6
|
+
"base_currency": {
|
|
7
|
+
"comment": "기준 통화 (ISO 4217)",
|
|
8
|
+
"type": "varchar(3)",
|
|
8
9
|
"required": true
|
|
9
10
|
},
|
|
10
|
-
"
|
|
11
|
-
"comment": "
|
|
12
|
-
"type":
|
|
13
|
-
"
|
|
14
|
-
},
|
|
15
|
-
"max_members": {
|
|
16
|
-
"comment": "최대 팀원 수 (자동추론: 직접 uint 선언)"
|
|
11
|
+
"quote_currency": {
|
|
12
|
+
"comment": "환산 통화 (ISO 4217)",
|
|
13
|
+
"type": "varchar(3)",
|
|
14
|
+
"required": true
|
|
17
15
|
},
|
|
18
|
-
"
|
|
19
|
-
"comment": "
|
|
16
|
+
"rate": {
|
|
17
|
+
"comment": "환산 비율 (*_rate → 자동추론 없음, decimal 명시)",
|
|
18
|
+
"type": "decimal",
|
|
19
|
+
"required": true
|
|
20
20
|
},
|
|
21
|
-
"
|
|
22
|
-
"comment": "
|
|
23
|
-
"
|
|
21
|
+
"effective_date": {
|
|
22
|
+
"comment": "적용일 (*_date → DATE 자동 추론)",
|
|
23
|
+
"required": true
|
|
24
24
|
},
|
|
25
|
-
"
|
|
26
|
-
"comment": "
|
|
25
|
+
"source": {
|
|
26
|
+
"comment": "환율 출처",
|
|
27
|
+
"type": ["ecb", "openexchangerates", "manual"],
|
|
28
|
+
"default": "manual"
|
|
27
29
|
}
|
|
28
30
|
},
|
|
29
|
-
"types": {
|
|
30
|
-
"max_members": "uint",
|
|
31
|
-
"settings_json": "text"
|
|
32
|
-
},
|
|
33
|
-
"comments": {
|
|
34
|
-
"settings_json": "워크스페이스 설정 JSON"
|
|
35
|
-
},
|
|
36
|
-
"defaults": {
|
|
37
|
-
"max_members": 5
|
|
38
|
-
},
|
|
39
31
|
"cache": {
|
|
40
32
|
"enabled": true,
|
|
41
|
-
"ttl_seconds":
|
|
42
|
-
}
|
|
33
|
+
"ttl_seconds": 3600
|
|
34
|
+
},
|
|
35
|
+
"unique": [["base_currency", "quote_currency", "effective_date"]],
|
|
36
|
+
"reset_defaults": [
|
|
37
|
+
{
|
|
38
|
+
"base_currency": "USD",
|
|
39
|
+
"quote_currency": "KRW",
|
|
40
|
+
"rate": 1350.0,
|
|
41
|
+
"effective_date": "2025-01-01",
|
|
42
|
+
"source": "manual"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"base_currency": "EUR",
|
|
46
|
+
"quote_currency": "KRW",
|
|
47
|
+
"rate": 1480.0,
|
|
48
|
+
"effective_date": "2025-01-01",
|
|
49
|
+
"source": "manual"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
43
52
|
}
|
|
@@ -28,13 +28,15 @@
|
|
|
28
28
|
"comment": "결제 완료일시 (*_at → DATETIME 자동 추론)"
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
|
-
"
|
|
32
|
-
"pg_transaction_id":
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
31
|
+
"fields": {
|
|
32
|
+
"pg_transaction_id": {
|
|
33
|
+
"type": "varchar(100)",
|
|
34
|
+
"comment": "PG사 거래 ID"
|
|
35
|
+
},
|
|
36
|
+
"failure_reason": {
|
|
37
|
+
"type": "text",
|
|
38
|
+
"comment": "결제 실패 사유"
|
|
39
|
+
}
|
|
38
40
|
},
|
|
39
41
|
"hooks": {
|
|
40
42
|
"after_insert": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "delivery",
|
|
3
|
-
"description": "push 훅 예제 — 배송 상태 변경 시 고객에게 푸시 알림 전송 (다단계 상태 알림)",
|
|
3
|
+
"description": "push 훅 예제 — 배송 상태 변경 시 고객에게 푸시 알림 전송 (FCM / APNs 공통, 다단계 상태 알림)",
|
|
4
4
|
"index": {
|
|
5
5
|
"order_seq": {
|
|
6
6
|
"comment": "주문 seq",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
{
|
|
44
44
|
"comment": "배송 시작 푸시 알림",
|
|
45
45
|
"type": "push",
|
|
46
|
-
"
|
|
46
|
+
"target_account_seq": "customer_seq",
|
|
47
47
|
"title": "배송 시작",
|
|
48
48
|
"push_body": "주문 #${new.order_seq}의 배송이 시작되었습니다. 운송장: ${new.tracking_number}",
|
|
49
49
|
"push_data": {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
{
|
|
58
58
|
"comment": "배송 상태 변경 시 푸시 알림",
|
|
59
59
|
"type": "push",
|
|
60
|
-
"
|
|
60
|
+
"target_account_seq": "customer_seq",
|
|
61
61
|
"title": "배송 상태 업데이트",
|
|
62
62
|
"push_body": "배송 상태가 '${new.status}'(으)로 변경되었습니다. 운송장: ${new.tracking_number}",
|
|
63
63
|
"push_data": {
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"name": "activity_log",
|
|
3
3
|
"description": "read_only 예제 — API를 통한 수정·삭제가 불가하고 서버 내부(훅/SP) 로만 기록되는 감사 로그",
|
|
4
4
|
"read_only": true,
|
|
5
|
-
"license_scope": false,
|
|
6
5
|
"hard_delete": true,
|
|
7
6
|
"history_ttl": 0,
|
|
8
7
|
"index": {
|
|
@@ -38,14 +37,18 @@
|
|
|
38
37
|
"type": "int"
|
|
39
38
|
}
|
|
40
39
|
},
|
|
41
|
-
"
|
|
42
|
-
"before_snapshot":
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
"fields": {
|
|
41
|
+
"before_snapshot": {
|
|
42
|
+
"type": "json",
|
|
43
|
+
"comment": "변경 전 데이터 스냅샷"
|
|
44
|
+
},
|
|
45
|
+
"after_snapshot": {
|
|
46
|
+
"type": "json",
|
|
47
|
+
"comment": "변경 후 데이터 스냅샷"
|
|
48
|
+
},
|
|
49
|
+
"detail": {
|
|
50
|
+
"type": "text",
|
|
51
|
+
"comment": "작업 상세 설명"
|
|
52
|
+
}
|
|
50
53
|
}
|
|
51
54
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "organization",
|
|
3
|
+
"description": "isolated: license 예제 — 이 엔티티가 테넌트(라이선스) 경계를 정의하는 루트 엔티티. license_seq FK 없이 license_seq 컬럼을 직접 소유",
|
|
4
|
+
"isolated": "license",
|
|
5
|
+
"index": {
|
|
6
|
+
"name": {
|
|
7
|
+
"comment": "조직명",
|
|
8
|
+
"required": true,
|
|
9
|
+
"unique": true
|
|
10
|
+
},
|
|
11
|
+
"plan": {
|
|
12
|
+
"comment": "구독 플랜",
|
|
13
|
+
"type": ["free", "starter", "pro", "enterprise"],
|
|
14
|
+
"default": "free"
|
|
15
|
+
},
|
|
16
|
+
"max_members": {
|
|
17
|
+
"comment": "최대 팀원 수",
|
|
18
|
+
"type": "uint",
|
|
19
|
+
"default": 5
|
|
20
|
+
},
|
|
21
|
+
"owner_seq": {
|
|
22
|
+
"comment": "소유자 account seq"
|
|
23
|
+
},
|
|
24
|
+
"is_active": {
|
|
25
|
+
"comment": "활성 여부 (is_* → TINYINT(1) 자동 추론)",
|
|
26
|
+
"default": true
|
|
27
|
+
},
|
|
28
|
+
"expires_at": {
|
|
29
|
+
"comment": "구독 만료일시 (*_at → DATETIME 자동 추론)"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"fields": {
|
|
33
|
+
"billing_email": {
|
|
34
|
+
"type": "varchar(255)",
|
|
35
|
+
"comment": "청구용 이메일"
|
|
36
|
+
},
|
|
37
|
+
"settings": {
|
|
38
|
+
"comment": "조직 설정 (중첩 fields 그룹)",
|
|
39
|
+
"fields": {
|
|
40
|
+
"theme": {
|
|
41
|
+
"type": ["light", "dark", "system"],
|
|
42
|
+
"comment": "기본 UI 테마",
|
|
43
|
+
"default": "system"
|
|
44
|
+
},
|
|
45
|
+
"language": {
|
|
46
|
+
"type": "varchar(10)",
|
|
47
|
+
"comment": "기본 인터페이스 언어",
|
|
48
|
+
"default": "ko"
|
|
49
|
+
},
|
|
50
|
+
"timezone": {
|
|
51
|
+
"type": "varchar(50)",
|
|
52
|
+
"comment": "기본 타임존",
|
|
53
|
+
"default": "Asia/Seoul"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"cache": {
|
|
59
|
+
"enabled": true,
|
|
60
|
+
"ttl_seconds": 300
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
| 파일 | 엔티티 | 설명 |
|
|
16
16
|
| -------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
17
17
|
| [01_basic_fields.json](01_basic_fields.json) | `contact` | 필드명 패턴으로 타입이 **자동 추론**되는 모든 케이스 (`_seq`, `_date`, `_at`, `is_*`, `_count`, `_amount`, `email`, `phone`) |
|
|
18
|
-
| [02_types_and_defaults.json](02_types_and_defaults.json) | `product` | 자동 추론이 안 될 때 **`
|
|
18
|
+
| [02_types_and_defaults.json](02_types_and_defaults.json) | `product` | 자동 추론이 안 될 때 **`fields` 명시 선언** (`type`, `comment`, `default` 인라인) + `reset_defaults` 시딩 |
|
|
19
19
|
|
|
20
20
|
### 제약 & 참조
|
|
21
21
|
|
|
@@ -32,11 +32,12 @@
|
|
|
32
32
|
| [06_history_and_hard_delete.json](06_history_and_hard_delete.json) | `article` | **`history_ttl`** 수정 이력 3년 보관 + **`hard_delete: false`** 논리 삭제 |
|
|
33
33
|
| [14_optimistic_lock.json](14_optimistic_lock.json) | `inventory` | **`optimistic_lock`** 동시 수정 충돌 방지 (재고 등 경쟁 조건 있는 데이터) |
|
|
34
34
|
|
|
35
|
-
###
|
|
35
|
+
### 데이터 격리 & 공유
|
|
36
36
|
|
|
37
|
-
| 파일
|
|
38
|
-
|
|
|
39
|
-
| [07_license_scope.json](07_license_scope.json)
|
|
37
|
+
| 파일 | 엔티티 | 설명 |
|
|
38
|
+
| ---------------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
39
|
+
| [07_license_scope.json](07_license_scope.json) | `exchange_rate` | **`license_scope: false`** — 전 라이선스 **공용** 기준 데이터 (환율). `license_seq` 컬럼 없이 모든 테넌트가 공유 |
|
|
40
|
+
| [16_isolated_license.json](16_isolated_license.json) | `organization` | **`isolated: "license"`** — 테넌트 경계를 정의하는 루트 엔티티. `license_seq` FK 없이 직접 소유 (멀티테넌트 루트) |
|
|
40
41
|
|
|
41
42
|
### 특수 모드
|
|
42
43
|
|
|
@@ -47,48 +48,44 @@
|
|
|
47
48
|
|
|
48
49
|
### 훅 (Hooks)
|
|
49
50
|
|
|
50
|
-
| 파일 | 엔티티 | 훅 타입 | 설명
|
|
51
|
-
| -------------------------------------------------------- | ------------ | ------------------- |
|
|
52
|
-
| [08_hook_sql.json](08_hook_sql.json) | `user_point` | `sql` | 실행형 SQL (포인트 이력 INSERT) + 조회형 SQL (`assign_to`로 결과 주입)
|
|
53
|
-
| [09_hook_entity.json](09_hook_entity.json) | `post` | `entity` | `after_get`/`after_list`에서 관련 엔티티 자동 주입 (작성자 프로필, 댓글)
|
|
54
|
-
| [10_hook_submit_delete.json](10_hook_submit_delete.json) | `project` | `submit` / `delete` | 생성 시 연관 엔티티 자동 생성(Upsert 포함), 삭제 시 연관 데이터 자동 정리
|
|
55
|
-
| [11_hook_webhook.json](11_hook_webhook.json) | `payment` | `webhook` | 외부 HTTP 통보 — 비동기(결제 생성) + 동기(상태 변경)
|
|
56
|
-
| [12_hook_push.json](12_hook_push.json) | `delivery` | `push` | 배송 상태 변경 시 고객 FCM
|
|
57
|
-
|
|
58
|
-
### 이전 예제
|
|
59
|
-
|
|
60
|
-
| 파일 | 엔티티 | 설명 |
|
|
61
|
-
| -------------------------------------------------- | -------------------- | --------------------------------------------- |
|
|
62
|
-
| [order_notification.json](order_notification.json) | `order_notification` | 주문 생성/수정 시 push 훅 (push 훅 기본 예제) |
|
|
51
|
+
| 파일 | 엔티티 | 훅 타입 | 설명 |
|
|
52
|
+
| -------------------------------------------------------- | ------------ | ------------------- | ------------------------------------------------------------------------------- |
|
|
53
|
+
| [08_hook_sql.json](08_hook_sql.json) | `user_point` | `sql` | 실행형 SQL (포인트 이력 INSERT) + 조회형 SQL (`assign_to`로 결과 주입) |
|
|
54
|
+
| [09_hook_entity.json](09_hook_entity.json) | `post` | `entity` | `after_get`/`after_list`에서 관련 엔티티 자동 주입 (작성자 프로필, 댓글) |
|
|
55
|
+
| [10_hook_submit_delete.json](10_hook_submit_delete.json) | `project` | `submit` / `delete` | 생성 시 연관 엔티티 자동 생성(Upsert 포함), 삭제 시 연관 데이터 자동 정리 |
|
|
56
|
+
| [11_hook_webhook.json](11_hook_webhook.json) | `payment` | `webhook` | 외부 HTTP 통보 — 비동기(결제 생성) + 동기(상태 변경) |
|
|
57
|
+
| [12_hook_push.json](12_hook_push.json) | `delivery` | `push` | 배송 상태 변경 시 고객 푸시 알림 (FCM / APNs 공통, 등록된 모든 디바이스로 전송) |
|
|
63
58
|
|
|
64
59
|
---
|
|
65
60
|
|
|
66
61
|
## 훅 타입 한눈에 보기
|
|
67
62
|
|
|
68
|
-
| 훅 타입 | 핵심 필드
|
|
69
|
-
| --------- |
|
|
70
|
-
| `sql` | `query`, `params`
|
|
71
|
-
| `entity` | `entity`, `action`, `assign_to`
|
|
72
|
-
| `submit` | `entity`, `data`, `match`
|
|
73
|
-
| `delete` | `entity`, `match`
|
|
74
|
-
| `webhook` | `url`, `body`, `async`
|
|
75
|
-
| `push` | `
|
|
63
|
+
| 훅 타입 | 핵심 필드 | 주요 용도 | 샘플 |
|
|
64
|
+
| --------- | ------------------------------------------ | ------------------------- | ---------------------------- |
|
|
65
|
+
| `sql` | `query`, `params` | SQL 실행 또는 결과 주입 | `08_hook_sql.json` |
|
|
66
|
+
| `entity` | `entity`, `action`, `assign_to` | 관련 데이터 자동 로드 | `09_hook_entity.json` |
|
|
67
|
+
| `submit` | `entity`, `data`, `match` | 다른 엔티티 생성/수정 | `10_hook_submit_delete.json` |
|
|
68
|
+
| `delete` | `entity`, `match` | 다른 엔티티 삭제 | `10_hook_submit_delete.json` |
|
|
69
|
+
| `webhook` | `url`, `body`, `async` | 외부 HTTP 호출 | `11_hook_webhook.json` |
|
|
70
|
+
| `push` | `target_account_seq`, `title`, `push_body` | FCM / APNs 푸시 알림 전송 | `12_hook_push.json` |
|
|
76
71
|
|
|
77
72
|
## 훅 실행 시점
|
|
78
73
|
|
|
79
|
-
| 시점
|
|
80
|
-
|
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
74
|
+
| 시점 | 설명 | 주로 사용 |
|
|
75
|
+
| --------------- | --------------------- | -------------------------- |
|
|
76
|
+
| `before_insert` | 데이터 삽입 전 | 유효성 검사, 값 주입 |
|
|
77
|
+
| `after_insert` | 데이터 삽입 후 | 감사 로그, 알림, 연관 생성 |
|
|
78
|
+
| `before_update` | 데이터 수정 전 | 변경 검증, 권한 확인 |
|
|
79
|
+
| `after_update` | 데이터 수정 후 | 변경 이력, 상태 알림 |
|
|
80
|
+
| `before_delete` | 데이터 삭제 전 | 참조 무결성 확인 |
|
|
81
|
+
| `after_delete` | 데이터 삭제 후 | 연관 데이터 정리 |
|
|
82
|
+
| `after_get` | seq로 단건 조회 후 | 관련 데이터 병합 |
|
|
83
|
+
| `after_find` | 조건으로 단건 조회 후 | 관련 데이터 병합 |
|
|
84
|
+
| `after_list` | 목록 조회 후 | 각 항목 추가 정보 주입 |
|
|
86
85
|
|
|
87
86
|
## 훅 템플릿 변수
|
|
88
87
|
|
|
89
|
-
| 변수
|
|
90
|
-
|
|
|
91
|
-
| `${new.field}`
|
|
92
|
-
| `${old.field}`
|
|
93
|
-
| `${ctx.license_seq}` | 현재 요청의 라이선스 seq |
|
|
94
|
-
| `${ctx.user_seq}` | 현재 로그인 사용자 seq |
|
|
88
|
+
| 변수 | 설명 |
|
|
89
|
+
| -------------- | ----------------------------- |
|
|
90
|
+
| `${new.field}` | 삽입/수정 후 데이터의 필드 값 |
|
|
91
|
+
| `${old.field}` | 수정/삭제 전 데이터의 필드 값 |
|