@roottale/cms-client 0.71.0 → 0.72.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @roottale/cms-client
2
2
 
3
+ ## 0.72.1
4
+
5
+ ### Patch Changes
6
+
7
+ - ROOT-ADMIN 연동 설정의 GTM 컨테이너 ID를 theme.siteTracking으로 전달하고 안전한 표준 스니펫 헬퍼를 제공합니다.
8
+ - @roottale/cms-core@0.72.1
9
+
10
+ ## 0.72.0
11
+
12
+ ### Minor Changes
13
+
14
+ - 280e850: 고정 페이지 문구·표·사진용 fields 편집 계약과 연결한 사업장 필드 선언을 추가한다.
15
+ 접수 마감의 미지정·해제·시각을 저장 및 공개 응답에서 구분한다. 의료진 시간표 표 입력,
16
+ 문자열 추천값·내부 의료진 주소 선택, 모델별 관리 제목·목록 필드·편집 영역 숨김을 지원한다.
17
+ 새 계약·모델을 동기화하기 전에 관리자와 API 파서를 먼저 배포해야 한다.
18
+ - fa50476: 전체 글을 조회하는 fetchAllPosts와 명시적인 페이지 상한·커서 정지 검사 옵션을 추가하고 외부 Next.js 예제의 조회 루프를 교체합니다.
19
+ - 4341571: 공개 콘텐츠에 섹션 표시 상태·대표 분류·CTA와 콘텐츠 버전·페이지 계약 key를 전달합니다. 미리보기는 지정한 작업본 버전의 전체 내용을 사용하고, 교체된 작업본은 `preview_superseded` 오류와 새 미리보기 안내로 처리합니다. SDK·렌더러·외부 연동 문서와 Next.js 예제를 함께 갱신합니다.
20
+
21
+ 실제화면 편집 계약에 등록된 템플릿은 허용된 최상위 필드의 저장 구조를 보존합니다. `visualEditing` 선언 사이트의 일반 필드 포맷에서도 반복 항목의 UUID `_id`를 유지해 순서 변경 후 편집 주소가 달라지지 않습니다. 미선언 사이트에는 새 응답 필드·반복행 ID·계약 기반 경로 계산을 적용하지 않습니다. `cms-fields`의 직접 소비자는 `ResolveContext.preserveRowIds`로 명시적으로 활성화할 수 있습니다.
22
+
23
+ - 9f0d086: `@roottale/cms-client/server`에 `parseContentEditorState(raw)`와 `ContentEditorStateParseResult`를 추가합니다. 성공은 `{ success: true, data }`, 잘못되거나 없는 입력은 `{ success: false, error }`로 반환하며 기본값을 보충하지 않습니다. 기존 `contentEditorFromWire`는 새 해석기를 사용하고 잘못된 입력의 `undefined` 반환을 유지합니다.
24
+ - e97a94f: 공개·미리보기 글에 optional contentEditorResult를 추가해 편집 상태 원본 부재와 해석 실패를 구분합니다. 기존 contentEditor 동작은 유지합니다.
25
+
26
+ 커버리지 검사에서 계약 컨테이너의 자식 주소와 flexible_content의 행별 layouts를 지원하고, visualEditorOrigins의 HTTP 허용 범위를 브리지와 같은 loopback으로 제한합니다. 연결 문서와 Next.js 예제를 갱신합니다.
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies [c60835a]
31
+ - Updated dependencies [e97a94f]
32
+ - Updated dependencies [4341571]
33
+ - Updated dependencies [fa50476]
34
+ - @roottale/cms-core@0.72.0
35
+
3
36
  ## 0.71.0
4
37
 
5
38
  ### Patch Changes
package/README.md CHANGED
@@ -139,3 +139,40 @@ registration, manual `/v1/cms/revalidate` usage, and troubleshooting, see
139
139
  ## License
140
140
 
141
141
  Proprietary (UNLICENSED). Issued under the RootTale customer contract.
