@spfn/cms 0.1.0-alpha.6 → 0.1.0-alpha.60
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/dist/actions.d.ts +140 -6
- package/dist/actions.js +97 -10
- package/dist/actions.js.map +1 -1
- package/dist/client.d.ts +43 -9
- package/dist/client.js +406 -56
- package/dist/client.js.map +1 -1
- package/dist/contracts/labels.d.ts +149 -0
- package/dist/contracts/labels.js +166 -0
- package/dist/contracts/labels.js.map +1 -0
- package/dist/contracts/published-cache.d.ts +25 -0
- package/dist/contracts/published-cache.js +32 -0
- package/dist/contracts/published-cache.js.map +1 -0
- package/dist/contracts/values.d.ts +69 -0
- package/dist/contracts/values.js +100 -0
- package/dist/contracts/values.js.map +1 -0
- package/dist/entities/cms-audit-logs.d.ts +15 -70
- package/dist/entities/cms-audit-logs.js +75 -100
- package/dist/entities/cms-audit-logs.js.map +1 -1
- package/dist/entities/cms-draft-cache.d.ts +13 -73
- package/dist/entities/cms-draft-cache.js +35 -109
- package/dist/entities/cms-draft-cache.js.map +1 -1
- package/dist/entities/cms-label-values.d.ts +14 -65
- package/dist/entities/cms-label-values.js +78 -102
- package/dist/entities/cms-label-values.js.map +1 -1
- package/dist/entities/cms-label-versions.d.ts +16 -49
- package/dist/entities/cms-label-versions.js +73 -77
- package/dist/entities/cms-label-versions.js.map +1 -1
- package/dist/entities/cms-labels.d.ts +17 -14
- package/dist/entities/cms-labels.js +39 -45
- package/dist/entities/cms-labels.js.map +1 -1
- package/dist/entities/cms-published-cache.d.ts +14 -69
- package/dist/entities/cms-published-cache.js +33 -100
- package/dist/entities/cms-published-cache.js.map +1 -1
- package/dist/entities/index.d.ts +7 -10
- package/dist/entities/index.js +217 -9
- package/dist/entities/index.js.map +1 -1
- package/dist/generators/index.d.ts +8 -7
- package/dist/generators/index.js +657 -17
- package/dist/generators/index.js.map +1 -1
- package/dist/index.d.ts +134 -20
- package/dist/index.js +1115 -23
- package/dist/index.js.map +1 -1
- package/dist/{generators/label-sync-generator.d.ts → label-sync-generator-lQrcVfja.d.ts} +9 -6
- package/dist/labels/index.d.ts +31 -4
- package/dist/labels/index.js +31 -6
- package/dist/labels/index.js.map +1 -1
- package/dist/repositories/index.d.ts +205 -6
- package/dist/repositories/index.js +435 -8
- package/dist/repositories/index.js.map +1 -1
- package/dist/routes/labels/[id]/index.js +499 -89
- package/dist/routes/labels/[id]/index.js.map +1 -1
- package/dist/routes/labels/{[id] → _id_}/index.d.ts +5 -3
- package/dist/routes/labels/by-key/[key]/index.js +453 -29
- package/dist/routes/labels/by-key/[key]/index.js.map +1 -1
- package/dist/routes/labels/by-key/_key_/index.d.ts +10 -0
- package/dist/routes/labels/index.d.ts +5 -3
- package/dist/routes/labels/index.js +488 -68
- package/dist/routes/labels/index.js.map +1 -1
- package/dist/routes/published-cache/index.d.ts +5 -3
- package/dist/routes/published-cache/index.js +325 -30
- package/dist/routes/published-cache/index.js.map +1 -1
- package/dist/routes/values/[labelId]/[version]/index.js +467 -41
- package/dist/routes/values/[labelId]/[version]/index.js.map +1 -1
- package/dist/routes/values/[labelId]/index.js +463 -39
- package/dist/routes/values/[labelId]/index.js.map +1 -1
- package/dist/routes/values/_labelId_/_version_/index.d.ts +10 -0
- package/dist/routes/values/_labelId_/index.d.ts +10 -0
- package/dist/server.d.ts +17 -7
- package/dist/server.js +263 -252
- package/dist/server.js.map +1 -1
- package/dist/store.d.ts +8 -14
- package/dist/store.js +396 -198
- package/dist/store.js.map +1 -1
- package/dist/types.d.ts +14 -7
- package/dist/types.js +0 -6
- package/dist/types.js.map +1 -1
- package/migrations/0000_condemned_centennial.sql +89 -0
- package/migrations/meta/0000_snapshot.json +687 -0
- package/migrations/meta/_journal.json +13 -0
- package/package.json +33 -16
- package/dist/actions.d.ts.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/cms.config.d.ts +0 -77
- package/dist/cms.config.d.ts.map +0 -1
- package/dist/cms.config.js +0 -111
- package/dist/cms.config.js.map +0 -1
- package/dist/entities/cms-audit-logs.d.ts.map +0 -1
- package/dist/entities/cms-draft-cache.d.ts.map +0 -1
- package/dist/entities/cms-label-values.d.ts.map +0 -1
- package/dist/entities/cms-label-versions.d.ts.map +0 -1
- package/dist/entities/cms-labels.d.ts.map +0 -1
- package/dist/entities/cms-published-cache.d.ts.map +0 -1
- package/dist/entities/index.d.ts.map +0 -1
- package/dist/generators/index.d.ts.map +0 -1
- package/dist/generators/label-sync-generator.d.ts.map +0 -1
- package/dist/generators/label-sync-generator.js +0 -87
- package/dist/generators/label-sync-generator.js.map +0 -1
- package/dist/helpers/locale.actions.d.ts +0 -132
- package/dist/helpers/locale.actions.d.ts.map +0 -1
- package/dist/helpers/locale.actions.js +0 -210
- package/dist/helpers/locale.actions.js.map +0 -1
- package/dist/helpers/locale.constants.d.ts +0 -10
- package/dist/helpers/locale.constants.d.ts.map +0 -1
- package/dist/helpers/locale.constants.js +0 -10
- package/dist/helpers/locale.constants.js.map +0 -1
- package/dist/helpers/locale.d.ts +0 -17
- package/dist/helpers/locale.d.ts.map +0 -1
- package/dist/helpers/locale.js +0 -20
- package/dist/helpers/locale.js.map +0 -1
- package/dist/helpers/sync.d.ts +0 -41
- package/dist/helpers/sync.d.ts.map +0 -1
- package/dist/helpers/sync.js +0 -309
- package/dist/helpers/sync.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/init.d.ts +0 -31
- package/dist/init.d.ts.map +0 -1
- package/dist/init.js +0 -36
- package/dist/init.js.map +0 -1
- package/dist/labels/helpers.d.ts +0 -31
- package/dist/labels/helpers.d.ts.map +0 -1
- package/dist/labels/helpers.js +0 -60
- package/dist/labels/helpers.js.map +0 -1
- package/dist/labels/index.d.ts.map +0 -1
- package/dist/repositories/cms-draft-cache.repository.d.ts +0 -62
- package/dist/repositories/cms-draft-cache.repository.d.ts.map +0 -1
- package/dist/repositories/cms-draft-cache.repository.js +0 -56
- package/dist/repositories/cms-draft-cache.repository.js.map +0 -1
- package/dist/repositories/cms-label-values.repository.d.ts +0 -32
- package/dist/repositories/cms-label-values.repository.d.ts.map +0 -1
- package/dist/repositories/cms-label-values.repository.js +0 -72
- package/dist/repositories/cms-label-values.repository.js.map +0 -1
- package/dist/repositories/cms-labels.repository.d.ts +0 -53
- package/dist/repositories/cms-labels.repository.d.ts.map +0 -1
- package/dist/repositories/cms-labels.repository.js +0 -77
- package/dist/repositories/cms-labels.repository.js.map +0 -1
- package/dist/repositories/cms-published-cache.repository.d.ts +0 -53
- package/dist/repositories/cms-published-cache.repository.d.ts.map +0 -1
- package/dist/repositories/cms-published-cache.repository.js +0 -54
- package/dist/repositories/cms-published-cache.repository.js.map +0 -1
- package/dist/repositories/index.d.ts.map +0 -1
- package/dist/routes/labels/[id]/contract.d.ts +0 -68
- package/dist/routes/labels/[id]/contract.d.ts.map +0 -1
- package/dist/routes/labels/[id]/contract.js +0 -84
- package/dist/routes/labels/[id]/contract.js.map +0 -1
- package/dist/routes/labels/[id]/index.d.ts.map +0 -1
- package/dist/routes/labels/by-key/[key]/contract.d.ts +0 -24
- package/dist/routes/labels/by-key/[key]/contract.d.ts.map +0 -1
- package/dist/routes/labels/by-key/[key]/contract.js +0 -28
- package/dist/routes/labels/by-key/[key]/contract.js.map +0 -1
- package/dist/routes/labels/by-key/[key]/index.d.ts +0 -8
- package/dist/routes/labels/by-key/[key]/index.d.ts.map +0 -1
- package/dist/routes/labels/contract.d.ts +0 -59
- package/dist/routes/labels/contract.d.ts.map +0 -1
- package/dist/routes/labels/contract.js +0 -75
- package/dist/routes/labels/contract.js.map +0 -1
- package/dist/routes/labels/index.d.ts.map +0 -1
- package/dist/routes/published-cache/contract.d.ts +0 -25
- package/dist/routes/published-cache/contract.d.ts.map +0 -1
- package/dist/routes/published-cache/contract.js +0 -35
- package/dist/routes/published-cache/contract.js.map +0 -1
- package/dist/routes/published-cache/index.d.ts.map +0 -1
- package/dist/routes/values/[labelId]/[version]/contract.d.ts +0 -29
- package/dist/routes/values/[labelId]/[version]/contract.d.ts.map +0 -1
- package/dist/routes/values/[labelId]/[version]/contract.js +0 -33
- package/dist/routes/values/[labelId]/[version]/contract.js.map +0 -1
- package/dist/routes/values/[labelId]/[version]/index.d.ts +0 -8
- package/dist/routes/values/[labelId]/[version]/index.d.ts.map +0 -1
- package/dist/routes/values/[labelId]/contract.d.ts +0 -38
- package/dist/routes/values/[labelId]/contract.d.ts.map +0 -1
- package/dist/routes/values/[labelId]/contract.js +0 -59
- package/dist/routes/values/[labelId]/contract.js.map +0 -1
- package/dist/routes/values/[labelId]/index.d.ts +0 -8
- package/dist/routes/values/[labelId]/index.d.ts.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/store.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* CMS Server Module
|
|
3
|
+
*
|
|
4
|
+
* Next.js 서버 컴포넌트용 CMS 유틸리티
|
|
5
|
+
* - React cache를 사용한 데이터 중복 제거
|
|
6
|
+
* - SPFN API를 통한 contract-based 호출
|
|
7
|
+
* - 변수 치환 지원
|
|
8
|
+
* - 쿠키 기반 locale 자동 관리
|
|
9
|
+
*
|
|
10
|
+
* @note This module should only be imported in server-side code
|
|
11
|
+
*/
|
|
2
12
|
/**
|
|
3
13
|
* Section Data Type
|
|
4
14
|
*/
|
|
5
|
-
|
|
15
|
+
type SectionData = {
|
|
6
16
|
section: string;
|
|
7
17
|
locale: string;
|
|
8
18
|
content: Record<string, any>;
|
|
@@ -16,7 +26,7 @@ type ServerTranslationFunction = (key: string, defaultValue?: any, replace?: Rec
|
|
|
16
26
|
/**
|
|
17
27
|
* Section API Return Type
|
|
18
28
|
*/
|
|
19
|
-
|
|
29
|
+
type SectionAPI = {
|
|
20
30
|
/**
|
|
21
31
|
* 라벨 값 가져오기 (변수 치환 지원)
|
|
22
32
|
*
|
|
@@ -63,7 +73,7 @@ export type SectionAPI = {
|
|
|
63
73
|
* }
|
|
64
74
|
* ```
|
|
65
75
|
*/
|
|
66
|
-
|
|
76
|
+
declare const getSection: (section: string, locale?: string) => Promise<SectionAPI>;
|
|
67
77
|
/**
|
|
68
78
|
* 여러 섹션 한번에 로드 (React cache 적용)
|
|
69
79
|
* 단일 API 호출로 여러 섹션을 효율적으로 가져옵니다
|
|
@@ -94,6 +104,6 @@ export declare const getSection: (section: string, locale?: string) => Promise<S
|
|
|
94
104
|
* }
|
|
95
105
|
* ```
|
|
96
106
|
*/
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
declare const getSections: (sections: string[], locale?: string) => Promise<Record<string, SectionAPI>>;
|
|
108
|
+
|
|
109
|
+
export { type SectionAPI, type SectionData, getSection, getSections };
|
package/dist/server.js
CHANGED
|
@@ -1,264 +1,275 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
// src/server.ts
|
|
2
|
+
import { cache } from "react";
|
|
3
|
+
import { client } from "@spfn/core/client";
|
|
4
|
+
|
|
5
|
+
// src/contracts/published-cache.ts
|
|
6
|
+
import { Type } from "@sinclair/typebox";
|
|
7
|
+
var SectionData = Type.Object({
|
|
8
|
+
section: Type.String(),
|
|
9
|
+
locale: Type.String(),
|
|
10
|
+
content: Type.Record(Type.String(), Type.Any()),
|
|
11
|
+
version: Type.Number(),
|
|
12
|
+
publishedAt: Type.Union([Type.String(), Type.Null()])
|
|
13
|
+
});
|
|
14
|
+
var getPublishedCacheContract = {
|
|
15
|
+
method: "GET",
|
|
16
|
+
path: "/cms/published-cache",
|
|
17
|
+
query: Type.Object({
|
|
18
|
+
sections: Type.Union([
|
|
19
|
+
Type.String({ description: "\uB2E8\uC77C \uC139\uC158 \uC774\uB984 (\uC608: home)" }),
|
|
20
|
+
Type.Array(Type.String(), { description: '\uC5EC\uB7EC \uC139\uC158 \uC774\uB984 (\uC608: ["home", "footer"])' })
|
|
21
|
+
]),
|
|
22
|
+
locale: Type.Optional(Type.String({ default: "ko", description: "\uC5B8\uC5B4 \uCF54\uB4DC" }))
|
|
23
|
+
}),
|
|
24
|
+
response: Type.Union([
|
|
25
|
+
// 성공: 항상 배열로 반환
|
|
26
|
+
Type.Array(SectionData),
|
|
27
|
+
// 에러
|
|
28
|
+
Type.Object({
|
|
29
|
+
error: Type.String()
|
|
30
|
+
})
|
|
31
|
+
])
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// src/helpers/locale.actions.ts
|
|
35
|
+
import { cookies, headers } from "next/headers.js";
|
|
36
|
+
|
|
37
|
+
// src/cms.config.ts
|
|
38
|
+
function getEnvVar(key, defaultValue) {
|
|
39
|
+
return process.env[key] || defaultValue;
|
|
40
|
+
}
|
|
41
|
+
function getEnvBoolean(key, defaultValue) {
|
|
42
|
+
const value = process.env[key];
|
|
43
|
+
if (value === void 0) return defaultValue;
|
|
44
|
+
return value === "true" || value === "1";
|
|
45
|
+
}
|
|
46
|
+
function loadConfigFromEnv() {
|
|
47
|
+
const defaultLocale = getEnvVar("SPFN_CMS_DEFAULT_LOCALE", "en");
|
|
48
|
+
const supportedLocalesStr = getEnvVar("SPFN_CMS_SUPPORTED_LOCALES", "en,ko");
|
|
49
|
+
const detectBrowserLanguage2 = getEnvBoolean("SPFN_CMS_DETECT_BROWSER_LANGUAGE", true);
|
|
50
|
+
const supportedLocales = supportedLocalesStr.split(",").map((locale) => locale.trim()).filter((locale) => locale.length > 0);
|
|
51
|
+
if (!supportedLocales.includes(defaultLocale)) {
|
|
52
|
+
supportedLocales.unshift(defaultLocale);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
defaultLocale,
|
|
56
|
+
supportedLocales,
|
|
57
|
+
detectBrowserLanguage: detectBrowserLanguage2
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
var currentConfig = loadConfigFromEnv();
|
|
61
|
+
function getCmsConfig() {
|
|
62
|
+
return currentConfig;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/helpers/locale.constants.ts
|
|
66
|
+
var LOCALE_COOKIE_KEY = "spfn-locale";
|
|
67
|
+
|
|
68
|
+
// src/helpers/locale.actions.ts
|
|
69
|
+
async function detectBrowserLanguage() {
|
|
70
|
+
try {
|
|
71
|
+
const headersList = await headers();
|
|
72
|
+
const acceptLanguage = headersList.get("accept-language");
|
|
73
|
+
if (!acceptLanguage) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const languages = acceptLanguage.split(",").map((lang) => {
|
|
77
|
+
const [code] = lang.split(";");
|
|
78
|
+
return code.split("-")[0].trim();
|
|
26
79
|
});
|
|
80
|
+
const config = getCmsConfig();
|
|
81
|
+
for (const lang of languages) {
|
|
82
|
+
if (config.supportedLocales.includes(lang)) {
|
|
83
|
+
return lang;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
27
90
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const found = response[0];
|
|
84
|
-
if (!found) {
|
|
85
|
-
// Section not found, return empty
|
|
86
|
-
const sectionData = {
|
|
87
|
-
section,
|
|
88
|
-
locale: actualLocale,
|
|
89
|
-
content: {},
|
|
90
|
-
version: 0,
|
|
91
|
-
publishedAt: null,
|
|
92
|
-
};
|
|
93
|
-
const t = (_key, defaultValue) => defaultValue ?? '';
|
|
94
|
-
return { t, data: sectionData };
|
|
95
|
-
}
|
|
96
|
-
// Success response
|
|
97
|
-
const sectionData = {
|
|
98
|
-
section: found.section,
|
|
99
|
-
locale: found.locale,
|
|
100
|
-
content: found.content || {},
|
|
101
|
-
version: found.version,
|
|
102
|
-
publishedAt: found.publishedAt,
|
|
103
|
-
};
|
|
104
|
-
// Translation function
|
|
105
|
-
const t = (key, defaultValue, replace) => {
|
|
106
|
-
const fullKey = `${section}.${key}`;
|
|
107
|
-
let value = sectionData.content[fullKey];
|
|
108
|
-
if (value === undefined || value === null) {
|
|
109
|
-
value = defaultValue ?? '';
|
|
110
|
-
}
|
|
111
|
-
// 문자열이 아니면 빈 문자열 반환
|
|
112
|
-
if (typeof value !== 'string') {
|
|
113
|
-
return '';
|
|
114
|
-
}
|
|
115
|
-
// 문자열이고 치환 맵이 있으면 변수 치환
|
|
116
|
-
if (replace) {
|
|
117
|
-
value = replaceVariables(value, replace);
|
|
118
|
-
}
|
|
119
|
-
return value;
|
|
120
|
-
};
|
|
121
|
-
return {
|
|
122
|
-
t,
|
|
123
|
-
data: sectionData,
|
|
124
|
-
};
|
|
91
|
+
async function getLocale() {
|
|
92
|
+
const config = getCmsConfig();
|
|
93
|
+
const cookieStore = await cookies();
|
|
94
|
+
const cookieLocale = cookieStore.get(LOCALE_COOKIE_KEY)?.value;
|
|
95
|
+
if (cookieLocale && config.supportedLocales.includes(cookieLocale)) {
|
|
96
|
+
return cookieLocale;
|
|
97
|
+
}
|
|
98
|
+
if (config.detectBrowserLanguage) {
|
|
99
|
+
const browserLang = await detectBrowserLanguage();
|
|
100
|
+
if (browserLang) {
|
|
101
|
+
return browserLang;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return config.defaultLocale;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/server.ts
|
|
108
|
+
function replaceVariables(text, replace) {
|
|
109
|
+
return text.replace(/\{(\w+)}/g, (match, key) => {
|
|
110
|
+
const value = replace[key];
|
|
111
|
+
return value !== void 0 ? String(value) : match;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
var getSection = cache(async (section, locale) => {
|
|
115
|
+
const actualLocale = locale ?? await getLocale();
|
|
116
|
+
try {
|
|
117
|
+
const response = await client.call(
|
|
118
|
+
getPublishedCacheContract,
|
|
119
|
+
{
|
|
120
|
+
query: { sections: section, locale: actualLocale }
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
if ("error" in response) {
|
|
124
|
+
console.warn(`[CMS] ${response.error}`);
|
|
125
|
+
const sectionData2 = {
|
|
126
|
+
section,
|
|
127
|
+
locale: actualLocale,
|
|
128
|
+
content: {},
|
|
129
|
+
version: 0,
|
|
130
|
+
publishedAt: null
|
|
131
|
+
};
|
|
132
|
+
const t2 = (_key, defaultValue) => defaultValue ?? "";
|
|
133
|
+
return { t: t2, data: sectionData2 };
|
|
134
|
+
}
|
|
135
|
+
const found = response[0];
|
|
136
|
+
if (!found) {
|
|
137
|
+
const sectionData2 = {
|
|
138
|
+
section,
|
|
139
|
+
locale: actualLocale,
|
|
140
|
+
content: {},
|
|
141
|
+
version: 0,
|
|
142
|
+
publishedAt: null
|
|
143
|
+
};
|
|
144
|
+
const t2 = (_key, defaultValue) => defaultValue ?? "";
|
|
145
|
+
return { t: t2, data: sectionData2 };
|
|
125
146
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
147
|
+
const sectionData = {
|
|
148
|
+
section: found.section,
|
|
149
|
+
locale: found.locale,
|
|
150
|
+
content: found.content || {},
|
|
151
|
+
version: found.version,
|
|
152
|
+
publishedAt: found.publishedAt
|
|
153
|
+
};
|
|
154
|
+
const t = (key, defaultValue, replace) => {
|
|
155
|
+
const fullKey = `${section}.${key}`;
|
|
156
|
+
let value = sectionData.content[fullKey];
|
|
157
|
+
if (value === void 0 || value === null) {
|
|
158
|
+
value = defaultValue ?? "";
|
|
159
|
+
}
|
|
160
|
+
if (typeof value !== "string") {
|
|
161
|
+
return "";
|
|
162
|
+
}
|
|
163
|
+
if (replace) {
|
|
164
|
+
value = replaceVariables(value, replace);
|
|
165
|
+
}
|
|
166
|
+
return value;
|
|
167
|
+
};
|
|
168
|
+
return {
|
|
169
|
+
t,
|
|
170
|
+
data: sectionData
|
|
171
|
+
};
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.error(`[CMS] Failed to fetch section "${section}":`, error);
|
|
174
|
+
const sectionData = {
|
|
175
|
+
section,
|
|
176
|
+
locale: actualLocale,
|
|
177
|
+
content: {},
|
|
178
|
+
version: 0,
|
|
179
|
+
publishedAt: null
|
|
180
|
+
};
|
|
181
|
+
const t = (_key, defaultValue) => defaultValue ?? "";
|
|
182
|
+
return { t, data: sectionData };
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
var getSections = cache(async (sections, locale) => {
|
|
186
|
+
const actualLocale = locale ?? await getLocale();
|
|
187
|
+
try {
|
|
188
|
+
const response = await client.call(
|
|
189
|
+
getPublishedCacheContract,
|
|
190
|
+
{
|
|
191
|
+
query: { sections, locale: actualLocale }
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
if ("error" in response) {
|
|
195
|
+
console.warn(`[CMS] ${response.error}`);
|
|
196
|
+
const sectionsMap2 = {};
|
|
197
|
+
sections.forEach((section) => {
|
|
198
|
+
sectionsMap2[section] = {
|
|
199
|
+
t: (_key, defaultValue) => defaultValue ?? "",
|
|
200
|
+
data: {
|
|
130
201
|
section,
|
|
131
202
|
locale: actualLocale,
|
|
132
203
|
content: {},
|
|
133
204
|
version: 0,
|
|
134
|
-
publishedAt: null
|
|
205
|
+
publishedAt: null
|
|
206
|
+
}
|
|
135
207
|
};
|
|
136
|
-
|
|
137
|
-
|
|
208
|
+
});
|
|
209
|
+
return sectionsMap2;
|
|
138
210
|
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
* ```tsx
|
|
150
|
-
* // Server Component
|
|
151
|
-
* import { getSections } from '@spfn/cms/server';
|
|
152
|
-
*
|
|
153
|
-
* export default async function Page()
|
|
154
|
-
* {
|
|
155
|
-
* // locale을 지정하지 않으면 쿠키에서 자동으로 가져옴
|
|
156
|
-
* const sections = await getSections(['home', 'why-futureplay']);
|
|
157
|
-
*
|
|
158
|
-
* // 또는 명시적으로 locale 지정
|
|
159
|
-
* const sectionsEn = await getSections(['home', 'why-futureplay'], 'en');
|
|
160
|
-
*
|
|
161
|
-
* return (
|
|
162
|
-
* <div>
|
|
163
|
-
* <h1>{sections.home.t('hero.title')}</h1>
|
|
164
|
-
* <p>{sections['why-futureplay'].t('intro.text')}</p>
|
|
165
|
-
* </div>
|
|
166
|
-
* );
|
|
167
|
-
* }
|
|
168
|
-
* ```
|
|
169
|
-
*/
|
|
170
|
-
export const getSections = cache(async (sections, locale) => {
|
|
171
|
-
// locale이 지정되지 않으면 쿠키에서 가져옴
|
|
172
|
-
const actualLocale = locale ?? await getLocale();
|
|
173
|
-
try {
|
|
174
|
-
// Call SPFN API with array of sections (single HTTP request)
|
|
175
|
-
const response = await client.call('/cms/published-cache', getPublishedCacheContract, {
|
|
176
|
-
query: { sections, locale: actualLocale },
|
|
177
|
-
});
|
|
178
|
-
// Check if response has error
|
|
179
|
-
if ('error' in response) {
|
|
180
|
-
console.warn(`[CMS] ${response.error}`);
|
|
181
|
-
// Return empty sections
|
|
182
|
-
const sectionsMap = {};
|
|
183
|
-
sections.forEach(section => {
|
|
184
|
-
sectionsMap[section] = {
|
|
185
|
-
t: (_key, defaultValue) => defaultValue ?? '',
|
|
186
|
-
data: {
|
|
187
|
-
section,
|
|
188
|
-
locale: actualLocale,
|
|
189
|
-
content: {},
|
|
190
|
-
version: 0,
|
|
191
|
-
publishedAt: null,
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
});
|
|
195
|
-
return sectionsMap;
|
|
211
|
+
const sectionsMap = {};
|
|
212
|
+
sections.forEach((section) => {
|
|
213
|
+
sectionsMap[section] = {
|
|
214
|
+
t: (_key, defaultValue) => defaultValue ?? "",
|
|
215
|
+
data: {
|
|
216
|
+
section,
|
|
217
|
+
locale: actualLocale,
|
|
218
|
+
content: {},
|
|
219
|
+
version: 0,
|
|
220
|
+
publishedAt: null
|
|
196
221
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
catch (error) {
|
|
246
|
-
console.error(`[CMS] Failed to fetch sections:`, error);
|
|
247
|
-
// Return empty sections on error
|
|
248
|
-
const sectionsMap = {};
|
|
249
|
-
sections.forEach(section => {
|
|
250
|
-
sectionsMap[section] = {
|
|
251
|
-
t: (_key, defaultValue) => defaultValue ?? '',
|
|
252
|
-
data: {
|
|
253
|
-
section,
|
|
254
|
-
locale: actualLocale,
|
|
255
|
-
content: {},
|
|
256
|
-
version: 0,
|
|
257
|
-
publishedAt: null,
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
});
|
|
261
|
-
return sectionsMap;
|
|
262
|
-
}
|
|
222
|
+
};
|
|
223
|
+
});
|
|
224
|
+
response.forEach((sectionData) => {
|
|
225
|
+
const createTranslationFn = (section, content) => {
|
|
226
|
+
return (key, defaultValue, replace) => {
|
|
227
|
+
const fullKey = `${section}.${key}`;
|
|
228
|
+
let value = content[fullKey];
|
|
229
|
+
if (value === void 0 || value === null) {
|
|
230
|
+
value = defaultValue ?? "";
|
|
231
|
+
}
|
|
232
|
+
if (typeof value !== "string") {
|
|
233
|
+
return "";
|
|
234
|
+
}
|
|
235
|
+
if (replace) {
|
|
236
|
+
value = replaceVariables(value, replace);
|
|
237
|
+
}
|
|
238
|
+
return value;
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
sectionsMap[sectionData.section] = {
|
|
242
|
+
t: createTranslationFn(sectionData.section, sectionData.content),
|
|
243
|
+
data: {
|
|
244
|
+
section: sectionData.section,
|
|
245
|
+
locale: sectionData.locale,
|
|
246
|
+
content: sectionData.content,
|
|
247
|
+
version: sectionData.version,
|
|
248
|
+
publishedAt: sectionData.publishedAt
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
return sectionsMap;
|
|
253
|
+
} catch (error) {
|
|
254
|
+
console.error(`[CMS] Failed to fetch sections:`, error);
|
|
255
|
+
const sectionsMap = {};
|
|
256
|
+
sections.forEach((section) => {
|
|
257
|
+
sectionsMap[section] = {
|
|
258
|
+
t: (_key, defaultValue) => defaultValue ?? "",
|
|
259
|
+
data: {
|
|
260
|
+
section,
|
|
261
|
+
locale: actualLocale,
|
|
262
|
+
content: {},
|
|
263
|
+
version: 0,
|
|
264
|
+
publishedAt: null
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
});
|
|
268
|
+
return sectionsMap;
|
|
269
|
+
}
|
|
263
270
|
});
|
|
271
|
+
export {
|
|
272
|
+
getSection,
|
|
273
|
+
getSections
|
|
274
|
+
};
|
|
264
275
|
//# sourceMappingURL=server.js.map
|