@spfn/cms 0.1.0-alpha.64 → 0.1.0-alpha.65

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 (103) hide show
  1. package/README.md +67 -30
  2. package/dist/actions-CwvmPG0e.d.ts +296 -0
  3. package/dist/actions.d.ts +1 -143
  4. package/dist/actions.js +5 -5
  5. package/dist/actions.js.map +1 -1
  6. package/dist/api.d.ts +376 -0
  7. package/dist/api.js +364 -0
  8. package/dist/api.js.map +1 -0
  9. package/dist/client.d.ts +115 -141
  10. package/dist/client.js +860 -63
  11. package/dist/client.js.map +1 -1
  12. package/dist/{types.d.ts → index-Dh5FjWzR.d.ts} +32 -1
  13. package/dist/index.d.ts +21 -43
  14. package/dist/index.js +556 -1061
  15. package/dist/index.js.map +1 -1
  16. package/dist/label-sync-generator-B0EmvtWM.d.ts +32 -0
  17. package/dist/{contracts → lib/contracts}/labels.d.ts +13 -12
  18. package/dist/{contracts → lib/contracts}/labels.js +7 -7
  19. package/dist/lib/contracts/labels.js.map +1 -0
  20. package/dist/{contracts → lib/contracts}/published-cache.d.ts +3 -2
  21. package/dist/{contracts → lib/contracts}/published-cache.js +2 -2
  22. package/dist/lib/contracts/published-cache.js.map +1 -0
  23. package/dist/{contracts → lib/contracts}/values.d.ts +6 -4
  24. package/dist/{contracts → lib/contracts}/values.js +3 -3
  25. package/dist/lib/contracts/values.js.map +1 -0
  26. package/dist/{entities → server/entities}/cms-audit-logs.js +3 -3
  27. package/dist/server/entities/cms-audit-logs.js.map +1 -0
  28. package/dist/{entities → server/entities}/cms-draft-cache.js +1 -1
  29. package/dist/server/entities/cms-draft-cache.js.map +1 -0
  30. package/dist/{entities → server/entities}/cms-label-values.js +3 -3
  31. package/dist/server/entities/cms-label-values.js.map +1 -0
  32. package/dist/{entities → server/entities}/cms-label-versions.js +3 -3
  33. package/dist/server/entities/cms-label-versions.js.map +1 -0
  34. package/dist/{entities → server/entities}/cms-labels.js +1 -1
  35. package/dist/server/entities/cms-labels.js.map +1 -0
  36. package/dist/{entities → server/entities}/cms-published-cache.js +1 -1
  37. package/dist/server/entities/cms-published-cache.js.map +1 -0
  38. package/dist/{entities → server/entities}/index.js +6 -6
  39. package/dist/server/entities/index.js.map +1 -0
  40. package/dist/{generators → server/generators}/index.d.ts +1 -2
  41. package/dist/{generators → server/generators}/index.js +169 -75
  42. package/dist/server/generators/index.js.map +1 -0
  43. package/dist/server/labels/index.d.ts +1 -0
  44. package/dist/{labels → server/labels}/index.js +1 -1
  45. package/dist/server/labels/index.js.map +1 -0
  46. package/dist/{repositories → server/repositories}/index.js +11 -11
  47. package/dist/server/repositories/index.js.map +1 -0
  48. package/dist/{routes → server/routes}/labels/[id]/index.js +20 -20
  49. package/dist/server/routes/labels/[id]/index.js.map +1 -0
  50. package/dist/{routes → server/routes}/labels/by-key/[key]/index.js +20 -20
  51. package/dist/server/routes/labels/by-key/[key]/index.js.map +1 -0
  52. package/dist/{routes → server/routes}/labels/index.d.ts +2 -2
  53. package/dist/{routes → server/routes}/labels/index.js +21 -22
  54. package/dist/server/routes/labels/index.js.map +1 -0
  55. package/dist/{routes → server/routes}/published-cache/index.js +14 -14
  56. package/dist/server/routes/published-cache/index.js.map +1 -0
  57. package/dist/{routes → server/routes}/values/[labelId]/[version]/index.js +16 -16
  58. package/dist/server/routes/values/[labelId]/[version]/index.js.map +1 -0
  59. package/dist/{routes → server/routes}/values/[labelId]/index.js +16 -16
  60. package/dist/server/routes/values/[labelId]/index.js.map +1 -0
  61. package/dist/server.d.ts +76 -7
  62. package/dist/server.js +1601 -42
  63. package/dist/server.js.map +1 -1
  64. package/package.json +37 -35
  65. package/dist/contracts/labels.js.map +0 -1
  66. package/dist/contracts/published-cache.js.map +0 -1
  67. package/dist/contracts/values.js.map +0 -1
  68. package/dist/entities/cms-audit-logs.js.map +0 -1
  69. package/dist/entities/cms-draft-cache.js.map +0 -1
  70. package/dist/entities/cms-label-values.js.map +0 -1
  71. package/dist/entities/cms-label-versions.js.map +0 -1
  72. package/dist/entities/cms-labels.js.map +0 -1
  73. package/dist/entities/cms-published-cache.js.map +0 -1
  74. package/dist/entities/index.js.map +0 -1
  75. package/dist/generators/index.js.map +0 -1
  76. package/dist/label-sync-generator-lQrcVfja.d.ts +0 -36
  77. package/dist/labels/index.d.ts +0 -34
  78. package/dist/labels/index.js.map +0 -1
  79. package/dist/repositories/index.js.map +0 -1
  80. package/dist/routes/labels/[id]/index.js.map +0 -1
  81. package/dist/routes/labels/by-key/[key]/index.js.map +0 -1
  82. package/dist/routes/labels/index.js.map +0 -1
  83. package/dist/routes/published-cache/index.js.map +0 -1
  84. package/dist/routes/values/[labelId]/[version]/index.js.map +0 -1
  85. package/dist/routes/values/[labelId]/index.js.map +0 -1
  86. package/dist/store.d.ts +0 -81
  87. package/dist/store.js +0 -403
  88. package/dist/store.js.map +0 -1
  89. package/dist/types.js +0 -1
  90. package/dist/types.js.map +0 -1
  91. package/dist/{entities → server/entities}/cms-audit-logs.d.ts +0 -0
  92. package/dist/{entities → server/entities}/cms-draft-cache.d.ts +0 -0
  93. package/dist/{entities → server/entities}/cms-label-values.d.ts +0 -0
  94. package/dist/{entities → server/entities}/cms-label-versions.d.ts +0 -0
  95. package/dist/{entities → server/entities}/cms-labels.d.ts +0 -0
  96. package/dist/{entities → server/entities}/cms-published-cache.d.ts +0 -0
  97. package/dist/{entities → server/entities}/index.d.ts +0 -0
  98. package/dist/{repositories → server/repositories}/index.d.ts +14 -14
  99. /package/dist/{routes → server/routes}/labels/_id_/index.d.ts +0 -0
  100. /package/dist/{routes → server/routes}/labels/by-key/_key_/index.d.ts +0 -0
  101. /package/dist/{routes → server/routes}/published-cache/index.d.ts +0 -0
  102. /package/dist/{routes → server/routes}/values/_labelId_/_version_/index.d.ts +0 -0
  103. /package/dist/{routes → server/routes}/values/_labelId_/index.d.ts +0 -0
