@roottale/cms-client 0.62.0 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/server.d.ts +68 -1
- package/dist/server.js +134 -1
- package/dist/server.js.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @roottale/cms-client
|
|
2
2
|
|
|
3
|
+
## 0.64.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5ccf503: 한 사이트의 여러 문의 폼을 발행 버전별로 연결할 수 있도록 공통 폼 정의·검증 계약과 `fetchInquiryForm`·`submitFormInquiry` 서버 SDK를 추가합니다. 구조화 답변·동의·중복 재시도·접수증과 같은 사이트의 견적/AS 폼 연동 예제를 제공합니다. 기존 문의 SDK는 유지합니다.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [5ccf503]
|
|
12
|
+
- @roottale/inquiry-forms@0.2.0
|
|
13
|
+
|
|
14
|
+
## 0.63.0
|
|
15
|
+
|
|
3
16
|
## 0.62.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/dist/server.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { InquiryFormDefinition, InquiryAnswer } from '@roottale/inquiry-forms';
|
|
2
|
+
export { InquiryAnswer, InquiryFormDefinition, InquiryFormField, InquiryKind } from '@roottale/inquiry-forms';
|
|
1
3
|
import { InquiryAttribution } from './attribution.js';
|
|
2
4
|
export { parseAttributionJson } from './attribution.js';
|
|
3
5
|
|
|
@@ -1162,6 +1164,71 @@ declare function fetchSiteInquiries(options: FetchSiteInquiriesOptions): Promise
|
|
|
1162
1164
|
declare function fetchSiteInquiry(options: FetchSiteInquiryOptions): Promise<SiteInquiryDetail | null>;
|
|
1163
1165
|
declare function submitSiteInquiry(options: SubmitSiteInquiryOptions): Promise<SubmitSiteInquiryResult>;
|
|
1164
1166
|
|
|
1167
|
+
/** A published form belongs to exactly one site. Versions are immutable. */
|
|
1168
|
+
interface PublishedInquiryForm {
|
|
1169
|
+
formId: string;
|
|
1170
|
+
siteId: string;
|
|
1171
|
+
formKey: string;
|
|
1172
|
+
version: number;
|
|
1173
|
+
definition: InquiryFormDefinition;
|
|
1174
|
+
}
|
|
1175
|
+
interface FetchInquiryFormOptions {
|
|
1176
|
+
apiKey: string;
|
|
1177
|
+
baseUrl?: string;
|
|
1178
|
+
/** Required for a tenant-wide key; a site-bound key already identifies its site. */
|
|
1179
|
+
siteId?: string;
|
|
1180
|
+
formId: string;
|
|
1181
|
+
signal?: AbortSignal;
|
|
1182
|
+
}
|
|
1183
|
+
interface SubmitFormInquiryFields {
|
|
1184
|
+
siteId?: string;
|
|
1185
|
+
/** Version that the visitor saw, including its consent notice. */
|
|
1186
|
+
version: number;
|
|
1187
|
+
answers: Record<string, InquiryAnswer>;
|
|
1188
|
+
privacyConsent: boolean;
|
|
1189
|
+
/** Caller-generated key. Reuse the same key and payload after an uncertain response. */
|
|
1190
|
+
idempotencyKey: string;
|
|
1191
|
+
placement?: string;
|
|
1192
|
+
turnstileToken?: string;
|
|
1193
|
+
attribution?: InquiryAttribution | null;
|
|
1194
|
+
/** readJourney() array; the API validates entries and enforces the site's privacy mode. */
|
|
1195
|
+
journey?: readonly unknown[];
|
|
1196
|
+
}
|
|
1197
|
+
interface SubmitFormInquiryOptions {
|
|
1198
|
+
apiKey: string;
|
|
1199
|
+
baseUrl?: string;
|
|
1200
|
+
formId: string;
|
|
1201
|
+
fields: SubmitFormInquiryFields;
|
|
1202
|
+
signal?: AbortSignal;
|
|
1203
|
+
}
|
|
1204
|
+
interface FormInquiryReceipt {
|
|
1205
|
+
id: string;
|
|
1206
|
+
inquiryNo: number;
|
|
1207
|
+
receivedAt: string;
|
|
1208
|
+
/** True when this is the receipt of an already saved submission. */
|
|
1209
|
+
replayed: boolean;
|
|
1210
|
+
}
|
|
1211
|
+
type SubmitFormInquiryResult = {
|
|
1212
|
+
ok: true;
|
|
1213
|
+
receipt: FormInquiryReceipt;
|
|
1214
|
+
} | {
|
|
1215
|
+
ok: false;
|
|
1216
|
+
/** Transport/invalid_response can mean the server saved the inquiry before the response was lost. */
|
|
1217
|
+
kind: "api" | "transport" | "invalid_response";
|
|
1218
|
+
code: string;
|
|
1219
|
+
status: number | null;
|
|
1220
|
+
message: string;
|
|
1221
|
+
fieldErrors: Record<string, string[]>;
|
|
1222
|
+
formErrors: string[];
|
|
1223
|
+
};
|
|
1224
|
+
/** Server-only. Always reads the current published form; 404 returns null. */
|
|
1225
|
+
declare function fetchInquiryForm(options: FetchInquiryFormOptions): Promise<PublishedInquiryForm | null>;
|
|
1226
|
+
/**
|
|
1227
|
+
* Server-only JSON intake. A successful HTTP status is insufficient without a valid receipt.
|
|
1228
|
+
* Does not retry or generate keys; the caller keeps its key until the receipt is confirmed.
|
|
1229
|
+
*/
|
|
1230
|
+
declare function submitFormInquiry(options: SubmitFormInquiryOptions): Promise<SubmitFormInquiryResult>;
|
|
1231
|
+
|
|
1165
1232
|
/**
|
|
1166
1233
|
* 글 미리보기 — 어드민 편집기가 발급한 토큰으로 초안을 **발행 글과 같은 모양**으로
|
|
1167
1234
|
* 받아 온다. 고객 사이트는 글 상세 템플릿을 그대로 재사용해 미리보기를 그리면
|
|
@@ -1564,4 +1631,4 @@ declare function formatKoreanPhoneNumber(input: string): string;
|
|
|
1564
1631
|
*/
|
|
1565
1632
|
declare function submitInquiry(options: SubmitInquiryOptions): Promise<SubmitInquiryResult>;
|
|
1566
1633
|
|
|
1567
|
-
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, 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 FetchMenuOptions, type FetchMenusOptions, type FetchPageBySlugOptions, type FetchPostOptions, type FetchPostPreviewOptions, type FetchPostsOptions, type FetchRedirectsOptions, type FetchSiteInquiriesOptions, type FetchSiteInquiryOptions, type FetchSitePatternsOptions, type FetchThemeOptions, INQUIRY_ERROR_MESSAGES, InquiryAttribution, type InquiryBoardSettings, type InquiryVertical, LOCAL_BUSINESS_MAX_SERVICES, LOCAL_BUSINESS_SERVICE_MAX_LENGTH, type LocalBusinessProfileInput, MENUS_CACHE_TAG, POST_FOOTER_PATTERN_SLOT, 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_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 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, fetchMenu, fetchMenus, fetchPageBySlug, fetchPost, fetchPostPreview, fetchPosts, fetchRedirects, fetchSiteInquiries, fetchSiteInquiry, fetchSitePatterns, fetchTheme, formatKoreanPhoneNumber, generateRssXml, inquiryErrorMessage, isPreviewExpiredError, jsonLdJson, jsonLdScript, localBusinessSchema, organizationSchema, parseInquiryRedirect, profilePageSchema, resolvePostDisplay, resolveSearchHitPath, rssItemsFromPosts, searchPosts, selectRelatedPosts, selectSitePatternForSlot, sitePatternPresentationAttributes, submitInquiry, submitSiteInquiry, websiteSchema };
|
|
1634
|
+
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, 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 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, 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_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 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, fetchSiteInquiries, fetchSiteInquiry, fetchSitePatterns, fetchTheme, formatKoreanPhoneNumber, generateRssXml, inquiryErrorMessage, isPreviewExpiredError, jsonLdJson, jsonLdScript, localBusinessSchema, organizationSchema, parseInquiryRedirect, profilePageSchema, resolvePostDisplay, resolveSearchHitPath, rssItemsFromPosts, searchPosts, selectRelatedPosts, selectSitePatternForSlot, sitePatternPresentationAttributes, submitFormInquiry, submitInquiry, submitSiteInquiry, websiteSchema };
|
package/dist/server.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// src/server-base.ts
|
|
6
6
|
var DEFAULT_BASE_URL = "https://api.roottale.com";
|
|
7
|
-
var CLIENT_VERSION = true ? "0.
|
|
7
|
+
var CLIENT_VERSION = true ? "0.64.0" : "dev";
|
|
8
8
|
var CMS_CLIENT_VERSION = CLIENT_VERSION;
|
|
9
9
|
function authHeaders(apiKey) {
|
|
10
10
|
return {
|
|
@@ -953,6 +953,137 @@ function fromDetailWire(item) {
|
|
|
953
953
|
};
|
|
954
954
|
}
|
|
955
955
|
|
|
956
|
+
// src/server-inquiry-forms.ts
|
|
957
|
+
import { inquiryFormDefinitionSchema } from "@roottale/inquiry-forms";
|
|
958
|
+
async function fetchInquiryForm(options) {
|
|
959
|
+
assertServer();
|
|
960
|
+
const params = new URLSearchParams();
|
|
961
|
+
if (options.siteId) params.set("site_id", options.siteId);
|
|
962
|
+
const query = params.toString();
|
|
963
|
+
const response = await fetch(`${formUrl(options)}${query ? `?${query}` : ""}`, {
|
|
964
|
+
headers: authHeaders(options.apiKey),
|
|
965
|
+
cache: "no-store",
|
|
966
|
+
redirect: "manual",
|
|
967
|
+
signal: options.signal
|
|
968
|
+
});
|
|
969
|
+
if (response.status === 404) return null;
|
|
970
|
+
if (!response.ok) throw await toApiError(response);
|
|
971
|
+
const body = await readJson(response);
|
|
972
|
+
if (!isRecord(body) || body.form_id !== options.formId || !isId(body.site_id) || options.siteId !== void 0 && body.site_id !== options.siteId || !isNonEmptyString(body.form_key) || !isPositiveInteger(body.version)) {
|
|
973
|
+
throw invalidFormResponse(response.status);
|
|
974
|
+
}
|
|
975
|
+
const definition = inquiryFormDefinitionSchema.safeParse(body.definition);
|
|
976
|
+
if (!definition.success) throw invalidFormResponse(response.status);
|
|
977
|
+
return {
|
|
978
|
+
formId: options.formId,
|
|
979
|
+
siteId: body.site_id,
|
|
980
|
+
formKey: body.form_key,
|
|
981
|
+
version: body.version,
|
|
982
|
+
definition: definition.data
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
async function submitFormInquiry(options) {
|
|
986
|
+
assertServer();
|
|
987
|
+
const fields = options.fields;
|
|
988
|
+
let response;
|
|
989
|
+
try {
|
|
990
|
+
response = await fetch(`${formUrl(options)}/submissions`, {
|
|
991
|
+
method: "POST",
|
|
992
|
+
headers: { ...authHeaders(options.apiKey), "content-type": "application/json" },
|
|
993
|
+
body: JSON.stringify({
|
|
994
|
+
site_id: fields.siteId,
|
|
995
|
+
version: fields.version,
|
|
996
|
+
answers: fields.answers,
|
|
997
|
+
privacy_consent: fields.privacyConsent,
|
|
998
|
+
idempotency_key: fields.idempotencyKey,
|
|
999
|
+
placement: fields.placement,
|
|
1000
|
+
turnstile_token: fields.turnstileToken,
|
|
1001
|
+
attribution: fields.attribution ?? void 0,
|
|
1002
|
+
journey: fields.journey
|
|
1003
|
+
}),
|
|
1004
|
+
cache: "no-store",
|
|
1005
|
+
redirect: "manual",
|
|
1006
|
+
signal: options.signal
|
|
1007
|
+
});
|
|
1008
|
+
} catch {
|
|
1009
|
+
return failure(
|
|
1010
|
+
"transport",
|
|
1011
|
+
"network_error",
|
|
1012
|
+
null,
|
|
1013
|
+
"\uC811\uC218 \uACB0\uACFC\uB97C \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uAC19\uC740 \uB0B4\uC6A9\uC73C\uB85C \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694."
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
const body = await readJson(response);
|
|
1017
|
+
if (!response.ok) {
|
|
1018
|
+
const code = isRecord(body) && isNonEmptyString(body.code) ? body.code : codeForStatus(response.status);
|
|
1019
|
+
const message = isRecord(body) && isNonEmptyString(body.message) ? body.message : "\uBB38\uC758 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uC785\uB825 \uB0B4\uC6A9\uACFC \uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uD655\uC778\uD574\uC8FC\uC138\uC694.";
|
|
1020
|
+
const details = isRecord(body) && isRecord(body.details) ? body.details : void 0;
|
|
1021
|
+
return {
|
|
1022
|
+
...failure("api", code, response.status, message),
|
|
1023
|
+
fieldErrors: parseFieldErrors(details?.field_errors),
|
|
1024
|
+
formErrors: stringArray(details?.form_errors)
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
if (!isRecord(body) || !isId(body.id) || !isPositiveInteger(body.inquiry_no) || !isTimestamp(body.received_at) || typeof body.replayed !== "boolean") {
|
|
1028
|
+
return failure(
|
|
1029
|
+
"invalid_response",
|
|
1030
|
+
"invalid_response",
|
|
1031
|
+
response.status,
|
|
1032
|
+
"\uC811\uC218\uC99D\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uAC19\uC740 \uB0B4\uC6A9\uC73C\uB85C \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694."
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
return {
|
|
1036
|
+
ok: true,
|
|
1037
|
+
receipt: { id: body.id, inquiryNo: body.inquiry_no, receivedAt: body.received_at, replayed: body.replayed }
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
function formUrl(options) {
|
|
1041
|
+
const base = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
1042
|
+
return `${base}/v1/public/inquiry-forms/${encodeURIComponent(options.formId)}`;
|
|
1043
|
+
}
|
|
1044
|
+
function failure(kind, code, status, message) {
|
|
1045
|
+
return { ok: false, kind, code, status, message, fieldErrors: {}, formErrors: [] };
|
|
1046
|
+
}
|
|
1047
|
+
function invalidFormResponse(status) {
|
|
1048
|
+
return new CmsApiError("RootTale inquiry form response is invalid", status, "invalid_response");
|
|
1049
|
+
}
|
|
1050
|
+
async function readJson(response) {
|
|
1051
|
+
try {
|
|
1052
|
+
return await response.json();
|
|
1053
|
+
} catch {
|
|
1054
|
+
return null;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
function isRecord(value) {
|
|
1058
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1059
|
+
}
|
|
1060
|
+
function isNonEmptyString(value) {
|
|
1061
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
1062
|
+
}
|
|
1063
|
+
function isId(value) {
|
|
1064
|
+
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
1065
|
+
}
|
|
1066
|
+
function isPositiveInteger(value) {
|
|
1067
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
1068
|
+
}
|
|
1069
|
+
function isTimestamp(value) {
|
|
1070
|
+
return typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && Number.isFinite(Date.parse(value));
|
|
1071
|
+
}
|
|
1072
|
+
function stringArray(value) {
|
|
1073
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
1074
|
+
}
|
|
1075
|
+
function parseFieldErrors(value) {
|
|
1076
|
+
if (!isRecord(value)) return {};
|
|
1077
|
+
return Object.fromEntries(Object.entries(value).map(([key, errors]) => [key, stringArray(errors)]));
|
|
1078
|
+
}
|
|
1079
|
+
function codeForStatus(status) {
|
|
1080
|
+
if (status === 401) return "invalid_api_key";
|
|
1081
|
+
if (status === 403) return "insufficient_scope";
|
|
1082
|
+
if (status === 404) return "not_found";
|
|
1083
|
+
if (status === 429) return "rate_limited";
|
|
1084
|
+
return "request_failed";
|
|
1085
|
+
}
|
|
1086
|
+
|
|
956
1087
|
// src/server-preview.ts
|
|
957
1088
|
function isPreviewExpiredError(error) {
|
|
958
1089
|
return error instanceof CmsApiError && (error.code === "preview_expired" || error.status === 410);
|
|
@@ -1523,6 +1654,7 @@ export {
|
|
|
1523
1654
|
fetchContentModels,
|
|
1524
1655
|
fetchExposure,
|
|
1525
1656
|
fetchExposureDecision,
|
|
1657
|
+
fetchInquiryForm,
|
|
1526
1658
|
fetchMenu,
|
|
1527
1659
|
fetchMenus,
|
|
1528
1660
|
fetchPageBySlug,
|
|
@@ -1552,6 +1684,7 @@ export {
|
|
|
1552
1684
|
selectRelatedPosts,
|
|
1553
1685
|
selectSitePatternForSlot,
|
|
1554
1686
|
sitePatternPresentationAttributes,
|
|
1687
|
+
submitFormInquiry,
|
|
1555
1688
|
submitInquiry,
|
|
1556
1689
|
submitSiteInquiry,
|
|
1557
1690
|
websiteSchema
|