@spfn/cms 0.1.0-alpha.7 → 0.1.0-alpha.70

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 (224) hide show
  1. package/README.md +28 -416
  2. package/dist/{helpers/locale.actions.d.ts → actions-BpTAYuBA.d.ts} +70 -7
  3. package/dist/actions.d.ts +2 -9
  4. package/dist/actions.js +97 -10
  5. package/dist/actions.js.map +1 -1
  6. package/dist/api.d.ts +214 -0
  7. package/dist/api.js +353 -0
  8. package/dist/api.js.map +1 -0
  9. package/dist/client.d.ts +136 -127
  10. package/dist/client.js +1199 -59
  11. package/dist/client.js.map +1 -1
  12. package/dist/{types.d.ts → index-Dh5FjWzR.d.ts} +45 -7
  13. package/dist/index.d.ts +108 -16
  14. package/dist/index.js +610 -23
  15. package/dist/index.js.map +1 -1
  16. package/dist/label-sync-generator-B0EmvtWM.d.ts +32 -0
  17. package/dist/lib/contracts/labels.d.ts +151 -0
  18. package/dist/lib/contracts/labels.js +168 -0
  19. package/dist/lib/contracts/labels.js.map +1 -0
  20. package/dist/lib/contracts/published-cache.d.ts +48 -0
  21. package/dist/lib/contracts/published-cache.js +49 -0
  22. package/dist/lib/contracts/published-cache.js.map +1 -0
  23. package/dist/lib/contracts/values.d.ts +71 -0
  24. package/dist/lib/contracts/values.js +103 -0
  25. package/dist/lib/contracts/values.js.map +1 -0
  26. package/dist/locale.constants-BMBK70YM.d.ts +104 -0
  27. package/dist/{entities → server/entities}/cms-audit-logs.d.ts +15 -70
  28. package/dist/server/entities/cms-audit-logs.js +78 -0
  29. package/dist/server/entities/cms-audit-logs.js.map +1 -0
  30. package/dist/{entities → server/entities}/cms-draft-cache.d.ts +13 -73
  31. package/dist/server/entities/cms-draft-cache.js +38 -0
  32. package/dist/server/entities/cms-draft-cache.js.map +1 -0
  33. package/dist/{entities → server/entities}/cms-label-values.d.ts +16 -67
  34. package/dist/server/entities/cms-label-values.js +81 -0
  35. package/dist/server/entities/cms-label-values.js.map +1 -0
  36. package/dist/{entities → server/entities}/cms-label-versions.d.ts +16 -49
  37. package/dist/server/entities/cms-label-versions.js +76 -0
  38. package/dist/server/entities/cms-label-versions.js.map +1 -0
  39. package/dist/{entities → server/entities}/cms-labels.d.ts +17 -14
  40. package/dist/server/entities/cms-labels.js +42 -0
  41. package/dist/server/entities/cms-labels.js.map +1 -0
  42. package/dist/{entities → server/entities}/cms-published-cache.d.ts +14 -69
  43. package/dist/server/entities/cms-published-cache.js +36 -0
  44. package/dist/server/entities/cms-published-cache.js.map +1 -0
  45. package/dist/server/entities/index.d.ts +7 -0
  46. package/dist/server/entities/index.js +218 -0
  47. package/dist/server/entities/index.js.map +1 -0
  48. package/dist/server/generators/index.d.ts +19 -0
  49. package/dist/server/generators/index.js +753 -0
  50. package/dist/server/generators/index.js.map +1 -0
  51. package/dist/server/labels/index.d.ts +1 -0
  52. package/dist/server/labels/index.js +32 -0
  53. package/dist/server/labels/index.js.map +1 -0
  54. package/dist/server/repositories/index.d.ts +209 -0
  55. package/dist/server/repositories/index.js +441 -0
  56. package/dist/server/repositories/index.js.map +1 -0
  57. package/dist/server/routes/labels/[id]/index.js +508 -0
  58. package/dist/server/routes/labels/[id]/index.js.map +1 -0
  59. package/dist/{routes/labels/[id] → server/routes/labels/_id_}/index.d.ts +5 -3
  60. package/dist/server/routes/labels/by-key/[key]/index.js +458 -0
  61. package/dist/server/routes/labels/by-key/[key]/index.js.map +1 -0
  62. package/dist/server/routes/labels/by-key/_key_/index.d.ts +10 -0
  63. package/dist/server/routes/labels/index.d.ts +12 -0
  64. package/dist/server/routes/labels/index.js +617 -0
  65. package/dist/server/routes/labels/index.js.map +1 -0
  66. package/dist/server/routes/published-cache/index.d.ts +11 -0
  67. package/dist/server/routes/published-cache/index.js +369 -0
  68. package/dist/server/routes/published-cache/index.js.map +1 -0
  69. package/dist/server/routes/values/[labelId]/[version]/index.js +479 -0
  70. package/dist/server/routes/values/[labelId]/[version]/index.js.map +1 -0
  71. package/dist/server/routes/values/[labelId]/index.js +474 -0
  72. package/dist/server/routes/values/[labelId]/index.js.map +1 -0
  73. package/dist/server/routes/values/_labelId_/_version_/index.d.ts +10 -0
  74. package/dist/server/routes/values/_labelId_/index.d.ts +10 -0
  75. package/dist/server.d.ts +78 -7
  76. package/dist/server.js +1752 -247
  77. package/dist/server.js.map +1 -1
  78. package/migrations/0000_init.sql +3 -0
  79. package/migrations/0001_far_lady_vermin.sql +86 -0
  80. package/migrations/0002_heavy_the_enforcers.sql +2 -0
  81. package/migrations/meta/0000_snapshot.json +15 -0
  82. package/migrations/meta/0001_snapshot.json +687 -0
  83. package/migrations/meta/0002_snapshot.json +686 -0
  84. package/migrations/meta/_journal.json +27 -0
  85. package/package.json +55 -36
  86. package/dist/actions.d.ts.map +0 -1
  87. package/dist/client.d.ts.map +0 -1
  88. package/dist/cms.config.d.ts +0 -77
  89. package/dist/cms.config.d.ts.map +0 -1
  90. package/dist/cms.config.js +0 -111
  91. package/dist/cms.config.js.map +0 -1
  92. package/dist/entities/cms-audit-logs.d.ts.map +0 -1
  93. package/dist/entities/cms-audit-logs.js +0 -103
  94. package/dist/entities/cms-audit-logs.js.map +0 -1
  95. package/dist/entities/cms-draft-cache.d.ts.map +0 -1
  96. package/dist/entities/cms-draft-cache.js +0 -112
  97. package/dist/entities/cms-draft-cache.js.map +0 -1
  98. package/dist/entities/cms-label-values.d.ts.map +0 -1
  99. package/dist/entities/cms-label-values.js +0 -105
  100. package/dist/entities/cms-label-values.js.map +0 -1
  101. package/dist/entities/cms-label-versions.d.ts.map +0 -1
  102. package/dist/entities/cms-label-versions.js +0 -80
  103. package/dist/entities/cms-label-versions.js.map +0 -1
  104. package/dist/entities/cms-labels.d.ts.map +0 -1
  105. package/dist/entities/cms-labels.js +0 -48
  106. package/dist/entities/cms-labels.js.map +0 -1
  107. package/dist/entities/cms-published-cache.d.ts.map +0 -1
  108. package/dist/entities/cms-published-cache.js +0 -103
  109. package/dist/entities/cms-published-cache.js.map +0 -1
  110. package/dist/entities/index.d.ts +0 -10
  111. package/dist/entities/index.d.ts.map +0 -1
  112. package/dist/entities/index.js +0 -10
  113. package/dist/entities/index.js.map +0 -1
  114. package/dist/generators/index.d.ts +0 -19
  115. package/dist/generators/index.d.ts.map +0 -1
  116. package/dist/generators/index.js +0 -19
  117. package/dist/generators/index.js.map +0 -1
  118. package/dist/generators/label-sync-generator.d.ts +0 -33
  119. package/dist/generators/label-sync-generator.d.ts.map +0 -1
  120. package/dist/generators/label-sync-generator.js +0 -87
  121. package/dist/generators/label-sync-generator.js.map +0 -1
  122. package/dist/helpers/locale.actions.d.ts.map +0 -1
  123. package/dist/helpers/locale.actions.js +0 -210
  124. package/dist/helpers/locale.actions.js.map +0 -1
  125. package/dist/helpers/locale.constants.d.ts +0 -10
  126. package/dist/helpers/locale.constants.d.ts.map +0 -1
  127. package/dist/helpers/locale.constants.js +0 -10
  128. package/dist/helpers/locale.constants.js.map +0 -1
  129. package/dist/helpers/locale.d.ts +0 -17
  130. package/dist/helpers/locale.d.ts.map +0 -1
  131. package/dist/helpers/locale.js +0 -20
  132. package/dist/helpers/locale.js.map +0 -1
  133. package/dist/helpers/sync.d.ts +0 -41
  134. package/dist/helpers/sync.d.ts.map +0 -1
  135. package/dist/helpers/sync.js +0 -309
  136. package/dist/helpers/sync.js.map +0 -1
  137. package/dist/index.d.ts.map +0 -1
  138. package/dist/init.d.ts +0 -31
  139. package/dist/init.d.ts.map +0 -1
  140. package/dist/init.js +0 -36
  141. package/dist/init.js.map +0 -1
  142. package/dist/labels/helpers.d.ts +0 -31
  143. package/dist/labels/helpers.d.ts.map +0 -1
  144. package/dist/labels/helpers.js +0 -60
  145. package/dist/labels/helpers.js.map +0 -1
  146. package/dist/labels/index.d.ts +0 -7
  147. package/dist/labels/index.d.ts.map +0 -1
  148. package/dist/labels/index.js +0 -7
  149. package/dist/labels/index.js.map +0 -1
  150. package/dist/repositories/cms-draft-cache.repository.d.ts +0 -62
  151. package/dist/repositories/cms-draft-cache.repository.d.ts.map +0 -1
  152. package/dist/repositories/cms-draft-cache.repository.js +0 -56
  153. package/dist/repositories/cms-draft-cache.repository.js.map +0 -1
  154. package/dist/repositories/cms-label-values.repository.d.ts +0 -32
  155. package/dist/repositories/cms-label-values.repository.d.ts.map +0 -1
  156. package/dist/repositories/cms-label-values.repository.js +0 -72
  157. package/dist/repositories/cms-label-values.repository.js.map +0 -1
  158. package/dist/repositories/cms-labels.repository.d.ts +0 -53
  159. package/dist/repositories/cms-labels.repository.d.ts.map +0 -1
  160. package/dist/repositories/cms-labels.repository.js +0 -77
  161. package/dist/repositories/cms-labels.repository.js.map +0 -1
  162. package/dist/repositories/cms-published-cache.repository.d.ts +0 -53
  163. package/dist/repositories/cms-published-cache.repository.d.ts.map +0 -1
  164. package/dist/repositories/cms-published-cache.repository.js +0 -54
  165. package/dist/repositories/cms-published-cache.repository.js.map +0 -1
  166. package/dist/repositories/index.d.ts +0 -8
  167. package/dist/repositories/index.d.ts.map +0 -1
  168. package/dist/repositories/index.js +0 -9
  169. package/dist/repositories/index.js.map +0 -1
  170. package/dist/routes/labels/[id]/contract.d.ts +0 -68
  171. package/dist/routes/labels/[id]/contract.d.ts.map +0 -1
  172. package/dist/routes/labels/[id]/contract.js +0 -84
  173. package/dist/routes/labels/[id]/contract.js.map +0 -1
  174. package/dist/routes/labels/[id]/index.d.ts.map +0 -1
  175. package/dist/routes/labels/[id]/index.js +0 -96
  176. package/dist/routes/labels/[id]/index.js.map +0 -1
  177. package/dist/routes/labels/by-key/[key]/contract.d.ts +0 -24
  178. package/dist/routes/labels/by-key/[key]/contract.d.ts.map +0 -1
  179. package/dist/routes/labels/by-key/[key]/contract.js +0 -28
  180. package/dist/routes/labels/by-key/[key]/contract.js.map +0 -1
  181. package/dist/routes/labels/by-key/[key]/index.d.ts +0 -8
  182. package/dist/routes/labels/by-key/[key]/index.d.ts.map +0 -1
  183. package/dist/routes/labels/by-key/[key]/index.js +0 -32
  184. package/dist/routes/labels/by-key/[key]/index.js.map +0 -1
  185. package/dist/routes/labels/contract.d.ts +0 -59
  186. package/dist/routes/labels/contract.d.ts.map +0 -1
  187. package/dist/routes/labels/contract.js +0 -75
  188. package/dist/routes/labels/contract.js.map +0 -1
  189. package/dist/routes/labels/index.d.ts +0 -10
  190. package/dist/routes/labels/index.d.ts.map +0 -1
  191. package/dist/routes/labels/index.js +0 -73
  192. package/dist/routes/labels/index.js.map +0 -1
  193. package/dist/routes/published-cache/contract.d.ts +0 -25
  194. package/dist/routes/published-cache/contract.d.ts.map +0 -1
  195. package/dist/routes/published-cache/contract.js +0 -35
  196. package/dist/routes/published-cache/contract.js.map +0 -1
  197. package/dist/routes/published-cache/index.d.ts +0 -8
  198. package/dist/routes/published-cache/index.d.ts.map +0 -1
  199. package/dist/routes/published-cache/index.js +0 -33
  200. package/dist/routes/published-cache/index.js.map +0 -1
  201. package/dist/routes/values/[labelId]/[version]/contract.d.ts +0 -29
  202. package/dist/routes/values/[labelId]/[version]/contract.d.ts.map +0 -1
  203. package/dist/routes/values/[labelId]/[version]/contract.js +0 -33
  204. package/dist/routes/values/[labelId]/[version]/contract.js.map +0 -1
  205. package/dist/routes/values/[labelId]/[version]/index.d.ts +0 -8
  206. package/dist/routes/values/[labelId]/[version]/index.d.ts.map +0 -1
  207. package/dist/routes/values/[labelId]/[version]/index.js +0 -45
  208. package/dist/routes/values/[labelId]/[version]/index.js.map +0 -1
  209. package/dist/routes/values/[labelId]/contract.d.ts +0 -38
  210. package/dist/routes/values/[labelId]/contract.d.ts.map +0 -1
  211. package/dist/routes/values/[labelId]/contract.js +0 -59
  212. package/dist/routes/values/[labelId]/contract.js.map +0 -1
  213. package/dist/routes/values/[labelId]/index.d.ts +0 -8
  214. package/dist/routes/values/[labelId]/index.d.ts.map +0 -1
  215. package/dist/routes/values/[labelId]/index.js +0 -42
  216. package/dist/routes/values/[labelId]/index.js.map +0 -1
  217. package/dist/server.d.ts.map +0 -1
  218. package/dist/store.d.ts +0 -87
  219. package/dist/store.d.ts.map +0 -1
  220. package/dist/store.js +0 -205
  221. package/dist/store.js.map +0 -1
  222. package/dist/types.d.ts.map +0 -1
  223. package/dist/types.js +0 -7
  224. package/dist/types.js.map +0 -1