142
+
143
+ ### 편집 상태 해석
144
+
145
+ `@roottale/cms-client/server`의 `parseContentEditorState(raw)`는 기본값을 보충하지
146
+ 않으며 `ContentEditorStateParseResult`를 반환합니다. 성공이면
147
+ `{ success: true, data: CmsContentEditorState }`, 입력이 없거나 잘못되면
148
+ `{ success: false, error: string }`입니다. 소비자는 값이 없는 경우의 기본값과
149
+ 잘못된 값의 오류 처리를 구분할 수 있습니다. 기존 wire 변환은 잘못된 상태를
150
+ 계속 `undefined`로 처리합니다.
151
+
152
+ 공개·미리보기 조회의 `CmsPostContent.contentEditorResult?`는 wire 원본이 있을 때
153
+ 성공·실패 결과를 보존합니다. 원본 필드가 없으면 결과 필드도 생략합니다. `null`은
154
+ 존재하는 잘못된 값이므로 실패입니다. 엄격한 사이트는 `contentEditor`만 확인하지 말고
155
+ `contentEditorResult`의 실패를 먼저 처리해야 숨긴 섹션을 기본값으로 다시 노출하지 않습니다.
156
+
157
+ ## 전체 글 조회
158
+
159
+ `fetchAllPosts`는 `@roottale/cms-client/server`의 추가 export입니다. `fetchPosts`의
160
+ 필터·캐시·signal 옵션을 그대로 받고 `cursor`는 내부에서 관리합니다.
161
+
162
+ ```ts
163
+ import { fetchAllPosts } from "@roottale/cms-client/server";
164
+
165
+ const posts = await fetchAllPosts({
166
+ apiKey: process.env.ROOTTALE_API_KEY!,
167
+ modelKey: "condition",
168
+ limit: 100,
169
+ maxPages: 100,
170
+ cursorGuard: "repeated",
171
+ });
172
+ ```
173
+
174
+ `maxPages`는 양의 정수로 반드시 지정합니다. `cursorGuard`도 필수이며
175
+ `"non-advancing"`은 다음 커서 누락·동일 커서를, `"repeated"`는 과거 커서로 돌아가는
176
+ 순환까지 거부합니다. `hasMore: false`에서 완료하며, 상한 초과·정지·통신 오류에는
177
+ 부분 목록을 반환하지 않고 예외를 전달합니다. 페이지 크기 `limit`의 기본값은
178
+ `fetchPosts`와 같은 20입니다. 사이트의 관련 콘텐츠 개수 제한은 호출 사이트에서 정합니다.
package/dist/server.d.ts CHANGED
@@ -5,6 +5,25 @@ export { parseAttributionJson } from './attribution.js';
5
5
  import { PublicRouteMetadata } from '@roottale/cms-core';
6
6
  export { MetadataDefaultRules, MetadataDefaultRulesSchema, MetadataDefaultsDeclaration, MetadataDefaultsInput, MetadataField, MetadataPatch, MetadataResolutionInput, MetadataRobotsPolicy, MetadataTextRule, MetadataValues, PublicRouteMetadata, formatMetadataDefaults, metadataBodyParagraphs, metadataContentImageUrl, readMetadataValues, resolveMetadata } from '@roottale/cms-core';
7
7
 
8
+ /** 공개 렌더링에 필요한 편집 상태. 내부 검수 정보는 포함하지 않는다. */
9
+ interface CmsContentEditorState {
10
+ sectionStates: Record<string, "visible" | "hidden" | "deleted">;
11
+ primaryTermId: string | null;
12
+ cta: {
13
+ mode: "auto" | "manual" | "off";
14
+ targetPostId: string | null;
15
+ };
16
+ }
17
+ type ContentEditorStateParseResult = {
18
+ success: true;
19
+ data: CmsContentEditorState;
20
+ } | {
21
+ success: false;
22
+ error: string;
23
+ };
24
+ /** 기본값을 보충하지 않는다. 잘못되거나 없는 값은 명시적인 실패 결과로 돌려준다. */
25
+ declare function parseContentEditorState(raw: unknown): ContentEditorStateParseResult;
26
+
8
27
  /**
9
28
  * `@roottale/cms-client/server` — RootTale CMS Public API server-side fetch client.
10
29
  *
@@ -81,6 +100,14 @@ interface CmsPostTranslationRef {
81
100
  slug: string;
82
101
  }
83
102
  interface CmsPostContent {
103
+ /** 반영된 콘텐츠 버전. 미리보기에서는 작업본의 기준 버전. 구 서버는 미포함. */
104
+ contentVersion?: number;
105
+ /** 사이트 콘텐츠 계약의 페이지 key. 연결되지 않은 콘텐츠는 null. */
106
+ contractPageKey?: string | null;
107
+ /** 섹션 표시 상태·대표 분류·CTA 연결. */
108
+ contentEditor?: CmsContentEditorState;
109
+ /** wire 원본이 있을 때의 엄격한 해석 결과. 원본 부재와 잘못된 상태를 구별한다. */
110
+ contentEditorResult?: ContentEditorStateParseResult;
84
111
  /** UUIDv7. */
