@spfn/cms 0.1.0-alpha.8 → 0.1.0-alpha.80

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 (233) hide show
  1. package/README.md +28 -416
  2. package/dist/{helpers/locale.actions.d.ts → actions-BEFWwQsh.d.ts} +70 -7
  3. package/dist/actions.d.ts +2 -9
  4. package/dist/actions.js +99 -10
  5. package/dist/actions.js.map +1 -1
  6. package/dist/api.d.ts +319 -0
  7. package/dist/api.js +467 -0
  8. package/dist/api.js.map +1 -0
  9. package/dist/client.d.ts +135 -127
  10. package/dist/client.js +1318 -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 +112 -16
  14. package/dist/index.js +625 -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 +244 -0
  18. package/dist/lib/contracts/labels.js +269 -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 +104 -0
  25. package/dist/lib/contracts/values.js.map +1 -0
  26. package/dist/locale.constants-BNkSdNP1.d.ts +108 -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-labels.d.ts +17 -14
  37. package/dist/server/entities/cms-labels.js +42 -0
  38. package/dist/server/entities/cms-labels.js.map +1 -0
  39. package/dist/{entities → server/entities}/cms-published-cache.d.ts +14 -69
  40. package/dist/server/entities/cms-published-cache.js +36 -0
  41. package/dist/server/entities/cms-published-cache.js.map +1 -0
  42. package/dist/server/entities/index.d.ts +6 -0
  43. package/dist/server/entities/index.js +185 -0
  44. package/dist/server/entities/index.js.map +1 -0
  45. package/dist/server/generators/index.d.ts +19 -0
  46. package/dist/server/generators/index.js +724 -0
  47. package/dist/server/generators/index.js.map +1 -0
  48. package/dist/server/labels/index.d.ts +1 -0
  49. package/dist/server/labels/index.js +33 -0
  50. package/dist/server/labels/index.js.map +1 -0
  51. package/dist/server/repositories/index.d.ts +212 -0
  52. package/dist/server/repositories/index.js +418 -0
  53. package/dist/server/repositories/index.js.map +1 -0
  54. package/dist/server/routes/labels/[id]/admin/index.js +679 -0
  55. package/dist/server/routes/labels/[id]/admin/index.js.map +1 -0
  56. package/dist/server/routes/labels/[id]/index.js +576 -0
  57. package/dist/server/routes/labels/[id]/index.js.map +1 -0
  58. package/dist/server/routes/labels/[id]/publish/index.js +720 -0
  59. package/dist/server/routes/labels/[id]/publish/index.js.map +1 -0
  60. package/dist/server/routes/labels/[id]/versions/index.js +548 -0
  61. package/dist/server/routes/labels/[id]/versions/index.js.map +1 -0
  62. package/dist/server/routes/labels/_id_/admin/index.d.ts +11 -0
  63. package/dist/{routes/labels/[id] → server/routes/labels/_id_}/index.d.ts +5 -3
  64. package/dist/server/routes/labels/_id_/publish/index.d.ts +11 -0
  65. package/dist/server/routes/labels/_id_/versions/index.d.ts +11 -0
  66. package/dist/server/routes/labels/by-key/[key]/index.js +525 -0
  67. package/dist/server/routes/labels/by-key/[key]/index.js.map +1 -0
  68. package/dist/server/routes/labels/by-key/_key_/index.d.ts +10 -0
  69. package/dist/server/routes/labels/index.d.ts +12 -0
  70. package/dist/server/routes/labels/index.js +684 -0
  71. package/dist/server/routes/labels/index.js.map +1 -0
  72. package/dist/server/routes/published-cache/index.d.ts +11 -0
  73. package/dist/server/routes/published-cache/index.js +337 -0
  74. package/dist/server/routes/published-cache/index.js.map +1 -0
  75. package/dist/server/routes/values/[labelId]/[version]/index.js +457 -0
  76. package/dist/server/routes/values/[labelId]/[version]/index.js.map +1 -0
  77. package/dist/server/routes/values/[labelId]/index.js +452 -0
  78. package/dist/server/routes/values/[labelId]/index.js.map +1 -0
  79. package/dist/server/routes/values/_labelId_/_version_/index.d.ts +10 -0
  80. package/dist/server/routes/values/_labelId_/index.d.ts +10 -0
  81. package/dist/server.d.ts +77 -7
  82. package/dist/server.js +1740 -247
  83. package/dist/server.js.map +1 -1
  84. package/migrations/0000_init.sql +3 -0
  85. package/migrations/0001_far_lady_vermin.sql +86 -0
  86. package/migrations/0002_heavy_the_enforcers.sql +2 -0
  87. package/migrations/0003_rare_runaways.sql +1 -0
  88. package/migrations/meta/0000_snapshot.json +15 -0
  89. package/migrations/meta/0001_snapshot.json +687 -0
  90. package/migrations/meta/0002_snapshot.json +686 -0
  91. package/migrations/meta/0003_snapshot.json +563 -0
  92. package/migrations/meta/_journal.json +34 -0
  93. package/package.json +55 -36
  94. package/dist/actions.d.ts.map +0 -1
  95. package/dist/client.d.ts.map +0 -1
  96. package/dist/cms.config.d.ts +0 -77
  97. package/dist/cms.config.d.ts.map +0 -1
  98. package/dist/cms.config.js +0 -111
  99. package/dist/cms.config.js.map +0 -1
  100. package/dist/entities/cms-audit-logs.d.ts.map +0 -1
  101. package/dist/entities/cms-audit-logs.js +0 -103
  102. package/dist/entities/cms-audit-logs.js.map +0 -1
  103. package/dist/entities/cms-draft-cache.d.ts.map +0 -1
  104. package/dist/entities/cms-draft-cache.js +0 -112
  105. package/dist/entities/cms-draft-cache.js.map +0 -1
  106. package/dist/entities/cms-label-values.d.ts.map +0 -1
  107. package/dist/entities/cms-label-values.js +0 -105
  108. package/dist/entities/cms-label-values.js.map +0 -1
  109. package/dist/entities/cms-label-versions.d.ts +0 -207
  110. package/dist/entities/cms-label-versions.d.ts.map +0 -1
  111. package/dist/entities/cms-label-versions.js +0 -80
  112. package/dist/entities/cms-label-versions.js.map +0 -1
  113. package/dist/entities/cms-labels.d.ts.map +0 -1
  114. package/dist/entities/cms-labels.js +0 -48
  115. package/dist/entities/cms-labels.js.map +0 -1
  116. package/dist/entities/cms-published-cache.d.ts.map +0 -1
  117. package/dist/entities/cms-published-cache.js +0 -103
  118. package/dist/entities/cms-published-cache.js.map +0 -1
  119. package/dist/entities/index.d.ts +0 -10
  120. package/dist/entities/index.d.ts.map +0 -1
  121. package/dist/entities/index.js +0 -10
  122. package/dist/entities/index.js.map +0 -1
  123. package/dist/generators/index.d.ts +0 -19
  124. package/dist/generators/index.d.ts.map +0 -1
  125. package/dist/generators/index.js +0 -19
  126. package/dist/generators/index.js.map +0 -1
  127. package/dist/generators/label-sync-generator.d.ts +0 -33
  128. package/dist/generators/label-sync-generator.d.ts.map +0 -1
  129. package/dist/generators/label-sync-generator.js +0 -86
  130. package/dist/generators/label-sync-generator.js.map +0 -1
  131. package/dist/helpers/locale.actions.d.ts.map +0 -1
  132. package/dist/helpers/locale.actions.js +0 -210
  133. package/dist/helpers/locale.actions.js.map +0 -1
  134. package/dist/helpers/locale.constants.d.ts +0 -10
  135. package/dist/helpers/locale.constants.d.ts.map +0 -1
  136. package/dist/helpers/locale.constants.js +0 -10
  137. package/dist/helpers/locale.constants.js.map +0 -1
  138. package/dist/helpers/locale.d.ts +0 -17
  139. package/dist/helpers/locale.d.ts.map +0 -1
  140. package/dist/helpers/locale.js +0 -20
  141. package/dist/helpers/locale.js.map +0 -1
  142. package/dist/helpers/sync.d.ts +0 -41
  143. package/dist/helpers/sync.d.ts.map +0 -1
  144. package/dist/helpers/sync.js +0 -309
  145. package/dist/helpers/sync.js.map +0 -1
  146. package/dist/index.d.ts.map +0 -1
  147. package/dist/init.d.ts +0 -31
  148. package/dist/init.d.ts.map +0 -1
  149. package/dist/init.js +0 -36
  150. package/dist/init.js.map +0 -1
  151. package/dist/labels/helpers.d.ts +0 -31
  152. package/dist/labels/helpers.d.ts.map +0 -1
  153. package/dist/labels/helpers.js +0 -60
  154. package/dist/labels/helpers.js.map +0 -1
  155. package/dist/labels/index.d.ts +0 -7
  156. package/dist/labels/index.d.ts.map +0 -1
  157. package/dist/labels/index.js +0 -7
  158. package/dist/labels/index.js.map +0 -1
  159. package/dist/repositories/cms-draft-cache.repository.d.ts +0 -62
  160. package/dist/repositories/cms-draft-cache.repository.d.ts.map +0 -1
  161. package/dist/repositories/cms-draft-cache.repository.js +0 -56
  162. package/dist/repositories/cms-draft-cache.repository.js.map +0 -1
  163. package/dist/repositories/cms-label-values.repository.d.ts +0 -32
  164. package/dist/repositories/cms-label-values.repository.d.ts.map +0 -1
  165. package/dist/repositories/cms-label-values.repository.js +0 -72
  166. package/dist/repositories/cms-label-values.repository.js.map +0 -1
  167. package/dist/repositories/cms-labels.repository.d.ts +0 -53
  168. package/dist/repositories/cms-labels.repository.d.ts.map +0 -1
  169. package/dist/repositories/cms-labels.repository.js +0 -77
  170. package/dist/repositories/cms-labels.repository.js.map +0 -1
  171. package/dist/repositories/cms-published-cache.repository.d.ts +0 -53
  172. package/dist/repositories/cms-published-cache.repository.d.ts.map +0 -1
  173. package/dist/repositories/cms-published-cache.repository.js +0 -54
  174. package/dist/repositories/cms-published-cache.repository.js.map +0 -1
  175. package/dist/repositories/index.d.ts +0 -8
  176. package/dist/repositories/index.d.ts.map +0 -1
  177. package/dist/repositories/index.js +0 -9
  178. package/dist/repositories/index.js.map +0 -1
  179. package/dist/routes/labels/[id]/contract.d.ts +0 -68
  180. package/dist/routes/labels/[id]/contract.d.ts.map +0 -1
  181. package/dist/routes/labels/[id]/contract.js +0 -84
  182. package/dist/routes/labels/[id]/contract.js.map +0 -1
  183. package/dist/routes/labels/[id]/index.d.ts.map +0 -1
  184. package/dist/routes/labels/[id]/index.js +0 -96
  185. package/dist/routes/labels/[id]/index.js.map +0 -1
  186. package/dist/routes/labels/by-key/[key]/contract.d.ts +0 -24
  187. package/dist/routes/labels/by-key/[key]/contract.d.ts.map +0 -1
  188. package/dist/routes/labels/by-key/[key]/contract.js +0 -28
  189. package/dist/routes/labels/by-key/[key]/contract.js.map +0 -1
  190. package/dist/routes/labels/by-key/[key]/index.d.ts +0 -8
  191. package/dist/routes/labels/by-key/[key]/index.d.ts.map +0 -1
  192. package/dist/routes/labels/by-key/[key]/index.js +0 -32
  193. package/dist/routes/labels/by-key/[key]/index.js.map +0 -1
  194. package/dist/routes/labels/contract.d.ts +0 -59
  195. package/dist/routes/labels/contract.d.ts.map +0 -1
  196. package/dist/routes/labels/contract.js +0 -75
  197. package/dist/routes/labels/contract.js.map +0 -1
  198. package/dist/routes/labels/index.d.ts +0 -10
  199. package/dist/routes/labels/index.d.ts.map +0 -1
  200. package/dist/routes/labels/index.js +0 -73
  201. package/dist/routes/labels/index.js.map +0 -1
  202. package/dist/routes/published-cache/contract.d.ts +0 -25
  203. package/dist/routes/published-cache/contract.d.ts.map +0 -1
  204. package/dist/routes/published-cache/contract.js +0 -35
  205. package/dist/routes/published-cache/contract.js.map +0 -1
  206. package/dist/routes/published-cache/index.d.ts +0 -8
  207. package/dist/routes/published-cache/index.d.ts.map +0 -1
  208. package/dist/routes/published-cache/index.js +0 -33
  209. package/dist/routes/published-cache/index.js.map +0 -1
  210. package/dist/routes/values/[labelId]/[version]/contract.d.ts +0 -29
  211. package/dist/routes/values/[labelId]/[version]/contract.d.ts.map +0 -1
  212. package/dist/routes/values/[labelId]/[version]/contract.js +0 -33
  213. package/dist/routes/values/[labelId]/[version]/contract.js.map +0 -1
  214. package/dist/routes/values/[labelId]/[version]/index.d.ts +0 -8
  215. package/dist/routes/values/[labelId]/[version]/index.d.ts.map +0 -1
  216. package/dist/routes/values/[labelId]/[version]/index.js +0 -45
  217. package/dist/routes/values/[labelId]/[version]/index.js.map +0 -1
  218. package/dist/routes/values/[labelId]/contract.d.ts +0 -38
  219. package/dist/routes/values/[labelId]/contract.d.ts.map +0 -1
  220. package/dist/routes/values/[labelId]/contract.js +0 -59
  221. package/dist/routes/values/[labelId]/contract.js.map +0 -1
  222. package/dist/routes/values/[labelId]/index.d.ts +0 -8
  223. package/dist/routes/values/[labelId]/index.d.ts.map +0 -1
  224. package/dist/routes/values/[labelId]/index.js +0 -42
  225. package/dist/routes/values/[labelId]/index.js.map +0 -1
  226. package/dist/server.d.ts.map +0 -1
  227. package/dist/store.d.ts +0 -87
  228. package/dist/store.d.ts.map +0 -1
  229. package/dist/store.js +0 -205
  230. package/dist/store.js.map +0 -1
  231. package/dist/types.d.ts.map +0 -1
  232. package/dist/types.js +0 -7
  233. package/dist/types.js.map +0 -1