package/dist/client.js CHANGED
@@ -1,62 +1,1202 @@
1
- /**
2
- * @spfn/cms/client
3
- *
4
- * Client Components Only
5
- * 클라이언트 컴포넌트 전용 (브라우저에서 실행)
6
- */
7
- import { client } from '@spfn/core/client';
8
- // Labels
9
- import { getLabelsContract, createLabelContract } from './routes/labels/contract';
10
- import { getLabelContract, updateLabelContract, deleteLabelContract } from './routes/labels/[id]/contract';
11
- // Published Cache
12
- import { getPublishedCacheContract } from './routes/published-cache/contract';
13
- /**
14
- * CMS API Client
15
- */
16
- export const cmsApi = {
17
- /**
18
- * Labels API
19
- */
20
- labels: {
21
- /**
22
- * GET /cms/labels
23
- * 라벨 목록 조회 (섹션 필터, 페이지네이션)
24
- */
25
- list: (options) => client.call('/cms/labels', getLabelsContract, options),
26
- /**
27
- * GET /cms/labels/:id
28
- * 특정 라벨 조회
29
- */
30
- getById: (options) => client.call('/cms/labels/:id', getLabelContract, options),
31
- /**
32
- * POST /cms/labels
33
- * 새 라벨 생성
34
- */
35
- create: (options) => client.call('/cms/labels', createLabelContract, options),
36
- /**
37
- * PATCH /cms/labels/:id
38
- * 라벨 업데이트
39
- */
40
- update: (options) => client.call('/cms/labels/:id', updateLabelContract, options),
41
- /**
42
- * DELETE /cms/labels/:id
43
- * 라벨 삭제
44
- */
45
- delete: (options) => client.call('/cms/labels/:id', deleteLabelContract, options),
46
- },
47
- /**
48
- * Published Cache API
49
- */
50
- publishedCache: {
51
- /**
52
- * GET /cms/published-cache
53
- * 발행된 콘텐츠 캐시 조회
54
- */
55
- get: (options) => client.call('/cms/published-cache', getPublishedCacheContract, options),
1
+ // src/client/hooks/useSection.ts
2
+ import React from "react";
3
+
4
+ // src/client/store/cms.store.ts
5
+ import { create } from "zustand";
6
+
7
+ // src/api/index.ts
8
+ import { client as client5 } from "@spfn/core/client";
9
+
10
+ // src/api/cms-labels.ts
11
+ import { client } from "@spfn/core/client";
12
+
13
+ // src/lib/contracts/labels.ts
14
+ import { Type } from "@sinclair/typebox";
15
+ var getLabelsContract = {
16
+ method: "GET",
17
+ path: "/_cms/labels",
18
+ query: Type.Object({
19
+ section: Type.Optional(Type.String({ description: "\uC139\uC158\uC73C\uB85C \uD544\uD130\uB9C1 (\uC608: home, why-futureplay)" })),
20
+ limit: Type.Optional(Type.Number({ minimum: 1, maximum: 100, default: 20, description: "\uD398\uC774\uC9C0\uB2F9 \uD56D\uBAA9 \uC218" })),
21
+ offset: Type.Optional(Type.Number({ minimum: 0, default: 0, description: "\uC2DC\uC791 \uC624\uD504\uC14B" })),
22
+ includeDefaultValues: Type.Optional(Type.Boolean({ description: "\uAE30\uBCF8\uAC12 \uD3EC\uD568 \uC5EC\uBD80", default: false }))
23
+ }),
24
+ response: Type.Object({
25
+ labels: Type.Array(Type.Object({
26
+ id: Type.Number(),
27
+ key: Type.String(),
28
+ section: Type.String(),
29
+ type: Type.String(),
30
+ publishedVersion: Type.Union([Type.Number(), Type.Null()]),
31
+ createdBy: Type.Union([Type.String(), Type.Null()]),
32
+ createdAt: Type.String(),
33
+ updatedAt: Type.String(),
34
+ defaultValue: Type.Optional(Type.Any({ description: "\uB77C\uBCA8 \uC815\uC758 \uD30C\uC77C\uC758 \uAE30\uBCF8\uAC12" }))
35
+ })),
36
+ total: Type.Number(),
37
+ limit: Type.Number(),
38
+ offset: Type.Number()
39
+ })
40
+ };
41
+ var createLabelContract = {
42
+ method: "POST",
43
+ path: "/_cms/labels",
44
+ body: Type.Object({
45
+ key: Type.String({
46
+ description: "\uACE0\uC720 \uD0A4 (\uC608: home.hero.title)",
47
+ pattern: "^[a-z0-9-]+\\.[a-z0-9-]+\\.[a-z0-9-]+$"
48
+ }),
49
+ section: Type.String({
50
+ description: "\uC139\uC158 \uC774\uB984 (\uC608: home, why-futureplay)",
51
+ pattern: "^[a-z0-9-]+$"
52
+ }),
53
+ type: Type.Union([
54
+ Type.Literal("text"),
55
+ Type.Literal("image"),
56
+ Type.Literal("video"),
57
+ Type.Literal("file"),
58
+ Type.Literal("object")
59
+ ], { description: "\uAC12 \uD0C0\uC785" }),
60
+ createdBy: Type.Optional(Type.String({ description: "\uC0DD\uC131\uC790 ID" }))
61
+ }),
62
+ response: Type.Union([
63
+ Type.Object({
64
+ id: Type.Number(),
65
+ key: Type.String(),
66
+ section: Type.String(),
67
+ type: Type.String(),
68
+ publishedVersion: Type.Union([Type.Number(), Type.Null()]),
69
+ createdBy: Type.Union([Type.String(), Type.Null()]),
70
+ createdAt: Type.String(),
71
+ updatedAt: Type.String()
72
+ }),
73
+ Type.Object({
74
+ error: Type.String(),
75
+ key: Type.Optional(Type.String())
76
+ })
77
+ ])
78
+ };
79
+ var getLabelContract = {
80
+ method: "GET",
81
+ path: "/_cms/labels/:id",
82
+ params: Type.Object({
83
+ id: Type.String({ description: "\uB77C\uBCA8 ID" })
84
+ }),
85
+ response: Type.Union([
86
+ Type.Object({
87
+ id: Type.Number(),
88
+ key: Type.String(),
89
+ section: Type.String(),
90
+ type: Type.String(),
91
+ publishedVersion: Type.Union([Type.Number(), Type.Null()]),
92
+ createdBy: Type.Union([Type.String(), Type.Null()]),
93
+ createdAt: Type.String(),
94
+ updatedAt: Type.String()
95
+ }),
96
+ Type.Object({
97
+ error: Type.String()
98
+ })
99
+ ])
100
+ };
101
+ var updateLabelContract = {
102
+ method: "PATCH",
103
+ path: "/_cms/labels/:id",
104
+ params: Type.Object({
105
+ id: Type.String({ description: "\uB77C\uBCA8 ID" })
106
+ }),
107
+ body: Type.Object({
108
+ section: Type.Optional(Type.String({ description: "\uC139\uC158 \uBCC0\uACBD" })),
109
+ type: Type.Optional(Type.Union([
110
+ Type.Literal("text"),
111
+ Type.Literal("image"),
112
+ Type.Literal("video"),
113
+ Type.Literal("file"),
114
+ Type.Literal("object")
115
+ ]))
116
+ }),
117
+ response: Type.Union([
118
+ Type.Object({
119
+ id: Type.Number(),
120
+ key: Type.String(),
121
+ section: Type.String(),
122
+ type: Type.String(),
123
+ publishedVersion: Type.Union([Type.Number(), Type.Null()]),
124
+ createdBy: Type.Union([Type.String(), Type.Null()]),
125
+ createdAt: Type.String(),
126
+ updatedAt: Type.String()
127
+ }),
128
+ Type.Object({
129
+ error: Type.String()
130
+ })
131
+ ])
132
+ };
133
+ var deleteLabelContract = {
134
+ method: "DELETE",
135
+ path: "/_cms/labels/:id",
136
+ params: Type.Object({
137
+ id: Type.String({ description: "\uB77C\uBCA8 ID" })
138
+ }),
139
+ response: Type.Union([
140
+ Type.Object({
141
+ success: Type.Boolean(),
142
+ id: Type.Number()
143
+ }),
144
+ Type.Object({
145
+ error: Type.String()
146
+ })
147
+ ])
148
+ };
149
+ var getLabelByKeyContract = {
150
+ method: "GET",
151
+ path: "/_cms/labels/by-key/:key",
152
+ params: Type.Object({
153
+ key: Type.String({ description: "\uB77C\uBCA8 Key (\uC608: home.hero.title)" })
154
+ }),
155
+ response: Type.Union([
156
+ Type.Object({
157
+ id: Type.Number(),
158
+ key: Type.String(),
159
+ section: Type.String(),
160
+ type: Type.String(),
161
+ publishedVersion: Type.Union([Type.Number(), Type.Null()]),
162
+ createdBy: Type.Union([Type.String(), Type.Null()]),
163
+ createdAt: Type.String(),
164
+ updatedAt: Type.String()
165
+ }),
166
+ Type.Object({
167
+ error: Type.String(),
168
+ key: Type.Optional(Type.String())
169
+ })
170
+ ])
171
+ };
172
+
173
+ // src/api/cms-labels.ts
174
+ var getLabels = (options) => client.call(getLabelsContract, options);
175
+ var createLabel = (options) => client.call(createLabelContract, options);
176
+ var getLabel = (options) => client.call(getLabelContract, options);
177
+ var updateLabel = (options) => client.call(updateLabelContract, options);
178
+ var deleteLabel = (options) => client.call(deleteLabelContract, options);
179
+
180
+ // src/api/cms-labels-by-key.ts
181
+ import { client as client2 } from "@spfn/core/client";
182
+ var getLabelByKey = (options) => client2.call(getLabelByKeyContract, options);
183
+
184
+ // src/api/cms-published-cache.ts
185
+ import { client as client3 } from "@spfn/core/client";
186
+
187
+ // src/lib/contracts/published-cache.ts
188
+ import { Type as Type2 } from "@sinclair/typebox";
189
+ var SectionData = Type2.Object({
190
+ section: Type2.String(),
191
+ locale: Type2.String(),
192
+ content: Type2.Record(Type2.String(), Type2.Any()),
193
+ version: Type2.Number(),
194
+ publishedAt: Type2.Union([Type2.String(), Type2.Null()])
195
+ });
196
+ var getPublishedCacheContract = {
197
+ method: "GET",
198
+ path: "/_cms/published-cache",
199
+ query: Type2.Object({
200
+ sections: Type2.Union([
201
+ Type2.String({ description: "\uB2E8\uC77C \uC139\uC158 \uC774\uB984 (\uC608: home)" }),
202
+ Type2.Array(Type2.String(), { description: '\uC5EC\uB7EC \uC139\uC158 \uC774\uB984 (\uC608: ["home", "footer"])' })
203
+ ]),
204
+ locale: Type2.Optional(Type2.String({ default: "ko", description: "\uC5B8\uC5B4 \uCF54\uB4DC" }))
205
+ }),
206
+ response: Type2.Union([
207
+ // 성공: 항상 배열로 반환
208
+ Type2.Array(SectionData),
209
+ // 에러
210
+ Type2.Object({
211
+ error: Type2.String()
212
+ })
213
+ ])
214
+ };
215
+ var upsertPublishedCacheContract = {
216
+ method: "POST",
217
+ path: "/_cms/published-cache",
218
+ body: Type2.Object({
219
+ section: Type2.String({ description: "\uC139\uC158 \uC774\uB984 (\uC608: home)" }),
220
+ locale: Type2.String({ description: "\uC5B8\uC5B4 \uCF54\uB4DC (\uC608: ko, en, ja)" }),
221
+ content: Type2.Record(Type2.String(), Type2.Any(), { description: "\uBC1C\uD589\uD560 \uCF58\uD150\uCE20 (key-value \uD615\uD0DC)" }),
222
+ version: Type2.Number({ description: "\uBC84\uC804 \uBC88\uD638" })
223
+ }),
224
+ response: Type2.Union([
225
+ SectionData,
226
+ Type2.Object({
227
+ error: Type2.String()
228
+ })
229
+ ])
230
+ };
231
+
232
+ // src/api/cms-published-cache.ts
233
+ var getPublishedCache = (options) => client3.call(getPublishedCacheContract, options);
234
+ var upsertPublishedCache = (options) => client3.call(upsertPublishedCacheContract, options);
235
+
236
+ // src/api/cms-values.ts
237
+ import { client as client4 } from "@spfn/core/client";
238
+
239
+ // src/lib/contracts/values.ts
240
+ import { Type as Type3 } from "@sinclair/typebox";
241
+ var LabelValueSchema = Type3.Object({
242
+ type: Type3.Union([
243
+ Type3.Literal("text"),
244
+ Type3.Literal("image"),
245
+ Type3.Literal("video"),
246
+ Type3.Literal("file"),
247
+ Type3.Literal("object")
248
+ ]),
249
+ content: Type3.Optional(Type3.String()),
250
+ // text type
251
+ url: Type3.Optional(Type3.String()),
252
+ // image, video, file types
253
+ alt: Type3.Optional(Type3.String()),
254
+ // image type
255
+ width: Type3.Optional(Type3.Number()),
256
+ // image type
257
+ height: Type3.Optional(Type3.Number()),
258
+ // image type
259
+ thumbnail: Type3.Optional(Type3.String()),
260
+ // video type
261
+ duration: Type3.Optional(Type3.Number()),
262
+ // video type
263
+ filename: Type3.Optional(Type3.String()),
264
+ // file type
265
+ size: Type3.Optional(Type3.Number()),
266
+ // file type
267
+ fields: Type3.Optional(Type3.Any())
268
+ // object type - recursive structure
269
+ });
270
+ var saveValuesContract = {
271
+ method: "POST",
272
+ path: "/_cms/values/:labelId",
273
+ params: Type3.Object({
274
+ labelId: Type3.String({ description: "\uB77C\uBCA8 ID" })
275
+ }),
276
+ body: Type3.Object({
277
+ version: Type3.Union([
278
+ Type3.Null({ description: "Draft \uC800\uC7A5 (\uB36E\uC5B4\uC4F0\uAE30)" }),
279
+ Type3.Number({ description: "\uBC84\uC804 \uBC88\uD638 (\uBD88\uBCC0)", minimum: 1 })
280
+ ]),
281
+ values: Type3.Array(
282
+ Type3.Object({
283
+ locale: Type3.String({ description: "\uC5B8\uC5B4 \uCF54\uB4DC (ko, en, ja)", default: "ko" }),
284
+ breakpoint: Type3.Optional(Type3.Union([
285
+ Type3.Literal("sm"),
286
+ Type3.Literal("md"),
287
+ Type3.Literal("lg"),
288
+ Type3.Literal("xl"),
289
+ Type3.Literal("2xl"),
290
+ Type3.Null()
291
+ ], { description: "\uBC18\uC751\uD615 \uBE0C\uB808\uC774\uD06C\uD3EC\uC778\uD2B8" })),
292
+ value: LabelValueSchema
293
+ })
294
+ )
295
+ }),
296
+ response: Type3.Union([
297
+ Type3.Object({
298
+ success: Type3.Boolean(),
299
+ saved: Type3.Number(),
300
+ version: Type3.Union([Type3.Null(), Type3.Number()])
301
+ }),
302
+ Type3.Object({
303
+ error: Type3.String()
304
+ })
305
+ ])
306
+ };
307
+ var getValuesContract = {
308
+ method: "GET",
309
+ path: "/_cms/values/:labelId/:version",
310
+ params: Type3.Object({
311
+ labelId: Type3.String({ description: "\uB77C\uBCA8 ID" }),
312
+ version: Type3.String({ description: "\uBC84\uC804 \uBC88\uD638" })
313
+ }),
314
+ query: Type3.Object({
315
+ locale: Type3.Optional(Type3.String({ description: "\uC5B8\uC5B4 \uCF54\uB4DC (ko, en, ja)" })),
316
+ breakpoint: Type3.Optional(Type3.String({ description: "\uBC18\uC751\uD615 \uBE0C\uB808\uC774\uD06C\uD3EC\uC778\uD2B8" }))
317
+ }),
318
+ response: Type3.Union([
319
+ Type3.Object({
320
+ labelId: Type3.Number(),
321
+ version: Type3.Number(),
322
+ values: Type3.Array(
323
+ Type3.Object({
324
+ id: Type3.Number(),
325
+ locale: Type3.String(),
326
+ breakpoint: Type3.Union([Type3.String(), Type3.Null()]),
327
+ value: Type3.Any(),
328
+ createdAt: Type3.String()
329
+ })
330
+ )
331
+ }),
332
+ Type3.Object({
333
+ error: Type3.String()
334
+ })
335
+ ])
336
+ };
337
+
338
+ // src/api/cms-values.ts
339
+ var saveValues = (options) => client4.call(saveValuesContract, options);
340
+ var getValues = (options) => client4.call(getValuesContract, options);
341
+
342
+ // src/api/index.ts
343
+ var cmsApi = {
344
+ getLabels,
345
+ createLabel,
346
+ getLabel,
347
+ updateLabel,
348
+ deleteLabel,
349
+ getLabelByKey,
350
+ getPublishedCache,
351
+ upsertPublishedCache,
352
+ saveValues,
353
+ getValues
354
+ };
355
+
356
+ // src/client/store/cms.store.ts
357
+ var useCmsStore = create((set, get) => ({
358
+ sections: {},
359
+ loading: {},
360
+ setSection: (section, data) => {
361
+ set((state) => ({
362
+ sections: {
363
+ ...state.sections,
364
+ [section]: data
365
+ }
366
+ }));
367
+ },
368
+ setSections: (sections) => {
369
+ set((state) => ({
370
+ sections: {
371
+ ...state.sections,
372
+ ...sections
373
+ }
374
+ }));
375
+ },
376
+ loadSection: async (section, locale = "ko") => {
377
+ const state = get();
378
+ if (state.loading[section]) {
379
+ return;
380
+ }
381
+ if (state.sections[section]) {
382
+ return;
383
+ }
384
+ set((state2) => ({
385
+ loading: { ...state2.loading, [section]: true }
386
+ }));
387
+ try {
388
+ const response = await cmsApi.getPublishedCache({
389
+ query: { sections: section, locale }
390
+ });
391
+ if ("error" in response) {
392
+ console.error(`Failed to load section ${section}:`, response.error);
393
+ return;
394
+ }
395
+ const data = response[0];
396
+ if (!data) {
397
+ console.warn(`Section ${section} not found`);
398
+ return;
399
+ }
400
+ const sectionData = {
401
+ section: data.section,
402
+ locale: data.locale,
403
+ content: data.content || {},
404
+ version: data.version || 0,
405
+ publishedAt: data.publishedAt || null
406
+ };
407
+ set((state2) => ({
408
+ sections: {
409
+ ...state2.sections,
410
+ [section]: sectionData
411
+ },
412
+ loading: { ...state2.loading, [section]: false }
413
+ }));
414
+ } catch (error) {
415
+ console.error(`Error loading CMS section ${section}:`, error);
416
+ set((state2) => ({
417
+ loading: { ...state2.loading, [section]: false }
418
+ }));
419
+ }
420
+ },
421
+ updateLabel: (section, key, value) => {
422
+ set((state) => ({
423
+ sections: {
424
+ ...state.sections,
425
+ [section]: {
426
+ ...state.sections[section],
427
+ content: {
428
+ ...state.sections[section]?.content,
429
+ [`${section}.${key}`]: value
430
+ }
431
+ }
432
+ }
433
+ }));
434
+ },
435
+ reset: () => {
436
+ set({
437
+ sections: {},
438
+ loading: {}
439
+ });
440
+ }
441
+ }));
442
+
443
+ // src/client/hooks/useSection.ts
444
+ function replaceVariables(text, replace) {
445
+ return text.replace(/\{(\w+)}/g, (match, key) => {
446
+ const value = replace[key];
447
+ return value !== void 0 ? String(value) : match;
448
+ });
449
+ }
450
+ function useSection(section, options = {}) {
451
+ const { autoLoad = false, locale = "ko" } = options;
452
+ const sectionData = useCmsStore((state) => state.sections[section]);
453
+ const loading = useCmsStore((state) => state.loading[section] ?? false);
454
+ const loadSection = useCmsStore((state) => state.loadSection);
455
+ React.useEffect(() => {
456
+ if (autoLoad && !sectionData && !loading) {
457
+ loadSection(section, locale);
458
+ }
459
+ }, [autoLoad, section, locale, sectionData, loading, loadSection]);
460
+ const t = React.useCallback(
461
+ (key, defaultValue, replace) => {
462
+ if (!sectionData) {
463
+ return defaultValue;
464
+ }
465
+ const fullKey = `${section}.${key}`;
466
+ let value = sectionData.content[fullKey];
467
+ if (value === void 0) {
468
+ value = defaultValue;
469
+ }
470
+ if (typeof value === "string" && replace) {
471
+ value = replaceVariables(value, replace);
472
+ }
473
+ return value;
56
474
  },
475
+ [section, sectionData]
476
+ );
477
+ return {
478
+ t,
479
+ data: sectionData,
480
+ loading
481
+ };
482
+ }
483
+
484
+ // src/client/hooks/useSections.ts
485
+ function replaceVariables2(text, replace) {
486
+ return text.replace(/\{(\w+)}/g, (match, key) => {
487
+ const value = replace[key];
488
+ return value !== void 0 ? String(value) : match;
489
+ });
490
+ }
491
+ function useSections(sectionNames) {
492
+ const allSections = useCmsStore((state) => state.sections);
493
+ const allLoading = useCmsStore((state) => state.loading);
494
+ const result = {};
495
+ sectionNames.forEach((section) => {
496
+ const sectionData = allSections[section];
497
+ const loading = allLoading[section] ?? false;
498
+ const t = (key, defaultValue, replace) => {
499
+ if (!sectionData) {
500
+ return defaultValue;
501
+ }
502
+ const fullKey = `${section}.${key}`;
503
+ let value = sectionData.content[fullKey];
504
+ if (value === void 0) {
505
+ value = defaultValue;
506
+ }
507
+ if (typeof value === "string" && replace) {
508
+ value = replaceVariables2(value, replace);
509
+ }
510
+ return value;
511
+ };
512
+ result[section] = {
513
+ t,
514
+ data: sectionData,
515
+ loading
516
+ };
517
+ });
518
+ return result;
519
+ }
520
+
521
+ // src/client/components/InitCms.tsx
522
+ import { useEffect } from "react";
523
+ function InitCms({ sections }) {
524
+ const setSections = useCmsStore((state) => state.setSections);
525
+ useEffect(() => {
526
+ const sectionsData = {};
527
+ Object.entries(sections).forEach(([key, { data }]) => {
528
+ sectionsData[key] = data;
529
+ });
530
+ setSections(sectionsData);
531
+ }, [sections, setSections]);
532
+ return null;
533
+ }
534
+
535
+ // src/server/helpers/locale.actions.ts
536
+ import { cookies, headers } from "next/headers";
537
+
538
+ // src/server/config/cms.config.ts
539
+ function getEnvVar(key, defaultValue) {
540
+ return process.env[key] || defaultValue;
541
+ }
542
+ function getEnvBoolean(key, defaultValue) {
543
+ const value = process.env[key];
544
+ if (value === void 0) return defaultValue;
545
+ return value === "true" || value === "1";
546
+ }
547
+ function loadConfigFromEnv() {
548
+ const defaultLocale = getEnvVar("SPFN_CMS_DEFAULT_LOCALE", "en");
549
+ const supportedLocalesStr = getEnvVar("SPFN_CMS_SUPPORTED_LOCALES", "en,ko");
550
+ const detectBrowserLanguage2 = getEnvBoolean("SPFN_CMS_DETECT_BROWSER_LANGUAGE", true);
551
+ const supportedLocales = supportedLocalesStr.split(",").map((locale) => locale.trim()).filter((locale) => locale.length > 0);
552
+ if (!supportedLocales.includes(defaultLocale)) {
553
+ supportedLocales.unshift(defaultLocale);
554
+ }
555
+ return {
556
+ defaultLocale,
557
+ supportedLocales,
558
+ detectBrowserLanguage: detectBrowserLanguage2
559
+ };
560
+ }
561
+ var currentConfig = loadConfigFromEnv();
562
+ function getCmsConfig() {
563
+ return currentConfig;
564
+ }
565
+
566
+ // src/lib/constants/locale.constants.ts
567
+ var LOCALE_COOKIE_KEY = "spfn-locale";
568
+ var LOCALE_INFO_MAP = {
569
+ // 한국어
570
+ ko: {
571
+ locale: "ko",
572
+ countryCode: "KR",
573
+ flag: "🇰🇷",
574
+ dialCode: "+82",
575
+ nativeName: "\uD55C\uAD6D\uC5B4",
576
+ englishName: "Korean",
577
+ currencyCode: "KRW",
578
+ dateFormat: "YYYY.MM.DD"
579
+ },
580
+ // 영어 (미국)
581
+ en: {
582
+ locale: "en",
583
+ countryCode: "US",
584
+ flag: "🇺🇸",
585
+ dialCode: "+1",
586
+ nativeName: "English",
587
+ englishName: "English",
588
+ currencyCode: "USD",
589
+ dateFormat: "MM/DD/YYYY"
590
+ },
591
+ // 일본어
592
+ ja: {
593
+ locale: "ja",
594
+ countryCode: "JP",
595
+ flag: "🇯🇵",
596
+ dialCode: "+81",
597
+ nativeName: "\u65E5\u672C\u8A9E",
598
+ englishName: "Japanese",
599
+ currencyCode: "JPY",
600
+ dateFormat: "YYYY/MM/DD"
601
+ },
602
+ // 중국어 (간체)
603
+ zh: {
604
+ locale: "zh",
605
+ countryCode: "CN",
606
+ flag: "🇨🇳",
607
+ dialCode: "+86",
608
+ nativeName: "\u7B80\u4F53\u4E2D\u6587",
609
+ englishName: "Chinese (Simplified)",
610
+ currencyCode: "CNY",
611
+ dateFormat: "YYYY-MM-DD"
612
+ },
613
+ // 중국어 (번체, 대만)
614
+ "zh-TW": {
615
+ locale: "zh-TW",
616
+ countryCode: "TW",
617
+ flag: "🇹🇼",
618
+ dialCode: "+886",
619
+ nativeName: "\u7E41\u9AD4\u4E2D\u6587",
620
+ englishName: "Chinese (Traditional)",
621
+ currencyCode: "TWD",
622
+ dateFormat: "YYYY/MM/DD"
623
+ },
624
+ // 스페인어
625
+ es: {
626
+ locale: "es",
627
+ countryCode: "ES",
628
+ flag: "🇪🇸",
629
+ dialCode: "+34",
630
+ nativeName: "Espa\xF1ol",
631
+ englishName: "Spanish",
632
+ currencyCode: "EUR",
633
+ dateFormat: "DD/MM/YYYY"
634
+ },
635
+ // 프랑스어
636
+ fr: {
637
+ locale: "fr",
638
+ countryCode: "FR",
639
+ flag: "🇫🇷",
640
+ dialCode: "+33",
641
+ nativeName: "Fran\xE7ais",
642
+ englishName: "French",
643
+ currencyCode: "EUR",
644
+ dateFormat: "DD/MM/YYYY"
645
+ },
646
+ // 독일어
647
+ de: {
648
+ locale: "de",
649
+ countryCode: "DE",
650
+ flag: "🇩🇪",
651
+ dialCode: "+49",
652
+ nativeName: "Deutsch",
653
+ englishName: "German",
654
+ currencyCode: "EUR",
655
+ dateFormat: "DD.MM.YYYY"
656
+ },
657
+ // 이탈리아어
658
+ it: {
659
+ locale: "it",
660
+ countryCode: "IT",
661
+ flag: "🇮🇹",
662
+ dialCode: "+39",
663
+ nativeName: "Italiano",
664
+ englishName: "Italian",
665
+ currencyCode: "EUR",
666
+ dateFormat: "DD/MM/YYYY"
667
+ },
668
+ // 포르투갈어 (브라질)
669
+ pt: {
670
+ locale: "pt",
671
+ countryCode: "BR",
672
+ flag: "🇧🇷",
673
+ dialCode: "+55",
674
+ nativeName: "Portugu\xEAs",
675
+ englishName: "Portuguese",
676
+ currencyCode: "BRL",
677
+ dateFormat: "DD/MM/YYYY"
678
+ },
679
+ // 러시아어
680
+ ru: {
681
+ locale: "ru",
682
+ countryCode: "RU",
683
+ flag: "🇷🇺",
684
+ dialCode: "+7",
685
+ nativeName: "\u0420\u0443\u0441\u0441\u043A\u0438\u0439",
686
+ englishName: "Russian",
687
+ currencyCode: "RUB",
688
+ dateFormat: "DD.MM.YYYY"
689
+ },
690
+ // 아랍어
691
+ ar: {
692
+ locale: "ar",
693
+ countryCode: "SA",
694
+ flag: "🇸🇦",
695
+ dialCode: "+966",
696
+ nativeName: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629",
697
+ englishName: "Arabic",
698
+ rtl: true,
699
+ currencyCode: "SAR",
700
+ dateFormat: "DD/MM/YYYY"
701
+ },
702
+ // 힌디어
703
+ hi: {
704
+ locale: "hi",
705
+ countryCode: "IN",
706
+ flag: "🇮🇳",
707
+ dialCode: "+91",
708
+ nativeName: "\u0939\u093F\u0928\u094D\u0926\u0940",
709
+ englishName: "Hindi",
710
+ currencyCode: "INR",
711
+ dateFormat: "DD/MM/YYYY"
712
+ },
713
+ // 태국어
714
+ th: {
715
+ locale: "th",
716
+ countryCode: "TH",
717
+ flag: "🇹🇭",
718
+ dialCode: "+66",
719
+ nativeName: "\u0E44\u0E17\u0E22",
720
+ englishName: "Thai",
721
+ currencyCode: "THB",
722
+ dateFormat: "DD/MM/YYYY"
723
+ },
724
+ // 베트남어
725
+ vi: {
726
+ locale: "vi",
727
+ countryCode: "VN",
728
+ flag: "🇻🇳",
729
+ dialCode: "+84",
730
+ nativeName: "Ti\u1EBFng Vi\u1EC7t",
731
+ englishName: "Vietnamese",
732
+ currencyCode: "VND",
733
+ dateFormat: "DD/MM/YYYY"
734
+ },
735
+ // 인도네시아어
736
+ id: {
737
+ locale: "id",
738
+ countryCode: "ID",
739
+ flag: "🇮🇩",
740
+ dialCode: "+62",
741
+ nativeName: "Bahasa Indonesia",
742
+ englishName: "Indonesian",
743
+ currencyCode: "IDR",
744
+ dateFormat: "DD/MM/YYYY"
745
+ },
746
+ // 터키어
747
+ tr: {
748
+ locale: "tr",
749
+ countryCode: "TR",
750
+ flag: "🇹🇷",
751
+ dialCode: "+90",
752
+ nativeName: "T\xFCrk\xE7e",
753
+ englishName: "Turkish",
754
+ currencyCode: "TRY",
755
+ dateFormat: "DD.MM.YYYY"
756
+ },
757
+ // 폴란드어
758
+ pl: {
759
+ locale: "pl",
760
+ countryCode: "PL",
761
+ flag: "🇵🇱",
762
+ dialCode: "+48",
763
+ nativeName: "Polski",
764
+ englishName: "Polish",
765
+ currencyCode: "PLN",
766
+ dateFormat: "DD.MM.YYYY"
767
+ },
768
+ // 네덜란드어
769
+ nl: {
770
+ locale: "nl",
771
+ countryCode: "NL",
772
+ flag: "🇳🇱",
773
+ dialCode: "+31",
774
+ nativeName: "Nederlands",
775
+ englishName: "Dutch",
776
+ currencyCode: "EUR",
777
+ dateFormat: "DD-MM-YYYY"
778
+ },
779
+ // 중국어 (홍콩)
780
+ "zh-HK": {
781
+ locale: "zh-HK",
782
+ countryCode: "HK",
783
+ flag: "🇭🇰",
784
+ dialCode: "+852",
785
+ nativeName: "\u7E41\u9AD4\u4E2D\u6587 (\u9999\u6E2F)",
786
+ englishName: "Chinese (Hong Kong)",
787
+ currencyCode: "HKD",
788
+ dateFormat: "YYYY/MM/DD"
789
+ },
790
+ // 말레이어
791
+ ms: {
792
+ locale: "ms",
793
+ countryCode: "MY",
794
+ flag: "🇲🇾",
795
+ dialCode: "+60",
796
+ nativeName: "Bahasa Melayu",
797
+ englishName: "Malay",
798
+ currencyCode: "MYR",
799
+ dateFormat: "DD/MM/YYYY"
800
+ },
801
+ // 영어 (영국)
802
+ "en-GB": {
803
+ locale: "en-GB",
804
+ countryCode: "GB",
805
+ flag: "🇬🇧",
806
+ dialCode: "+44",
807
+ nativeName: "English (UK)",
808
+ englishName: "English (United Kingdom)",
809
+ currencyCode: "GBP",
810
+ dateFormat: "DD/MM/YYYY"
811
+ },
812
+ // 영어 (캐나다)
813
+ "en-CA": {
814
+ locale: "en-CA",
815
+ countryCode: "CA",
816
+ flag: "🇨🇦",
817
+ dialCode: "+1",
818
+ nativeName: "English (Canada)",
819
+ englishName: "English (Canada)",
820
+ currencyCode: "CAD",
821
+ dateFormat: "YYYY-MM-DD"
822
+ },
823
+ // 영어 (호주)
824
+ "en-AU": {
825
+ locale: "en-AU",
826
+ countryCode: "AU",
827
+ flag: "🇦🇺",
828
+ dialCode: "+61",
829
+ nativeName: "English (Australia)",
830
+ englishName: "English (Australia)",
831
+ currencyCode: "AUD",
832
+ dateFormat: "DD/MM/YYYY"
833
+ },
834
+ // 영어 (뉴질랜드)
835
+ "en-NZ": {
836
+ locale: "en-NZ",
837
+ countryCode: "NZ",
838
+ flag: "🇳🇿",
839
+ dialCode: "+64",
840
+ nativeName: "English (New Zealand)",
841
+ englishName: "English (New Zealand)",
842
+ currencyCode: "NZD",
843
+ dateFormat: "DD/MM/YYYY"
844
+ },
845
+ // 스페인어 (멕시코)
846
+ "es-MX": {
847
+ locale: "es-MX",
848
+ countryCode: "MX",
849
+ flag: "🇲🇽",
850
+ dialCode: "+52",
851
+ nativeName: "Espa\xF1ol (M\xE9xico)",
852
+ englishName: "Spanish (Mexico)",
853
+ currencyCode: "MXN",
854
+ dateFormat: "DD/MM/YYYY"
855
+ },
856
+ // 스페인어 (아르헨티나)
857
+ "es-AR": {
858
+ locale: "es-AR",
859
+ countryCode: "AR",
860
+ flag: "🇦🇷",
861
+ dialCode: "+54",
862
+ nativeName: "Espa\xF1ol (Argentina)",
863
+ englishName: "Spanish (Argentina)",
864
+ currencyCode: "ARS",
865
+ dateFormat: "DD/MM/YYYY"
866
+ },
867
+ // 스페인어 (콜롬비아)
868
+ "es-CO": {
869
+ locale: "es-CO",
870
+ countryCode: "CO",
871
+ flag: "🇨🇴",
872
+ dialCode: "+57",
873
+ nativeName: "Espa\xF1ol (Colombia)",
874
+ englishName: "Spanish (Colombia)",
875
+ currencyCode: "COP",
876
+ dateFormat: "DD/MM/YYYY"
877
+ },
878
+ // 스웨덴어
879
+ sv: {
880
+ locale: "sv",
881
+ countryCode: "SE",
882
+ flag: "🇸🇪",
883
+ dialCode: "+46",
884
+ nativeName: "Svenska",
885
+ englishName: "Swedish",
886
+ currencyCode: "SEK",
887
+ dateFormat: "YYYY-MM-DD"
888
+ },
889
+ // 노르웨이어
890
+ no: {
891
+ locale: "no",
892
+ countryCode: "NO",
893
+ flag: "🇳🇴",
894
+ dialCode: "+47",
895
+ nativeName: "Norsk",
896
+ englishName: "Norwegian",
897
+ currencyCode: "NOK",
898
+ dateFormat: "DD.MM.YYYY"
899
+ },
900
+ // 덴마크어
901
+ da: {
902
+ locale: "da",
903
+ countryCode: "DK",
904
+ flag: "🇩🇰",
905
+ dialCode: "+45",
906
+ nativeName: "Dansk",
907
+ englishName: "Danish",
908
+ currencyCode: "DKK",
909
+ dateFormat: "DD-MM-YYYY"
910
+ },
911
+ // 핀란드어
912
+ fi: {
913
+ locale: "fi",
914
+ countryCode: "FI",
915
+ flag: "🇫🇮",
916
+ dialCode: "+358",
917
+ nativeName: "Suomi",
918
+ englishName: "Finnish",
919
+ currencyCode: "EUR",
920
+ dateFormat: "DD.MM.YYYY"
921
+ },
922
+ // 우크라이나어
923
+ uk: {
924
+ locale: "uk",
925
+ countryCode: "UA",
926
+ flag: "🇺🇦",
927
+ dialCode: "+380",
928
+ nativeName: "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430",
929
+ englishName: "Ukrainian",
930
+ currencyCode: "UAH",
931
+ dateFormat: "DD.MM.YYYY"
932
+ },
933
+ // 체코어
934
+ cs: {
935
+ locale: "cs",
936
+ countryCode: "CZ",
937
+ flag: "🇨🇿",
938
+ dialCode: "+420",
939
+ nativeName: "\u010Ce\u0161tina",
940
+ englishName: "Czech",
941
+ currencyCode: "CZK",
942
+ dateFormat: "DD.MM.YYYY"
943
+ },
944
+ // 헝가리어
945
+ hu: {
946
+ locale: "hu",
947
+ countryCode: "HU",
948
+ flag: "🇭🇺",
949
+ dialCode: "+36",
950
+ nativeName: "Magyar",
951
+ englishName: "Hungarian",
952
+ currencyCode: "HUF",
953
+ dateFormat: "YYYY.MM.DD."
954
+ },
955
+ // 루마니아어
956
+ ro: {
957
+ locale: "ro",
958
+ countryCode: "RO",
959
+ flag: "🇷🇴",
960
+ dialCode: "+40",
961
+ nativeName: "Rom\xE2n\u0103",
962
+ englishName: "Romanian",
963
+ currencyCode: "RON",
964
+ dateFormat: "DD.MM.YYYY"
965
+ },
966
+ // 불가리아어
967
+ bg: {
968
+ locale: "bg",
969
+ countryCode: "BG",
970
+ flag: "🇧🇬",
971
+ dialCode: "+359",
972
+ nativeName: "\u0411\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438",
973
+ englishName: "Bulgarian",
974
+ currencyCode: "BGN",
975
+ dateFormat: "DD.MM.YYYY"
976
+ },
977
+ // 크로아티아어
978
+ hr: {
979
+ locale: "hr",
980
+ countryCode: "HR",
981
+ flag: "🇭🇷",
982
+ dialCode: "+385",
983
+ nativeName: "Hrvatski",
984
+ englishName: "Croatian",
985
+ currencyCode: "HRK",
986
+ dateFormat: "DD.MM.YYYY."
987
+ },
988
+ // 세르비아어
989
+ sr: {
990
+ locale: "sr",
991
+ countryCode: "RS",
992
+ flag: "🇷🇸",
993
+ dialCode: "+381",
994
+ nativeName: "\u0421\u0440\u043F\u0441\u043A\u0438",
995
+ englishName: "Serbian",
996
+ currencyCode: "RSD",
997
+ dateFormat: "DD.MM.YYYY."
998
+ },
999
+ // 슬로바키아어
1000
+ sk: {
1001
+ locale: "sk",
1002
+ countryCode: "SK",
1003
+ flag: "🇸🇰",
1004
+ dialCode: "+421",
1005
+ nativeName: "Sloven\u010Dina",
1006
+ englishName: "Slovak",
1007
+ currencyCode: "EUR",
1008
+ dateFormat: "DD.MM.YYYY"
1009
+ },
1010
+ // 슬로베니아어
1011
+ sl: {
1012
+ locale: "sl",
1013
+ countryCode: "SI",
1014
+ flag: "🇸🇮",
1015
+ dialCode: "+386",
1016
+ nativeName: "Sloven\u0161\u010Dina",
1017
+ englishName: "Slovenian",
1018
+ currencyCode: "EUR",
1019
+ dateFormat: "DD.MM.YYYY"
1020
+ },
1021
+ // 리투아니아어
1022
+ lt: {
1023
+ locale: "lt",
1024
+ countryCode: "LT",
1025
+ flag: "🇱🇹",
1026
+ dialCode: "+370",
1027
+ nativeName: "Lietuvi\u0173",
1028
+ englishName: "Lithuanian",
1029
+ currencyCode: "EUR",
1030
+ dateFormat: "YYYY-MM-DD"
1031
+ },
1032
+ // 라트비아어
1033
+ lv: {
1034
+ locale: "lv",
1035
+ countryCode: "LV",
1036
+ flag: "🇱🇻",
1037
+ dialCode: "+371",
1038
+ nativeName: "Latvie\u0161u",
1039
+ englishName: "Latvian",
1040
+ currencyCode: "EUR",
1041
+ dateFormat: "DD.MM.YYYY."
1042
+ },
1043
+ // 에스토니아어
1044
+ et: {
1045
+ locale: "et",
1046
+ countryCode: "EE",
1047
+ flag: "🇪🇪",
1048
+ dialCode: "+372",
1049
+ nativeName: "Eesti",
1050
+ englishName: "Estonian",
1051
+ currencyCode: "EUR",
1052
+ dateFormat: "DD.MM.YYYY"
1053
+ },
1054
+ // 그리스어
1055
+ el: {
1056
+ locale: "el",
1057
+ countryCode: "GR",
1058
+ flag: "🇬🇷",
1059
+ dialCode: "+30",
1060
+ nativeName: "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC",
1061
+ englishName: "Greek",
1062
+ currencyCode: "EUR",
1063
+ dateFormat: "DD/MM/YYYY"
1064
+ },
1065
+ // 페르시아어
1066
+ fa: {
1067
+ locale: "fa",
1068
+ countryCode: "IR",
1069
+ flag: "🇮🇷",
1070
+ dialCode: "+98",
1071
+ nativeName: "\u0641\u0627\u0631\u0633\u06CC",
1072
+ englishName: "Persian",
1073
+ rtl: true,
1074
+ currencyCode: "IRR",
1075
+ dateFormat: "YYYY/MM/DD"
1076
+ },
1077
+ // 히브리어
1078
+ he: {
1079
+ locale: "he",
1080
+ countryCode: "IL",
1081
+ flag: "🇮🇱",
1082
+ dialCode: "+972",
1083
+ nativeName: "\u05E2\u05D1\u05E8\u05D9\u05EA",
1084
+ englishName: "Hebrew",
1085
+ rtl: true,
1086
+ currencyCode: "ILS",
1087
+ dateFormat: "DD/MM/YYYY"
1088
+ },
1089
+ // 스와힐리어
1090
+ sw: {
1091
+ locale: "sw",
1092
+ countryCode: "KE",
1093
+ flag: "🇰🇪",
1094
+ dialCode: "+254",
1095
+ nativeName: "Kiswahili",
1096
+ englishName: "Swahili",
1097
+ currencyCode: "KES",
1098
+ dateFormat: "DD/MM/YYYY"
1099
+ }
1100
+ };
1101
+ function getLocaleInfo(locale) {
1102
+ return LOCALE_INFO_MAP[locale];
1103
+ }
1104
+ function getSupportedLocales() {
1105
+ return Object.keys(LOCALE_INFO_MAP);
1106
+ }
1107
+ function getFlag(locale) {
1108
+ return LOCALE_INFO_MAP[locale]?.flag ?? "";
1109
+ }
1110
+ function getDialCode(locale) {
1111
+ return LOCALE_INFO_MAP[locale]?.dialCode ?? "";
1112
+ }
1113
+ function isRTL(locale) {
1114
+ return LOCALE_INFO_MAP[locale]?.rtl ?? false;
1115
+ }
1116
+
1117
+ // src/server/helpers/locale.actions.ts
1118
+ async function detectBrowserLanguage() {
1119
+ try {
1120
+ const headersList = await headers();
1121
+ const acceptLanguage = headersList.get("accept-language");
1122
+ if (!acceptLanguage) {
1123
+ return null;
1124
+ }
1125
+ const languages = acceptLanguage.split(",").map((lang) => {
1126
+ const [code] = lang.split(";");
1127
+ return code.split("-")[0].trim();
1128
+ });
1129
+ const config = getCmsConfig();
1130
+ for (const lang of languages) {
1131
+ if (config.supportedLocales.includes(lang)) {
1132
+ return lang;
1133
+ }
1134
+ }
1135
+ return null;
1136
+ } catch (error) {
1137
+ return null;
1138
+ }
1139
+ }
1140
+ async function getLocale() {
1141
+ const config = getCmsConfig();
1142
+ const cookieStore = await cookies();
1143
+ const cookieLocale = cookieStore.get(LOCALE_COOKIE_KEY)?.value;
1144
+ if (cookieLocale && config.supportedLocales.includes(cookieLocale)) {
1145
+ return cookieLocale;
1146
+ }
1147
+ if (config.detectBrowserLanguage) {
1148
+ const browserLang = await detectBrowserLanguage();
1149
+ if (browserLang) {
1150
+ return browserLang;
1151
+ }
1152
+ }
1153
+ return config.defaultLocale;
1154
+ }
1155
+ async function setLocale(locale) {
1156
+ const config = getCmsConfig();
1157
+ if (!config.supportedLocales.includes(locale)) {
1158
+ throw new Error(
1159
+ `Unsupported locale: ${locale}. Supported locales: ${config.supportedLocales.join(", ")}`
1160
+ );
1161
+ }
1162
+ const cookieStore = await cookies();
1163
+ cookieStore.set(LOCALE_COOKIE_KEY, locale, {
1164
+ path: "/",
1165
+ maxAge: 60 * 60 * 24 * 365,
1166
+ // 1년
1167
+ sameSite: "lax"
1168
+ });
1169
+ }
1170
+ async function getLocales() {
1171
+ const config = getCmsConfig();
1172
+ return config.supportedLocales;
1173
+ }
1174
+ async function getLocaleWithInfo() {
1175
+ const locale = await getLocale();
1176
+ const info = getLocaleInfo(locale);
1177
+ return { locale, info };
1178
+ }
1179
+ async function getLocalesWithInfo() {
1180
+ const config = getCmsConfig();
1181
+ const supportedLocales = config.supportedLocales;
1182
+ return supportedLocales.map((locale) => getLocaleInfo(locale)).filter((info) => info !== void 0);
1183
+ }
1184
+ export {
1185
+ InitCms,
1186
+ LOCALE_COOKIE_KEY,
1187
+ LOCALE_INFO_MAP,
1188
+ getDialCode,
1189
+ getFlag,
1190
+ getLocale,
1191
+ getLocaleInfo,
1192
+ getLocaleWithInfo,
1193
+ getLocales,
1194
+ getLocalesWithInfo,
1195
+ getSupportedLocales,
1196
+ isRTL,
1197
+ setLocale,
1198
+ useCmsStore,
1199
+ useSection,
1200
+ useSections
57
1201
  };
58
- // Client-side Store & Hooks
59
- export { useCmsStore, useSection, useSections } from './store';
60
- // Client-side Initializer
61
- export { InitCms } from './init';
62
1202
  //# sourceMappingURL=client.js.map