85
112
  id: string;
86
113
  /** Owning tenant id. */
@@ -325,6 +352,11 @@ interface RootTaleTheme {
325
352
  * 로 Next metadata `verification` 모양으로 바꿔 루트 layout 에 출력한다.
326
353
  */
327
354
  siteVerification?: SiteVerificationSettings;
355
+ siteTracking?: SiteTrackingSettings;
356
+ }
357
+ /** ROOT-ADMIN에서 저장한 공개 추적 태그 설정. */
358
+ interface SiteTrackingSettings {
359
+ googleTagManagerId?: string;
328
360
  }
329
361
  /** 엔진별 소유 확인 코드(고객·RootTale 계정이 각각 확인할 수 있어 여러 개). */
330
362
  interface SiteVerificationSettings {
@@ -453,6 +485,15 @@ interface FetchPageBySlugOptions {
453
485
  }
454
486
  declare function fetchPageBySlug(options: FetchPageBySlugOptions): Promise<CmsPostContent | null>;
455
487
 
488
+ interface FetchAllPostsOptions extends Omit<FetchPostsOptions, "cursor"> {
489
+ /** 최대 조회 페이지 수. 초과하면 부분 결과를 반환하지 않고 실패한다. */
490
+ maxPages: number;
491
+ /** 같은 커서에서의 정지 또는 과거 커서로 돌아가는 순환까지 검사한다. */
492
+ cursorGuard: "non-advancing" | "repeated";
493
+ }
494
+ /** hasMore가 false일 때 완료한다. 통신·커서·상한 오류는 호출자에게 전달한다. */
495
+ declare function fetchAllPosts(options: FetchAllPostsOptions): Promise<CmsPostContent[]>;
496
+
456
497
  /**
457
498
  * 블로그 표시 설정 — admin /design 의 "블로그 표시" 에서 저장한 사이트 기본값.
458
499
  * renderer 가 prop 미지정 시 이 값을 기본으로 적용 (글별 override 는 post 의
@@ -824,6 +865,8 @@ interface BusinessOpeningHours {
824
865
  opens: string;
825
866
  /** HH:MM (24시간). */
826
867
  closes: string;
868
+ /** null = 접수 마감 안내 없음, undefined = 기존 미설정 행. */
869
+ receptionCloses?: string | null;
827
870
  }
828
871
  /**
829
872
  * 비즈니스 프로필 — admin "운영 > 비즈니스 프로필" 에서 저장한 사업장 정보.
@@ -916,6 +959,7 @@ type BusinessProfileWire = {
916
959
  days?: BusinessDayCode[];
917
960
  opens?: string;
918
961
  closes?: string;
962
+ reception_closes?: string | null;
919
963
  }[];
920
964
  price_range?: string | null;
921
965
  area_served?: string[];
@@ -1285,7 +1329,16 @@ interface FetchPostPreviewOptions {
1285
1329
  readonly siteId?: string;
1286
1330
  readonly signal?: AbortSignal;
1287
1331
  }
1332
+ interface CmsPostPreviewVisualTarget {
1333
+ readonly entityId: string;
1334
+ readonly draftId: string;
1335
+ readonly draftVersion: number;
1336
+ readonly contractVersion: string;
1337
+ readonly templateVersion: string;
1338
+ }
1288
1339
  interface CmsPostPreviewInfo {
1340
+ /** 이번 응답이 실제로 읽은 작업본과 사이트 템플릿 표식. 구 토큰은 미포함. */
1341
+ readonly visualTarget?: CmsPostPreviewVisualTarget;
1289
1342
  /** 토큰 만료 시각(ISO). */
1290
1343
  readonly expiresAt: string;
1291
1344
  /** 글의 실제 상태. 본문 `status` 는 템플릿 재사용을 위해 항상 `published`. */
@@ -1296,6 +1349,8 @@ interface CmsPostPreviewContent extends CmsPostContent {
1296
1349
  }
1297
1350
  /** 만료된 미리보기 링크(410 `preview_expired`)인지 구분한다. */
1298
1351
  declare function isPreviewExpiredError(error: unknown): boolean;
1352
+ /** 저장 후 교체된 작업본의 이전 링크(409)인지 구분한다. 새 미리보기를 요청해야 한다. */
1353
+ declare function isPreviewSupersededError(error: unknown): boolean;
1299
1354
  /**
1300
1355
  * 토큰이 없거나 다른 사이트의 것이면 `null`(404). 만료는 throw(410) — 두 경우를
1301
1356
  * 다르게 안내할 수 있게 구분한다.
@@ -1599,6 +1654,12 @@ interface SiteVerificationMetadata {
1599
1654
  */