package/dist/store.js DELETED
@@ -1,403 +0,0 @@
1
- "use client";
2
-
3
- // src/store.ts
4
- import React from "react";
5
- import { create } from "zustand";
6
-
7
- // src/client.ts
8
- import { client } from "@spfn/core/client";
9
-
10
- // src/contracts/labels.ts
11
- import { Type } from "@sinclair/typebox";
12
- var getLabelsContract = {
13
- method: "GET",
14
- path: "/cms/labels",
15
- query: Type.Object({
16
- section: Type.Optional(Type.String({ description: "\uC139\uC158\uC73C\uB85C \uD544\uD130\uB9C1 (\uC608: home, why-futureplay)" })),
17
- limit: Type.Optional(Type.Number({ minimum: 1, maximum: 100, default: 20, description: "\uD398\uC774\uC9C0\uB2F9 \uD56D\uBAA9 \uC218" })),
18
- offset: Type.Optional(Type.Number({ minimum: 0, default: 0, description: "\uC2DC\uC791 \uC624\uD504\uC14B" }))
19
- }),
20
- response: Type.Object({
21
- labels: Type.Array(Type.Object({
22
- id: Type.Number(),
23
- key: Type.String(),
24
- section: Type.String(),
25
- type: Type.String(),
26
- publishedVersion: Type.Union([Type.Number(), Type.Null()]),
27
- createdBy: Type.Union([Type.String(), Type.Null()]),
28
- createdAt: Type.String(),
29
- updatedAt: Type.String()
30
- })),
31
- total: Type.Number(),
32
- limit: Type.Number(),
33
- offset: Type.Number()
34
- })
35
- };
36
- var createLabelContract = {
37
- method: "POST",
38
- path: "/cms/labels",
39
- body: Type.Object({
40
- key: Type.String({
41
- description: "\uACE0\uC720 \uD0A4 (\uC608: home.hero.title)",
42
- pattern: "^[a-z0-9-]+\\.[a-z0-9-]+\\.[a-z0-9-]+$"
43
- }),
44
- section: Type.String({
45
- description: "\uC139\uC158 \uC774\uB984 (\uC608: home, why-futureplay)",
46
- pattern: "^[a-z0-9-]+$"
47
- }),
48
- type: Type.Union([
49
- Type.Literal("text"),
50
- Type.Literal("image"),
51
- Type.Literal("video"),
52
- Type.Literal("file"),
53
- Type.Literal("object")
54
- ], { description: "\uAC12 \uD0C0\uC785" }),
55
- createdBy: Type.Optional(Type.String({ description: "\uC0DD\uC131\uC790 ID" }))
56
- }),
57
- response: Type.Union([
58
- Type.Object({
59
- id: Type.Number(),
60
- key: Type.String(),
61
- section: Type.String(),
62
- type: Type.String(),
63
- publishedVersion: Type.Union([Type.Number(), Type.Null()]),
64
- createdBy: Type.Union([Type.String(), Type.Null()]),
65
- createdAt: Type.String(),
66
- updatedAt: Type.String()
67
- }),
68
- Type.Object({
69
- error: Type.String(),
70
- key: Type.Optional(Type.String())
71
- })
72
- ])
73
- };
74
- var getLabelContract = {
75
- method: "GET",
76
- path: "/cms/labels/:id",
77
- params: Type.Object({
78
- id: Type.String({ description: "\uB77C\uBCA8 ID" })
79
- }),
80
- response: Type.Union([
81
- Type.Object({
82
- id: Type.Number(),
83
- key: Type.String(),
84
- section: Type.String(),
85
- type: Type.String(),
86
- publishedVersion: Type.Union([Type.Number(), Type.Null()]),
87
- createdBy: Type.Union([Type.String(), Type.Null()]),
88
- createdAt: Type.String(),
89
- updatedAt: Type.String()
90
- }),
91
- Type.Object({
92
- error: Type.String()
93
- })
94
- ])
95
- };
96
- var updateLabelContract = {
97
- method: "PATCH",
98
- path: "/cms/labels/:id",
99
- params: Type.Object({
100
- id: Type.String({ description: "\uB77C\uBCA8 ID" })
101
- }),
102
- body: Type.Object({
103
- section: Type.Optional(Type.String({ description: "\uC139\uC158 \uBCC0\uACBD" })),
104
- type: Type.Optional(Type.Union([
105
- Type.Literal("text"),
106
- Type.Literal("image"),
107
- Type.Literal("video"),
108
- Type.Literal("file"),
109
- Type.Literal("object")
110
- ]))
111
- }),
112
- response: Type.Union([
113
- Type.Object({
114
- id: Type.Number(),
115
- key: Type.String(),
116
- section: Type.String(),
117
- type: Type.String(),
118
- publishedVersion: Type.Union([Type.Number(), Type.Null()]),
119
- createdBy: Type.Union([Type.String(), Type.Null()]),
120
- createdAt: Type.String(),
121
- updatedAt: Type.String()
122
- }),
123
- Type.Object({
124
- error: Type.String()
125
- })
126
- ])
127
- };
128
- var deleteLabelContract = {
129
- method: "DELETE",
130
- path: "/cms/labels/:id",
131
- params: Type.Object({
132
- id: Type.String({ description: "\uB77C\uBCA8 ID" })
133
- }),
134
- response: Type.Union([
135
- Type.Object({
136
- success: Type.Boolean(),
137
- id: Type.Number()
138
- }),
139
- Type.Object({
140
- error: Type.String()
141
- })
142
- ])
143
- };
144
- var getLabelByKeyContract = {
145
- method: "GET",
146
- path: "/cms/labels/by-key/:key",
147
- params: Type.Object({
148
- key: Type.String({ description: "\uB77C\uBCA8 Key (\uC608: home.hero.title)" })
149
- }),
150
- response: Type.Union([
151
- Type.Object({
152
- id: Type.Number(),
153
- key: Type.String(),
154
- section: Type.String(),
155
- type: Type.String(),
156
- publishedVersion: Type.Union([Type.Number(), Type.Null()]),
157
- createdBy: Type.Union([Type.String(), Type.Null()]),
158
- createdAt: Type.String(),
159
- updatedAt: Type.String()
160
- }),
161
- Type.Object({
162
- error: Type.String(),
163
- key: Type.Optional(Type.String())
164
- })
165
- ])
166
- };
167
-
168
- // src/contracts/published-cache.ts
169
- import { Type as Type2 } from "@sinclair/typebox";
170
- var SectionData = Type2.Object({
171
- section: Type2.String(),
172
- locale: Type2.String(),
173
- content: Type2.Record(Type2.String(), Type2.Any()),
174
- version: Type2.Number(),
175
- publishedAt: Type2.Union([Type2.String(), Type2.Null()])
176
- });
177
- var getPublishedCacheContract = {
178
- method: "GET",
179
- path: "/cms/published-cache",
180
- query: Type2.Object({
181
- sections: Type2.Union([
182
- Type2.String({ description: "\uB2E8\uC77C \uC139\uC158 \uC774\uB984 (\uC608: home)" }),
183
- Type2.Array(Type2.String(), { description: '\uC5EC\uB7EC \uC139\uC158 \uC774\uB984 (\uC608: ["home", "footer"])' })
184
- ]),
185
- locale: Type2.Optional(Type2.String({ default: "ko", description: "\uC5B8\uC5B4 \uCF54\uB4DC" }))
186
- }),
187
- response: Type2.Union([
188
- // 성공: 항상 배열로 반환
189
- Type2.Array(SectionData),
190
- // 에러
191
- Type2.Object({
192
- error: Type2.String()
193
- })
194
- ])
195
- };
196
-
197
- // src/init.tsx
198
- import { useEffect } from "react";
199
-
200
- // src/client.ts
201
- var cmsApi = {
202
- /**
203
- * Labels API
204
- */
205
- labels: {
206
- /**
207
- * GET /cms/labels
208
- * 라벨 목록 조회 (섹션 필터, 페이지네이션)
209
- */
210
- list: (options) => client.call(getLabelsContract, options),
211
- /**
212
- * GET /cms/labels/:id
213
- * 특정 라벨 조회
214
- */
215
- getById: (options) => client.call(getLabelContract, options),
216
- /**
217
- * POST /cms/labels
218
- * 새 라벨 생성
219
- */
220
- create: (options) => client.call(createLabelContract, options),
221
- /**
222
- * PATCH /cms/labels/:id
223
- * 라벨 업데이트
224
- */
225
- update: (options) => client.call(updateLabelContract, options),
226
- /**
227
- * DELETE /cms/labels/:id
228
- * 라벨 삭제
229
- */
230
- delete: (options) => client.call(deleteLabelContract, options)
231
- },
232
- /**
233
- * Published Cache API
234
- */
235
- publishedCache: {
236
- /**
237
- * GET /cms/published-cache
238
- * 발행된 콘텐츠 캐시 조회
239
- */
240
- get: (options) => client.call(getPublishedCacheContract, options)
241
- }
242
- };
243
-
244
- // src/store.ts
245
- function replaceVariables(text, replace) {
246
- return text.replace(/\{(\w+)}/g, (match, key) => {
247
- const value = replace[key];
248
- return value !== void 0 ? String(value) : match;
249
- });
250
- }
251
- var useCmsStore = create((set, get) => ({
252
- sections: {},
253
- loading: {},
254
- setSection: (section, data) => {
255
- set((state) => ({
256
- sections: {
257
- ...state.sections,
258
- [section]: data
259
- }
260
- }));
261
- },
262
- setSections: (sections) => {
263
- set((state) => ({
264
- sections: {
265
- ...state.sections,
266
- ...sections
267
- }
268
- }));
269
- },
270
- loadSection: async (section, locale = "ko") => {
271
- const state = get();
272
- if (state.loading[section]) {
273
- return;
274
- }
275
- if (state.sections[section]) {
276
- return;
277
- }
278
- set((state2) => ({
279
- loading: { ...state2.loading, [section]: true }
280
- }));
281
- try {
282
- const response = await cmsApi.publishedCache.get({
283
- query: { sections: section, locale }
284
- });
285
- if ("error" in response) {
286
- console.error(`Failed to load section ${section}:`, response.error);
287
- return;
288
- }
289
- const data = response[0];
290
- if (!data) {
291
- console.warn(`Section ${section} not found`);
292
- return;
293
- }
294
- const sectionData = {
295
- section: data.section,
296
- locale: data.locale,
297
- content: data.content || {},
298
- version: data.version || 0,
299
- publishedAt: data.publishedAt || null
300
- };
301
- set((state2) => ({
302
- sections: {
303
- ...state2.sections,
304
- [section]: sectionData
305
- },
306
- loading: { ...state2.loading, [section]: false }
307
- }));
308
- } catch (error) {
309
- console.error(`Error loading CMS section ${section}:`, error);
310
- set((state2) => ({
311
- loading: { ...state2.loading, [section]: false }
312
- }));
313
- }
314
- },
315
- updateLabel: (section, key, value) => {
316
- set((state) => ({
317
- sections: {
318
- ...state.sections,
319
- [section]: {
320
- ...state.sections[section],
321
- content: {
322
- ...state.sections[section]?.content,
323
- [`${section}.${key}`]: value
324
- }
325
- }
326
- }
327
- }));
328
- },
329
- reset: () => {
330
- set({
331
- sections: {},
332
- loading: {}
333
- });
334
- }
335
- }));
336
- function useSection(section, options = {}) {
337
- const { autoLoad = false, locale = "ko" } = options;
338
- const sectionData = useCmsStore((state) => state.sections[section]);
339
- const loading = useCmsStore((state) => state.loading[section] ?? false);
340
- const loadSection = useCmsStore((state) => state.loadSection);
341
- React.useEffect(() => {
342
- if (autoLoad && !sectionData && !loading) {
343
- loadSection(section, locale);
344
- }
345
- }, [autoLoad, section, locale, sectionData, loading, loadSection]);
346
- const t = React.useCallback(
347
- (key, defaultValue, replace) => {
348
- if (!sectionData) {
349
- return defaultValue;
350
- }
351
- const fullKey = `${section}.${key}`;
352
- let value = sectionData.content[fullKey];
353
- if (value === void 0) {
354
- value = defaultValue;
355
- }
356
- if (typeof value === "string" && replace) {
357
- value = replaceVariables(value, replace);
358
- }
359
- return value;
360
- },
361
- [section, sectionData]
362
- );
363
- return {
364
- t,
365
- data: sectionData,
366
- loading
367
- };
368
- }
369
- function useSections(sectionNames) {
370
- const allSections = useCmsStore((state) => state.sections);
371
- const allLoading = useCmsStore((state) => state.loading);
372
- const result = {};
373
- sectionNames.forEach((section) => {
374
- const sectionData = allSections[section];
375
- const loading = allLoading[section] ?? false;
376
- const t = (key, defaultValue, replace) => {
377
- if (!sectionData) {
378
- return defaultValue;
379
- }
380
- const fullKey = `${section}.${key}`;
381
- let value = sectionData.content[fullKey];
382
- if (value === void 0) {
383
- value = defaultValue;
384
- }
385
- if (typeof value === "string" && replace) {
386
- value = replaceVariables(value, replace);
387
- }
388
- return value;
389
- };
390
- result[section] = {
391
- t,
392
- data: sectionData,
393
- loading
394
- };
395
- });
396
- return result;
397
- }
398
- export {
399
- useCmsStore,
400
- useSection,
401
- useSections
402
- };
403
- //# sourceMappingURL=store.js.map
package/dist/store.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/store.ts","../src/client.ts","../src/contracts/labels.ts","../src/contracts/published-cache.ts","../src/init.tsx"],"sourcesContent":["/**\n * CMS Zustand Store\n *\n * 클라이언트 컴포넌트에서 CMS 사용을 위한 상태 관리\n * - 서버에서 초기화된 데이터를 클라이언트로 전달\n * - 클라이언트에서 비동기로 로드 가능\n * - 서버 API와 동일한 패턴 ({ t } 사용)\n */\n\n'use client';\n\nimport React from 'react';\nimport { create } from 'zustand';\nimport { cmsApi } from './client';\nimport type { SectionData } from './server';\n\n/**\n * 변수 치환 헬퍼 (서버와 동일)\n */\nfunction replaceVariables(text: string, replace: Record<string, string | number>): string\n{\n return text.replace(/\\{(\\w+)}/g, (match, key) =>\n {\n const value = replace[key];\n return value !== undefined ? String(value) : match;\n });\n}\n\ninterface CmsState\n{\n /**\n * 섹션별 데이터\n * { 'home': { section: 'home', content: {...}, version: 1, ... }, ... }\n */\n sections: Record<string, SectionData>;\n\n /**\n * 로딩 상태\n */\n loading: Record<string, boolean>;\n\n /**\n * 섹션 데이터 설정 (서버에서 초기화용)\n */\n setSection: (section: string, data: SectionData) => void;\n\n /**\n * 여러 섹션 한번에 설정\n */\n setSections: (sections: Record<string, SectionData>) => void;\n\n /**\n * 섹션 비동기 로드\n */\n loadSection: (section: string, locale?: string) => Promise<void>;\n\n /**\n * 라벨 업데이트 (Draft Mode용)\n */\n updateLabel: (section: string, key: string, value: any) => void;\n\n /**\n * 초기화\n */\n reset: () => void;\n}\n\nexport const useCmsStore = create<CmsState>((set, get) => ({\n sections: {},\n loading: {},\n\n setSection: (section, data) =>\n {\n set((state) => ({\n sections: {\n ...state.sections,\n [section]: data,\n },\n }));\n },\n\n setSections: (sections) =>\n {\n set((state) => ({\n sections: {\n ...state.sections,\n ...sections,\n },\n }));\n },\n\n loadSection: async (section, locale = 'ko') =>\n {\n const state = get();\n\n // 이미 로드 중이면 스킵\n if (state.loading[section])\n {\n return;\n }\n\n // 이미 로드되어 있으면 스킵\n if (state.sections[section])\n {\n return;\n }\n\n set((state) => ({\n loading: { ...state.loading, [section]: true },\n }));\n\n try\n {\n const response = await cmsApi.publishedCache.get({\n query: { sections: section, locale },\n });\n\n // Check for error response\n if ('error' in response)\n {\n console.error(`Failed to load section ${section}:`, response.error);\n return;\n }\n\n // Response is array, get first element\n const data = response[0];\n\n if (!data)\n {\n console.warn(`Section ${section} not found`);\n return;\n }\n\n const sectionData: SectionData = {\n section: data.section,\n locale: data.locale,\n content: (data.content as Record<string, any>) || {},\n version: data.version || 0,\n publishedAt: data.publishedAt || null,\n };\n\n set((state) => ({\n sections: {\n ...state.sections,\n [section]: sectionData,\n },\n loading: { ...state.loading, [section]: false },\n }));\n }\n catch (error)\n {\n console.error(`Error loading CMS section ${section}:`, error);\n set((state) => ({\n loading: { ...state.loading, [section]: false },\n }));\n }\n },\n\n updateLabel: (section, key, value) =>\n {\n set((state) => ({\n sections: {\n ...state.sections,\n [section]: {\n ...state.sections[section],\n content: {\n ...state.sections[section]?.content,\n [`${section}.${key}`]: value,\n },\n },\n },\n }));\n },\n\n reset: () =>\n {\n set({\n sections: {},\n loading: {},\n });\n },\n}));\n\n/**\n * 섹션 Hook (서버 API와 동일한 패턴)\n *\n * @param section - 섹션 이름\n * @param options - 옵션 (autoLoad: 자동 로드 여부)\n * @returns { t, data, loading }\n *\n * @example\n * ```tsx\n * 'use client';\n * import { useSection } from '@/lib/cms';\n *\n * export function ClientComponent()\n * {\n * const { t } = useSection('home');\n * return <h1>{t('hero.title')}</h1>;\n * }\n * ```\n */\nexport function useSection(\n section: string,\n options: { autoLoad?: boolean; locale?: string } = {}\n)\n{\n const { autoLoad = false, locale = 'ko' } = options;\n\n const sectionData = useCmsStore((state) => state.sections[section]);\n const loading = useCmsStore((state) => state.loading[section] ?? false);\n const loadSection = useCmsStore((state) => state.loadSection);\n\n // 자동 로드 옵션이 켜져있고 데이터가 없으면 로드\n React.useEffect(() =>\n {\n if (autoLoad && !sectionData && !loading)\n {\n loadSection(section, locale);\n }\n }, [autoLoad, section, locale, sectionData, loading, loadSection]);\n\n // Translation function (서버와 동일)\n const t = React.useCallback(\n (key: string, defaultValue?: any, replace?: Record<string, string | number>) =>\n {\n if (!sectionData)\n {\n return defaultValue;\n }\n\n const fullKey = `${section}.${key}`;\n let value = sectionData.content[fullKey];\n\n if (value === undefined)\n {\n value = defaultValue;\n }\n\n // 문자열이고 치환 맵이 있으면 변수 치환\n if (typeof value === 'string' && replace)\n {\n value = replaceVariables(value, replace);\n }\n\n return value;\n },\n [section, sectionData]\n );\n\n return {\n t,\n data: sectionData,\n loading,\n };\n}\n\n/**\n * 여러 섹션 Hook\n *\n * @param sectionNames - 섹션 이름 배열\n * @returns { [section]: { t, data, loading }, ... }\n *\n * @example\n * ```tsx\n * const sections = useSections(['home', 'why-futureplay']);\n * sections.home.t('hero.title');\n * ```\n */\nexport function useSections(sectionNames: string[])\n{\n const allSections = useCmsStore((state) => state.sections);\n const allLoading = useCmsStore((state) => state.loading);\n\n const result: Record<string, ReturnType<typeof useSection>> = {};\n\n sectionNames.forEach((section) =>\n {\n const sectionData = allSections[section];\n const loading = allLoading[section] ?? false;\n\n const t = (key: string, defaultValue?: any, replace?: Record<string, string | number>) =>\n {\n if (!sectionData)\n {\n return defaultValue;\n }\n\n const fullKey = `${section}.${key}`;\n let value = sectionData.content[fullKey];\n\n if (value === undefined)\n {\n value = defaultValue;\n }\n\n if (typeof value === 'string' && replace)\n {\n value = replaceVariables(value, replace);\n }\n\n return value;\n };\n\n result[section] = {\n t,\n data: sectionData,\n loading,\n };\n });\n\n return result;\n}","/**\n * @spfn/cms/client\n *\n * Client Components Only\n * 클라이언트 컴포넌트 전용 (브라우저에서 실행)\n */\n\nimport { client } from '@spfn/core/client';\nimport type { InferContract } from '@spfn/core';\n\n// Labels\nimport {\n getLabelsContract,\n createLabelContract,\n getLabelContract,\n updateLabelContract,\n deleteLabelContract\n} from './contracts/labels';\n\n// Published Cache\nimport { getPublishedCacheContract } from './contracts/published-cache';\n\n/**\n * CMS API Client\n */\nexport const cmsApi = {\n /**\n * Labels API\n */\n labels: {\n /**\n * GET /cms/labels\n * 라벨 목록 조회 (섹션 필터, 페이지네이션)\n */\n list: (options?: { query?: InferContract<typeof getLabelsContract>['query'] }) =>\n client.call(getLabelsContract, options),\n\n /**\n * GET /cms/labels/:id\n * 특정 라벨 조회\n */\n getById: (options: { params: InferContract<typeof getLabelContract>['params'] }) =>\n client.call(getLabelContract, options),\n\n /**\n * POST /cms/labels\n * 새 라벨 생성\n */\n create: (options: { body: InferContract<typeof createLabelContract>['body'] }) =>\n client.call(createLabelContract, options),\n\n /**\n * PATCH /cms/labels/:id\n * 라벨 업데이트\n */\n update: (options: {\n params: InferContract<typeof updateLabelContract>['params'];\n body: InferContract<typeof updateLabelContract>['body'];\n }) =>\n client.call(updateLabelContract, options),\n\n /**\n * DELETE /cms/labels/:id\n * 라벨 삭제\n */\n delete: (options: { params: InferContract<typeof deleteLabelContract>['params'] }) =>\n client.call(deleteLabelContract, options),\n },\n\n /**\n * Published Cache API\n */\n publishedCache: {\n /**\n * GET /cms/published-cache\n * 발행된 콘텐츠 캐시 조회\n */\n get: (options: { query: InferContract<typeof getPublishedCacheContract>['query'] }) =>\n client.call(getPublishedCacheContract, options),\n },\n} as const;\n\n/**\n * Type exports\n */\nexport type CmsApi = typeof cmsApi;\n\n// Client-side Store & Hooks\nexport { useCmsStore, useSection, useSections } from './store';\n\n// Client-side Initializer\nexport { InitCms } from './init';","import { Type } from '@sinclair/typebox';\nimport type { RouteContract } from '@spfn/core/route';\n\n/**\n * CMS Labels Contracts\n *\n * 라벨 메타데이터 관리 API\n */\n\n/**\n * GET /cms/labels - 라벨 목록 조회\n */\nexport const getLabelsContract = {\n method: 'GET' as const,\n path: '/cms/labels',\n query: Type.Object({\n section: Type.Optional(Type.String({ description: '섹션으로 필터링 (예: home, why-futureplay)' })),\n limit: Type.Optional(Type.Number({ minimum: 1, maximum: 100, default: 20, description: '페이지당 항목 수' })),\n offset: Type.Optional(Type.Number({ minimum: 0, default: 0, description: '시작 오프셋' }))\n }),\n response: Type.Object({\n labels: Type.Array(Type.Object({\n id: Type.Number(),\n key: Type.String(),\n section: Type.String(),\n type: Type.String(),\n publishedVersion: Type.Union([Type.Number(), Type.Null()]),\n createdBy: Type.Union([Type.String(), Type.Null()]),\n createdAt: Type.String(),\n updatedAt: Type.String()\n })),\n total: Type.Number(),\n limit: Type.Number(),\n offset: Type.Number()\n })\n} as const satisfies RouteContract;\n\n/**\n * POST /cms/labels - 새 라벨 생성\n */\nexport const createLabelContract = {\n method: 'POST' as const,\n path: '/cms/labels',\n body: Type.Object({\n key: Type.String({\n description: '고유 키 (예: home.hero.title)',\n pattern: '^[a-z0-9-]+\\\\.[a-z0-9-]+\\\\.[a-z0-9-]+$'\n }),\n section: Type.String({\n description: '섹션 이름 (예: home, why-futureplay)',\n pattern: '^[a-z0-9-]+$'\n }),\n type: Type.Union([\n Type.Literal('text'),\n Type.Literal('image'),\n Type.Literal('video'),\n Type.Literal('file'),\n Type.Literal('object')\n ], { description: '값 타입' }),\n createdBy: Type.Optional(Type.String({ description: '생성자 ID' }))\n }),\n response: Type.Union([\n Type.Object({\n id: Type.Number(),\n key: Type.String(),\n section: Type.String(),\n type: Type.String(),\n publishedVersion: Type.Union([Type.Number(), Type.Null()]),\n createdBy: Type.Union([Type.String(), Type.Null()]),\n createdAt: Type.String(),\n updatedAt: Type.String()\n }),\n Type.Object({\n error: Type.String(),\n key: Type.Optional(Type.String())\n })\n ])\n} as const satisfies RouteContract;\n\n/**\n * GET /cms/labels/:id - 라벨 단건 조회\n */\nexport const getLabelContract = {\n method: 'GET' as const,\n path: '/cms/labels/:id',\n params: Type.Object({\n id: Type.String({ description: '라벨 ID' })\n }),\n response: Type.Union([\n Type.Object({\n id: Type.Number(),\n key: Type.String(),\n section: Type.String(),\n type: Type.String(),\n publishedVersion: Type.Union([Type.Number(), Type.Null()]),\n createdBy: Type.Union([Type.String(), Type.Null()]),\n createdAt: Type.String(),\n updatedAt: Type.String()\n }),\n Type.Object({\n error: Type.String()\n })\n ])\n} as const satisfies RouteContract;\n\n/**\n * PATCH /cms/labels/:id - 라벨 메타데이터 수정\n */\nexport const updateLabelContract = {\n method: 'PATCH' as const,\n path: '/cms/labels/:id',\n params: Type.Object({\n id: Type.String({ description: '라벨 ID' })\n }),\n body: Type.Object({\n section: Type.Optional(Type.String({ description: '섹션 변경' })),\n type: Type.Optional(Type.Union([\n Type.Literal('text'),\n Type.Literal('image'),\n Type.Literal('video'),\n Type.Literal('file'),\n Type.Literal('object')\n ]))\n }),\n response: Type.Union([\n Type.Object({\n id: Type.Number(),\n key: Type.String(),\n section: Type.String(),\n type: Type.String(),\n publishedVersion: Type.Union([Type.Number(), Type.Null()]),\n createdBy: Type.Union([Type.String(), Type.Null()]),\n createdAt: Type.String(),\n updatedAt: Type.String()\n }),\n Type.Object({\n error: Type.String()\n })\n ])\n} as const satisfies RouteContract;\n\n/**\n * DELETE /cms/labels/:id - 라벨 삭제\n */\nexport const deleteLabelContract = {\n method: 'DELETE' as const,\n path: '/cms/labels/:id',\n params: Type.Object({\n id: Type.String({ description: '라벨 ID' })\n }),\n response: Type.Union([\n Type.Object({\n success: Type.Boolean(),\n id: Type.Number()\n }),\n Type.Object({\n error: Type.String()\n })\n ])\n} as const satisfies RouteContract;\n\n/**\n * GET /cms/labels/by-key/:key - Key로 라벨 조회\n */\nexport const getLabelByKeyContract = {\n method: 'GET' as const,\n path: '/cms/labels/by-key/:key',\n params: Type.Object({\n key: Type.String({ description: '라벨 Key (예: home.hero.title)' })\n }),\n response: Type.Union([\n Type.Object({\n id: Type.Number(),\n key: Type.String(),\n section: Type.String(),\n type: Type.String(),\n publishedVersion: Type.Union([Type.Number(), Type.Null()]),\n createdBy: Type.Union([Type.String(), Type.Null()]),\n createdAt: Type.String(),\n updatedAt: Type.String()\n }),\n Type.Object({\n error: Type.String(),\n key: Type.Optional(Type.String())\n })\n ])\n} as const satisfies RouteContract;","import { Type } from '@sinclair/typebox';\nimport type { RouteContract } from '@spfn/core/route';\n\nconst SectionData = Type.Object({\n section: Type.String(),\n locale: Type.String(),\n content: Type.Record(Type.String(), Type.Any()),\n version: Type.Number(),\n publishedAt: Type.Union([Type.String(), Type.Null()]),\n});\n\n/**\n * GET /cms/published-cache\n * 발행된 콘텐츠 캐시 조회 (단일 또는 여러 섹션)\n */\nexport const getPublishedCacheContract = {\n method: 'GET' as const,\n path: '/cms/published-cache',\n query: Type.Object({\n sections: Type.Union([\n Type.String({ description: '단일 섹션 이름 (예: home)' }),\n Type.Array(Type.String(), { description: '여러 섹션 이름 (예: [\"home\", \"footer\"])' })\n ]),\n locale: Type.Optional(Type.String({ default: 'ko', description: '언어 코드' })),\n }),\n response: Type.Union([\n // 성공: 항상 배열로 반환\n Type.Array(SectionData),\n // 에러\n Type.Object({\n error: Type.String()\n })\n ])\n} as const satisfies RouteContract;","/**\n * CMS Store Initializer\n *\n * 서버 컴포넌트에서 로드한 섹션 데이터를 클라이언트 store에 초기화\n */\n\n'use client';\n\nimport { useEffect } from 'react';\nimport { useCmsStore } from './store';\nimport type { SectionAPI } from './server';\n\ninterface InitCmsProps\n{\n /**\n * 서버에서 로드한 섹션 데이터\n * { home: { t, data }, ... }\n */\n sections: Record<string, SectionAPI>;\n}\n\n/**\n * CMS Store 초기화 컴포넌트\n *\n * 서버 컴포넌트에서 로드한 데이터를 클라이언트 store에 주입\n * 이후 하위 클라이언트 컴포넌트에서 useSection() 사용 가능\n *\n * @param props - InitCmsProps\n * @param props.sections - 서버에서 로드한 섹션 데이터\n *\n * @example\n * // Server Component\n * const home = await getSection('home');\n * <InitCms sections={{ home }} />\n * // 이후 하위 클라이언트 컴포넌트에서 useSection('home') 사용 가능\n */\nexport function InitCms({ sections }: InitCmsProps)\n{\n const setSections = useCmsStore((state) => state.setSections);\n\n useEffect(() =>\n {\n // SectionAPI → SectionData 변환\n const sectionsData: Record<string, any> = {};\n Object.entries(sections).forEach(([key, { data }]) =>\n {\n sectionsData[key] = data;\n });\n\n setSections(sectionsData);\n }, [sections, setSections]);\n\n return null;\n}"],"mappings":"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","names":["Type","state"]}
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
- //# sourceMappingURL=types.js.map
package/dist/types.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
File without changes
@@ -99,10 +99,10 @@ declare const cmsLabelValuesRepository: {
99
99
  * 섹션 + 언어 + 사용자로 초안 캐시 조회
100
100
  */
101
101
  declare function findByUser(section: string, locale: string, userId: string): Promise<{
102
- locale: string;
102
+ id: number;
103
103
  section: string;
104
+ locale: string;
104
105
  content: unknown;
105
- id: number;
106
106
  updatedAt: Date;
107
107
  userId: string;
108
108
  } | null>;
@@ -110,10 +110,10 @@ declare function findByUser(section: string, locale: string, userId: string): Pr
110
110
  * 초안 캐시 생성 또는 업데이트 (UPSERT)
111
111
  */
112
112
  declare function upsert$1(data: NewCmsDraftCache): Promise<{
113
- locale: string;
113
+ id: number;
114
114
  section: string;
115
+ locale: string;
115
116
  content: unknown;
116
- id: number;
117
117
  updatedAt: Date;
118
118
  userId: string;
119
119
  }>;
@@ -121,10 +121,10 @@ declare function upsert$1(data: NewCmsDraftCache): Promise<{
121
121
  * 특정 사용자의 모든 초안 조회
122
122
  */
123
123
  declare function findAllByUser(userId: string): Promise<{
124
- locale: string;
124
+ id: number;
125
125
  section: string;
126
+ locale: string;
126
127
  content: unknown;
127
- id: number;
128
128
  updatedAt: Date;
129
129
  userId: string;
130
130
  }[]>;
@@ -136,10 +136,10 @@ declare function deleteByUser(section: string, locale: string, userId: string):
136
136
  * 오래된 초안 정리 (30일 이상 미사용)
137
137
  */
138
138
  declare function cleanupOldDrafts(daysOld?: number): Promise<{
139
- locale: string;
139
+ id: number;
140
140
  section: string;
141
+ locale: string;
141
142
  content: unknown;
142
- id: number;
143
143
  updatedAt: Date;
144
144
  userId: string;
145
145
  }[]>;
@@ -161,36 +161,36 @@ declare const cmsDraftCacheRepository: {
161
161
  * 섹션 + 언어로 발행된 캐시 조회
162
162
  */
163
163
  declare function findBySection(section: string, locale?: string): Promise<{
164
- locale: string;
164
+ id: number;
165
165
  section: string;
166
+ locale: string;
166
167
  content: unknown;
167
168
  version: number;
168
169
  publishedAt: Date;
169
- id: number;
170
170
  publishedBy: string | null;
171
171
  } | null>;
172
172
  /**
173
173
  * 캐시 생성 또는 업데이트 (UPSERT)
174
174
  */
175
175
  declare function upsert(data: NewCmsPublishedCache): Promise<{
176
- locale: string;
176
+ id: number;
177
177
  section: string;
178
+ locale: string;
178
179
  content: unknown;
179
180
  version: number;
180
181
  publishedAt: Date;
181
- id: number;
182
182
  publishedBy: string | null;
183
183
  }>;
184
184
  /**
185
185
  * 섹션별 모든 언어 캐시 조회
186
186
  */
187
187
  declare function findAllLanguages(section: string): Promise<{
188
- locale: string;
188
+ id: number;
189
189
  section: string;
190
+ locale: string;
190
191
  content: unknown;
191
192
  version: number;
192
193
  publishedAt: Date;
193
- id: number;
194
194
  publishedBy: string | null;
195
195
  }[]>;
196
196
  /**