package/README.md CHANGED
@@ -4,94 +4,26 @@ Content Management System for Next.js with JSON-based labels and automatic datab
4
4
 
5
5
  ## Features
6
6
 
7
- - 📁 **JSON file-based labels** - Simple file structure for label management
8
- - 🔄 **Auto-sync to database** on server startup and during development
9
- - 🌐 **Multi-language support** (i18n)
10
- - 🍪 **Cookie-based locale management** - Automatic locale detection and persistence
11
- - 📦 **Folder-based structure** for better organization
12
- - 🔥 **Hot reload** during development
13
- - 💾 **Published cache** for optimal performance
14
- - ⚡ **Server Actions** for client-side locale management
15
- - 🛠️ **Built on Drizzle ORM**
7
+ - 📁 JSON file-based labels
8
+ - 🔄 Auto-sync to database
9
+ - 🌐 50+ languages support
10
+ - 🍪 Cookie-based locale management
11
+ - 🔥 Hot reload during development
12
+ - 💾 Published cache (17x faster)
13
+ - 📝 Draft system & version control
16
14
 
17
15
  ## Installation
18
16
 
19
- ### Recommended: Using SPFN CLI (Automatic Database Setup)
20
-
21
17
  ```bash
22
18
  pnpm spfn add @spfn/cms
23
19
  ```
