@otl-core/cms-api 1.1.0 → 1.1.2
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/index.cjs +13 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -39,9 +39,9 @@ function getBackendApiBaseUrl() {
|
|
|
39
39
|
return "http://localhost:8080";
|
|
40
40
|
}
|
|
41
41
|
if (process.env.STAGE === "staging") {
|
|
42
|
-
return "https://api-staging.otl
|
|
42
|
+
return "https://api-staging.otl.studio";
|
|
43
43
|
}
|
|
44
|
-
return "https://api.otl
|
|
44
|
+
return "https://api.otl.studio";
|
|
45
45
|
}
|
|
46
46
|
function getBackendSiteId() {
|
|
47
47
|
const siteId = process.env.SITE_ID;
|
|
@@ -168,7 +168,7 @@ var HttpClient = class {
|
|
|
168
168
|
...fetchOptions,
|
|
169
169
|
headers,
|
|
170
170
|
signal: controller.signal,
|
|
171
|
-
...
|
|
171
|
+
...this.resolveCacheOptions(nextOptions)
|
|
172
172
|
});
|
|
173
173
|
clearTimeout(timeoutId);
|
|
174
174
|
if (response.status >= 500 && process.env.NODE_ENV === "production" && nextOptions) {
|
|
@@ -230,7 +230,7 @@ var HttpClient = class {
|
|
|
230
230
|
});
|
|
231
231
|
if (staleResponse.ok) {
|
|
232
232
|
const staleData = await staleResponse.json();
|
|
233
|
-
console.
|
|
233
|
+
console.warn(`[HttpClient] Serving stale cache for: ${url}`);
|
|
234
234
|
return staleData;
|
|
235
235
|
}
|
|
236
236
|
} catch (cacheError) {
|
|
@@ -241,6 +241,15 @@ var HttpClient = class {
|
|
|
241
241
|
}
|
|
242
242
|
return null;
|
|
243
243
|
}
|
|
244
|
+
resolveCacheOptions(nextOptions) {
|
|
245
|
+
if (process.env.NODE_ENV === "development") {
|
|
246
|
+
return { cache: "no-store" };
|
|
247
|
+
}
|
|
248
|
+
if (nextOptions) {
|
|
249
|
+
return { next: nextOptions };
|
|
250
|
+
}
|
|
251
|
+
return {};
|
|
252
|
+
}
|
|
244
253
|
async get(endpoint, params, options) {
|
|
245
254
|
let url = endpoint;
|
|
246
255
|
if (params) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/collection.service.ts","../src/api.config.ts","../src/services/form.service.ts","../src/http-client.ts","../src/services/media.service.ts","../src/services/website.service.ts","../src/api-client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Collection Service\n * Handles collection, entry, and category retrieval\n */\n\nimport type {\n APIResponse,\n Collection,\n Category,\n Entry,\n} from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport class CollectionService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchCollections(siteId: string): Promise<APIResponse<Collection[]>> {\n return this.httpClient.get(`/api/v1/public/sites/${siteId}/collections`);\n }\n\n async fetchEntries(\n collectionId: string,\n params?: { page?: number; limit?: number; category?: string },\n ): Promise<APIResponse<Entry[]>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/entries`,\n params,\n );\n }\n\n async fetchEntry(\n collectionId: string,\n entrySlug: string,\n ): Promise<APIResponse<Entry>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/entries/${entrySlug}`,\n );\n }\n\n async fetchCategories(\n collectionId: string,\n ): Promise<APIResponse<Category[]>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/categories`,\n );\n }\n}\n","/**\n * API Configuration\n * Server-side only configuration for CMS backend communication.\n * Uses only process.env.API_URL (never NEXT_PUBLIC_ prefixed variables).\n */\n\nimport { HttpClientConfig } from \"./http-client\";\n\nexport interface APIConfig {\n http: HttpClientConfig;\n siteId: string;\n devToken?: string;\n environment: \"development\" | \"production\" | \"staging\";\n}\n\n/**\n * Get backend API base URL (server-side only, never exposed to client)\n */\nfunction getBackendApiBaseUrl(): string {\n if (process.env.API_URL) {\n return process.env.API_URL;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n return \"http://localhost:8080\";\n }\n\n if (process.env.STAGE === \"staging\") {\n return \"https://api-staging.otl-cms.com\";\n }\n\n return \"https://api.otl-cms.com\";\n}\n\n/**\n * Get site ID from environment (server-side only)\n */\nfunction getBackendSiteId(): string {\n const siteId = process.env.SITE_ID;\n if (!siteId) {\n console.error(\"SITE_ID environment variable is not set!\");\n console.error(\"Add the following to your .env.local:\");\n console.error(\" SITE_ID=your-site-id\");\n console.error(\" API_URL=http://localhost:8080\");\n throw new Error(\"SITE_ID environment variable is required.\");\n }\n return siteId;\n}\n\n/**\n * Get site access token from environment (server-side only)\n */\nfunction getSiteAccessToken(): string {\n const token = process.env.SITE_ACCESS_TOKEN;\n if (!token) {\n console.error(\"SITE_ACCESS_TOKEN environment variable is not set!\");\n console.error(\"Add the following to your .env.local:\");\n console.error(\" SITE_ACCESS_TOKEN=kpt_...\");\n console.error(\"\");\n console.error(\"To obtain an access token:\");\n console.error(\"1. Log into the CMS management interface\");\n console.error(\"2. Navigate to your site settings\");\n console.error(\"3. Go to Access Tokens section\");\n console.error(\"4. Create a new token and copy it here\");\n throw new Error(\n \"SITE_ACCESS_TOKEN environment variable is required. \" +\n \"Please obtain an access token from the CMS site settings.\",\n );\n }\n return token;\n}\n\n/**\n * Get current environment (server-side only)\n */\nfunction getBackendEnvironment(): \"development\" | \"production\" | \"staging\" {\n if (process.env.NODE_ENV === \"production\") {\n return process.env.STAGE === \"staging\" ? \"staging\" : \"production\";\n }\n return \"development\";\n}\n\n/**\n * Default API configuration\n */\nexport const defaultAPIConfig: APIConfig = {\n http: {\n baseUrl: getBackendApiBaseUrl(),\n timeout: 30000,\n defaultHeaders: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"OTL-CMS-Engine/1.0\",\n },\n },\n siteId: getBackendSiteId(),\n devToken: getSiteAccessToken(),\n environment: getBackendEnvironment(),\n};\n\n/**\n * Create API configuration with overrides\n */\nexport function createAPIConfig(overrides?: Partial<APIConfig>): APIConfig {\n return {\n ...defaultAPIConfig,\n ...overrides,\n http: {\n ...defaultAPIConfig.http,\n ...overrides?.http,\n },\n };\n}\n\n/**\n * Validate API configuration\n */\nexport function validateAPIConfig(config: APIConfig): void {\n if (!config.http.baseUrl) {\n throw new Error(\"API base URL is required\");\n }\n\n try {\n new URL(config.http.baseUrl);\n } catch {\n throw new Error(\"Invalid API base URL format\");\n }\n\n if (!config.siteId) {\n throw new Error(\"Site ID is required\");\n }\n\n if (!config.devToken) {\n throw new Error(\n \"Site access token is required. \" +\n \"Please set SITE_ACCESS_TOKEN environment variable.\",\n );\n }\n\n if (config.http.timeout && config.http.timeout < 1000) {\n console.warn(\"API timeout is very low, this might cause issues\");\n }\n}\n","/**\n * Form Service\n * Handles form submissions\n */\n\nimport type { HttpClient } from \"../http-client\";\n\nexport interface FormSubmissionRequest {\n type: string;\n locale: string;\n data: Record<string, unknown>;\n form_variant_id?: string;\n environment_type?: string;\n environment_id?: string;\n environment_path?: string;\n environment_variant_id?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface FormSubmissionResponse {\n success: boolean;\n submission_id: string;\n message?: string;\n}\n\nexport class FormService {\n constructor(private httpClient: HttpClient) {}\n\n async submitForm(\n formId: string,\n data: FormSubmissionRequest,\n ): Promise<FormSubmissionResponse> {\n return this.httpClient.post<FormSubmissionResponse>(\n `/api/v1/public/forms/${formId}/submit`,\n data,\n );\n }\n}\n","export interface HttpClientConfig {\n baseUrl: string;\n timeout?: number;\n defaultHeaders?: Record<string, string>;\n}\n\ninterface FetchOptions extends Omit<RequestInit, \"headers\"> {\n headers?: Record<string, string | undefined>;\n next?: {\n revalidate?: number | false;\n tags?: string[];\n };\n}\n\nexport class HttpClient {\n public baseUrl: string;\n private timeout: number;\n private defaultHeaders: Record<string, string>;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.timeout = config.timeout || 30000;\n this.defaultHeaders = {\n \"Content-Type\": \"application/json\",\n ...config.defaultHeaders,\n };\n }\n\n /**\n * Make a generic HTTP request\n */\n private async request<T>(\n endpoint: string,\n options: FetchOptions = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const { next: nextOptions, ...fetchOptions } = options;\n\n const mergedHeaders: Record<string, string | undefined> = {\n ...this.defaultHeaders,\n ...fetchOptions.headers,\n };\n const headers = Object.fromEntries(\n Object.entries(mergedHeaders).filter(\n (entry): entry is [string, string] => entry[1] !== undefined,\n ),\n );\n\n try {\n const response = await fetch(url, {\n ...fetchOptions,\n headers,\n signal: controller.signal,\n ...(process.env.NODE_ENV === \"development\"\n ? { cache: \"no-store\" as const }\n : nextOptions\n ? { next: nextOptions }\n : {}),\n });\n\n clearTimeout(timeoutId);\n\n // Server error (5xx) -- try stale cache before returning the error\n if (\n response.status >= 500 &&\n process.env.NODE_ENV === \"production\" &&\n nextOptions\n ) {\n const staleData = await this.tryStaleCache<T>(\n url,\n fetchOptions,\n headers,\n );\n if (staleData !== null) return staleData;\n }\n\n const data = await response.json();\n\n if (!response.ok) {\n if (data && typeof data === \"object\") {\n if (\"success\" in data) {\n return data;\n }\n if (\"type\" in data) {\n return {\n success: response.status >= 200 && response.status < 300,\n data,\n } as T;\n }\n }\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof Error) {\n // Network failure, timeout, or unstructured error -- try stale cache\n if (process.env.NODE_ENV === \"production\" && nextOptions) {\n const staleData = await this.tryStaleCache<T>(\n url,\n fetchOptions,\n headers,\n );\n if (staleData !== null) return staleData;\n }\n\n if (error.name === \"AbortError\") {\n throw new Error(\"Request timeout\");\n }\n throw error;\n }\n\n throw new Error(\"Unknown error occurred\");\n }\n }\n\n /**\n * Attempt to serve a stale cached response when the backend is unreachable\n * or returning server errors. Returns null if no cache entry exists.\n */\n private async tryStaleCache<T>(\n url: string,\n fetchOptions: Omit<RequestInit, \"headers\">,\n headers: Record<string, string>,\n ): Promise<T | null> {\n try {\n console.warn(\n `[HttpClient] Backend unavailable, attempting stale cache: ${url}`,\n );\n const staleResponse = await fetch(url, {\n ...fetchOptions,\n headers,\n cache: \"force-cache\" as const,\n });\n\n if (staleResponse.ok) {\n const staleData = await staleResponse.json();\n console.log(`[HttpClient] Serving stale cache for: ${url}`);\n return staleData;\n }\n } catch (cacheError) {\n console.error(\n `[HttpClient] No cache available for: ${url}`,\n cacheError instanceof Error ? cacheError.message : cacheError,\n );\n }\n return null;\n }\n\n async get<T>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: FetchOptions,\n ): Promise<T> {\n let url = endpoint;\n\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n\n if (searchParams.toString()) {\n url += `?${searchParams.toString()}`;\n }\n }\n\n return this.request<T>(url, { method: \"GET\", ...options });\n }\n\n async post<T>(endpoint: string, data?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"POST\",\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n async put<T>(endpoint: string, data?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"PUT\",\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n async delete<T>(endpoint: string): Promise<T> {\n return this.request<T>(endpoint, { method: \"DELETE\" });\n }\n\n async upload<T>(endpoint: string, formData: FormData): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"POST\",\n body: formData,\n headers: { \"Content-Type\": undefined },\n });\n }\n\n setAuthToken(token: string) {\n this.defaultHeaders[\"Authorization\"] = `Bearer ${token}`;\n }\n\n removeAuthToken() {\n delete this.defaultHeaders[\"Authorization\"];\n }\n\n setBaseUrl(baseUrl: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, \"\");\n }\n}\n","/**\n * Media Service\n * Handles media file retrieval\n */\n\nimport type { APIResponse, Media } from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport class MediaService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchMediaFile(\n siteId: string,\n mediaId: string,\n ): Promise<APIResponse<Media>> {\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/media/${mediaId}`,\n );\n }\n\n async fetchMedia(siteId: string): Promise<APIResponse<Media[]>> {\n return this.httpClient.get(`/api/v1/public/sites/${siteId}/media`);\n }\n}\n","/**\n * Website Service\n * Handles configuration, path resolution, sitemap, and redirect operations\n */\n\nimport type { APIResponse, SiteConfig } from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport interface PathResolutionResponse {\n path: string;\n type:\n | \"page\"\n | \"collection\"\n | \"entry\"\n | \"category\"\n | \"category_index\"\n | \"author\"\n | \"author_index\"\n | \"tag\"\n | \"tag_index\"\n | \"redirect\"\n | \"not_found\"\n | \"multiple\";\n content_id?: string;\n entry_id?: string;\n category_id?: string;\n collection_id?: string;\n locale: string;\n content?: Record<string, unknown>;\n redirect?: {\n to_path?: string;\n to_url?: string;\n status_code: number;\n query_string_behavior: string;\n };\n status_code?: number;\n cache_ttl: number;\n all_matches?: {\n redirect?: unknown;\n page?: unknown;\n category?: unknown;\n entry?: unknown;\n primary_match: string;\n };\n}\n\nexport interface BatchPathResolutionResponse {\n results: PathResolutionResponse[];\n}\n\nexport interface PathInfo {\n path: string;\n content_type: string;\n content_id?: string;\n locale: string;\n}\n\nexport interface AllPathsResponse {\n paths: PathInfo[];\n pagination: {\n page: number;\n limit: number;\n total: number;\n total_pages: number;\n has_next: boolean;\n has_prev: boolean;\n };\n}\n\nexport class WebsiteService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchConfigs(\n siteId: string,\n locale?: string,\n headerPresetId?: string,\n footerPresetId?: string,\n ): Promise<APIResponse<SiteConfig>> {\n const params = new URLSearchParams();\n if (locale) params.set(\"locale\", locale);\n if (headerPresetId) params.set(\"header_preset\", headerPresetId);\n if (footerPresetId) params.set(\"footer_preset\", footerPresetId);\n\n const queryString = params.toString();\n const url = queryString\n ? `/api/v1/public/sites/${siteId}/configs?${queryString}`\n : `/api/v1/public/sites/${siteId}/configs`;\n\n const defaultRevalidate = parseInt(\n process.env.CACHE_REVALIDATE_SECONDS || \"60\",\n 10,\n );\n\n const tags = [`site:${siteId}`, `config:${siteId}`, \"config\"];\n if (headerPresetId) tags.push(`header-preset:${headerPresetId}`);\n if (footerPresetId) tags.push(`footer-preset:${footerPresetId}`);\n\n return this.httpClient.get(url, undefined, {\n next: {\n revalidate: defaultRevalidate === 0 ? false : defaultRevalidate,\n tags,\n },\n });\n }\n\n async resolvePath(\n siteId: string,\n path: string,\n locale: string,\n options?: {\n fetchContent?: boolean;\n mode?: \"default\" | \"all\";\n page?: number;\n perPage?: number;\n searchQuery?: string;\n },\n ): Promise<APIResponse<PathResolutionResponse>> {\n const params = new URLSearchParams({\n path,\n locale,\n ...(options?.fetchContent && { fetch_content: \"true\" }),\n ...(options?.mode && { mode: options.mode }),\n ...(options?.page && { page: options.page.toString() }),\n ...(options?.perPage && { perPage: options.perPage.toString() }),\n ...(options?.searchQuery && { q: options.searchQuery }),\n });\n\n const defaultRevalidate = parseInt(\n process.env.CACHE_REVALIDATE_SECONDS || \"60\",\n 10,\n );\n\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/resolve-path?${params}`,\n undefined,\n {\n next: {\n revalidate: defaultRevalidate === 0 ? false : defaultRevalidate,\n tags: [\n `site:${siteId}`,\n `path:${siteId}:${locale}:${path}`,\n \"content\",\n ],\n },\n },\n );\n }\n\n async resolvePaths(\n siteId: string,\n paths: string[],\n locale: string,\n fetchContent: boolean = false,\n ): Promise<APIResponse<BatchPathResolutionResponse>> {\n return this.httpClient.post(\n `/api/v1/public/sites/${siteId}/resolve-paths`,\n {\n paths,\n locale,\n fetch_content: fetchContent,\n },\n );\n }\n\n async fetchAllPaths(\n siteId: string,\n locale: string,\n options?: {\n limit?: number;\n offset?: number;\n },\n ): Promise<APIResponse<AllPathsResponse>> {\n const params = new URLSearchParams({\n locale,\n ...(options?.limit && { limit: options.limit.toString() }),\n ...(options?.offset && { offset: options.offset.toString() }),\n });\n\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/all-paths?${params}`,\n );\n }\n\n async fetchPageSections(\n siteId: string,\n path: string,\n ): Promise<APIResponse<unknown[]>> {\n const encodedPath = encodeURIComponent(path || \"/\");\n return this.httpClient.get(\n `/api/v1/sites/${siteId}/pages/${encodedPath}/sections`,\n );\n }\n\n async fetchPageSEO(\n siteId: string,\n path: string,\n ): Promise<APIResponse<unknown>> {\n const encodedPath = encodeURIComponent(path || \"/\");\n return this.httpClient.get(\n `/api/v1/sites/${siteId}/pages/${encodedPath}/seo`,\n );\n }\n\n async fetchRedirects(siteId: string): Promise<APIResponse<unknown[]>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/redirects`);\n }\n\n async fetchSitemap(siteId: string): Promise<APIResponse<string>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/sitemap`);\n }\n\n async fetchRobots(siteId: string): Promise<APIResponse<string>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/robots`);\n }\n}\n","/**\n * API Client\n * Main interface for CMS backend communication - SERVER-SIDE ONLY\n *\n * This module is protected by the `server-only` package.\n * Any attempt to import it from a client component will fail at build time.\n */\n\nimport { CollectionService } from \"./services/collection.service\";\nimport { APIConfig, defaultAPIConfig, validateAPIConfig } from \"./api.config\";\nimport { FormService } from \"./services/form.service\";\nimport { HttpClient } from \"./http-client\";\nimport { MediaService } from \"./services/media.service\";\nimport { WebsiteService } from \"./services/website.service\";\n\nexport class APIClient {\n private httpClient: HttpClient;\n private config: APIConfig;\n\n public readonly website: WebsiteService;\n public readonly collection: CollectionService;\n public readonly media: MediaService;\n public readonly forms: FormService;\n\n constructor(config?: Partial<APIConfig>) {\n this.config = {\n ...defaultAPIConfig,\n ...config,\n http: {\n ...defaultAPIConfig.http,\n ...config?.http,\n },\n };\n\n validateAPIConfig(this.config);\n\n this.httpClient = new HttpClient(this.config.http);\n\n if (this.config.devToken) {\n this.httpClient.setAuthToken(this.config.devToken);\n }\n\n this.website = new WebsiteService(this.httpClient);\n this.collection = new CollectionService(this.httpClient);\n this.media = new MediaService(this.httpClient);\n this.forms = new FormService(this.httpClient);\n }\n\n getSiteId(): string {\n return this.config.siteId;\n }\n\n setSiteId(siteId: string): void {\n this.config.siteId = siteId;\n }\n\n setAuthToken(token: string): void {\n this.httpClient.setAuthToken(token);\n }\n\n removeAuthToken(): void {\n this.httpClient.removeAuthToken();\n }\n\n setBaseUrl(baseUrl: string): void {\n this.httpClient.setBaseUrl(baseUrl);\n this.config.http.baseUrl = baseUrl;\n }\n\n getBaseUrl(): string {\n return this.httpClient.baseUrl;\n }\n\n getConfig(): APIConfig {\n return { ...this.config };\n }\n}\n\n// Singleton instance\nlet apiClient: APIClient;\n\n/**\n * Initialize the API client\n */\nexport function initializeAPIClient(config?: Partial<APIConfig>): APIClient {\n apiClient = new APIClient(config);\n return apiClient;\n}\n\n/**\n * Get the initialized API client instance\n */\nexport function getAPIClient(): APIClient {\n if (!apiClient) {\n try {\n apiClient = new APIClient();\n } catch (error) {\n console.error(\"Failed to initialize API client:\", error);\n throw error;\n }\n }\n return apiClient;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/services/collection.service.ts","../src/api.config.ts","../src/services/form.service.ts","../src/http-client.ts","../src/services/media.service.ts","../src/services/website.service.ts","../src/api-client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Collection Service\n * Handles collection, entry, and category retrieval\n */\n\nimport type {\n APIResponse,\n Collection,\n Category,\n Entry,\n} from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport class CollectionService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchCollections(siteId: string): Promise<APIResponse<Collection[]>> {\n return this.httpClient.get(`/api/v1/public/sites/${siteId}/collections`);\n }\n\n async fetchEntries(\n collectionId: string,\n params?: { page?: number; limit?: number; category?: string },\n ): Promise<APIResponse<Entry[]>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/entries`,\n params,\n );\n }\n\n async fetchEntry(\n collectionId: string,\n entrySlug: string,\n ): Promise<APIResponse<Entry>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/entries/${entrySlug}`,\n );\n }\n\n async fetchCategories(\n collectionId: string,\n ): Promise<APIResponse<Category[]>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/categories`,\n );\n }\n}\n","/**\n * API Configuration\n * Server-side only configuration for CMS backend communication.\n * Uses only process.env.API_URL (never NEXT_PUBLIC_ prefixed variables).\n */\n\nimport { HttpClientConfig } from \"./http-client\";\n\nexport interface APIConfig {\n http: HttpClientConfig;\n siteId: string;\n devToken?: string;\n environment: \"development\" | \"production\" | \"staging\";\n}\n\n/**\n * Get backend API base URL (server-side only, never exposed to client)\n */\nfunction getBackendApiBaseUrl(): string {\n if (process.env.API_URL) {\n return process.env.API_URL;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n return \"http://localhost:8080\";\n }\n\n if (process.env.STAGE === \"staging\") {\n return \"https://api-staging.otl.studio\";\n }\n\n return \"https://api.otl.studio\";\n}\n\n/**\n * Get site ID from environment (server-side only)\n */\nfunction getBackendSiteId(): string {\n const siteId = process.env.SITE_ID;\n if (!siteId) {\n console.error(\"SITE_ID environment variable is not set!\");\n console.error(\"Add the following to your .env.local:\");\n console.error(\" SITE_ID=your-site-id\");\n console.error(\" API_URL=http://localhost:8080\");\n throw new Error(\"SITE_ID environment variable is required.\");\n }\n return siteId;\n}\n\n/**\n * Get site access token from environment (server-side only)\n */\nfunction getSiteAccessToken(): string {\n const token = process.env.SITE_ACCESS_TOKEN;\n if (!token) {\n console.error(\"SITE_ACCESS_TOKEN environment variable is not set!\");\n console.error(\"Add the following to your .env.local:\");\n console.error(\" SITE_ACCESS_TOKEN=kpt_...\");\n console.error(\"\");\n console.error(\"To obtain an access token:\");\n console.error(\"1. Log into the CMS management interface\");\n console.error(\"2. Navigate to your site settings\");\n console.error(\"3. Go to Access Tokens section\");\n console.error(\"4. Create a new token and copy it here\");\n throw new Error(\n \"SITE_ACCESS_TOKEN environment variable is required. \" +\n \"Please obtain an access token from the CMS site settings.\",\n );\n }\n return token;\n}\n\n/**\n * Get current environment (server-side only)\n */\nfunction getBackendEnvironment(): \"development\" | \"production\" | \"staging\" {\n if (process.env.NODE_ENV === \"production\") {\n return process.env.STAGE === \"staging\" ? \"staging\" : \"production\";\n }\n return \"development\";\n}\n\n/**\n * Default API configuration\n */\nexport const defaultAPIConfig: APIConfig = {\n http: {\n baseUrl: getBackendApiBaseUrl(),\n timeout: 30000,\n defaultHeaders: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"OTL-CMS-Engine/1.0\",\n },\n },\n siteId: getBackendSiteId(),\n devToken: getSiteAccessToken(),\n environment: getBackendEnvironment(),\n};\n\n/**\n * Create API configuration with overrides\n */\nexport function createAPIConfig(overrides?: Partial<APIConfig>): APIConfig {\n return {\n ...defaultAPIConfig,\n ...overrides,\n http: {\n ...defaultAPIConfig.http,\n ...overrides?.http,\n },\n };\n}\n\n/**\n * Validate API configuration\n */\nexport function validateAPIConfig(config: APIConfig): void {\n if (!config.http.baseUrl) {\n throw new Error(\"API base URL is required\");\n }\n\n try {\n new URL(config.http.baseUrl);\n } catch {\n throw new Error(\"Invalid API base URL format\");\n }\n\n if (!config.siteId) {\n throw new Error(\"Site ID is required\");\n }\n\n if (!config.devToken) {\n throw new Error(\n \"Site access token is required. \" +\n \"Please set SITE_ACCESS_TOKEN environment variable.\",\n );\n }\n\n if (config.http.timeout && config.http.timeout < 1000) {\n console.warn(\"API timeout is very low, this might cause issues\");\n }\n}\n","/**\n * Form Service\n * Handles form submissions\n */\n\nimport type { HttpClient } from \"../http-client\";\n\nexport interface FormSubmissionRequest {\n type: string;\n locale: string;\n data: Record<string, unknown>;\n form_variant_id?: string;\n environment_type?: string;\n environment_id?: string;\n environment_path?: string;\n environment_variant_id?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface FormSubmissionResponse {\n success: boolean;\n submission_id: string;\n message?: string;\n}\n\nexport class FormService {\n constructor(private httpClient: HttpClient) {}\n\n async submitForm(\n formId: string,\n data: FormSubmissionRequest,\n ): Promise<FormSubmissionResponse> {\n return this.httpClient.post<FormSubmissionResponse>(\n `/api/v1/public/forms/${formId}/submit`,\n data,\n );\n }\n}\n","export interface HttpClientConfig {\n baseUrl: string;\n timeout?: number;\n defaultHeaders?: Record<string, string>;\n}\n\ninterface FetchOptions extends Omit<RequestInit, \"headers\"> {\n headers?: Record<string, string | undefined>;\n next?: {\n revalidate?: number | false;\n tags?: string[];\n };\n}\n\nexport class HttpClient {\n public baseUrl: string;\n private timeout: number;\n private defaultHeaders: Record<string, string>;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.timeout = config.timeout || 30000;\n this.defaultHeaders = {\n \"Content-Type\": \"application/json\",\n ...config.defaultHeaders,\n };\n }\n\n /**\n * Make a generic HTTP request\n */\n private async request<T>(\n endpoint: string,\n options: FetchOptions = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const { next: nextOptions, ...fetchOptions } = options;\n\n const mergedHeaders: Record<string, string | undefined> = {\n ...this.defaultHeaders,\n ...fetchOptions.headers,\n };\n const headers = Object.fromEntries(\n Object.entries(mergedHeaders).filter(\n (entry): entry is [string, string] => entry[1] !== undefined,\n ),\n );\n\n try {\n const response = await fetch(url, {\n ...fetchOptions,\n headers,\n signal: controller.signal,\n ...this.resolveCacheOptions(nextOptions),\n });\n\n clearTimeout(timeoutId);\n\n // Server error (5xx) -- try stale cache before returning the error\n if (\n response.status >= 500 &&\n process.env.NODE_ENV === \"production\" &&\n nextOptions\n ) {\n const staleData = await this.tryStaleCache<T>(\n url,\n fetchOptions,\n headers,\n );\n if (staleData !== null) return staleData;\n }\n\n const data = await response.json();\n\n if (!response.ok) {\n if (data && typeof data === \"object\") {\n if (\"success\" in data) {\n return data;\n }\n if (\"type\" in data) {\n return {\n success: response.status >= 200 && response.status < 300,\n data,\n } as T;\n }\n }\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof Error) {\n // Network failure, timeout, or unstructured error -- try stale cache\n if (process.env.NODE_ENV === \"production\" && nextOptions) {\n const staleData = await this.tryStaleCache<T>(\n url,\n fetchOptions,\n headers,\n );\n if (staleData !== null) return staleData;\n }\n\n if (error.name === \"AbortError\") {\n throw new Error(\"Request timeout\");\n }\n throw error;\n }\n\n throw new Error(\"Unknown error occurred\");\n }\n }\n\n /**\n * Attempt to serve a stale cached response when the backend is unreachable\n * or returning server errors. Returns null if no cache entry exists.\n */\n private async tryStaleCache<T>(\n url: string,\n fetchOptions: Omit<RequestInit, \"headers\">,\n headers: Record<string, string>,\n ): Promise<T | null> {\n try {\n console.warn(\n `[HttpClient] Backend unavailable, attempting stale cache: ${url}`,\n );\n const staleResponse = await fetch(url, {\n ...fetchOptions,\n headers,\n cache: \"force-cache\" as const,\n });\n\n if (staleResponse.ok) {\n const staleData = await staleResponse.json();\n console.warn(`[HttpClient] Serving stale cache for: ${url}`);\n return staleData;\n }\n } catch (cacheError) {\n console.error(\n `[HttpClient] No cache available for: ${url}`,\n cacheError instanceof Error ? cacheError.message : cacheError,\n );\n }\n return null;\n }\n\n private resolveCacheOptions(nextOptions?: FetchOptions[\"next\"]) {\n if (process.env.NODE_ENV === \"development\") {\n return { cache: \"no-store\" as const };\n }\n if (nextOptions) {\n return { next: nextOptions };\n }\n return {};\n }\n\n async get<T>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: FetchOptions,\n ): Promise<T> {\n let url = endpoint;\n\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n\n if (searchParams.toString()) {\n url += `?${searchParams.toString()}`;\n }\n }\n\n return this.request<T>(url, { method: \"GET\", ...options });\n }\n\n async post<T>(endpoint: string, data?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"POST\",\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n async put<T>(endpoint: string, data?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"PUT\",\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n async delete<T>(endpoint: string): Promise<T> {\n return this.request<T>(endpoint, { method: \"DELETE\" });\n }\n\n async upload<T>(endpoint: string, formData: FormData): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"POST\",\n body: formData,\n headers: { \"Content-Type\": undefined },\n });\n }\n\n setAuthToken(token: string) {\n this.defaultHeaders[\"Authorization\"] = `Bearer ${token}`;\n }\n\n removeAuthToken() {\n delete this.defaultHeaders[\"Authorization\"];\n }\n\n setBaseUrl(baseUrl: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, \"\");\n }\n}\n","/**\n * Media Service\n * Handles media file retrieval\n */\n\nimport type { APIResponse, Media } from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport class MediaService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchMediaFile(\n siteId: string,\n mediaId: string,\n ): Promise<APIResponse<Media>> {\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/media/${mediaId}`,\n );\n }\n\n async fetchMedia(siteId: string): Promise<APIResponse<Media[]>> {\n return this.httpClient.get(`/api/v1/public/sites/${siteId}/media`);\n }\n}\n","/**\n * Website Service\n * Handles configuration, path resolution, sitemap, and redirect operations\n */\n\nimport type { APIResponse, SiteConfig } from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport interface PathResolutionResponse {\n path: string;\n type:\n | \"page\"\n | \"collection\"\n | \"entry\"\n | \"category\"\n | \"category_index\"\n | \"author\"\n | \"author_index\"\n | \"tag\"\n | \"tag_index\"\n | \"redirect\"\n | \"not_found\"\n | \"multiple\";\n content_id?: string;\n entry_id?: string;\n category_id?: string;\n collection_id?: string;\n locale: string;\n content?: Record<string, unknown>;\n redirect?: {\n to_path?: string;\n to_url?: string;\n status_code: number;\n query_string_behavior: string;\n };\n status_code?: number;\n cache_ttl: number;\n all_matches?: {\n redirect?: unknown;\n page?: unknown;\n category?: unknown;\n entry?: unknown;\n primary_match: string;\n };\n}\n\nexport interface BatchPathResolutionResponse {\n results: PathResolutionResponse[];\n}\n\nexport interface PathInfo {\n path: string;\n content_type: string;\n content_id?: string;\n locale: string;\n}\n\nexport interface AllPathsResponse {\n paths: PathInfo[];\n pagination: {\n page: number;\n limit: number;\n total: number;\n total_pages: number;\n has_next: boolean;\n has_prev: boolean;\n };\n}\n\nexport class WebsiteService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchConfigs(\n siteId: string,\n locale?: string,\n headerPresetId?: string,\n footerPresetId?: string,\n ): Promise<APIResponse<SiteConfig>> {\n const params = new URLSearchParams();\n if (locale) params.set(\"locale\", locale);\n if (headerPresetId) params.set(\"header_preset\", headerPresetId);\n if (footerPresetId) params.set(\"footer_preset\", footerPresetId);\n\n const queryString = params.toString();\n const url = queryString\n ? `/api/v1/public/sites/${siteId}/configs?${queryString}`\n : `/api/v1/public/sites/${siteId}/configs`;\n\n const defaultRevalidate = parseInt(\n process.env.CACHE_REVALIDATE_SECONDS || \"60\",\n 10,\n );\n\n const tags = [`site:${siteId}`, `config:${siteId}`, \"config\"];\n if (headerPresetId) tags.push(`header-preset:${headerPresetId}`);\n if (footerPresetId) tags.push(`footer-preset:${footerPresetId}`);\n\n return this.httpClient.get(url, undefined, {\n next: {\n revalidate: defaultRevalidate === 0 ? false : defaultRevalidate,\n tags,\n },\n });\n }\n\n async resolvePath(\n siteId: string,\n path: string,\n locale: string,\n options?: {\n fetchContent?: boolean;\n mode?: \"default\" | \"all\";\n page?: number;\n perPage?: number;\n searchQuery?: string;\n },\n ): Promise<APIResponse<PathResolutionResponse>> {\n const params = new URLSearchParams({\n path,\n locale,\n ...(options?.fetchContent && { fetch_content: \"true\" }),\n ...(options?.mode && { mode: options.mode }),\n ...(options?.page && { page: options.page.toString() }),\n ...(options?.perPage && { perPage: options.perPage.toString() }),\n ...(options?.searchQuery && { q: options.searchQuery }),\n });\n\n const defaultRevalidate = parseInt(\n process.env.CACHE_REVALIDATE_SECONDS || \"60\",\n 10,\n );\n\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/resolve-path?${params}`,\n undefined,\n {\n next: {\n revalidate: defaultRevalidate === 0 ? false : defaultRevalidate,\n tags: [\n `site:${siteId}`,\n `path:${siteId}:${locale}:${path}`,\n \"content\",\n ],\n },\n },\n );\n }\n\n async resolvePaths(\n siteId: string,\n paths: string[],\n locale: string,\n fetchContent: boolean = false,\n ): Promise<APIResponse<BatchPathResolutionResponse>> {\n return this.httpClient.post(\n `/api/v1/public/sites/${siteId}/resolve-paths`,\n {\n paths,\n locale,\n fetch_content: fetchContent,\n },\n );\n }\n\n async fetchAllPaths(\n siteId: string,\n locale: string,\n options?: {\n limit?: number;\n offset?: number;\n },\n ): Promise<APIResponse<AllPathsResponse>> {\n const params = new URLSearchParams({\n locale,\n ...(options?.limit && { limit: options.limit.toString() }),\n ...(options?.offset && { offset: options.offset.toString() }),\n });\n\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/all-paths?${params}`,\n );\n }\n\n async fetchPageSections(\n siteId: string,\n path: string,\n ): Promise<APIResponse<unknown[]>> {\n const encodedPath = encodeURIComponent(path || \"/\");\n return this.httpClient.get(\n `/api/v1/sites/${siteId}/pages/${encodedPath}/sections`,\n );\n }\n\n async fetchPageSEO(\n siteId: string,\n path: string,\n ): Promise<APIResponse<unknown>> {\n const encodedPath = encodeURIComponent(path || \"/\");\n return this.httpClient.get(\n `/api/v1/sites/${siteId}/pages/${encodedPath}/seo`,\n );\n }\n\n async fetchRedirects(siteId: string): Promise<APIResponse<unknown[]>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/redirects`);\n }\n\n async fetchSitemap(siteId: string): Promise<APIResponse<string>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/sitemap`);\n }\n\n async fetchRobots(siteId: string): Promise<APIResponse<string>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/robots`);\n }\n}\n","/**\n * API Client\n * Main interface for CMS backend communication - SERVER-SIDE ONLY\n *\n * This module is protected by the `server-only` package.\n * Any attempt to import it from a client component will fail at build time.\n */\n\nimport { CollectionService } from \"./services/collection.service\";\nimport { APIConfig, defaultAPIConfig, validateAPIConfig } from \"./api.config\";\nimport { FormService } from \"./services/form.service\";\nimport { HttpClient } from \"./http-client\";\nimport { MediaService } from \"./services/media.service\";\nimport { WebsiteService } from \"./services/website.service\";\n\nexport class APIClient {\n private httpClient: HttpClient;\n private config: APIConfig;\n\n public readonly website: WebsiteService;\n public readonly collection: CollectionService;\n public readonly media: MediaService;\n public readonly forms: FormService;\n\n constructor(config?: Partial<APIConfig>) {\n this.config = {\n ...defaultAPIConfig,\n ...config,\n http: {\n ...defaultAPIConfig.http,\n ...config?.http,\n },\n };\n\n validateAPIConfig(this.config);\n\n this.httpClient = new HttpClient(this.config.http);\n\n if (this.config.devToken) {\n this.httpClient.setAuthToken(this.config.devToken);\n }\n\n this.website = new WebsiteService(this.httpClient);\n this.collection = new CollectionService(this.httpClient);\n this.media = new MediaService(this.httpClient);\n this.forms = new FormService(this.httpClient);\n }\n\n getSiteId(): string {\n return this.config.siteId;\n }\n\n setSiteId(siteId: string): void {\n this.config.siteId = siteId;\n }\n\n setAuthToken(token: string): void {\n this.httpClient.setAuthToken(token);\n }\n\n removeAuthToken(): void {\n this.httpClient.removeAuthToken();\n }\n\n setBaseUrl(baseUrl: string): void {\n this.httpClient.setBaseUrl(baseUrl);\n this.config.http.baseUrl = baseUrl;\n }\n\n getBaseUrl(): string {\n return this.httpClient.baseUrl;\n }\n\n getConfig(): APIConfig {\n return { ...this.config };\n }\n}\n\n// Singleton instance\nlet apiClient: APIClient;\n\n/**\n * Initialize the API client\n */\nexport function initializeAPIClient(config?: Partial<APIConfig>): APIClient {\n apiClient = new APIClient(config);\n return apiClient;\n}\n\n/**\n * Get the initialized API client instance\n */\nexport function getAPIClient(): APIClient {\n if (!apiClient) {\n try {\n apiClient = new APIClient();\n } catch (error) {\n console.error(\"Failed to initialize API client:\", error);\n throw error;\n }\n }\n return apiClient;\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -26,6 +26,7 @@ declare class HttpClient {
|
|
|
26
26
|
* or returning server errors. Returns null if no cache entry exists.
|
|
27
27
|
*/
|
|
28
28
|
private tryStaleCache;
|
|
29
|
+
private resolveCacheOptions;
|
|
29
30
|
get<T>(endpoint: string, params?: Record<string, unknown>, options?: FetchOptions): Promise<T>;
|
|
30
31
|
post<T>(endpoint: string, data?: unknown): Promise<T>;
|
|
31
32
|
put<T>(endpoint: string, data?: unknown): Promise<T>;
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ declare class HttpClient {
|
|
|
26
26
|
* or returning server errors. Returns null if no cache entry exists.
|
|
27
27
|
*/
|
|
28
28
|
private tryStaleCache;
|
|
29
|
+
private resolveCacheOptions;
|
|
29
30
|
get<T>(endpoint: string, params?: Record<string, unknown>, options?: FetchOptions): Promise<T>;
|
|
30
31
|
post<T>(endpoint: string, data?: unknown): Promise<T>;
|
|
31
32
|
put<T>(endpoint: string, data?: unknown): Promise<T>;
|
package/dist/index.js
CHANGED
|
@@ -37,9 +37,9 @@ function getBackendApiBaseUrl() {
|
|
|
37
37
|
return "http://localhost:8080";
|
|
38
38
|
}
|
|
39
39
|
if (process.env.STAGE === "staging") {
|
|
40
|
-
return "https://api-staging.otl
|
|
40
|
+
return "https://api-staging.otl.studio";
|
|
41
41
|
}
|
|
42
|
-
return "https://api.otl
|
|
42
|
+
return "https://api.otl.studio";
|
|
43
43
|
}
|
|
44
44
|
function getBackendSiteId() {
|
|
45
45
|
const siteId = process.env.SITE_ID;
|
|
@@ -166,7 +166,7 @@ var HttpClient = class {
|
|
|
166
166
|
...fetchOptions,
|
|
167
167
|
headers,
|
|
168
168
|
signal: controller.signal,
|
|
169
|
-
...
|
|
169
|
+
...this.resolveCacheOptions(nextOptions)
|
|
170
170
|
});
|
|
171
171
|
clearTimeout(timeoutId);
|
|
172
172
|
if (response.status >= 500 && process.env.NODE_ENV === "production" && nextOptions) {
|
|
@@ -228,7 +228,7 @@ var HttpClient = class {
|
|
|
228
228
|
});
|
|
229
229
|
if (staleResponse.ok) {
|
|
230
230
|
const staleData = await staleResponse.json();
|
|
231
|
-
console.
|
|
231
|
+
console.warn(`[HttpClient] Serving stale cache for: ${url}`);
|
|
232
232
|
return staleData;
|
|
233
233
|
}
|
|
234
234
|
} catch (cacheError) {
|
|
@@ -239,6 +239,15 @@ var HttpClient = class {
|
|
|
239
239
|
}
|
|
240
240
|
return null;
|
|
241
241
|
}
|
|
242
|
+
resolveCacheOptions(nextOptions) {
|
|
243
|
+
if (process.env.NODE_ENV === "development") {
|
|
244
|
+
return { cache: "no-store" };
|
|
245
|
+
}
|
|
246
|
+
if (nextOptions) {
|
|
247
|
+
return { next: nextOptions };
|
|
248
|
+
}
|
|
249
|
+
return {};
|
|
250
|
+
}
|
|
242
251
|
async get(endpoint, params, options) {
|
|
243
252
|
let url = endpoint;
|
|
244
253
|
if (params) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/collection.service.ts","../src/api.config.ts","../src/services/form.service.ts","../src/http-client.ts","../src/services/media.service.ts","../src/services/website.service.ts","../src/api-client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Collection Service\n * Handles collection, entry, and category retrieval\n */\n\nimport type {\n APIResponse,\n Collection,\n Category,\n Entry,\n} from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport class CollectionService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchCollections(siteId: string): Promise<APIResponse<Collection[]>> {\n return this.httpClient.get(`/api/v1/public/sites/${siteId}/collections`);\n }\n\n async fetchEntries(\n collectionId: string,\n params?: { page?: number; limit?: number; category?: string },\n ): Promise<APIResponse<Entry[]>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/entries`,\n params,\n );\n }\n\n async fetchEntry(\n collectionId: string,\n entrySlug: string,\n ): Promise<APIResponse<Entry>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/entries/${entrySlug}`,\n );\n }\n\n async fetchCategories(\n collectionId: string,\n ): Promise<APIResponse<Category[]>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/categories`,\n );\n }\n}\n","/**\n * API Configuration\n * Server-side only configuration for CMS backend communication.\n * Uses only process.env.API_URL (never NEXT_PUBLIC_ prefixed variables).\n */\n\nimport { HttpClientConfig } from \"./http-client\";\n\nexport interface APIConfig {\n http: HttpClientConfig;\n siteId: string;\n devToken?: string;\n environment: \"development\" | \"production\" | \"staging\";\n}\n\n/**\n * Get backend API base URL (server-side only, never exposed to client)\n */\nfunction getBackendApiBaseUrl(): string {\n if (process.env.API_URL) {\n return process.env.API_URL;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n return \"http://localhost:8080\";\n }\n\n if (process.env.STAGE === \"staging\") {\n return \"https://api-staging.otl-cms.com\";\n }\n\n return \"https://api.otl-cms.com\";\n}\n\n/**\n * Get site ID from environment (server-side only)\n */\nfunction getBackendSiteId(): string {\n const siteId = process.env.SITE_ID;\n if (!siteId) {\n console.error(\"SITE_ID environment variable is not set!\");\n console.error(\"Add the following to your .env.local:\");\n console.error(\" SITE_ID=your-site-id\");\n console.error(\" API_URL=http://localhost:8080\");\n throw new Error(\"SITE_ID environment variable is required.\");\n }\n return siteId;\n}\n\n/**\n * Get site access token from environment (server-side only)\n */\nfunction getSiteAccessToken(): string {\n const token = process.env.SITE_ACCESS_TOKEN;\n if (!token) {\n console.error(\"SITE_ACCESS_TOKEN environment variable is not set!\");\n console.error(\"Add the following to your .env.local:\");\n console.error(\" SITE_ACCESS_TOKEN=kpt_...\");\n console.error(\"\");\n console.error(\"To obtain an access token:\");\n console.error(\"1. Log into the CMS management interface\");\n console.error(\"2. Navigate to your site settings\");\n console.error(\"3. Go to Access Tokens section\");\n console.error(\"4. Create a new token and copy it here\");\n throw new Error(\n \"SITE_ACCESS_TOKEN environment variable is required. \" +\n \"Please obtain an access token from the CMS site settings.\",\n );\n }\n return token;\n}\n\n/**\n * Get current environment (server-side only)\n */\nfunction getBackendEnvironment(): \"development\" | \"production\" | \"staging\" {\n if (process.env.NODE_ENV === \"production\") {\n return process.env.STAGE === \"staging\" ? \"staging\" : \"production\";\n }\n return \"development\";\n}\n\n/**\n * Default API configuration\n */\nexport const defaultAPIConfig: APIConfig = {\n http: {\n baseUrl: getBackendApiBaseUrl(),\n timeout: 30000,\n defaultHeaders: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"OTL-CMS-Engine/1.0\",\n },\n },\n siteId: getBackendSiteId(),\n devToken: getSiteAccessToken(),\n environment: getBackendEnvironment(),\n};\n\n/**\n * Create API configuration with overrides\n */\nexport function createAPIConfig(overrides?: Partial<APIConfig>): APIConfig {\n return {\n ...defaultAPIConfig,\n ...overrides,\n http: {\n ...defaultAPIConfig.http,\n ...overrides?.http,\n },\n };\n}\n\n/**\n * Validate API configuration\n */\nexport function validateAPIConfig(config: APIConfig): void {\n if (!config.http.baseUrl) {\n throw new Error(\"API base URL is required\");\n }\n\n try {\n new URL(config.http.baseUrl);\n } catch {\n throw new Error(\"Invalid API base URL format\");\n }\n\n if (!config.siteId) {\n throw new Error(\"Site ID is required\");\n }\n\n if (!config.devToken) {\n throw new Error(\n \"Site access token is required. \" +\n \"Please set SITE_ACCESS_TOKEN environment variable.\",\n );\n }\n\n if (config.http.timeout && config.http.timeout < 1000) {\n console.warn(\"API timeout is very low, this might cause issues\");\n }\n}\n","/**\n * Form Service\n * Handles form submissions\n */\n\nimport type { HttpClient } from \"../http-client\";\n\nexport interface FormSubmissionRequest {\n type: string;\n locale: string;\n data: Record<string, unknown>;\n form_variant_id?: string;\n environment_type?: string;\n environment_id?: string;\n environment_path?: string;\n environment_variant_id?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface FormSubmissionResponse {\n success: boolean;\n submission_id: string;\n message?: string;\n}\n\nexport class FormService {\n constructor(private httpClient: HttpClient) {}\n\n async submitForm(\n formId: string,\n data: FormSubmissionRequest,\n ): Promise<FormSubmissionResponse> {\n return this.httpClient.post<FormSubmissionResponse>(\n `/api/v1/public/forms/${formId}/submit`,\n data,\n );\n }\n}\n","export interface HttpClientConfig {\n baseUrl: string;\n timeout?: number;\n defaultHeaders?: Record<string, string>;\n}\n\ninterface FetchOptions extends Omit<RequestInit, \"headers\"> {\n headers?: Record<string, string | undefined>;\n next?: {\n revalidate?: number | false;\n tags?: string[];\n };\n}\n\nexport class HttpClient {\n public baseUrl: string;\n private timeout: number;\n private defaultHeaders: Record<string, string>;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.timeout = config.timeout || 30000;\n this.defaultHeaders = {\n \"Content-Type\": \"application/json\",\n ...config.defaultHeaders,\n };\n }\n\n /**\n * Make a generic HTTP request\n */\n private async request<T>(\n endpoint: string,\n options: FetchOptions = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const { next: nextOptions, ...fetchOptions } = options;\n\n const mergedHeaders: Record<string, string | undefined> = {\n ...this.defaultHeaders,\n ...fetchOptions.headers,\n };\n const headers = Object.fromEntries(\n Object.entries(mergedHeaders).filter(\n (entry): entry is [string, string] => entry[1] !== undefined,\n ),\n );\n\n try {\n const response = await fetch(url, {\n ...fetchOptions,\n headers,\n signal: controller.signal,\n ...(process.env.NODE_ENV === \"development\"\n ? { cache: \"no-store\" as const }\n : nextOptions\n ? { next: nextOptions }\n : {}),\n });\n\n clearTimeout(timeoutId);\n\n // Server error (5xx) -- try stale cache before returning the error\n if (\n response.status >= 500 &&\n process.env.NODE_ENV === \"production\" &&\n nextOptions\n ) {\n const staleData = await this.tryStaleCache<T>(\n url,\n fetchOptions,\n headers,\n );\n if (staleData !== null) return staleData;\n }\n\n const data = await response.json();\n\n if (!response.ok) {\n if (data && typeof data === \"object\") {\n if (\"success\" in data) {\n return data;\n }\n if (\"type\" in data) {\n return {\n success: response.status >= 200 && response.status < 300,\n data,\n } as T;\n }\n }\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof Error) {\n // Network failure, timeout, or unstructured error -- try stale cache\n if (process.env.NODE_ENV === \"production\" && nextOptions) {\n const staleData = await this.tryStaleCache<T>(\n url,\n fetchOptions,\n headers,\n );\n if (staleData !== null) return staleData;\n }\n\n if (error.name === \"AbortError\") {\n throw new Error(\"Request timeout\");\n }\n throw error;\n }\n\n throw new Error(\"Unknown error occurred\");\n }\n }\n\n /**\n * Attempt to serve a stale cached response when the backend is unreachable\n * or returning server errors. Returns null if no cache entry exists.\n */\n private async tryStaleCache<T>(\n url: string,\n fetchOptions: Omit<RequestInit, \"headers\">,\n headers: Record<string, string>,\n ): Promise<T | null> {\n try {\n console.warn(\n `[HttpClient] Backend unavailable, attempting stale cache: ${url}`,\n );\n const staleResponse = await fetch(url, {\n ...fetchOptions,\n headers,\n cache: \"force-cache\" as const,\n });\n\n if (staleResponse.ok) {\n const staleData = await staleResponse.json();\n console.log(`[HttpClient] Serving stale cache for: ${url}`);\n return staleData;\n }\n } catch (cacheError) {\n console.error(\n `[HttpClient] No cache available for: ${url}`,\n cacheError instanceof Error ? cacheError.message : cacheError,\n );\n }\n return null;\n }\n\n async get<T>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: FetchOptions,\n ): Promise<T> {\n let url = endpoint;\n\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n\n if (searchParams.toString()) {\n url += `?${searchParams.toString()}`;\n }\n }\n\n return this.request<T>(url, { method: \"GET\", ...options });\n }\n\n async post<T>(endpoint: string, data?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"POST\",\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n async put<T>(endpoint: string, data?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"PUT\",\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n async delete<T>(endpoint: string): Promise<T> {\n return this.request<T>(endpoint, { method: \"DELETE\" });\n }\n\n async upload<T>(endpoint: string, formData: FormData): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"POST\",\n body: formData,\n headers: { \"Content-Type\": undefined },\n });\n }\n\n setAuthToken(token: string) {\n this.defaultHeaders[\"Authorization\"] = `Bearer ${token}`;\n }\n\n removeAuthToken() {\n delete this.defaultHeaders[\"Authorization\"];\n }\n\n setBaseUrl(baseUrl: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, \"\");\n }\n}\n","/**\n * Media Service\n * Handles media file retrieval\n */\n\nimport type { APIResponse, Media } from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport class MediaService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchMediaFile(\n siteId: string,\n mediaId: string,\n ): Promise<APIResponse<Media>> {\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/media/${mediaId}`,\n );\n }\n\n async fetchMedia(siteId: string): Promise<APIResponse<Media[]>> {\n return this.httpClient.get(`/api/v1/public/sites/${siteId}/media`);\n }\n}\n","/**\n * Website Service\n * Handles configuration, path resolution, sitemap, and redirect operations\n */\n\nimport type { APIResponse, SiteConfig } from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport interface PathResolutionResponse {\n path: string;\n type:\n | \"page\"\n | \"collection\"\n | \"entry\"\n | \"category\"\n | \"category_index\"\n | \"author\"\n | \"author_index\"\n | \"tag\"\n | \"tag_index\"\n | \"redirect\"\n | \"not_found\"\n | \"multiple\";\n content_id?: string;\n entry_id?: string;\n category_id?: string;\n collection_id?: string;\n locale: string;\n content?: Record<string, unknown>;\n redirect?: {\n to_path?: string;\n to_url?: string;\n status_code: number;\n query_string_behavior: string;\n };\n status_code?: number;\n cache_ttl: number;\n all_matches?: {\n redirect?: unknown;\n page?: unknown;\n category?: unknown;\n entry?: unknown;\n primary_match: string;\n };\n}\n\nexport interface BatchPathResolutionResponse {\n results: PathResolutionResponse[];\n}\n\nexport interface PathInfo {\n path: string;\n content_type: string;\n content_id?: string;\n locale: string;\n}\n\nexport interface AllPathsResponse {\n paths: PathInfo[];\n pagination: {\n page: number;\n limit: number;\n total: number;\n total_pages: number;\n has_next: boolean;\n has_prev: boolean;\n };\n}\n\nexport class WebsiteService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchConfigs(\n siteId: string,\n locale?: string,\n headerPresetId?: string,\n footerPresetId?: string,\n ): Promise<APIResponse<SiteConfig>> {\n const params = new URLSearchParams();\n if (locale) params.set(\"locale\", locale);\n if (headerPresetId) params.set(\"header_preset\", headerPresetId);\n if (footerPresetId) params.set(\"footer_preset\", footerPresetId);\n\n const queryString = params.toString();\n const url = queryString\n ? `/api/v1/public/sites/${siteId}/configs?${queryString}`\n : `/api/v1/public/sites/${siteId}/configs`;\n\n const defaultRevalidate = parseInt(\n process.env.CACHE_REVALIDATE_SECONDS || \"60\",\n 10,\n );\n\n const tags = [`site:${siteId}`, `config:${siteId}`, \"config\"];\n if (headerPresetId) tags.push(`header-preset:${headerPresetId}`);\n if (footerPresetId) tags.push(`footer-preset:${footerPresetId}`);\n\n return this.httpClient.get(url, undefined, {\n next: {\n revalidate: defaultRevalidate === 0 ? false : defaultRevalidate,\n tags,\n },\n });\n }\n\n async resolvePath(\n siteId: string,\n path: string,\n locale: string,\n options?: {\n fetchContent?: boolean;\n mode?: \"default\" | \"all\";\n page?: number;\n perPage?: number;\n searchQuery?: string;\n },\n ): Promise<APIResponse<PathResolutionResponse>> {\n const params = new URLSearchParams({\n path,\n locale,\n ...(options?.fetchContent && { fetch_content: \"true\" }),\n ...(options?.mode && { mode: options.mode }),\n ...(options?.page && { page: options.page.toString() }),\n ...(options?.perPage && { perPage: options.perPage.toString() }),\n ...(options?.searchQuery && { q: options.searchQuery }),\n });\n\n const defaultRevalidate = parseInt(\n process.env.CACHE_REVALIDATE_SECONDS || \"60\",\n 10,\n );\n\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/resolve-path?${params}`,\n undefined,\n {\n next: {\n revalidate: defaultRevalidate === 0 ? false : defaultRevalidate,\n tags: [\n `site:${siteId}`,\n `path:${siteId}:${locale}:${path}`,\n \"content\",\n ],\n },\n },\n );\n }\n\n async resolvePaths(\n siteId: string,\n paths: string[],\n locale: string,\n fetchContent: boolean = false,\n ): Promise<APIResponse<BatchPathResolutionResponse>> {\n return this.httpClient.post(\n `/api/v1/public/sites/${siteId}/resolve-paths`,\n {\n paths,\n locale,\n fetch_content: fetchContent,\n },\n );\n }\n\n async fetchAllPaths(\n siteId: string,\n locale: string,\n options?: {\n limit?: number;\n offset?: number;\n },\n ): Promise<APIResponse<AllPathsResponse>> {\n const params = new URLSearchParams({\n locale,\n ...(options?.limit && { limit: options.limit.toString() }),\n ...(options?.offset && { offset: options.offset.toString() }),\n });\n\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/all-paths?${params}`,\n );\n }\n\n async fetchPageSections(\n siteId: string,\n path: string,\n ): Promise<APIResponse<unknown[]>> {\n const encodedPath = encodeURIComponent(path || \"/\");\n return this.httpClient.get(\n `/api/v1/sites/${siteId}/pages/${encodedPath}/sections`,\n );\n }\n\n async fetchPageSEO(\n siteId: string,\n path: string,\n ): Promise<APIResponse<unknown>> {\n const encodedPath = encodeURIComponent(path || \"/\");\n return this.httpClient.get(\n `/api/v1/sites/${siteId}/pages/${encodedPath}/seo`,\n );\n }\n\n async fetchRedirects(siteId: string): Promise<APIResponse<unknown[]>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/redirects`);\n }\n\n async fetchSitemap(siteId: string): Promise<APIResponse<string>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/sitemap`);\n }\n\n async fetchRobots(siteId: string): Promise<APIResponse<string>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/robots`);\n }\n}\n","/**\n * API Client\n * Main interface for CMS backend communication - SERVER-SIDE ONLY\n *\n * This module is protected by the `server-only` package.\n * Any attempt to import it from a client component will fail at build time.\n */\n\nimport { CollectionService } from \"./services/collection.service\";\nimport { APIConfig, defaultAPIConfig, validateAPIConfig } from \"./api.config\";\nimport { FormService } from \"./services/form.service\";\nimport { HttpClient } from \"./http-client\";\nimport { MediaService } from \"./services/media.service\";\nimport { WebsiteService } from \"./services/website.service\";\n\nexport class APIClient {\n private httpClient: HttpClient;\n private config: APIConfig;\n\n public readonly website: WebsiteService;\n public readonly collection: CollectionService;\n public readonly media: MediaService;\n public readonly forms: FormService;\n\n constructor(config?: Partial<APIConfig>) {\n this.config = {\n ...defaultAPIConfig,\n ...config,\n http: {\n ...defaultAPIConfig.http,\n ...config?.http,\n },\n };\n\n validateAPIConfig(this.config);\n\n this.httpClient = new HttpClient(this.config.http);\n\n if (this.config.devToken) {\n this.httpClient.setAuthToken(this.config.devToken);\n }\n\n this.website = new WebsiteService(this.httpClient);\n this.collection = new CollectionService(this.httpClient);\n this.media = new MediaService(this.httpClient);\n this.forms = new FormService(this.httpClient);\n }\n\n getSiteId(): string {\n return this.config.siteId;\n }\n\n setSiteId(siteId: string): void {\n this.config.siteId = siteId;\n }\n\n setAuthToken(token: string): void {\n this.httpClient.setAuthToken(token);\n }\n\n removeAuthToken(): void {\n this.httpClient.removeAuthToken();\n }\n\n setBaseUrl(baseUrl: string): void {\n this.httpClient.setBaseUrl(baseUrl);\n this.config.http.baseUrl = baseUrl;\n }\n\n getBaseUrl(): string {\n return this.httpClient.baseUrl;\n }\n\n getConfig(): APIConfig {\n return { ...this.config };\n }\n}\n\n// Singleton instance\nlet apiClient: APIClient;\n\n/**\n * Initialize the API client\n */\nexport function initializeAPIClient(config?: Partial<APIConfig>): APIClient {\n apiClient = new APIClient(config);\n return apiClient;\n}\n\n/**\n * Get the initialized API client instance\n */\nexport function getAPIClient(): APIClient {\n if (!apiClient) {\n try {\n apiClient = new APIClient();\n } catch (error) {\n console.error(\"Failed to initialize API client:\", error);\n throw error;\n }\n }\n return apiClient;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/services/collection.service.ts","../src/api.config.ts","../src/services/form.service.ts","../src/http-client.ts","../src/services/media.service.ts","../src/services/website.service.ts","../src/api-client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Collection Service\n * Handles collection, entry, and category retrieval\n */\n\nimport type {\n APIResponse,\n Collection,\n Category,\n Entry,\n} from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport class CollectionService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchCollections(siteId: string): Promise<APIResponse<Collection[]>> {\n return this.httpClient.get(`/api/v1/public/sites/${siteId}/collections`);\n }\n\n async fetchEntries(\n collectionId: string,\n params?: { page?: number; limit?: number; category?: string },\n ): Promise<APIResponse<Entry[]>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/entries`,\n params,\n );\n }\n\n async fetchEntry(\n collectionId: string,\n entrySlug: string,\n ): Promise<APIResponse<Entry>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/entries/${entrySlug}`,\n );\n }\n\n async fetchCategories(\n collectionId: string,\n ): Promise<APIResponse<Category[]>> {\n return this.httpClient.get(\n `/api/v1/public/collections/${collectionId}/categories`,\n );\n }\n}\n","/**\n * API Configuration\n * Server-side only configuration for CMS backend communication.\n * Uses only process.env.API_URL (never NEXT_PUBLIC_ prefixed variables).\n */\n\nimport { HttpClientConfig } from \"./http-client\";\n\nexport interface APIConfig {\n http: HttpClientConfig;\n siteId: string;\n devToken?: string;\n environment: \"development\" | \"production\" | \"staging\";\n}\n\n/**\n * Get backend API base URL (server-side only, never exposed to client)\n */\nfunction getBackendApiBaseUrl(): string {\n if (process.env.API_URL) {\n return process.env.API_URL;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n return \"http://localhost:8080\";\n }\n\n if (process.env.STAGE === \"staging\") {\n return \"https://api-staging.otl.studio\";\n }\n\n return \"https://api.otl.studio\";\n}\n\n/**\n * Get site ID from environment (server-side only)\n */\nfunction getBackendSiteId(): string {\n const siteId = process.env.SITE_ID;\n if (!siteId) {\n console.error(\"SITE_ID environment variable is not set!\");\n console.error(\"Add the following to your .env.local:\");\n console.error(\" SITE_ID=your-site-id\");\n console.error(\" API_URL=http://localhost:8080\");\n throw new Error(\"SITE_ID environment variable is required.\");\n }\n return siteId;\n}\n\n/**\n * Get site access token from environment (server-side only)\n */\nfunction getSiteAccessToken(): string {\n const token = process.env.SITE_ACCESS_TOKEN;\n if (!token) {\n console.error(\"SITE_ACCESS_TOKEN environment variable is not set!\");\n console.error(\"Add the following to your .env.local:\");\n console.error(\" SITE_ACCESS_TOKEN=kpt_...\");\n console.error(\"\");\n console.error(\"To obtain an access token:\");\n console.error(\"1. Log into the CMS management interface\");\n console.error(\"2. Navigate to your site settings\");\n console.error(\"3. Go to Access Tokens section\");\n console.error(\"4. Create a new token and copy it here\");\n throw new Error(\n \"SITE_ACCESS_TOKEN environment variable is required. \" +\n \"Please obtain an access token from the CMS site settings.\",\n );\n }\n return token;\n}\n\n/**\n * Get current environment (server-side only)\n */\nfunction getBackendEnvironment(): \"development\" | \"production\" | \"staging\" {\n if (process.env.NODE_ENV === \"production\") {\n return process.env.STAGE === \"staging\" ? \"staging\" : \"production\";\n }\n return \"development\";\n}\n\n/**\n * Default API configuration\n */\nexport const defaultAPIConfig: APIConfig = {\n http: {\n baseUrl: getBackendApiBaseUrl(),\n timeout: 30000,\n defaultHeaders: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"OTL-CMS-Engine/1.0\",\n },\n },\n siteId: getBackendSiteId(),\n devToken: getSiteAccessToken(),\n environment: getBackendEnvironment(),\n};\n\n/**\n * Create API configuration with overrides\n */\nexport function createAPIConfig(overrides?: Partial<APIConfig>): APIConfig {\n return {\n ...defaultAPIConfig,\n ...overrides,\n http: {\n ...defaultAPIConfig.http,\n ...overrides?.http,\n },\n };\n}\n\n/**\n * Validate API configuration\n */\nexport function validateAPIConfig(config: APIConfig): void {\n if (!config.http.baseUrl) {\n throw new Error(\"API base URL is required\");\n }\n\n try {\n new URL(config.http.baseUrl);\n } catch {\n throw new Error(\"Invalid API base URL format\");\n }\n\n if (!config.siteId) {\n throw new Error(\"Site ID is required\");\n }\n\n if (!config.devToken) {\n throw new Error(\n \"Site access token is required. \" +\n \"Please set SITE_ACCESS_TOKEN environment variable.\",\n );\n }\n\n if (config.http.timeout && config.http.timeout < 1000) {\n console.warn(\"API timeout is very low, this might cause issues\");\n }\n}\n","/**\n * Form Service\n * Handles form submissions\n */\n\nimport type { HttpClient } from \"../http-client\";\n\nexport interface FormSubmissionRequest {\n type: string;\n locale: string;\n data: Record<string, unknown>;\n form_variant_id?: string;\n environment_type?: string;\n environment_id?: string;\n environment_path?: string;\n environment_variant_id?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface FormSubmissionResponse {\n success: boolean;\n submission_id: string;\n message?: string;\n}\n\nexport class FormService {\n constructor(private httpClient: HttpClient) {}\n\n async submitForm(\n formId: string,\n data: FormSubmissionRequest,\n ): Promise<FormSubmissionResponse> {\n return this.httpClient.post<FormSubmissionResponse>(\n `/api/v1/public/forms/${formId}/submit`,\n data,\n );\n }\n}\n","export interface HttpClientConfig {\n baseUrl: string;\n timeout?: number;\n defaultHeaders?: Record<string, string>;\n}\n\ninterface FetchOptions extends Omit<RequestInit, \"headers\"> {\n headers?: Record<string, string | undefined>;\n next?: {\n revalidate?: number | false;\n tags?: string[];\n };\n}\n\nexport class HttpClient {\n public baseUrl: string;\n private timeout: number;\n private defaultHeaders: Record<string, string>;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.timeout = config.timeout || 30000;\n this.defaultHeaders = {\n \"Content-Type\": \"application/json\",\n ...config.defaultHeaders,\n };\n }\n\n /**\n * Make a generic HTTP request\n */\n private async request<T>(\n endpoint: string,\n options: FetchOptions = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const { next: nextOptions, ...fetchOptions } = options;\n\n const mergedHeaders: Record<string, string | undefined> = {\n ...this.defaultHeaders,\n ...fetchOptions.headers,\n };\n const headers = Object.fromEntries(\n Object.entries(mergedHeaders).filter(\n (entry): entry is [string, string] => entry[1] !== undefined,\n ),\n );\n\n try {\n const response = await fetch(url, {\n ...fetchOptions,\n headers,\n signal: controller.signal,\n ...this.resolveCacheOptions(nextOptions),\n });\n\n clearTimeout(timeoutId);\n\n // Server error (5xx) -- try stale cache before returning the error\n if (\n response.status >= 500 &&\n process.env.NODE_ENV === \"production\" &&\n nextOptions\n ) {\n const staleData = await this.tryStaleCache<T>(\n url,\n fetchOptions,\n headers,\n );\n if (staleData !== null) return staleData;\n }\n\n const data = await response.json();\n\n if (!response.ok) {\n if (data && typeof data === \"object\") {\n if (\"success\" in data) {\n return data;\n }\n if (\"type\" in data) {\n return {\n success: response.status >= 200 && response.status < 300,\n data,\n } as T;\n }\n }\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return data;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof Error) {\n // Network failure, timeout, or unstructured error -- try stale cache\n if (process.env.NODE_ENV === \"production\" && nextOptions) {\n const staleData = await this.tryStaleCache<T>(\n url,\n fetchOptions,\n headers,\n );\n if (staleData !== null) return staleData;\n }\n\n if (error.name === \"AbortError\") {\n throw new Error(\"Request timeout\");\n }\n throw error;\n }\n\n throw new Error(\"Unknown error occurred\");\n }\n }\n\n /**\n * Attempt to serve a stale cached response when the backend is unreachable\n * or returning server errors. Returns null if no cache entry exists.\n */\n private async tryStaleCache<T>(\n url: string,\n fetchOptions: Omit<RequestInit, \"headers\">,\n headers: Record<string, string>,\n ): Promise<T | null> {\n try {\n console.warn(\n `[HttpClient] Backend unavailable, attempting stale cache: ${url}`,\n );\n const staleResponse = await fetch(url, {\n ...fetchOptions,\n headers,\n cache: \"force-cache\" as const,\n });\n\n if (staleResponse.ok) {\n const staleData = await staleResponse.json();\n console.warn(`[HttpClient] Serving stale cache for: ${url}`);\n return staleData;\n }\n } catch (cacheError) {\n console.error(\n `[HttpClient] No cache available for: ${url}`,\n cacheError instanceof Error ? cacheError.message : cacheError,\n );\n }\n return null;\n }\n\n private resolveCacheOptions(nextOptions?: FetchOptions[\"next\"]) {\n if (process.env.NODE_ENV === \"development\") {\n return { cache: \"no-store\" as const };\n }\n if (nextOptions) {\n return { next: nextOptions };\n }\n return {};\n }\n\n async get<T>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: FetchOptions,\n ): Promise<T> {\n let url = endpoint;\n\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n\n if (searchParams.toString()) {\n url += `?${searchParams.toString()}`;\n }\n }\n\n return this.request<T>(url, { method: \"GET\", ...options });\n }\n\n async post<T>(endpoint: string, data?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"POST\",\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n async put<T>(endpoint: string, data?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"PUT\",\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n async delete<T>(endpoint: string): Promise<T> {\n return this.request<T>(endpoint, { method: \"DELETE\" });\n }\n\n async upload<T>(endpoint: string, formData: FormData): Promise<T> {\n return this.request<T>(endpoint, {\n method: \"POST\",\n body: formData,\n headers: { \"Content-Type\": undefined },\n });\n }\n\n setAuthToken(token: string) {\n this.defaultHeaders[\"Authorization\"] = `Bearer ${token}`;\n }\n\n removeAuthToken() {\n delete this.defaultHeaders[\"Authorization\"];\n }\n\n setBaseUrl(baseUrl: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, \"\");\n }\n}\n","/**\n * Media Service\n * Handles media file retrieval\n */\n\nimport type { APIResponse, Media } from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport class MediaService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchMediaFile(\n siteId: string,\n mediaId: string,\n ): Promise<APIResponse<Media>> {\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/media/${mediaId}`,\n );\n }\n\n async fetchMedia(siteId: string): Promise<APIResponse<Media[]>> {\n return this.httpClient.get(`/api/v1/public/sites/${siteId}/media`);\n }\n}\n","/**\n * Website Service\n * Handles configuration, path resolution, sitemap, and redirect operations\n */\n\nimport type { APIResponse, SiteConfig } from \"@otl-core/cms-types\";\nimport { HttpClient } from \"../http-client\";\n\nexport interface PathResolutionResponse {\n path: string;\n type:\n | \"page\"\n | \"collection\"\n | \"entry\"\n | \"category\"\n | \"category_index\"\n | \"author\"\n | \"author_index\"\n | \"tag\"\n | \"tag_index\"\n | \"redirect\"\n | \"not_found\"\n | \"multiple\";\n content_id?: string;\n entry_id?: string;\n category_id?: string;\n collection_id?: string;\n locale: string;\n content?: Record<string, unknown>;\n redirect?: {\n to_path?: string;\n to_url?: string;\n status_code: number;\n query_string_behavior: string;\n };\n status_code?: number;\n cache_ttl: number;\n all_matches?: {\n redirect?: unknown;\n page?: unknown;\n category?: unknown;\n entry?: unknown;\n primary_match: string;\n };\n}\n\nexport interface BatchPathResolutionResponse {\n results: PathResolutionResponse[];\n}\n\nexport interface PathInfo {\n path: string;\n content_type: string;\n content_id?: string;\n locale: string;\n}\n\nexport interface AllPathsResponse {\n paths: PathInfo[];\n pagination: {\n page: number;\n limit: number;\n total: number;\n total_pages: number;\n has_next: boolean;\n has_prev: boolean;\n };\n}\n\nexport class WebsiteService {\n constructor(private httpClient: HttpClient) {}\n\n async fetchConfigs(\n siteId: string,\n locale?: string,\n headerPresetId?: string,\n footerPresetId?: string,\n ): Promise<APIResponse<SiteConfig>> {\n const params = new URLSearchParams();\n if (locale) params.set(\"locale\", locale);\n if (headerPresetId) params.set(\"header_preset\", headerPresetId);\n if (footerPresetId) params.set(\"footer_preset\", footerPresetId);\n\n const queryString = params.toString();\n const url = queryString\n ? `/api/v1/public/sites/${siteId}/configs?${queryString}`\n : `/api/v1/public/sites/${siteId}/configs`;\n\n const defaultRevalidate = parseInt(\n process.env.CACHE_REVALIDATE_SECONDS || \"60\",\n 10,\n );\n\n const tags = [`site:${siteId}`, `config:${siteId}`, \"config\"];\n if (headerPresetId) tags.push(`header-preset:${headerPresetId}`);\n if (footerPresetId) tags.push(`footer-preset:${footerPresetId}`);\n\n return this.httpClient.get(url, undefined, {\n next: {\n revalidate: defaultRevalidate === 0 ? false : defaultRevalidate,\n tags,\n },\n });\n }\n\n async resolvePath(\n siteId: string,\n path: string,\n locale: string,\n options?: {\n fetchContent?: boolean;\n mode?: \"default\" | \"all\";\n page?: number;\n perPage?: number;\n searchQuery?: string;\n },\n ): Promise<APIResponse<PathResolutionResponse>> {\n const params = new URLSearchParams({\n path,\n locale,\n ...(options?.fetchContent && { fetch_content: \"true\" }),\n ...(options?.mode && { mode: options.mode }),\n ...(options?.page && { page: options.page.toString() }),\n ...(options?.perPage && { perPage: options.perPage.toString() }),\n ...(options?.searchQuery && { q: options.searchQuery }),\n });\n\n const defaultRevalidate = parseInt(\n process.env.CACHE_REVALIDATE_SECONDS || \"60\",\n 10,\n );\n\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/resolve-path?${params}`,\n undefined,\n {\n next: {\n revalidate: defaultRevalidate === 0 ? false : defaultRevalidate,\n tags: [\n `site:${siteId}`,\n `path:${siteId}:${locale}:${path}`,\n \"content\",\n ],\n },\n },\n );\n }\n\n async resolvePaths(\n siteId: string,\n paths: string[],\n locale: string,\n fetchContent: boolean = false,\n ): Promise<APIResponse<BatchPathResolutionResponse>> {\n return this.httpClient.post(\n `/api/v1/public/sites/${siteId}/resolve-paths`,\n {\n paths,\n locale,\n fetch_content: fetchContent,\n },\n );\n }\n\n async fetchAllPaths(\n siteId: string,\n locale: string,\n options?: {\n limit?: number;\n offset?: number;\n },\n ): Promise<APIResponse<AllPathsResponse>> {\n const params = new URLSearchParams({\n locale,\n ...(options?.limit && { limit: options.limit.toString() }),\n ...(options?.offset && { offset: options.offset.toString() }),\n });\n\n return this.httpClient.get(\n `/api/v1/public/sites/${siteId}/all-paths?${params}`,\n );\n }\n\n async fetchPageSections(\n siteId: string,\n path: string,\n ): Promise<APIResponse<unknown[]>> {\n const encodedPath = encodeURIComponent(path || \"/\");\n return this.httpClient.get(\n `/api/v1/sites/${siteId}/pages/${encodedPath}/sections`,\n );\n }\n\n async fetchPageSEO(\n siteId: string,\n path: string,\n ): Promise<APIResponse<unknown>> {\n const encodedPath = encodeURIComponent(path || \"/\");\n return this.httpClient.get(\n `/api/v1/sites/${siteId}/pages/${encodedPath}/seo`,\n );\n }\n\n async fetchRedirects(siteId: string): Promise<APIResponse<unknown[]>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/redirects`);\n }\n\n async fetchSitemap(siteId: string): Promise<APIResponse<string>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/sitemap`);\n }\n\n async fetchRobots(siteId: string): Promise<APIResponse<string>> {\n return this.httpClient.get(`/api/v1/sites/${siteId}/robots`);\n }\n}\n","/**\n * API Client\n * Main interface for CMS backend communication - SERVER-SIDE ONLY\n *\n * This module is protected by the `server-only` package.\n * Any attempt to import it from a client component will fail at build time.\n */\n\nimport { CollectionService } from \"./services/collection.service\";\nimport { APIConfig, defaultAPIConfig, validateAPIConfig } from \"./api.config\";\nimport { FormService } from \"./services/form.service\";\nimport { HttpClient } from \"./http-client\";\nimport { MediaService } from \"./services/media.service\";\nimport { WebsiteService } from \"./services/website.service\";\n\nexport class APIClient {\n private httpClient: HttpClient;\n private config: APIConfig;\n\n public readonly website: WebsiteService;\n public readonly collection: CollectionService;\n public readonly media: MediaService;\n public readonly forms: FormService;\n\n constructor(config?: Partial<APIConfig>) {\n this.config = {\n ...defaultAPIConfig,\n ...config,\n http: {\n ...defaultAPIConfig.http,\n ...config?.http,\n },\n };\n\n validateAPIConfig(this.config);\n\n this.httpClient = new HttpClient(this.config.http);\n\n if (this.config.devToken) {\n this.httpClient.setAuthToken(this.config.devToken);\n }\n\n this.website = new WebsiteService(this.httpClient);\n this.collection = new CollectionService(this.httpClient);\n this.media = new MediaService(this.httpClient);\n this.forms = new FormService(this.httpClient);\n }\n\n getSiteId(): string {\n return this.config.siteId;\n }\n\n setSiteId(siteId: string): void {\n this.config.siteId = siteId;\n }\n\n setAuthToken(token: string): void {\n this.httpClient.setAuthToken(token);\n }\n\n removeAuthToken(): void {\n this.httpClient.removeAuthToken();\n }\n\n setBaseUrl(baseUrl: string): void {\n this.httpClient.setBaseUrl(baseUrl);\n this.config.http.baseUrl = baseUrl;\n }\n\n getBaseUrl(): string {\n return this.httpClient.baseUrl;\n }\n\n getConfig(): APIConfig {\n return { ...this.config };\n }\n}\n\n// Singleton instance\nlet apiClient: APIClient;\n\n/**\n * Initialize the API client\n */\nexport function initializeAPIClient(config?: Partial<APIConfig>): APIClient {\n apiClient = new APIClient(config);\n return apiClient;\n}\n\n/**\n * Get the initialized API client instance\n */\nexport function getAPIClient(): APIClient {\n if (!apiClient) {\n try {\n apiClient = new APIClient();\n } catch (error) {\n console.error(\"Failed to initialize API client:\", error);\n throw error;\n }\n }\n return apiClient;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otl-core/cms-api",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Server-side API client for OTL CMS backend communication",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"url": "https://github.com/otl-core/cms-api.git"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@otl-core/cms-types": "^1.1.
|
|
39
|
+
"@otl-core/cms-types": "^1.1.2",
|
|
40
40
|
"server-only": "^0.0.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|