@spfn/cms 0.1.0-alpha.0
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/LICENSE +21 -0
- package/README.md +490 -0
- package/dist/actions.d.ts +9 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +11 -0
- package/dist/actions.js.map +1 -0
- package/dist/client.d.ts +138 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +62 -0
- package/dist/client.js.map +1 -0
- package/dist/cms.config.d.ts +77 -0
- package/dist/cms.config.d.ts.map +1 -0
- package/dist/cms.config.js +111 -0
- package/dist/cms.config.js.map +1 -0
- package/dist/entities/cms-audit-logs.d.ts +213 -0
- package/dist/entities/cms-audit-logs.d.ts.map +1 -0
- package/dist/entities/cms-audit-logs.js +103 -0
- package/dist/entities/cms-audit-logs.js.map +1 -0
- package/dist/entities/cms-draft-cache.d.ts +188 -0
- package/dist/entities/cms-draft-cache.d.ts.map +1 -0
- package/dist/entities/cms-draft-cache.js +112 -0
- package/dist/entities/cms-draft-cache.js.map +1 -0
- package/dist/entities/cms-label-values.d.ts +192 -0
- package/dist/entities/cms-label-values.d.ts.map +1 -0
- package/dist/entities/cms-label-values.js +105 -0
- package/dist/entities/cms-label-values.js.map +1 -0
- package/dist/entities/cms-label-versions.d.ts +207 -0
- package/dist/entities/cms-label-versions.d.ts.map +1 -0
- package/dist/entities/cms-label-versions.js +80 -0
- package/dist/entities/cms-label-versions.js.map +1 -0
- package/dist/entities/cms-labels.d.ts +189 -0
- package/dist/entities/cms-labels.d.ts.map +1 -0
- package/dist/entities/cms-labels.js +48 -0
- package/dist/entities/cms-labels.js.map +1 -0
- package/dist/entities/cms-published-cache.d.ts +199 -0
- package/dist/entities/cms-published-cache.d.ts.map +1 -0
- package/dist/entities/cms-published-cache.js +103 -0
- package/dist/entities/cms-published-cache.js.map +1 -0
- package/dist/entities/index.d.ts +10 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +10 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/generators/index.d.ts +19 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +19 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/label-sync-generator.d.ts +33 -0
- package/dist/generators/label-sync-generator.d.ts.map +1 -0
- package/dist/generators/label-sync-generator.js +86 -0
- package/dist/generators/label-sync-generator.js.map +1 -0
- package/dist/helpers/locale.actions.d.ts +132 -0
- package/dist/helpers/locale.actions.d.ts.map +1 -0
- package/dist/helpers/locale.actions.js +210 -0
- package/dist/helpers/locale.actions.js.map +1 -0
- package/dist/helpers/locale.constants.d.ts +10 -0
- package/dist/helpers/locale.constants.d.ts.map +1 -0
- package/dist/helpers/locale.constants.js +10 -0
- package/dist/helpers/locale.constants.js.map +1 -0
- package/dist/helpers/locale.d.ts +17 -0
- package/dist/helpers/locale.d.ts.map +1 -0
- package/dist/helpers/locale.js +20 -0
- package/dist/helpers/locale.js.map +1 -0
- package/dist/helpers/sync.d.ts +41 -0
- package/dist/helpers/sync.d.ts.map +1 -0
- package/dist/helpers/sync.js +309 -0
- package/dist/helpers/sync.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +31 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +36 -0
- package/dist/init.js.map +1 -0
- package/dist/labels/helpers.d.ts +31 -0
- package/dist/labels/helpers.d.ts.map +1 -0
- package/dist/labels/helpers.js +60 -0
- package/dist/labels/helpers.js.map +1 -0
- package/dist/labels/index.d.ts +7 -0
- package/dist/labels/index.d.ts.map +1 -0
- package/dist/labels/index.js +7 -0
- package/dist/labels/index.js.map +1 -0
- package/dist/repositories/cms-draft-cache.repository.d.ts +62 -0
- package/dist/repositories/cms-draft-cache.repository.d.ts.map +1 -0
- package/dist/repositories/cms-draft-cache.repository.js +56 -0
- package/dist/repositories/cms-draft-cache.repository.js.map +1 -0
- package/dist/repositories/cms-label-values.repository.d.ts +32 -0
- package/dist/repositories/cms-label-values.repository.d.ts.map +1 -0
- package/dist/repositories/cms-label-values.repository.js +72 -0
- package/dist/repositories/cms-label-values.repository.js.map +1 -0
- package/dist/repositories/cms-labels.repository.d.ts +53 -0
- package/dist/repositories/cms-labels.repository.d.ts.map +1 -0
- package/dist/repositories/cms-labels.repository.js +77 -0
- package/dist/repositories/cms-labels.repository.js.map +1 -0
- package/dist/repositories/cms-published-cache.repository.d.ts +53 -0
- package/dist/repositories/cms-published-cache.repository.d.ts.map +1 -0
- package/dist/repositories/cms-published-cache.repository.js +54 -0
- package/dist/repositories/cms-published-cache.repository.js.map +1 -0
- package/dist/repositories/index.d.ts +8 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +9 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/routes/labels/[id]/contract.d.ts +68 -0
- package/dist/routes/labels/[id]/contract.d.ts.map +1 -0
- package/dist/routes/labels/[id]/contract.js +84 -0
- package/dist/routes/labels/[id]/contract.js.map +1 -0
- package/dist/routes/labels/[id]/index.d.ts +10 -0
- package/dist/routes/labels/[id]/index.d.ts.map +1 -0
- package/dist/routes/labels/[id]/index.js +96 -0
- package/dist/routes/labels/[id]/index.js.map +1 -0
- package/dist/routes/labels/by-key/[key]/contract.d.ts +24 -0
- package/dist/routes/labels/by-key/[key]/contract.d.ts.map +1 -0
- package/dist/routes/labels/by-key/[key]/contract.js +28 -0
- package/dist/routes/labels/by-key/[key]/contract.js.map +1 -0
- package/dist/routes/labels/by-key/[key]/index.d.ts +8 -0
- package/dist/routes/labels/by-key/[key]/index.d.ts.map +1 -0
- package/dist/routes/labels/by-key/[key]/index.js +32 -0
- package/dist/routes/labels/by-key/[key]/index.js.map +1 -0
- package/dist/routes/labels/contract.d.ts +59 -0
- package/dist/routes/labels/contract.d.ts.map +1 -0
- package/dist/routes/labels/contract.js +75 -0
- package/dist/routes/labels/contract.js.map +1 -0
- package/dist/routes/labels/index.d.ts +10 -0
- package/dist/routes/labels/index.d.ts.map +1 -0
- package/dist/routes/labels/index.js +73 -0
- package/dist/routes/labels/index.js.map +1 -0
- package/dist/routes/published-cache/contract.d.ts +25 -0
- package/dist/routes/published-cache/contract.d.ts.map +1 -0
- package/dist/routes/published-cache/contract.js +35 -0
- package/dist/routes/published-cache/contract.js.map +1 -0
- package/dist/routes/published-cache/index.d.ts +8 -0
- package/dist/routes/published-cache/index.d.ts.map +1 -0
- package/dist/routes/published-cache/index.js +33 -0
- package/dist/routes/published-cache/index.js.map +1 -0
- package/dist/routes/sync/contract.d.ts +33 -0
- package/dist/routes/sync/contract.d.ts.map +1 -0
- package/dist/routes/sync/contract.js +34 -0
- package/dist/routes/sync/contract.js.map +1 -0
- package/dist/routes/sync/index.d.ts +13 -0
- package/dist/routes/sync/index.d.ts.map +1 -0
- package/dist/routes/sync/index.js +241 -0
- package/dist/routes/sync/index.js.map +1 -0
- package/dist/routes/values/[labelId]/[version]/contract.d.ts +29 -0
- package/dist/routes/values/[labelId]/[version]/contract.d.ts.map +1 -0
- package/dist/routes/values/[labelId]/[version]/contract.js +33 -0
- package/dist/routes/values/[labelId]/[version]/contract.js.map +1 -0
- package/dist/routes/values/[labelId]/[version]/index.d.ts +8 -0
- package/dist/routes/values/[labelId]/[version]/index.d.ts.map +1 -0
- package/dist/routes/values/[labelId]/[version]/index.js +45 -0
- package/dist/routes/values/[labelId]/[version]/index.js.map +1 -0
- package/dist/routes/values/[labelId]/contract.d.ts +38 -0
- package/dist/routes/values/[labelId]/contract.d.ts.map +1 -0
- package/dist/routes/values/[labelId]/contract.js +59 -0
- package/dist/routes/values/[labelId]/contract.js.map +1 -0
- package/dist/routes/values/[labelId]/index.d.ts +8 -0
- package/dist/routes/values/[labelId]/index.d.ts.map +1 -0
- package/dist/routes/values/[labelId]/index.js +42 -0
- package/dist/routes/values/[labelId]/index.js.map +1 -0
- package/dist/server.d.ts +99 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +256 -0
- package/dist/server.js.map +1 -0
- package/dist/store.d.ts +87 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +205 -0
- package/dist/store.js.map +1 -0
- package/dist/sync.d.ts +11 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +179 -0
- package/dist/sync.js.map +1 -0
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
/**
|
|
3
|
+
* Locale Management Server Actions
|
|
4
|
+
*
|
|
5
|
+
* Server ActionsμΌλ‘ ꡬνλ locale κ΄λ¦¬ ν¨μ
|
|
6
|
+
* - μλ² μ»΄ν¬λνΈ: μΌλ° ν¨μ νΈμΆλ‘ λμ
|
|
7
|
+
* - ν΄λΌμ΄μΈνΈ μ»΄ν¬λνΈ: Server ActionμΌλ‘ μλ μ²λ¦¬
|
|
8
|
+
*/
|
|
9
|
+
import { cookies, headers } from 'next/headers';
|
|
10
|
+
import { getCmsConfig } from '../cms.config.js';
|
|
11
|
+
import { LOCALE_COOKIE_KEY } from './locale.constants.js';
|
|
12
|
+
/**
|
|
13
|
+
* λΈλΌμ°μ μΈμ΄ κ°μ§
|
|
14
|
+
*
|
|
15
|
+
* Accept-Language ν€λμμ μ§μνλ μΈμ΄λ₯Ό μ°Ύμ΅λλ€.
|
|
16
|
+
*
|
|
17
|
+
* @returns κ°μ§λ μΈμ΄ μ½λ λλ null
|
|
18
|
+
*/
|
|
19
|
+
async function detectBrowserLanguage() {
|
|
20
|
+
try {
|
|
21
|
+
const headersList = await headers();
|
|
22
|
+
const acceptLanguage = headersList.get('accept-language');
|
|
23
|
+
if (!acceptLanguage) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
// "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7" νμ νμ±
|
|
27
|
+
const languages = acceptLanguage
|
|
28
|
+
.split(',')
|
|
29
|
+
.map(lang => {
|
|
30
|
+
const [code] = lang.split(';');
|
|
31
|
+
return code.split('-')[0].trim();
|
|
32
|
+
});
|
|
33
|
+
const config = getCmsConfig();
|
|
34
|
+
// μ§μνλ μΈμ΄ μ€ μ²« λ²μ§Έ λ§€μΉλλ μΈμ΄ λ°ν
|
|
35
|
+
for (const lang of languages) {
|
|
36
|
+
if (config.supportedLocales.includes(lang)) {
|
|
37
|
+
return lang;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// ν€λ μ κ·Ό μ€ν¨ μ
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* νμ¬ locale κ°μ Έμ€κΈ° (Server Action)
|
|
49
|
+
*
|
|
50
|
+
* μλ²/ν΄λΌμ΄μΈνΈ μ»΄ν¬λνΈ λͺ¨λμμ μ¬μ© κ°λ₯
|
|
51
|
+
*
|
|
52
|
+
* μ°μ μμ:
|
|
53
|
+
* 1. μΏ ν€ (μ¬μ©μκ° λͺ
μμ μΌλ‘ μ νν μΈμ΄)
|
|
54
|
+
* 2. λΈλΌμ°μ μΈμ΄ κ°μ§ (μ€μ μμ νμ±νλ κ²½μ°)
|
|
55
|
+
* 3. μμ€ν
κΈ°λ³Έ μΈμ΄ (CMS μ€μ )
|
|
56
|
+
*
|
|
57
|
+
* @returns νμ¬ locale (μ: 'ko', 'en')
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* // Server Component
|
|
62
|
+
* import { getLocale } from '@spfn/cms';
|
|
63
|
+
*
|
|
64
|
+
* export default async function Page()
|
|
65
|
+
* {
|
|
66
|
+
* const locale = await getLocale();
|
|
67
|
+
* return <div>Current locale: {locale}</div>;
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```tsx
|
|
73
|
+
* // Client Component
|
|
74
|
+
* 'use client';
|
|
75
|
+
* import { getLocale } from '@spfn/cms/client';
|
|
76
|
+
*
|
|
77
|
+
* export default function LanguageSwitcher()
|
|
78
|
+
* {
|
|
79
|
+
* const [locale, setLocale] = useState('');
|
|
80
|
+
*
|
|
81
|
+
* useEffect(() => {
|
|
82
|
+
* getLocale().then(setLocale);
|
|
83
|
+
* }, []);
|
|
84
|
+
*
|
|
85
|
+
* return <div>Current locale: {locale}</div>;
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export async function getLocale() {
|
|
90
|
+
const config = getCmsConfig();
|
|
91
|
+
// 1μμ: μΏ ν€ (μ¬μ©μκ° λͺ
μμ μΌλ‘ μ νν μΈμ΄)
|
|
92
|
+
const cookieStore = await cookies();
|
|
93
|
+
const cookieLocale = cookieStore.get(LOCALE_COOKIE_KEY)?.value;
|
|
94
|
+
if (cookieLocale && config.supportedLocales.includes(cookieLocale)) {
|
|
95
|
+
return cookieLocale;
|
|
96
|
+
}
|
|
97
|
+
// 2μμ: λΈλΌμ°μ μΈμ΄ κ°μ§ (μ€μ μμ νμ±νλ κ²½μ°)
|
|
98
|
+
if (config.detectBrowserLanguage) {
|
|
99
|
+
const browserLang = await detectBrowserLanguage();
|
|
100
|
+
if (browserLang) {
|
|
101
|
+
return browserLang;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// 3μμ: μμ€ν
κΈ°λ³Έ μΈμ΄
|
|
105
|
+
return config.defaultLocale;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Locale μ€μ νκΈ° (Server Action)
|
|
109
|
+
*
|
|
110
|
+
* μλ²/ν΄λΌμ΄μΈνΈ μ»΄ν¬λνΈ λͺ¨λμμ μ¬μ© κ°λ₯
|
|
111
|
+
* μΏ ν€μ localeμ μ μ₯ν©λλ€.
|
|
112
|
+
*
|
|
113
|
+
* @param locale - μ€μ ν locale (μ: 'ko', 'en')
|
|
114
|
+
* @throws {Error} μ§μνμ§ μλ localeμΈ κ²½μ°
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```tsx
|
|
118
|
+
* // Server Component (Server Action)
|
|
119
|
+
* import { setLocale } from '@spfn/cms';
|
|
120
|
+
*
|
|
121
|
+
* export default async function Page()
|
|
122
|
+
* {
|
|
123
|
+
* await setLocale('en');
|
|
124
|
+
* return <div>Locale changed</div>;
|
|
125
|
+
* }
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```tsx
|
|
130
|
+
* // Client Component (Server Action)
|
|
131
|
+
* 'use client';
|
|
132
|
+
* import { setLocale } from '@spfn/cms/client';
|
|
133
|
+
*
|
|
134
|
+
* export default function LanguageSwitcher()
|
|
135
|
+
* {
|
|
136
|
+
* const handleChange = async (newLocale: string) =>
|
|
137
|
+
* {
|
|
138
|
+
* await setLocale(newLocale);
|
|
139
|
+
* window.location.reload(); // νμ΄μ§ μλ‘κ³ μΉ¨
|
|
140
|
+
* };
|
|
141
|
+
*
|
|
142
|
+
* return (
|
|
143
|
+
* <button onClick={() => handleChange('en')}>
|
|
144
|
+
* Switch to English
|
|
145
|
+
* </button>
|
|
146
|
+
* );
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export async function setLocale(locale) {
|
|
151
|
+
const config = getCmsConfig();
|
|
152
|
+
// μ ν¨μ± κ²μ¬
|
|
153
|
+
if (!config.supportedLocales.includes(locale)) {
|
|
154
|
+
throw new Error(`Unsupported locale: ${locale}. Supported locales: ${config.supportedLocales.join(', ')}`);
|
|
155
|
+
}
|
|
156
|
+
const cookieStore = await cookies();
|
|
157
|
+
cookieStore.set(LOCALE_COOKIE_KEY, locale, {
|
|
158
|
+
path: '/',
|
|
159
|
+
maxAge: 60 * 60 * 24 * 365, // 1λ
|
|
160
|
+
sameSite: 'lax',
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* μ§μνλ locale λͺ©λ‘ κ°μ Έμ€κΈ° (Server Action)
|
|
165
|
+
*
|
|
166
|
+
* μλ²/ν΄λΌμ΄μΈνΈ μ»΄ν¬λνΈ λͺ¨λμμ μ¬μ© κ°λ₯
|
|
167
|
+
*
|
|
168
|
+
* @returns μ§μνλ locale λ°°μ΄ (μ: ['ko', 'en', 'ja'])
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```tsx
|
|
172
|
+
* // Server Component
|
|
173
|
+
* import { getLocales } from '@spfn/cms';
|
|
174
|
+
*
|
|
175
|
+
* export default async function Page()
|
|
176
|
+
* {
|
|
177
|
+
* const locales = await getLocales();
|
|
178
|
+
* return <div>Supported: {locales.join(', ')}</div>;
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```tsx
|
|
184
|
+
* // Client Component
|
|
185
|
+
* 'use client';
|
|
186
|
+
* import { getLocales } from '@spfn/cms/client';
|
|
187
|
+
*
|
|
188
|
+
* export default function LanguageSwitcher()
|
|
189
|
+
* {
|
|
190
|
+
* const [locales, setLocales] = useState<string[]>([]);
|
|
191
|
+
*
|
|
192
|
+
* useEffect(() => {
|
|
193
|
+
* getLocales().then(setLocales);
|
|
194
|
+
* }, []);
|
|
195
|
+
*
|
|
196
|
+
* return (
|
|
197
|
+
* <div>
|
|
198
|
+
* {locales.map(locale => (
|
|
199
|
+
* <button key={locale}>{locale}</button>
|
|
200
|
+
* ))}
|
|
201
|
+
* </div>
|
|
202
|
+
* );
|
|
203
|
+
* }
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
export async function getLocales() {
|
|
207
|
+
const config = getCmsConfig();
|
|
208
|
+
return config.supportedLocales;
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=locale.actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale.actions.js","sourceRoot":"","sources":["../../src/helpers/locale.actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale.constants.d.ts","sourceRoot":"","sources":["../../src/helpers/locale.constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale.constants.js","sourceRoot":"","sources":["../../src/helpers/locale.constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import "server-only";
|
|
2
|
+
/**
|
|
3
|
+
* Locale Management Module (Server Components)
|
|
4
|
+
*
|
|
5
|
+
* μλ² μ»΄ν¬λνΈμ© locale κ΄λ¦¬ (Server Actions re-export)
|
|
6
|
+
* μ€μ ꡬνμ locale.actions.ts μ°Έμ‘°
|
|
7
|
+
*/
|
|
8
|
+
export { getLocale, setLocale, getLocales, } from './locale.actions.js';
|
|
9
|
+
export { LOCALE_COOKIE_KEY } from './locale.constants.js';
|
|
10
|
+
/**
|
|
11
|
+
* Locale μ ν¨μ± κ²μ¬
|
|
12
|
+
*
|
|
13
|
+
* @param locale - κ²μ¬ν locale
|
|
14
|
+
* @returns μ§μ μ¬λΆ
|
|
15
|
+
*/
|
|
16
|
+
export declare function isValidLocale(locale: string): Promise<boolean>;
|
|
17
|
+
//# sourceMappingURL=locale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../src/helpers/locale.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;AAErB;;;;;GAKG;AAEH,OAAO,EACH,SAAS,EACT,SAAS,EACT,UAAU,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIpE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "server-only";
|
|
2
|
+
/**
|
|
3
|
+
* Locale Management Module (Server Components)
|
|
4
|
+
*
|
|
5
|
+
* μλ² μ»΄ν¬λνΈμ© locale κ΄λ¦¬ (Server Actions re-export)
|
|
6
|
+
* μ€μ ꡬνμ locale.actions.ts μ°Έμ‘°
|
|
7
|
+
*/
|
|
8
|
+
export { getLocale, setLocale, getLocales, } from './locale.actions.js';
|
|
9
|
+
export { LOCALE_COOKIE_KEY } from './locale.constants.js';
|
|
10
|
+
/**
|
|
11
|
+
* Locale μ ν¨μ± κ²μ¬
|
|
12
|
+
*
|
|
13
|
+
* @param locale - κ²μ¬ν locale
|
|
14
|
+
* @returns μ§μ μ¬λΆ
|
|
15
|
+
*/
|
|
16
|
+
export async function isValidLocale(locale) {
|
|
17
|
+
const locales = await import('./locale.actions.js').then(m => m.getLocales());
|
|
18
|
+
return locales.includes(locale);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=locale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale.js","sourceRoot":"","sources":["../../src/helpers/locale.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;AAErB;;;;;GAKG;AAEH,OAAO,EACH,SAAS,EACT,SAAS,EACT,UAAU,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc;IAE9C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9E,OAAO,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CMS Sync Utilities
|
|
3
|
+
*
|
|
4
|
+
* JSON νμΌ κΈ°λ° λΌλ²¨ λκΈ°ν
|
|
5
|
+
*/
|
|
6
|
+
import type { SectionDefinition, SyncOptions, SyncResult } from '../types';
|
|
7
|
+
/**
|
|
8
|
+
* μ¬λ¬ μΉμ
λκΈ°ν
|
|
9
|
+
*/
|
|
10
|
+
export declare function syncAll(sections: SectionDefinition[], options?: SyncOptions): Promise<SyncResult[]>;
|
|
11
|
+
/**
|
|
12
|
+
* JSON νμΌμμ λΌλ²¨ λ‘λ
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadLabelsFromJson(labelsDir: string): SectionDefinition[];
|
|
15
|
+
/**
|
|
16
|
+
* μΉμ
λΌλ²¨ λκΈ°ν
|
|
17
|
+
*/
|
|
18
|
+
export declare function syncSection(definition: SectionDefinition, options?: SyncOptions): Promise<SyncResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Initialize label sync for server startup
|
|
21
|
+
*
|
|
22
|
+
* Call this in your server.config.ts beforeRoutes hook
|
|
23
|
+
*
|
|
24
|
+
* @param options - Sync options
|
|
25
|
+
* @param options.labelsDir - Path to labels directory (default: 'src/cms/labels')
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { initLabelSync } from '@spfn/cms';
|
|
30
|
+
*
|
|
31
|
+
* export default {
|
|
32
|
+
* beforeRoutes: async (app) => {
|
|
33
|
+
* await initLabelSync({ verbose: true });
|
|
34
|
+
* },
|
|
35
|
+
* } satisfies ServerConfig;
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function initLabelSync(options?: SyncOptions & {
|
|
39
|
+
labelsDir?: string;
|
|
40
|
+
}): Promise<void>;
|
|
41
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/helpers/sync.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAgB,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEzF;;GAEG;AACH,wBAAsB,OAAO,CACzB,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,OAAO,GAAE,WAAgB,GAC1B,OAAO,CAAC,UAAU,EAAE,CAAC,CAWvB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAqCzE;AAqCD;;GAEG;AACH,wBAAsB,WAAW,CAC7B,UAAU,EAAE,iBAAiB,EAC7B,OAAO,GAAE,WAAgB,GAC1B,OAAO,CAAC,UAAU,CAAC,CAoKrB;AAyDD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,WAAW,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAgErG"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CMS Sync Utilities
|
|
3
|
+
*
|
|
4
|
+
* JSON νμΌ κΈ°λ° λΌλ²¨ λκΈ°ν
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
|
|
7
|
+
import { basename, extname, join } from 'path';
|
|
8
|
+
import { extractLabels } from '../labels';
|
|
9
|
+
import { cmsLabelsRepository, cmsPublishedCacheRepository } from '../repositories';
|
|
10
|
+
/**
|
|
11
|
+
* μ¬λ¬ μΉμ
λκΈ°ν
|
|
12
|
+
*/
|
|
13
|
+
export async function syncAll(sections, options = {}) {
|
|
14
|
+
const results = [];
|
|
15
|
+
for (const definition of sections) {
|
|
16
|
+
const result = await syncSection(definition, options);
|
|
17
|
+
results.push(result);
|
|
18
|
+
}
|
|
19
|
+
return results;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* JSON νμΌμμ λΌλ²¨ λ‘λ
|
|
23
|
+
*/
|
|
24
|
+
export function loadLabelsFromJson(labelsDir) {
|
|
25
|
+
const sections = [];
|
|
26
|
+
if (!existsSync(labelsDir)) {
|
|
27
|
+
console.warn(`[CMS] Labels directory not found: ${labelsDir}`);
|
|
28
|
+
return sections;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const entries = readdirSync(labelsDir);
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
const sectionPath = join(labelsDir, entry);
|
|
34
|
+
const stat = statSync(sectionPath);
|
|
35
|
+
if (stat.isDirectory()) {
|
|
36
|
+
const sectionName = entry;
|
|
37
|
+
const labels = loadSectionLabels(sectionPath);
|
|
38
|
+
if (Object.keys(labels).length > 0) {
|
|
39
|
+
sections.push({ section: sectionName, labels });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.warn(`[CMS] Could not scan labels directory: ${labelsDir}`);
|
|
46
|
+
}
|
|
47
|
+
return sections;
|
|
48
|
+
}
|
|
49
|
+
function loadSectionLabels(sectionPath) {
|
|
50
|
+
const labels = {};
|
|
51
|
+
try {
|
|
52
|
+
const files = readdirSync(sectionPath);
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
if (extname(file) === '.json') {
|
|
55
|
+
const filePath = join(sectionPath, file);
|
|
56
|
+
const categoryName = basename(file, '.json');
|
|
57
|
+
try {
|
|
58
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
59
|
+
labels[categoryName] = JSON.parse(content);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.warn(`[CMS] Failed to parse ${filePath}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.warn(`[CMS] Could not read section directory: ${sectionPath}`);
|
|
69
|
+
}
|
|
70
|
+
return labels;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* μΉμ
λΌλ²¨ λκΈ°ν
|
|
74
|
+
*/
|
|
75
|
+
export async function syncSection(definition, options = {}) {
|
|
76
|
+
const { dryRun = false, updateExisting = false, removeUnused = false, verbose = false, } = options;
|
|
77
|
+
const { section } = definition;
|
|
78
|
+
const result = {
|
|
79
|
+
section,
|
|
80
|
+
created: 0,
|
|
81
|
+
updated: 0,
|
|
82
|
+
deleted: 0,
|
|
83
|
+
unchanged: 0,
|
|
84
|
+
errors: [],
|
|
85
|
+
};
|
|
86
|
+
try {
|
|
87
|
+
const definedLabels = extractLabels(definition);
|
|
88
|
+
const definedKeys = new Set(definedLabels.map((l) => l.key));
|
|
89
|
+
const existingLabels = await cmsLabelsRepository.findBySection(section);
|
|
90
|
+
const existingMap = new Map(existingLabels.map((l) => [l.key, l]));
|
|
91
|
+
if (verbose) {
|
|
92
|
+
console.log(`\n[${section}] Found ${definedLabels.length} labels in definition`);
|
|
93
|
+
console.log(`[${section}] Found ${existingLabels.length} labels in DB`);
|
|
94
|
+
}
|
|
95
|
+
// μμ± λ° μ
λ°μ΄νΈ
|
|
96
|
+
for (const label of definedLabels) {
|
|
97
|
+
const existing = existingMap.get(label.key);
|
|
98
|
+
if (!existing) {
|
|
99
|
+
if (verbose)
|
|
100
|
+
console.log(` [CREATE] ${label.key}`);
|
|
101
|
+
if (!dryRun) {
|
|
102
|
+
try {
|
|
103
|
+
const defaultValue = typeof label.defaultValue === 'object'
|
|
104
|
+
? JSON.stringify(label.defaultValue)
|
|
105
|
+
: label.defaultValue;
|
|
106
|
+
await cmsLabelsRepository.create({
|
|
107
|
+
section,
|
|
108
|
+
key: label.key,
|
|
109
|
+
type: 'text',
|
|
110
|
+
defaultValue,
|
|
111
|
+
description: label.description,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
result.errors.push({
|
|
116
|
+
key: label.key,
|
|
117
|
+
error: error instanceof Error ? error.message : String(error),
|
|
118
|
+
});
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
result.created++;
|
|
123
|
+
}
|
|
124
|
+
else if (updateExisting) {
|
|
125
|
+
const newDefaultValue = typeof label.defaultValue === 'object'
|
|
126
|
+
? JSON.stringify(label.defaultValue)
|
|
127
|
+
: label.defaultValue;
|
|
128
|
+
const hasChanged = existing.defaultValue !== newDefaultValue;
|
|
129
|
+
if (hasChanged) {
|
|
130
|
+
if (verbose) {
|
|
131
|
+
console.log(` [UPDATE] ${label.key}`);
|
|
132
|
+
console.log(` Old: "${existing.defaultValue}"`);
|
|
133
|
+
console.log(` New: "${newDefaultValue}"`);
|
|
134
|
+
}
|
|
135
|
+
if (!dryRun) {
|
|
136
|
+
try {
|
|
137
|
+
await cmsLabelsRepository.updateById(existing.id, {
|
|
138
|
+
defaultValue: newDefaultValue,
|
|
139
|
+
description: label.description,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
result.errors.push({
|
|
144
|
+
key: label.key,
|
|
145
|
+
error: error instanceof Error ? error.message : String(error),
|
|
146
|
+
});
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
result.updated++;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
result.unchanged++;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
result.unchanged++;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// μ¬μ©λμ§ μλ λΌλ²¨ μμ
|
|
161
|
+
if (removeUnused) {
|
|
162
|
+
for (const existing of existingLabels) {
|
|
163
|
+
if (!definedKeys.has(existing.key)) {
|
|
164
|
+
if (verbose)
|
|
165
|
+
console.log(` [DELETE] ${existing.key}`);
|
|
166
|
+
if (!dryRun) {
|
|
167
|
+
try {
|
|
168
|
+
await cmsLabelsRepository.deleteById(existing.id);
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
result.errors.push({
|
|
172
|
+
key: existing.key,
|
|
173
|
+
error: error instanceof Error ? error.message : String(error),
|
|
174
|
+
});
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
result.deleted++;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Published cache μ
λ°μ΄νΈ
|
|
183
|
+
if (!dryRun && (result.created > 0 || result.updated > 0 || result.deleted > 0)) {
|
|
184
|
+
if (verbose)
|
|
185
|
+
console.log(` [CACHE] Updating published cache for section: ${section}`);
|
|
186
|
+
await updatePublishedCache(section);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
result.errors.push({
|
|
191
|
+
key: '__section__',
|
|
192
|
+
error: error instanceof Error ? error.message : String(error),
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Published Cache μ
λ°μ΄νΈ
|
|
199
|
+
*/
|
|
200
|
+
async function updatePublishedCache(section) {
|
|
201
|
+
const labels = await cmsLabelsRepository.findBySection(section);
|
|
202
|
+
const localesSet = new Set();
|
|
203
|
+
const labelsByLocale = {};
|
|
204
|
+
labels.forEach((label) => {
|
|
205
|
+
try {
|
|
206
|
+
const parsed = JSON.parse(label.defaultValue || '{}');
|
|
207
|
+
if (typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
208
|
+
// Multilingual
|
|
209
|
+
Object.keys(parsed).forEach((locale) => localesSet.add(locale));
|
|
210
|
+
Object.entries(parsed).forEach(([locale, value]) => {
|
|
211
|
+
if (!labelsByLocale[locale])
|
|
212
|
+
labelsByLocale[locale] = {};
|
|
213
|
+
labelsByLocale[locale][label.key] = value;
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// Single value
|
|
218
|
+
if (!labelsByLocale.ko)
|
|
219
|
+
labelsByLocale.ko = {};
|
|
220
|
+
labelsByLocale.ko[label.key] = label.defaultValue;
|
|
221
|
+
localesSet.add('ko');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// Plain string
|
|
226
|
+
if (!labelsByLocale.ko)
|
|
227
|
+
labelsByLocale.ko = {};
|
|
228
|
+
labelsByLocale.ko[label.key] = label.defaultValue;
|
|
229
|
+
localesSet.add('ko');
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
const timestamp = new Date();
|
|
233
|
+
for (const locale of localesSet) {
|
|
234
|
+
await cmsPublishedCacheRepository.upsert({
|
|
235
|
+
section,
|
|
236
|
+
locale,
|
|
237
|
+
content: labelsByLocale[locale] || {},
|
|
238
|
+
publishedAt: timestamp,
|
|
239
|
+
publishedBy: 'system',
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Initialize label sync for server startup
|
|
245
|
+
*
|
|
246
|
+
* Call this in your server.config.ts beforeRoutes hook
|
|
247
|
+
*
|
|
248
|
+
* @param options - Sync options
|
|
249
|
+
* @param options.labelsDir - Path to labels directory (default: 'src/cms/labels')
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```typescript
|
|
253
|
+
* import { initLabelSync } from '@spfn/cms';
|
|
254
|
+
*
|
|
255
|
+
* export default {
|
|
256
|
+
* beforeRoutes: async (app) => {
|
|
257
|
+
* await initLabelSync({ verbose: true });
|
|
258
|
+
* },
|
|
259
|
+
* } satisfies ServerConfig;
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export async function initLabelSync(options = {}) {
|
|
263
|
+
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
264
|
+
const verbose = options.verbose ?? isDevelopment;
|
|
265
|
+
const labelsDir = options.labelsDir ?? 'src/cms/labels';
|
|
266
|
+
if (verbose) {
|
|
267
|
+
console.log('\nπ Initializing label sync...\n');
|
|
268
|
+
}
|
|
269
|
+
// Load labels from JSON files
|
|
270
|
+
const sections = loadLabelsFromJson(labelsDir);
|
|
271
|
+
if (sections.length === 0) {
|
|
272
|
+
if (verbose) {
|
|
273
|
+
console.log('β οΈ No labels found in', labelsDir);
|
|
274
|
+
console.log('');
|
|
275
|
+
}
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const results = await syncAll(sections, {
|
|
279
|
+
updateExisting: isDevelopment, // π κ°λ° νκ²½μμλ μλμΌλ‘ μ
λ°μ΄νΈ
|
|
280
|
+
...options,
|
|
281
|
+
verbose,
|
|
282
|
+
});
|
|
283
|
+
const totalCreated = results.reduce((sum, r) => sum + r.created, 0);
|
|
284
|
+
const totalUpdated = results.reduce((sum, r) => sum + r.updated, 0);
|
|
285
|
+
const totalUnchanged = results.reduce((sum, r) => sum + r.unchanged, 0);
|
|
286
|
+
const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0);
|
|
287
|
+
if (verbose) {
|
|
288
|
+
console.log('β
Label sync completed\n');
|
|
289
|
+
console.log(` Sections: ${results.length}`);
|
|
290
|
+
console.log(` Created: ${totalCreated}`);
|
|
291
|
+
console.log(` Updated: ${totalUpdated}`);
|
|
292
|
+
console.log(` Unchanged: ${totalUnchanged}`);
|
|
293
|
+
if (totalErrors > 0) {
|
|
294
|
+
console.log(` Errors: ${totalErrors}\n`);
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
console.log('');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// Log errors
|
|
301
|
+
if (totalErrors > 0) {
|
|
302
|
+
results.forEach((result) => {
|
|
303
|
+
result.errors.forEach((error) => {
|
|
304
|
+
console.error(`[${result.section}] ${error.key}: ${error.error}`);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/helpers/sync.ts"],"names":[],"mappings":"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"}
|