24
20
 
25
- This command will:
26
- 1. ✅ Install the package
27
- 2. ✅ Discover CMS database schemas automatically
28
- 3. ✅ Generate migrations for 6 CMS tables
29
- 4. ✅ Apply migrations to your database
30
- 5. ✅ Show setup guide
31
-
32
- **Tables created:**
33
- - `cms_labels` - Label definitions (10 columns, 2 indexes)
34
- - `cms_label_values` - Label values per locale (7 columns, 2 indexes, 1 FK)
35
- - `cms_label_versions` - Version history (9 columns, 2 indexes, 1 FK)
36
- - `cms_draft_cache` - Draft content cache (6 columns, 2 indexes)
37
- - `cms_published_cache` - Published content cache (7 columns, 1 index)
38
- - `cms_audit_logs` - Change audit trail (8 columns, 4 indexes, 1 FK)
39
-
40
- ### Manual Installation
41
-
42
- ```bash
43
- pnpm add @spfn/cms
44
- ```
45
-
46
- Then run database migrations:
47
-
48
- ```bash
49
- pnpm spfn db generate # Generate migrations
50
- pnpm spfn db migrate # Apply migrations
51
- ```
52
-
53
- **Note:** Manual installation requires that you have `DATABASE_URL` configured in your `.env.local` file.
54
-
55
21
  ## Quick Start
