@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/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
|
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.d.ts
CHANGED
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 라이브러리 코드 - 향후 @spfn/cms로 분리 예정
|
|
5
5
|
*/
|
|
6
|
+
/**
|
|
7
|
+
* 라벨 타입
|
|
8
|
+
*/
|
|
9
|
+
type LabelType = 'text' | 'image' | 'video' | 'file' | 'object';
|
|
6
10
|
/**
|
|
7
11
|
* 개별 라벨 정의
|
|
8
12
|
*/
|
|
9
|
-
|
|
13
|
+
interface LabelDefinition {
|
|
10
14
|
key: string;
|
|
15
|
+
type?: LabelType;
|
|
11
16
|
defaultValue: string | Record<string, string>;
|
|
12
17
|
description?: string;
|
|
13
18
|
}
|
|
@@ -15,7 +20,7 @@ export interface LabelDefinition {
|
|
|
15
20
|
* 중첩된 라벨 구조
|
|
16
21
|
* LabelDefinition과 구분하기 위해 key, defaultValue 속성을 명시적으로 제외
|
|
17
22
|
*/
|
|
18
|
-
|
|
23
|
+
type NestedLabels = {
|
|
19
24
|
[key: string]: LabelDefinition | NestedLabels;
|
|
20
25
|
} & {
|
|
21
26
|
key?: never;
|
|
@@ -24,14 +29,14 @@ export type NestedLabels = {
|
|
|
24
29
|
/**
|
|
25
30
|
* 섹션 정의
|
|
26
31
|
*/
|
|
27
|
-
|
|
32
|
+
interface SectionDefinition {
|
|
28
33
|
section: string;
|
|
29
34
|
labels: NestedLabels;
|
|
30
35
|
}
|
|
31
36
|
/**
|
|
32
37
|
* Sync 옵션
|
|
33
38
|
*/
|
|
34
|
-
|
|
39
|
+
interface SyncOptions {
|
|
35
40
|
/**
|
|
36
41
|
* Dry run - 실제로 적용하지 않고 변경사항만 출력
|
|
37
42
|
*/
|
|
@@ -52,7 +57,7 @@ export interface SyncOptions {
|
|
|
52
57
|
/**
|
|
53
58
|
* Sync 결과
|
|
54
59
|
*/
|
|
55
|
-
|
|
60
|
+
interface SyncResult {
|
|
56
61
|
section: string;
|
|
57
62
|
created: number;
|
|
58
63
|
updated: number;
|
|
@@ -66,9 +71,11 @@ export interface SyncResult {
|
|
|
66
71
|
/**
|
|
67
72
|
* 라벨 정의 플랫화된 형태
|
|
68
73
|
*/
|
|
69
|
-
|
|
74
|
+
interface FlatLabel {
|
|
70
75
|
key: string;
|
|
76
|
+
type?: LabelType;
|
|
71
77
|
defaultValue: string | Record<string, string>;
|
|
72
78
|
description?: string;
|
|
73
79
|
}
|
|
74
|
-
|
|
80
|
+
|
|
81
|
+
export type { FlatLabel, LabelDefinition, LabelType, NestedLabels, SectionDefinition, SyncOptions, SyncResult };
|
package/dist/types.js
CHANGED
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
-- Create schema for CMS package
|
|
2
|
+
CREATE SCHEMA IF NOT EXISTS spfn_cms;
|
|
3
|
+
--> statement-breakpoint
|
|
4
|
+
CREATE TABLE "spfn_cms"."audit_logs" (
|
|
5
|
+
"id" serial PRIMARY KEY NOT NULL,
|
|
6
|
+
"label_id" integer,
|
|
7
|
+
"action" text NOT NULL,
|
|
8
|
+
"user_id" text NOT NULL,
|
|
9
|
+
"user_name" text,
|
|
10
|
+
"changes" jsonb,
|
|
11
|
+
"metadata" jsonb,
|
|
12
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
13
|
+
);
|
|
14
|
+
--> statement-breakpoint
|
|
15
|
+
CREATE TABLE "spfn_cms"."draft_cache" (
|
|
16
|
+
"id" serial PRIMARY KEY NOT NULL,
|
|
17
|
+
"section" text NOT NULL,
|
|
18
|
+
"locale" text NOT NULL,
|
|
19
|
+
"user_id" text NOT NULL,
|
|
20
|
+
"content" jsonb NOT NULL,
|
|
21
|
+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
22
|
+
CONSTRAINT "cms_draft_cache_unique" UNIQUE("section","locale","user_id")
|
|
23
|
+
);
|
|
24
|
+
--> statement-breakpoint
|
|
25
|
+
CREATE TABLE "spfn_cms"."label_values" (
|
|
26
|
+
"id" serial PRIMARY KEY NOT NULL,
|
|
27
|
+
"label_id" integer NOT NULL,
|
|
28
|
+
"version" integer DEFAULT 1 NOT NULL,
|
|
29
|
+
"locale" text DEFAULT 'ko' NOT NULL,
|
|
30
|
+
"breakpoint" text,
|
|
31
|
+
"value" jsonb NOT NULL,
|
|
32
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
33
|
+
CONSTRAINT "cms_label_values_locale_breakpoint_unique" UNIQUE("label_id","version","locale","breakpoint")
|
|
34
|
+
);
|
|
35
|
+
--> statement-breakpoint
|
|
36
|
+
CREATE TABLE "spfn_cms"."label_versions" (
|
|
37
|
+
"id" serial PRIMARY KEY NOT NULL,
|
|
38
|
+
"label_id" integer NOT NULL,
|
|
39
|
+
"version" integer NOT NULL,
|
|
40
|
+
"status" text NOT NULL,
|
|
41
|
+
"published_at" timestamp with time zone,
|
|
42
|
+
"published_by" text,
|
|
43
|
+
"notes" text,
|
|
44
|
+
"created_by" text,
|
|
45
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
46
|
+
CONSTRAINT "cms_label_versions_label_version_unique" UNIQUE("label_id","version")
|
|
47
|
+
);
|
|
48
|
+
--> statement-breakpoint
|
|
49
|
+
CREATE TABLE "spfn_cms"."labels" (
|
|
50
|
+
"id" serial PRIMARY KEY NOT NULL,
|
|
51
|
+
"key" text NOT NULL,
|
|
52
|
+
"section" text NOT NULL,
|
|
53
|
+
"type" text NOT NULL,
|
|
54
|
+
"default_value" text,
|
|
55
|
+
"description" text,
|
|
56
|
+
"published_version" integer,
|
|
57
|
+
"created_by" text,
|
|
58
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
59
|
+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
60
|
+
CONSTRAINT "labels_key_unique" UNIQUE("key")
|
|
61
|
+
);
|
|
62
|
+
--> statement-breakpoint
|
|
63
|
+
CREATE TABLE "spfn_cms"."published_cache" (
|
|
64
|
+
"id" serial PRIMARY KEY NOT NULL,
|
|
65
|
+
"section" text NOT NULL,
|
|
66
|
+
"locale" text NOT NULL,
|
|
67
|
+
"content" jsonb NOT NULL,
|
|
68
|
+
"published_at" timestamp with time zone NOT NULL,
|
|
69
|
+
"published_by" text,
|
|
70
|
+
"version" integer DEFAULT 1 NOT NULL,
|
|
71
|
+
CONSTRAINT "cms_published_cache_unique" UNIQUE("section","locale")
|
|
72
|
+
);
|
|
73
|
+
--> statement-breakpoint
|
|
74
|
+
ALTER TABLE "spfn_cms"."audit_logs" ADD CONSTRAINT "audit_logs_label_id_labels_id_fk" FOREIGN KEY ("label_id") REFERENCES "spfn_cms"."labels"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
75
|
+
ALTER TABLE "spfn_cms"."label_values" ADD CONSTRAINT "label_values_label_id_labels_id_fk" FOREIGN KEY ("label_id") REFERENCES "spfn_cms"."labels"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
76
|
+
ALTER TABLE "spfn_cms"."label_versions" ADD CONSTRAINT "label_versions_label_id_labels_id_fk" FOREIGN KEY ("label_id") REFERENCES "spfn_cms"."labels"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
77
|
+
CREATE INDEX "cms_audit_logs_label_id_idx" ON "spfn_cms"."audit_logs" USING btree ("label_id");--> statement-breakpoint
|
|
78
|
+
CREATE INDEX "cms_audit_logs_user_id_idx" ON "spfn_cms"."audit_logs" USING btree ("user_id");--> statement-breakpoint
|
|
79
|
+
CREATE INDEX "cms_audit_logs_action_idx" ON "spfn_cms"."audit_logs" USING btree ("action");--> statement-breakpoint
|
|
80
|
+
CREATE INDEX "cms_audit_logs_created_at_idx" ON "spfn_cms"."audit_logs" USING btree ("created_at");--> statement-breakpoint
|
|
81
|
+
CREATE INDEX "cms_draft_cache_section_idx" ON "spfn_cms"."draft_cache" USING btree ("section");--> statement-breakpoint
|
|
82
|
+
CREATE INDEX "cms_draft_cache_user_idx" ON "spfn_cms"."draft_cache" USING btree ("user_id");--> statement-breakpoint
|
|
83
|
+
CREATE INDEX "cms_label_values_label_version_idx" ON "spfn_cms"."label_values" USING btree ("label_id","version");--> statement-breakpoint
|
|
84
|
+
CREATE INDEX "cms_label_values_locale_idx" ON "spfn_cms"."label_values" USING btree ("locale");--> statement-breakpoint
|
|
85
|
+
CREATE INDEX "cms_label_versions_label_id_idx" ON "spfn_cms"."label_versions" USING btree ("label_id");--> statement-breakpoint
|
|
86
|
+
CREATE INDEX "cms_label_versions_status_idx" ON "spfn_cms"."label_versions" USING btree ("status");--> statement-breakpoint
|
|
87
|
+
CREATE INDEX "cms_labels_section_idx" ON "spfn_cms"."labels" USING btree ("section");--> statement-breakpoint
|
|
88
|
+
CREATE INDEX "cms_labels_key_idx" ON "spfn_cms"."labels" USING btree ("key");--> statement-breakpoint
|
|
89
|
+
CREATE INDEX "cms_published_cache_section_idx" ON "spfn_cms"."published_cache" USING btree ("section");
|