1600
1655
  declare function siteVerificationMetadata(settings: SiteVerificationSettings | undefined): SiteVerificationMetadata | undefined;
1601
1656
 
1657
+ /** Google의 표준 스니펫. 공개 컨테이너 ID만 허용한다. */
1658
+ declare function googleTagManagerSnippet(id: string | undefined): {
1659
+ script: string;
1660
+ iframeUrl: string;
1661
+ } | undefined;
1662
+
1602
1663
  /**
1603
1664
  * `@roottale/cms-client` — 리드(문의) 접수 server-side 헬퍼.
1604
1665
  *
@@ -1707,4 +1768,4 @@ declare function formatKoreanPhoneNumber(input: string): string;
1707
1768
  */
1708
1769
  declare function submitInquiry(options: SubmitInquiryOptions): Promise<SubmitInquiryResult>;
1709
1770
 
1710
- export { type ActionDockAction, type ActionDockKind, type ActionDockPosition, type ActionDockSettings, type AnalyticsTagConfig, type AnalyticsTagProvider, type AnnouncementItem, type AnnouncementSettings, type AnnouncementTone, type AnnouncementVariant, type ArticleSchemaInput, BLOG_SETTINGS_CACHE_TAG, BUSINESS_CACHE_TAG, type BusinessDayCode, type BusinessOpeningHours, type BusinessType, CMS_CLIENT_VERSION, COLLECTIONS_CACHE_TAG, CONTENT_POLICY_CACHE_TAG, CmsApiError, type CmsArchiveRelatedGroup, type CmsArchiveRelatedPost, type CmsCategoryCount, type CmsCategoryCounts, type CmsContentModel, type CmsExposureCampaign, type CmsExposureDecision, type CmsFieldMetaEntry, type CmsPostContent, type CmsPostContentPage, type CmsPostPreviewContent, type CmsPostPreviewInfo, type CmsPostTranslationRef, type CmsPostType, type CmsRouteCollection, type CmsSearchHit, type CmsSitePattern, type CmsSitePatternPresentation, type CmsTaxonomyKind, type CmsTermRef, DEFAULT_BLOG_SETTINGS, DEFAULT_SITE_PATTERN_PRESENTATION, EXPOSURE_CACHE_TAG, type FetchAnalyticsOptions, type FetchAuthorsOptions, type FetchBlogSettingsOptions, type FetchBusinessProfileOptions, type FetchCategoryCountsOptions, type FetchCollectionsOptions, type FetchContentModelsOptions, type FetchExposureDecisionOptions, type FetchExposureOptions, type FetchInquiryFormOptions, type FetchMenuOptions, type FetchMenusOptions, type FetchPageBySlugOptions, type FetchPostOptions, type FetchPostPreviewOptions, type FetchPostsOptions, type FetchRedirectsOptions, type FetchRouteMetadataOptions, type FetchSiteInquiriesOptions, type FetchSiteInquiryOptions, type FetchSitePatternsOptions, type FetchThemeOptions, type FormInquiryReceipt, INQUIRY_ERROR_MESSAGES, InquiryAttribution, type InquiryBoardSettings, type InquiryVertical, LOCAL_BUSINESS_MAX_SERVICES, LOCAL_BUSINESS_SERVICE_MAX_LENGTH, type LocalBusinessProfileInput, MENUS_CACHE_TAG, METADATA_CACHE_TAG, POST_FOOTER_PATTERN_SLOT, type PublishedInquiryForm, type ResolvedPostDisplay, type RootTaleAuthor, type RootTaleBlogPostCta, type RootTaleBlogSettings, type RootTaleBusinessProfile, type RootTaleMenu, type RootTaleMenuItem, type RootTaleRedirect, type RootTaleSiteProfile, type RootTaleSitemapSettings, type RootTaleTheme, type RssFeedInput, type RssItemInput, SETTINGS_CACHE_TAGS, SITE_METADATA_DEFAULTS_CACHE_TAG, SITE_PATTERNS_CACHE_TAG, type SearchPostsOptions, type SiteAnalyticsTags, type SiteInquiryDetail, type SiteInquiryListItem, type SiteInquiryListPage, type SiteInquiryStatus, type SiteNavColumn, type SiteNavCta, type SiteNavGroup, type SiteNavLink, type SiteNavSettings, type SiteVerificationMetadata, type SiteVerificationSettings, type SubmitFormInquiryFields, type SubmitFormInquiryOptions, type SubmitFormInquiryResult, type SubmitInquiryFields, type SubmitInquiryOptions, type SubmitInquiryResult, type SubmitSiteInquiryFields, type SubmitSiteInquiryOptions, type SubmitSiteInquiryResult, THEME_CACHE_TAG, articleSchema, breadcrumbSchema, businessProfileFromWire, collectionPageSchema, contentIdMeta, faqSchema, fetchAnalyticsConfig, fetchAuthors, fetchBlogSettings, fetchBusinessProfile, fetchCategoryCounts, fetchCollections, fetchCollectionsSafeDefault, fetchContentModels, fetchExposure, fetchExposureDecision, fetchInquiryForm, fetchMenu, fetchMenus, fetchPageBySlug, fetchPost, fetchPostPreview, fetchPosts, fetchRedirects, fetchRouteMetadata, fetchSiteInquiries, fetchSiteInquiry, fetchSitePatterns, fetchTheme, formatKoreanPhoneNumber, generateRssXml, inquiryErrorMessage, isPreviewExpiredError, jsonLdJson, jsonLdScript, localBusinessSchema, metadataContractChecksum, organizationSchema, parseInquiryRedirect, profilePageSchema, resolvePostDisplay, resolveSearchHitPath, routeMetadataCacheTag, rssItemsFromPosts, searchPosts, selectRelatedPosts, selectSitePatternForSlot, sitePatternPresentationAttributes, siteVerificationMetadata, submitFormInquiry, submitInquiry, submitSiteInquiry, websiteSchema };
1771
+ export { type ActionDockAction, type ActionDockKind, type ActionDockPosition, type ActionDockSettings, type AnalyticsTagConfig, type AnalyticsTagProvider, type AnnouncementItem, type AnnouncementSettings, type AnnouncementTone, type AnnouncementVariant, type ArticleSchemaInput, BLOG_SETTINGS_CACHE_TAG, BUSINESS_CACHE_TAG, type BusinessDayCode, type BusinessOpeningHours, type BusinessType, CMS_CLIENT_VERSION, COLLECTIONS_CACHE_TAG, CONTENT_POLICY_CACHE_TAG, CmsApiError, type CmsArchiveRelatedGroup, type CmsArchiveRelatedPost, type CmsCategoryCount, type CmsCategoryCounts, type CmsContentEditorState, type CmsContentModel, type CmsExposureCampaign, type CmsExposureDecision, type CmsFieldMetaEntry, type CmsPostContent, type CmsPostContentPage, type CmsPostPreviewContent, type CmsPostPreviewInfo, type CmsPostPreviewVisualTarget, type CmsPostTranslationRef, type CmsPostType, type CmsRouteCollection, type CmsSearchHit, type CmsSitePattern, type CmsSitePatternPresentation, type CmsTaxonomyKind, type CmsTermRef, type ContentEditorStateParseResult, DEFAULT_BLOG_SETTINGS, DEFAULT_SITE_PATTERN_PRESENTATION, EXPOSURE_CACHE_TAG, type FetchAllPostsOptions, type FetchAnalyticsOptions, type FetchAuthorsOptions, type FetchBlogSettingsOptions, type FetchBusinessProfileOptions, type FetchCategoryCountsOptions, type FetchCollectionsOptions, type FetchContentModelsOptions, type FetchExposureDecisionOptions, type FetchExposureOptions, type FetchInquiryFormOptions, type FetchMenuOptions, type FetchMenusOptions, type FetchPageBySlugOptions, type FetchPostOptions, type FetchPostPreviewOptions, type FetchPostsOptions, type FetchRedirectsOptions, type FetchRouteMetadataOptions, type FetchSiteInquiriesOptions, type FetchSiteInquiryOptions, type FetchSitePatternsOptions, type FetchThemeOptions, type FormInquiryReceipt, INQUIRY_ERROR_MESSAGES, InquiryAttribution, type InquiryBoardSettings, type InquiryVertical, LOCAL_BUSINESS_MAX_SERVICES, LOCAL_BUSINESS_SERVICE_MAX_LENGTH, type LocalBusinessProfileInput, MENUS_CACHE_TAG, METADATA_CACHE_TAG, POST_FOOTER_PATTERN_SLOT, type PublishedInquiryForm, type ResolvedPostDisplay, type RootTaleAuthor, type RootTaleBlogPostCta, type RootTaleBlogSettings, type RootTaleBusinessProfile, type RootTaleMenu, type RootTaleMenuItem, type RootTaleRedirect, type RootTaleSiteProfile, type RootTaleSitemapSettings, type RootTaleTheme, type RssFeedInput, type RssItemInput, SETTINGS_CACHE_TAGS, SITE_METADATA_DEFAULTS_CACHE_TAG, SITE_PATTERNS_CACHE_TAG, type SearchPostsOptions, type SiteAnalyticsTags, type SiteInquiryDetail, type SiteInquiryListItem, type SiteInquiryListPage, type SiteInquiryStatus, type SiteNavColumn, type SiteNavCta, type SiteNavGroup, type SiteNavLink, type SiteNavSettings, type SiteTrackingSettings, type SiteVerificationMetadata, type SiteVerificationSettings, type SubmitFormInquiryFields, type SubmitFormInquiryOptions, type SubmitFormInquiryResult, type SubmitInquiryFields, type SubmitInquiryOptions, type SubmitInquiryResult, type SubmitSiteInquiryFields, type SubmitSiteInquiryOptions, type SubmitSiteInquiryResult, THEME_CACHE_TAG, articleSchema, breadcrumbSchema, businessProfileFromWire, collectionPageSchema, contentIdMeta, faqSchema, fetchAllPosts, fetchAnalyticsConfig, fetchAuthors, fetchBlogSettings, fetchBusinessProfile, fetchCategoryCounts, fetchCollections, fetchCollectionsSafeDefault, fetchContentModels, fetchExposure, fetchExposureDecision, fetchInquiryForm, fetchMenu, fetchMenus, fetchPageBySlug, fetchPost, fetchPostPreview, fetchPosts, fetchRedirects, fetchRouteMetadata, fetchSiteInquiries, fetchSiteInquiry, fetchSitePatterns, fetchTheme, formatKoreanPhoneNumber, generateRssXml, googleTagManagerSnippet, inquiryErrorMessage, isPreviewExpiredError, isPreviewSupersededError, jsonLdJson, jsonLdScript, localBusinessSchema, metadataContractChecksum, organizationSchema, parseContentEditorState, parseInquiryRedirect, profilePageSchema, resolvePostDisplay, resolveSearchHitPath, routeMetadataCacheTag, rssItemsFromPosts, searchPosts, selectRelatedPosts, selectSitePatternForSlot, sitePatternPresentationAttributes, siteVerificationMetadata, submitFormInquiry, submitInquiry, submitSiteInquiry, websiteSchema };
package/dist/server.js CHANGED
@@ -8,7 +8,7 @@ var DEFAULT_SERVER_FETCH_TIMEOUT_MS = 1e4;
8
8
  function requestSignal(signal) {
9
9
  return signal ?? AbortSignal.timeout(DEFAULT_SERVER_FETCH_TIMEOUT_MS);
10
10
  }