56
22
 
57
23
  ### 1. Create Label Files
58
24
 
59
- Create JSON files organized by sections and categories:
60
-
61
- ```
62
- src/cms/labels/
63
- layout/ ← Section name
64
- nav.json ← Category
65
- footer.json
66
- home/
67
- hero.json
68
- features.json
69
- ```
70
-
71
- **Example:** `src/cms/labels/layout/nav.json`
72
-
73
- ```json
74
- {
75
- "about": {
76
- "key": "layout.nav.about",
77
- "defaultValue": "About",
78
- "description": "Navigation link for About page"
79
- },
80
- "services": {
81
- "key": "layout.nav.services",
82
- "defaultValue": "Services",
83
- "description": "Navigation link for Services page"
84
- },
85
- "team": {
86
- "key": "layout.nav.team",
87
- "defaultValue": "Team"
88
- }
89
- }
90
- ```
91
-
92
- **Multi-language example:** `src/cms/labels/home/hero.json`
93
-
94
25
  ```json
26
+ // src/lib/labels/home/hero.json
95
27
  {
96
28
  "title": {
97
29
  "key": "home.hero.title",
@@ -99,66 +31,24 @@ src/cms/labels/
99
31
  "ko": "혁신적인 솔루션",
100
32
  "en": "Innovative Solutions"
101
33
  }
102
- },
103
- "subtitle": {
104
- "key": "home.hero.subtitle",
105
- "defaultValue": {
106
- "ko": "비즈니스 성장을 위한 최고의 파트너",
107
- "en": "Your Best Partner for Business Growth"
108
- }
109
34
  }
110
35
  }
111
36
  ```
112
37
 
113
- **Variable substitution:** `src/cms/labels/layout/footer.json`
114
-
115
- ```json
116
- {
117
- "copyright": {
118
- "key": "layout.footer.copyright",
119
- "defaultValue": "© {year} Company. All rights reserved."
120
- }
121
- }
122
- ```
123
-
124
- ### 2. Enable Auto-Sync on Server Startup
125
-
126
- Configure `src/server/server.config.ts`:
38
+ ### 2. Enable Auto-Sync
127
39
 
128
40
  ```typescript
129
- import type { ServerConfig } from '@spfn/core/server';
130
- import { initLabelSync } from '@spfn/cms';
41
+ // src/server/server.config.ts
42
+ import { initLabelSync } from '@spfn/cms/server';
131
43
 
132
44
  export default {
133
45
  beforeRoutes: async (app) => {
134
- await initLabelSync({
135
- verbose: true,
136
- labelsDir: 'src/cms/labels' // Optional, this is the default
137
- });
46
+ await initLabelSync({ verbose: true });
138
47
  },
139
48
  } satisfies ServerConfig;
140
49
  ```
141
50
 
142
- ### 3. Enable Auto-Sync During Development
143
-
144
- Your `.spfnrc.json` should include:
145
-
146
- ```json
147
- {
148
- "codegen": {
149
- "generators": [
150
- {
151
- "name": "@spfn/cms:label-sync",
152
- "enabled": true
153
- }
154
- ]
155
- }
156
- }
157
- ```
158
-
159
- This is automatically configured when you run `pnpm spfn add @spfn/cms`.
160
-
161
- ### 4. Use Labels in Your App
51
+ ### 3. Use in Your App
162
52
 
163
53
  **Server Component:**
164
54
 
@@ -166,22 +56,11 @@ This is automatically configured when you run `pnpm spfn add @spfn/cms`.
166
56
  import { getSection } from '@spfn/cms/server';
167
57
 
168
58
  export default async function HomePage() {
169
- const { t } = await getSection('layout', 'ko');
170
-
171
- return <h1>{t('nav.team')}</h1>;
59
+ const { t } = await getSection('home');
60
+ return <h1>{t('hero.title')}</h1>;
172
61
  }
173
62
  ```
174
63
 
175
- **With variable substitution:**
176
-
177
- ```typescript
178
- const { t } = await getSection('layout');
179
- const copyright = t('footer.copyright', undefined, {
180
- year: new Date().getFullYear()
181
- });
182
- // → "© 2025 Company. All rights reserved."
183
- ```
184
-
185
64
  **Client Component:**
186
65
 
187
66
  ```typescript