11
- var CLIENT_VERSION = true ? "0.71.0" : "dev";
11
+ var CLIENT_VERSION = true ? "0.72.1" : "dev";
12
12
  var CMS_CLIENT_VERSION = CLIENT_VERSION;
13
13
  function authHeaders(apiKey) {
14
14
  return {
@@ -59,6 +59,29 @@ function assertServer() {
59
59
  }
60
60
  }
61
61
 
62
+ // src/server-content-editor.ts
63
+ function parseContentEditorState(raw) {
64
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { success: false, error: "\uD3B8\uC9D1 \uC0C1\uD0DC\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4." };
65
+ const value = raw;
66
+ if (!value.sectionStates || typeof value.sectionStates !== "object" || Array.isArray(value.sectionStates)) return { success: false, error: "\uC139\uC158 \uD45C\uC2DC \uC0C1\uD0DC\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4." };
67
+ const sectionStates = {};
68
+ for (const [key, state] of Object.entries(value.sectionStates)) {
69
+ if (state !== "visible" && state !== "hidden" && state !== "deleted") return { success: false, error: `\uC798\uBABB\uB41C \uC139\uC158 \uD45C\uC2DC \uC0C1\uD0DC: ${key}` };
70
+ Object.defineProperty(sectionStates, key, { value: state, enumerable: true, writable: true, configurable: true });
71
+ }
72
+ if (value.primaryTermId !== null && typeof value.primaryTermId !== "string") return { success: false, error: "\uB300\uD45C \uC8FC\uC81C\uB294 \uBB38\uC790\uC5F4 \uB610\uB294 null\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4." };
73
+ if (!value.cta || typeof value.cta !== "object" || Array.isArray(value.cta)) return { success: false, error: "\uC9C4\uB8CC \uC548\uB0B4 \uCE74\uB4DC \uC124\uC815\uC740 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4." };
74
+ const cta = value.cta;
75
+ if (cta.mode !== "auto" && cta.mode !== "manual" && cta.mode !== "off") return { success: false, error: "\uC798\uBABB\uB41C \uC9C4\uB8CC \uC548\uB0B4 \uCE74\uB4DC \uBAA8\uB4DC\uC785\uB2C8\uB2E4." };
76
+ if (cta.targetPostId !== null && typeof cta.targetPostId !== "string") return { success: false, error: "\uC9C4\uB8CC \uC548\uB0B4 \uCE74\uB4DC \uB300\uC0C1\uC740 \uBB38\uC790\uC5F4 \uB610\uB294 null\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4." };
77
+ if (cta.mode === "manual" && !cta.targetPostId) return { success: false, error: "\uC218\uB3D9 \uC9C4\uB8CC \uC548\uB0B4 \uCE74\uB4DC\uC5D0\uB294 \uB300\uC0C1\uC774 \uD544\uC694\uD569\uB2C8\uB2E4." };
78
+ return { success: true, data: { sectionStates, primaryTermId: value.primaryTermId, cta: { mode: cta.mode, targetPostId: cta.targetPostId } } };
79
+ }
80
+ function contentEditorFromWire(raw) {
81
+ const result = parseContentEditorState(raw);
82
+ return result.success ? result.data : void 0;
83
+ }
84
+
62
85
  // src/server-post-wire.ts
63
86
  function patternSlotsFromWire(raw) {
64
87
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
@@ -91,6 +114,7 @@ function relatedPostsFromWire(raw) {
91
114
  return out;
92
115
  }
93
116
  function postFromWire(wire) {
117
+ const contentEditor = contentEditorFromWire(wire.content_editor);
94
118
  const imagePosition = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 100 ? value : null;
95
119
  return {
96
120
  id: wire.id,
@@ -99,6 +123,10 @@ function postFromWire(wire) {
99
123
  type: wire.type,
100
124
  collectionKey: wire.collection_key ?? null,
101
125
  modelKey: wire.model_key ?? null,
126
+ ...Number.isInteger(wire.content_version) && (wire.content_version ?? 0) > 0 ? { contentVersion: wire.content_version } : {},
127
+ ...wire.contract_page_key !== void 0 ? { contractPageKey: wire.contract_page_key } : {},
128
+ ...contentEditor ? { contentEditor } : {},
129
+ ...wire.content_editor !== void 0 ? { contentEditorResult: parseContentEditorState(wire.content_editor) } : {},
102
130
  slug: wire.slug,
103
131
  ...wire.locale !== void 0 ? { locale: wire.locale } : {},
104
132
  ...wire.translations !== void 0 ? { translations: wire.translations } : {},
@@ -182,6 +210,7 @@ async function fetchTheme(options) {
182
210
  if (json.inquiryBoard) theme.inquiryBoard = json.inquiryBoard;
183
211
  if (json.siteNav) theme.siteNav = json.siteNav;
184
212
  if (json.siteVerification) theme.siteVerification = json.siteVerification;
213
+ if (json.siteTracking) theme.siteTracking = json.siteTracking;
185
214
  return theme;
186
215
  }
187
216
  async function fetchAnalyticsConfig(options) {
@@ -261,6 +290,31 @@ async function fetchPageBySlug(options) {
261
290
  return null;
262
291
  }
263
292
 
293
+ // src/server-all-posts.ts
294
+ async function fetchAllPosts(options) {
295
+ const { maxPages, cursorGuard, ...query } = options;
296
+ if (!Number.isSafeInteger(maxPages) || maxPages < 1) {
297
+ throw new Error("CMS maxPages must be a positive safe integer.");
298
+ }
299
+ if (cursorGuard !== "non-advancing" && cursorGuard !== "repeated") {
300
+ throw new Error("CMS cursorGuard must be non-advancing or repeated.");
301
+ }
302
+ const posts = [];
303
+ const cursors = /* @__PURE__ */ new Set();
304
+ let cursor;
305
+ for (let page = 0; page < maxPages; page += 1) {
306
+ const result = await fetchPosts({ ...query, ...cursor ? { cursor } : {} });
307
+ posts.push(...result.items);
308
+ if (!result.hasMore) return posts;
309
+ if (!result.nextCursor || result.nextCursor === cursor || cursorGuard === "repeated" && cursors.has(result.nextCursor)) {
310
+ throw new Error("CMS \uD398\uC774\uC9C0 \uCEE4\uC11C\uAC00 \uC9C4\uD589\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.");
311
+ }
312
+ cursor = result.nextCursor;
313
+ cursors.add(cursor);
314
+ }
315
+ throw new Error("CMS \uCF58\uD150\uCE20 \uD398\uC774\uC9C0 \uC0C1\uD55C\uC744 \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.");
316
+ }
317
+
264
318
  // src/server-blog.ts
265
319
  var BLOG_SETTINGS_CACHE_TAG = "rt-blog-settings";
266
320
  async function fetchBlogSettings(options) {
@@ -601,7 +655,12 @@ function businessProfileFromWire(json) {
601
655
  const openingHours = [];
602
656
  for (const row of json.opening_hours ?? []) {
603
657
  if (Array.isArray(row.days) && row.days.length > 0 && typeof row.opens === "string" && typeof row.closes === "string") {
604
- openingHours.push({ days: row.days, opens: row.opens, closes: row.closes });
658
+ openingHours.push({
659
+ days: row.days,
660
+ opens: row.opens,
661
+ closes: row.closes,
662
+ ...row.reception_closes !== void 0 ? { receptionCloses: row.reception_closes } : {}
663
+ });
605
664
  }
606
665
  }
607
666
  return {
@@ -1112,6 +1171,9 @@ function codeForStatus(status) {
1112
1171
  function isPreviewExpiredError(error) {
1113
1172
  return error instanceof CmsApiError && (error.code === "preview_expired" || error.status === 410);
1114
1173
  }
1174
+ function isPreviewSupersededError(error) {
1175
+ return error instanceof CmsApiError && error.code === "preview_superseded";
1176
+ }
1115
1177
  async function fetchPostPreview(options) {
1116
1178
  assertServer();
1117
1179
  const token = options.token.trim();
@@ -1133,7 +1195,8 @@ async function fetchPostPreview(options) {
1133
1195
  ...postFromWire(json),
1134
1196
  preview: {
1135
1197
  expiresAt: json.preview.expires_at,
1136
- sourceStatus: json.preview.source_status
1198
+ sourceStatus: json.preview.source_status,
1199
+ ...json.preview.visual_target ? { visualTarget: json.preview.visual_target } : {}
1137
1200
  }
1138
1201
  };
1139
1202
  }
@@ -1571,6 +1634,15 @@ function siteVerificationMetadata(settings) {
1571
1634
  };
1572
1635
  }
1573
1636
 
1637
+ // src/tag-manager.ts
1638
+ function googleTagManagerSnippet(id) {
1639
+ if (!id || !/^GTM-[A-Z0-9]{4,20}$/.test(id)) return void 0;
1640
+ return {
1641
+ script: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','${id}');`,
1642
+ iframeUrl: `https://www.googletagmanager.com/ns.html?id=${id}`
1643
+ };
1644
+ }
1645
+
1574
1646
  // src/inquiry.ts
1575
1647
  var DEFAULT_BASE_URL2 = "https://api.roottale.com";
1576
1648
  var INQUIRY_ERROR_MESSAGES = {
@@ -1741,6 +1813,7 @@ export {
1741
1813
  collectionPageSchema,
1742
1814
  contentIdMeta,
1743
1815
  faqSchema,
1816
+ fetchAllPosts,
1744
1817
  fetchAnalyticsConfig,
1745
1818
  fetchAuthors,
1746
1819
  fetchBlogSettings,
@@ -1767,8 +1840,10 @@ export {
1767
1840
  formatKoreanPhoneNumber,
1768
1841
  formatMetadataDefaults,
1769
1842
  generateRssXml,
1843
+ googleTagManagerSnippet,
1770
1844
  inquiryErrorMessage,
1771
1845
  isPreviewExpiredError,
1846
+ isPreviewSupersededError,
1772
1847
  jsonLdJson,
1773
1848
  jsonLdScript,
1774
1849
  localBusinessSchema,
@@ -1777,6 +1852,7 @@ export {
1777
1852
  metadataContractChecksum,
1778
1853
  organizationSchema,
1779
1854
  parseAttributionJson,
1855
+ parseContentEditorState,
1780
1856
  parseInquiryRedirect,
1781
1857
  profilePageSchema,
1782
1858
  readMetadataValues,