@@ -189,301 +68,34 @@ const copyright = t('footer.copyright', undefined, {
189
68
  import { useSection } from '@spfn/cms/client';
190
69
 
191
70
  export default function Nav() {
192
- const { t, loading } = useSection('layout', { autoLoad: true });
193
-
194
- if (loading) return <div>Loading...</div>;
195
-
196
- return (
197
- <nav>
198
- <a>{t('nav.about')}</a>
199
- <a>{t('nav.services')}</a>
200
- </nav>
201
- );
71
+ const { t } = useSection('layout', { autoLoad: true });
72
+ return <nav><a>{t('nav.about')}</a></nav>;
202
73
  }
203
74
  ```
204
75
 
205
- ## File Structure
206
-
207
- ```
208
- src/cms/labels/
209
- layout/ # Section: layout
210
- nav.json # Category: nav
211
- footer.json # Category: footer
212
- home/ # Section: home
213
- hero.json # Category: hero
214
- features.json # Category: features
215
- ```
216
-
217
- **How it maps:**
218
- - Folder name = Section name
219
- - JSON file name = Category name (for organization only)
220
- - Inside JSON: `key` field defines the actual label key
221
-
222
- Example:
223
- ```
224
- src/cms/labels/layout/nav.json:
225
- key: "layout.nav.team" → t('nav.team') in code
226
- ```
227
-
228
- ## JSON Label Format
229
-
230
- ```typescript
231
- {
232
- "labelName": {
233
- "key": "section.category.name", // Required: Unique identifier
234
- "defaultValue": "Text" | {...}, // Required: String or i18n object
235
- "description": "Optional description" // Optional: For documentation
236
- }
237
- }
238
- ```
76
+ ## Documentation
239
77
 
240
- **Single language:**
241
- ```json
242
- {
243
- "welcome": {
244
- "key": "home.welcome",
245
- "defaultValue": "Welcome"
246
- }
247
- }
248
- ```
78
+ 📖 **[Full Documentation](../../docs/ecosystem/cms/index.md)**
249
79
 
250
- **Multi-language:**
251
- ```json
252
- {
253
- "welcome": {
254
- "key": "home.welcome",
255
- "defaultValue": {
256
- "ko": "환영합니다",
257
- "en": "Welcome",
258
- "ja": "ようこそ"
259
- }
260
- }
261
- }
262
- ```
263
-
264
- **Variable placeholders:**
265
- ```json
266
- {
267
- "greeting": {
268
- "key": "home.greeting",
269
- "defaultValue": "Hello, {name}!"
270
- }
271
- }
272
- ```
273
-
274
- Usage:
275
- ```typescript
276
- t('greeting', undefined, { name: 'John' })
277
- // → "Hello, John!"
278
- ```
80
+ - [Getting Started](../../docs/ecosystem/cms/getting-started.md) - Setup and configuration
81
+ - [Label Sync Guide](../../docs/ecosystem/cms/label-sync.md) - Auto-sync options
82
+ - [Advanced Features](../../docs/ecosystem/cms/advanced-features.md) - Breakpoints, value types, Draft Mode
83
+ - [Locale Management](../../docs/ecosystem/cms/locale-management.md) - 50+ languages guide
84
+ - [API Reference](../../docs/ecosystem/cms/api-reference.md) - Complete API docs
85
+ - [Draft & Versioning](../../docs/ecosystem/cms/draft-versioning.md) - Version control & audit logs
279
86
 
280
87
  ## Configuration
281
88
 
282
- ### Environment Variables
283
-
284
- Configure CMS behavior via environment variables in `.env.local`:
285
-
286
89
  ```bash
287
- # Default locale (default: 'en')
90
+ # .env.local
288
91
  SPFN_CMS_DEFAULT_LOCALE=ko
289
-
290
- # Supported locales, comma-separated (default: 'en,ko')
291
92
  SPFN_CMS_SUPPORTED_LOCALES=en,ko,ja
292
-
293
- # Auto-detect browser language (default: true)
294
93
  SPFN_CMS_DETECT_BROWSER_LANGUAGE=true
295
94
  ```
296
95
 
297
- ### Runtime Configuration
298
-
299
- Override configuration at runtime (mainly for testing):
300
-
301
- ```typescript
302
- import { configureCms, getCmsConfig } from '@spfn/cms';
303
-
304
- // Get current configuration
305
- const config = getCmsConfig();
306
- console.log(config.defaultLocale); // 'ko'
307
- console.log(config.supportedLocales); // ['ko', 'en']
308
-
309
- // Update configuration
310
- configureCms({
311
- defaultLocale: 'en',
312
- supportedLocales: ['en', 'ko', 'ja'],
313
- detectBrowserLanguage: false
314
- });
315
- ```
316
-
317
- ## Locale Management
318
-
319
- ### Automatic Locale Detection
320
-
321
- The CMS automatically manages user locale with the following priority:
322
-
323
- 1. **Cookie** - User's explicitly selected locale (persisted)
324
- 2. **Browser Language** - Auto-detected from `Accept-Language` header (if enabled)
325
- 3. **Default Locale** - System default from environment variables
326
-
327
- ### Server Actions (`@spfn/cms/actions`)
328
-
329
- Use Server Actions for locale management in both server and client components:
330
-
331
- **Get current locale:**
332
-
333
- ```typescript
334
- // Server Component
335
- import { getLocale } from '@spfn/cms/actions';
336
-
337
- export default async function RootLayout({ children }) {
338
- const locale = await getLocale();
339
-
340
- return <html lang={locale}>{children}</html>;
341
- }
342
- ```
343
-
344
- ```typescript
345
- // Client Component
346
- 'use client';
347
- import { getLocale } from '@spfn/cms/actions';
348
- import { useEffect, useState } from 'react';
349
-
350
- export default function LanguageSwitcher() {
351
- const [locale, setLocale] = useState('');
352
-
353
- useEffect(() => {
354
- getLocale().then(setLocale);
355
- }, []);
356
-
357
- return <div>Current: {locale}</div>;
358
- }
359
- ```
360
-
361
- **Change locale:**
362
-
363
- ```typescript
364
- import { setLocale } from '@spfn/cms/actions';
365
-
366
- async function changeLanguage(newLocale: string) {
367
- await setLocale(newLocale);
368
- window.location.reload(); // Reload to apply changes
369
- }
370
- ```
96
+ ## Development Status
371
97
 
372
- **Get supported locales:**
373
-
374
- ```typescript
375
- import { getLocales } from '@spfn/cms/actions';
376
-
377
- const locales = await getLocales(); // ['ko', 'en', 'ja']
378
- ```
379
-
380
- ### Auto-detect Locale in Server Components
381
-
382
- When `locale` is not specified, `getSection()` automatically uses the detected locale:
383
-
384
- ```typescript
385
- import { getSection } from '@spfn/cms/server';
386
-
387
- // Auto-detects locale from cookie → browser → default
388
- const { t } = await getSection('home');
389
-
390
- // Or explicitly specify locale
391
- const { t: tEn } = await getSection('home', 'en');
392
- ```
393
-
394
- ## Documentation
395
-
396
- - **[Label Auto-Sync Guide](./LABEL_SYNC_GUIDE.md)** - Detailed configuration guide
397
- - **[Examples](./examples/)** - Usage examples
398
-
399
- ## Architecture
400
-
401
- ```
402
- JSON Files (src/cms/labels/**/*.json)
403
-
404
- loadLabelsFromJson()
405
-
406
- ┌─────────────────────┐
407
- │ LabelSyncGenerator │ ← File watcher (development)
408
- │ initLabelSync() │ ← Server startup
409
- └─────────────────────┘
410
-
411
- syncAll()
412
-
413
- ┌─────────────────────┐
414
- │ PostgreSQL DB │
415
- │ - cms_labels │
416
- │ - published_cache │ ⭐ Used by API
417
- └─────────────────────┘
418
- ↓ HTTP API
419
- ┌─────────────────────┐
420
- │ Application │
421
- │ - getSection() │
422
- │ - useSection() │
423
- └─────────────────────┘
424
- ```
425
-
426
- ## API Reference
427
-
428
- ### Server-side API
429
-
430
- - `getSection(section, locale?)` - Get section labels (auto-detects locale if not specified)
431
- - `getSections(sections, locale?)` - Get multiple sections (auto-detects locale if not specified)
432
- - `initLabelSync(options?)` - Sync labels on server startup
433
-
434
- ### Server Actions API (`@spfn/cms/actions`)
435
-
436
- Available for both server and client components:
437
-
438
- - `getLocale()` - Get current locale (cookie → browser → default)
439
- - `setLocale(locale)` - Set locale (saves to cookie)
440
- - `getLocales()` - Get supported locale list
441
- - `LOCALE_COOKIE_KEY` - Locale cookie key constant
442
-
443
- ### Configuration API
444
-
445
- - `getCmsConfig()` - Get current CMS configuration
446
- - `configureCms(config)` - Update configuration (runtime)
447
- - `resetCmsConfig()` - Reset configuration to defaults
448
-
449
- ### Client-side API (`@spfn/cms/client`)
450
-
451
- - `useSection(section, options?)` - Section labels hook
452
- - `useSections(sections)` - Multiple sections hook
453
- - `useCmsStore()` - CMS store hook
454
- - `cmsApi` - CMS API client
455
- - `InitCms` - Client initialization component
456
-
457
- ### Sync API
458
-
459
- - `loadLabelsFromJson(labelsDir)` - Load labels from JSON files
460
- - `syncAll(sections, options?)` - Sync all sections
461
- - `syncSection(definition, options?)` - Sync specific section
462
-
463
- ### Codegen Integration
464
-
465
- - `createLabelSyncGenerator(config?)` - Generator factory
466
- - `LabelSyncGenerator` - Generator class
467
-
468
- ## Development Workflow
469
-
470
- 1. **Create/Edit JSON files** in `src/cms/labels/`
471
- 2. **Auto-sync happens** (if dev server is running)
472
- 3. **Labels immediately available** via `getSection()` or `useSection()`
473
-
474
- **Example:**
475
-
476
- ```bash
477
- # Terminal 1: Start dev server
478
- pnpm dev
479
-
480
- # Terminal 2: Edit label file
481
- echo '{"test": {"key": "layout.test", "defaultValue": "Test"}}' > src/cms/labels/layout/test.json
482
-
483
- # Auto-sync triggers
484
- # ✅ Label sync completed
485
- # Created: 1
486
- ```
98
+ This package is currently in alpha. APIs may change.
487
99
 
488
100
  ## License
489
101
 
@@ -1,3 +1,5 @@
1
+ import { f as LocaleInfo } from './locale.constants-BNkSdNP1.js';
2
+
1
3
  /**
2
4
  * 현재 locale 가져오기 (Server Action)
3
5
  *
@@ -13,7 +15,7 @@
13
15
  * @example
14
16
  * ```tsx
15
17
  * // Server Component
16
- * import { getLocale } from '@spfn/cms';
18
+ * import { getLocale } from '@spfn/cms/actions';
17
19
  *
18
20
  * export default async function Page()
19
21
  * {
@@ -40,7 +42,7 @@
40
42
  * }
41
43
  * ```
42
44
  */
43
- export declare function getLocale(): Promise<string>;
45
+ declare function getLocale(): Promise<string>;
44
46
  /**
45
47
  * Locale 설정하기 (Server Action)
46
48
  *
@@ -53,7 +55,7 @@ export declare function getLocale(): Promise<string>;
53
55
  * @example
54
56
  * ```tsx
55
57
  * // Server Component (Server Action)
56
- * import { setLocale } from '@spfn/cms';
58
+ * import { setLocale } from '@spfn/cms/actions';
57
59
  *
58
60
  * export default async function Page()
59
61
  * {
@@ -84,7 +86,7 @@ export declare function getLocale(): Promise<string>;
84
86
  * }
85
87
  * ```
86
88
  */
87
- export declare function setLocale(locale: string): Promise<void>;
89
+ declare function setLocale(locale: string): Promise<void>;
88
90
  /**
89
91
  * 지원하는 locale 목록 가져오기 (Server Action)
90
92
  *
@@ -95,7 +97,7 @@ export declare function setLocale(locale: string): Promise<void>;
95
97
  * @example
96
98
  * ```tsx
97
99
  * // Server Component
98
- * import { getLocales } from '@spfn/cms';
100
+ * import { getLocales } from '@spfn/cms/actions';
99
101
  *
100
102
  * export default async function Page()
101
103
  * {
@@ -128,5 +130,66 @@ export declare function setLocale(locale: string): Promise<void>;
128
130
  * }
129
131
  * ```
130
132
  */
131
- export declare function getLocales(): Promise<string[]>;
132
- //# sourceMappingURL=locale.actions.d.ts.map
133
+ declare function getLocales(): Promise<string[]>;
134
+ /**
135
+ * 현재 locale과 상세 정보 함께 가져오기 (Server Action)
136
+ *
137
+ * locale 코드와 함께 국가 코드, 국기, 전화번호 코드 등의 상세 정보를 반환합니다.
138
+ *
139
+ * @returns Locale 코드와 LocaleInfo 객체
140
+ *
141
+ * @example
142
+ * ```tsx
143
+ * // Server Component
144
+ * import { getLocaleWithInfo } from '@spfn/cms/actions';
145
+ *
146
+ * export default async function Page()
147
+ * {
148
+ * const { locale, info } = await getLocaleWithInfo();
149
+ *
150
+ * return (
151
+ * <div>
152
+ * <span>{info?.flag}</span>
153
+ * <span>{info?.nativeName}</span>
154
+ * <span>{info?.dialCode}</span>
155
+ * </div>
156
+ * );
157
+ * }
158
+ * ```
159
+ */
160
+ declare function getLocaleWithInfo(): Promise<{
161
+ locale: string;
162
+ info: LocaleInfo | undefined;
163
+ }>;
164
+ /**
165
+ * 지원하는 모든 locale과 상세 정보 가져오기 (Server Action)
166
+ *
167
+ * 시스템이 지원하는 모든 locale의 상세 정보를 배열로 반환합니다.
168
+ * 언어 선택 UI를 만들 때 유용합니다.
169
+ *
170
+ * @returns LocaleInfo 배열
171
+ *
172
+ * @example
173
+ * ```tsx
174
+ * // Server Component
175
+ * import { getLocalesWithInfo } from '@spfn/cms/actions';
176
+ *
177
+ * export default async function LanguageSelector()
178
+ * {
179
+ * const locales = await getLocalesWithInfo();
180
+ *
181
+ * return (
182
+ * <select>
183
+ * {locales.map(info => (
184
+ * <option key={info.locale} value={info.locale}>
185
+ * {info.flag} {info.nativeName}
186
+ * </option>
187
+ * ))}
188
+ * </select>
189
+ * );
190
+ * }
191
+ * ```
192
+ */
193
+ declare function getLocalesWithInfo(): Promise<LocaleInfo[]>;
194
+
195
+ export { getLocales as a, getLocaleWithInfo as b, getLocalesWithInfo as c, getLocale as g, setLocale as s };
package/dist/actions.d.ts CHANGED
@@ -1,9 +1,2 @@
1
- /**
2
- * @spfn/cms/actions
3
- *
4
- * Server Actions
5
- * 서버/클라이언트 컴포넌트 양쪽에서 사용 가능한 Server Actions
6
- */
7
- export { getLocale, setLocale, getLocales, } from './helpers/locale.actions.js';
8
- export { LOCALE_COOKIE_KEY } from './helpers/locale.constants.js';
9
- //# sourceMappingURL=actions.d.ts.map
1
+ export { g as getLocale, a as getLocales, s as setLocale } from './actions-BEFWwQsh.js';
2
+ export { L as LOCALE_COOKIE_KEY } from './locale.constants-BNkSdNP1.js';