@duffcloudservices/cms-react 0.1.0 → 0.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/README.md CHANGED
@@ -1,118 +1,118 @@
1
- # @duffcloudservices/cms-react
2
-
3
- React hooks and Vite plugins for DCS CMS integration.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- pnpm add @duffcloudservices/cms-react
9
- ```
10
-
11
- ## Usage
12
-
13
- ### Vite Configuration
14
-
15
- ```typescript
16
- // vite.config.ts
17
- import { defineConfig } from 'vite'
18
- import react from '@vitejs/plugin-react'
19
- import { dcsContentPlugin, dcsSeoPlugin } from '@duffcloudservices/cms-react/plugins'
20
-
21
- export default defineConfig({
22
- plugins: [
23
- react(),
24
- dcsContentPlugin(),
25
- dcsSeoPlugin(),
26
- ],
27
- })
28
- ```
29
-
30
- ### Using Hooks in Components
31
-
32
- ```tsx
33
- // src/pages/Home.tsx
34
- import { useTextContent, useSEO } from '@duffcloudservices/cms-react'
35
-
36
- export function Home() {
37
- const { t } = useTextContent({
38
- page: 'home',
39
- defaults: {
40
- 'hero.title': 'Welcome',
41
- 'hero.subtitle': 'Build amazing things',
42
- },
43
- })
44
-
45
- useSEO({ page: 'home' })
46
-
47
- return (
48
- <div>
49
- <h1>{t('hero.title')}</h1>
50
- <p>{t('hero.subtitle')}</p>
51
- </div>
52
- )
53
- }
54
- ```
55
-
56
- ### DCS Configuration Files
57
-
58
- Create `.dcs/content.yaml`:
59
-
60
- ```yaml
61
- version: 1
62
- global:
63
- nav.home: Home
64
- footer.copyright: © 2026 Company
65
- pages:
66
- home:
67
- hero.title: Welcome to Our Site
68
- hero.subtitle: Build something amazing
69
- ```
70
-
71
- Create `.dcs/seo.yaml`:
72
-
73
- ```yaml
74
- version: 1
75
- global:
76
- siteName: My Site
77
- defaultTitle: My Site
78
- titleTemplate: "%s | My Site"
79
- pages:
80
- home:
81
- title: Welcome
82
- description: The homepage of My Site
83
- ```
84
-
85
- ## API
86
-
87
- ### useTextContent(options)
88
-
89
- Hook for text content with build-time and runtime support.
90
-
91
- **Options:**
92
- - `page` (string, required): Page slug matching entry in content.yaml
93
- - `defaults` (Record<string, string>): Default text values
94
- - `runtime` (boolean): Enable runtime fetching (premium tier)
95
- - `siteSlug` (string): Site slug for runtime API
96
- - `apiBaseUrl` (string): API base URL
97
-
98
- **Returns:**
99
- - `t(key, fallback?)`: Get text by key
100
- - `content`: All resolved content
101
- - `isLoading`: Loading state
102
- - `error`: Error message
103
- - `refresh()`: Manually refresh content
104
-
105
- ### useSEO(options)
106
-
107
- Hook for SEO meta tags.
108
-
109
- **Options:**
110
- - `page` (string, required): Page slug
111
- - `overrides`: Override title, description, or image
112
-
113
- **Returns:**
114
- - `seo`: Resolved SEO configuration
115
-
116
- ## License
117
-
118
- MIT
1
+ # @duffcloudservices/cms-react
2
+
3
+ React hooks and Vite plugins for DCS CMS integration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @duffcloudservices/cms-react
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Vite Configuration
14
+
15
+ ```typescript
16
+ // vite.config.ts
17
+ import { defineConfig } from 'vite'
18
+ import react from '@vitejs/plugin-react'
19
+ import { dcsContentPlugin, dcsSeoPlugin } from '@duffcloudservices/cms-react/plugins'
20
+
21
+ export default defineConfig({
22
+ plugins: [
23
+ react(),
24
+ dcsContentPlugin(),
25
+ dcsSeoPlugin(),
26
+ ],
27
+ })
28
+ ```
29
+
30
+ ### Using Hooks in Components
31
+
32
+ ```tsx
33
+ // src/pages/Home.tsx
34
+ import { useTextContent, useSEO } from '@duffcloudservices/cms-react'
35
+
36
+ export function Home() {
37
+ const { t } = useTextContent({
38
+ page: 'home',
39
+ defaults: {
40
+ 'hero.title': 'Welcome',
41
+ 'hero.subtitle': 'Build amazing things',
42
+ },
43
+ })
44
+
45
+ useSEO({ page: 'home' })
46
+
47
+ return (
48
+ <div>
49
+ <h1>{t('hero.title')}</h1>
50
+ <p>{t('hero.subtitle')}</p>
51
+ </div>
52
+ )
53
+ }
54
+ ```
55
+
56
+ ### DCS Configuration Files
57
+
58
+ Create `.dcs/content.yaml`:
59
+
60
+ ```yaml
61
+ version: 1
62
+ global:
63
+ nav.home: Home
64
+ footer.copyright: © 2026 Company
65
+ pages:
66
+ home:
67
+ hero.title: Welcome to Our Site
68
+ hero.subtitle: Build something amazing
69
+ ```
70
+
71
+ Create `.dcs/seo.yaml`:
72
+
73
+ ```yaml
74
+ version: 1
75
+ global:
76
+ siteName: My Site
77
+ defaultTitle: My Site
78
+ titleTemplate: "%s | My Site"
79
+ pages:
80
+ home:
81
+ title: Welcome
82
+ description: The homepage of My Site
83
+ ```
84
+
85
+ ## API
86
+
87
+ ### useTextContent(options)
88
+
89
+ Hook for text content with build-time and runtime support.
90
+
91
+ **Options:**
92
+ - `page` (string, required): Page slug matching entry in content.yaml
93
+ - `defaults` (Record<string, string>): Default text values
94
+ - `runtime` (boolean): Enable runtime fetching (premium tier)
95
+ - `siteSlug` (string): Site slug for runtime API
96
+ - `apiBaseUrl` (string): API base URL
97
+
98
+ **Returns:**
99
+ - `t(key, fallback?)`: Get text by key
100
+ - `content`: All resolved content
101
+ - `isLoading`: Loading state
102
+ - `error`: Error message
103
+ - `refresh()`: Manually refresh content
104
+
105
+ ### useSEO(options)
106
+
107
+ Hook for SEO meta tags.
108
+
109
+ **Options:**
110
+ - `page` (string, required): Page slug
111
+ - `overrides`: Override title, description, or image
112
+
113
+ **Returns:**
114
+ - `seo`: Resolved SEO configuration
115
+
116
+ ## License
117
+
118
+ MIT
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/useTextContent.ts","../src/hooks/useSEO.ts"],"names":["normalizeOptions","useMemo","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * useTextContent Hook for React\r\n *\r\n * Provides text content management with build-time injection support and optional\r\n * runtime API overrides for DCS-managed customer sites.\r\n */\r\n\r\nimport { useState, useEffect, useCallback, useMemo } from 'react'\r\nimport {\r\n getPageContent,\r\n fetchRuntimeContent,\r\n type ContentConfiguration,\r\n} from '@duffcloudservices/cms-core/browser'\r\n\r\n// Declare the global injected by dcsContentPlugin\r\ndeclare const __DCS_CONTENT__: ContentConfiguration | undefined\r\ndeclare const __DCS_RUNTIME_MODE__: boolean | undefined\r\n\r\n/**\r\n * Configuration for useTextContent hook\r\n */\r\nexport interface UseTextContentOptions {\r\n /** Page slug matching entry in content.yaml */\r\n page: string\r\n /** Default text values for all keys used by this page */\r\n defaults?: Record<string, string>\r\n /** Enable runtime content fetching (premium tier only) */\r\n runtime?: boolean\r\n /** Site slug for runtime fetching */\r\n siteSlug?: string\r\n /** API base URL for runtime fetching */\r\n apiBaseUrl?: string\r\n}\r\n\r\n/**\r\n * Text translation function signature\r\n */\r\nexport type TextFunction = (key: string, fallback?: string) => string\r\n\r\n/**\r\n * Return type of useTextContent hook\r\n */\r\nexport interface UseTextContentReturn {\r\n /** Get text by key with optional fallback */\r\n t: TextFunction\r\n /** All resolved content for the page */\r\n content: Record<string, string>\r\n /** Loading state for runtime fetch */\r\n isLoading: boolean\r\n /** Error message if fetch failed */\r\n error: string | null\r\n /** Manually refresh content (runtime mode only) */\r\n refresh: () => Promise<void>\r\n}\r\n\r\n/**\r\n * Safely get build-time content configuration.\r\n */\r\nfunction getBuildTimeContent(): ContentConfiguration | undefined {\r\n try {\r\n if (__DCS_CONTENT__ !== undefined && __DCS_CONTENT__ !== null) {\r\n return __DCS_CONTENT__\r\n }\r\n } catch {\r\n // __DCS_CONTENT__ not defined - that's fine, use defaults\r\n }\r\n return undefined\r\n}\r\n\r\n/**\r\n * Check if runtime mode is enabled via build-time flag\r\n */\r\nfunction isRuntimeModeEnabled(): boolean {\r\n try {\r\n return __DCS_RUNTIME_MODE__ === true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * Get environment variable value\r\n */\r\nfunction getEnvVar(key: string, defaultValue = ''): string {\r\n try {\r\n const value = import.meta.env?.[key as keyof ImportMetaEnv]\r\n if (value !== undefined) return String(value)\r\n } catch {\r\n // import.meta not available\r\n }\r\n return defaultValue\r\n}\r\n\r\n/**\r\n * Normalize input to options object\r\n */\r\nfunction normalizeOptions(input: string | UseTextContentOptions): UseTextContentOptions {\r\n if (typeof input === 'string') {\r\n return { page: input }\r\n }\r\n return input\r\n}\r\n\r\n/**\r\n * useTextContent hook for React components.\r\n *\r\n * @example\r\n * // Simple usage with page slug - returns t function directly\r\n * const t = useTextContent('home')\r\n * return <h1>{t('hero.title', 'Welcome')}</h1>\r\n *\r\n * @example\r\n * // Advanced usage with options - returns full object\r\n * const { t, isLoading } = useTextContent({\r\n * page: 'home',\r\n * runtime: true,\r\n * siteSlug: 'my-site'\r\n * })\r\n *\r\n * @param input - Page slug string or configuration options\r\n * @returns Text function (simple usage) or full return object (advanced usage)\r\n */\r\nexport function useTextContent(input: string): TextFunction\r\nexport function useTextContent(input: UseTextContentOptions): UseTextContentReturn\r\nexport function useTextContent(input: string | UseTextContentOptions): TextFunction | UseTextContentReturn {\r\n const options = normalizeOptions(input)\r\n const isSimpleUsage = typeof input === 'string'\r\n const {\r\n page,\r\n defaults = {},\r\n runtime = isRuntimeModeEnabled(),\r\n siteSlug = getEnvVar('VITE_SITE_SLUG', ''),\r\n apiBaseUrl = getEnvVar('VITE_API_BASE_URL', ''),\r\n } = options\r\n\r\n // Get build-time content\r\n const buildContent = getBuildTimeContent()\r\n const buildPageContent = useMemo(\r\n () => (buildContent ? getPageContent(buildContent, page) : {}),\r\n [buildContent, page]\r\n )\r\n\r\n // Runtime state\r\n const [runtimeContent, setRuntimeContent] = useState<ContentConfiguration | null>(null)\r\n const [isLoading, setIsLoading] = useState(false)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n // Merged content: runtime > build-time > defaults\r\n const content = useMemo(() => {\r\n const runtimePage = runtimeContent ? getPageContent(runtimeContent, page) : {}\r\n return { ...defaults, ...buildPageContent, ...runtimePage }\r\n }, [defaults, buildPageContent, runtimeContent, page])\r\n\r\n // Text translation function\r\n const t = useCallback(\r\n (key: string, fallback?: string): string => {\r\n return content[key] ?? fallback ?? key\r\n },\r\n [content]\r\n )\r\n\r\n // Fetch runtime content\r\n const refresh = useCallback(async () => {\r\n if (!runtime || !siteSlug) return\r\n\r\n setIsLoading(true)\r\n setError(null)\r\n\r\n try {\r\n const data = await fetchRuntimeContent(siteSlug, { apiBaseUrl })\r\n if (data) {\r\n setRuntimeContent(data)\r\n }\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : 'Failed to fetch content')\r\n } finally {\r\n setIsLoading(false)\r\n }\r\n }, [runtime, siteSlug, apiBaseUrl])\r\n\r\n // Auto-fetch on mount if runtime mode\r\n useEffect(() => {\r\n if (runtime && siteSlug) {\r\n refresh()\r\n }\r\n }, [runtime, siteSlug]) // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n // Simple usage: return just the t function\r\n if (isSimpleUsage) {\r\n return t\r\n }\r\n\r\n // Advanced usage: return full object\r\n return { t, content, isLoading, error, refresh }\r\n}\r\n","/**\r\n * useSEO Hook for React\r\n *\r\n * Applies SEO meta tags to the document head based on .dcs/seo.yaml configuration.\r\n */\r\n\r\nimport { useEffect, useMemo } from 'react'\r\nimport {\r\n resolveSeoForPage,\r\n buildMetaTags,\r\n type SeoConfiguration,\r\n type ResolvedSeo,\r\n} from '@duffcloudservices/cms-core/browser'\r\n\r\n// Declare the global injected by dcsSeoPlugin\r\ndeclare const __DCS_SEO__: SeoConfiguration | undefined\r\n\r\n/**\r\n * Configuration for useSEO hook\r\n */\r\nexport interface UseSEOOptions {\r\n /** Page slug matching entry in seo.yaml */\r\n page: string\r\n /** Override resolved SEO values */\r\n overrides?: Partial<{\r\n title: string\r\n description: string\r\n image: string\r\n }>\r\n}\r\n\r\n/**\r\n * Return type of useSEO hook\r\n */\r\nexport interface UseSEOReturn {\r\n /** Resolved SEO configuration */\r\n seo: ResolvedSeo | null\r\n}\r\n\r\n/**\r\n * Safely get build-time SEO configuration.\r\n */\r\nfunction getBuildTimeSeo(): SeoConfiguration | undefined {\r\n try {\r\n if (__DCS_SEO__ !== undefined && __DCS_SEO__ !== null) {\r\n return __DCS_SEO__\r\n }\r\n } catch {\r\n // __DCS_SEO__ not defined\r\n }\r\n return undefined\r\n}\r\n\r\n/**\r\n * Update or create a meta tag in the document head\r\n */\r\nfunction updateMetaTag(\r\n attr: 'name' | 'property',\r\n key: string,\r\n content: string | undefined\r\n): void {\r\n if (!content) return\r\n\r\n let element = document.querySelector(`meta[${attr}=\"${key}\"]`)\r\n if (!element) {\r\n element = document.createElement('meta')\r\n element.setAttribute(attr, key)\r\n document.head.appendChild(element)\r\n }\r\n ;(element as HTMLMetaElement).content = content\r\n}\r\n\r\n/**\r\n * Normalize input to options object\r\n */\r\nfunction normalizeOptions(input: string | UseSEOOptions): UseSEOOptions {\r\n if (typeof input === 'string') {\r\n return { page: input }\r\n }\r\n return input\r\n}\r\n\r\n/**\r\n * useSEO hook for React components.\r\n * Automatically applies SEO meta tags to the document head.\r\n *\r\n * @example\r\n * // Simple usage with page slug\r\n * useSEO('home')\r\n *\r\n * @example\r\n * // Advanced usage with overrides\r\n * const { seo } = useSEO({\r\n * page: 'home',\r\n * overrides: { title: 'Custom Title' }\r\n * })\r\n *\r\n * @param input - Page slug string or configuration options\r\n * @returns Resolved SEO object\r\n */\r\nexport function useSEO(input: string): UseSEOReturn\r\nexport function useSEO(input: UseSEOOptions): UseSEOReturn\r\nexport function useSEO(input: string | UseSEOOptions): UseSEOReturn {\r\n const options = normalizeOptions(input)\r\n const { page, overrides } = options\r\n\r\n const seoConfig = getBuildTimeSeo()\r\n\r\n const resolvedSeo = useMemo(() => {\r\n if (!seoConfig) return null\r\n const base = resolveSeoForPage(seoConfig, page)\r\n return {\r\n ...base,\r\n ...(overrides?.title && { title: overrides.title }),\r\n ...(overrides?.description && { description: overrides.description }),\r\n ...(overrides?.image && { image: overrides.image }),\r\n }\r\n }, [seoConfig, page, overrides])\r\n\r\n // Apply to document head\r\n useEffect(() => {\r\n if (!resolvedSeo) return\r\n\r\n // Update document title\r\n document.title = resolvedSeo.title\r\n\r\n // Build and apply meta tags\r\n const tags = buildMetaTags(resolvedSeo)\r\n for (const tag of tags) {\r\n if (tag.property) {\r\n updateMetaTag('property', tag.property, tag.content)\r\n } else if (tag.name) {\r\n updateMetaTag('name', tag.name, tag.content)\r\n }\r\n }\r\n\r\n // Handle canonical link\r\n if (resolvedSeo.canonical) {\r\n let link = document.querySelector('link[rel=\"canonical\"]')\r\n if (!link) {\r\n link = document.createElement('link')\r\n link.setAttribute('rel', 'canonical')\r\n document.head.appendChild(link)\r\n }\r\n link.setAttribute('href', resolvedSeo.canonical)\r\n }\r\n }, [resolvedSeo])\r\n\r\n return { seo: resolvedSeo }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/hooks/useTextContent.ts","../src/hooks/useSEO.ts"],"names":["normalizeOptions","useMemo","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * useTextContent Hook for React\n *\n * Provides text content management with build-time injection support and optional\n * runtime API overrides for DCS-managed customer sites.\n */\n\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport {\n getPageContent,\n fetchRuntimeContent,\n type ContentConfiguration,\n} from '@duffcloudservices/cms-core/browser'\n\n// Declare the global injected by dcsContentPlugin\ndeclare const __DCS_CONTENT__: ContentConfiguration | undefined\ndeclare const __DCS_RUNTIME_MODE__: boolean | undefined\n\n/**\n * Configuration for useTextContent hook\n */\nexport interface UseTextContentOptions {\n /** Page slug matching entry in content.yaml */\n page: string\n /** Default text values for all keys used by this page */\n defaults?: Record<string, string>\n /** Enable runtime content fetching (premium tier only) */\n runtime?: boolean\n /** Site slug for runtime fetching */\n siteSlug?: string\n /** API base URL for runtime fetching */\n apiBaseUrl?: string\n}\n\n/**\n * Text translation function signature\n */\nexport type TextFunction = (key: string, fallback?: string) => string\n\n/**\n * Return type of useTextContent hook\n */\nexport interface UseTextContentReturn {\n /** Get text by key with optional fallback */\n t: TextFunction\n /** All resolved content for the page */\n content: Record<string, string>\n /** Loading state for runtime fetch */\n isLoading: boolean\n /** Error message if fetch failed */\n error: string | null\n /** Manually refresh content (runtime mode only) */\n refresh: () => Promise<void>\n}\n\n/**\n * Safely get build-time content configuration.\n */\nfunction getBuildTimeContent(): ContentConfiguration | undefined {\n try {\n if (__DCS_CONTENT__ !== undefined && __DCS_CONTENT__ !== null) {\n return __DCS_CONTENT__\n }\n } catch {\n // __DCS_CONTENT__ not defined - that's fine, use defaults\n }\n return undefined\n}\n\n/**\n * Check if runtime mode is enabled via build-time flag\n */\nfunction isRuntimeModeEnabled(): boolean {\n try {\n return __DCS_RUNTIME_MODE__ === true\n } catch {\n return false\n }\n}\n\n/**\n * Get environment variable value\n */\nfunction getEnvVar(key: string, defaultValue = ''): string {\n try {\n const value = import.meta.env?.[key as keyof ImportMetaEnv]\n if (value !== undefined) return String(value)\n } catch {\n // import.meta not available\n }\n return defaultValue\n}\n\n/**\n * Normalize input to options object\n */\nfunction normalizeOptions(input: string | UseTextContentOptions): UseTextContentOptions {\n if (typeof input === 'string') {\n return { page: input }\n }\n return input\n}\n\n/**\n * useTextContent hook for React components.\n *\n * @example\n * // Simple usage with page slug - returns t function directly\n * const t = useTextContent('home')\n * return <h1>{t('hero.title', 'Welcome')}</h1>\n *\n * @example\n * // Advanced usage with options - returns full object\n * const { t, isLoading } = useTextContent({\n * page: 'home',\n * runtime: true,\n * siteSlug: 'my-site'\n * })\n *\n * @param input - Page slug string or configuration options\n * @returns Text function (simple usage) or full return object (advanced usage)\n */\nexport function useTextContent(input: string): TextFunction\nexport function useTextContent(input: UseTextContentOptions): UseTextContentReturn\nexport function useTextContent(input: string | UseTextContentOptions): TextFunction | UseTextContentReturn {\n const options = normalizeOptions(input)\n const isSimpleUsage = typeof input === 'string'\n const {\n page,\n defaults = {},\n runtime = isRuntimeModeEnabled(),\n siteSlug = getEnvVar('VITE_SITE_SLUG', ''),\n apiBaseUrl = getEnvVar('VITE_API_BASE_URL', ''),\n } = options\n\n // Get build-time content\n const buildContent = getBuildTimeContent()\n const buildPageContent = useMemo(\n () => (buildContent ? getPageContent(buildContent, page) : {}),\n [buildContent, page]\n )\n\n // Runtime state\n const [runtimeContent, setRuntimeContent] = useState<ContentConfiguration | null>(null)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n // Merged content: runtime > build-time > defaults\n const content = useMemo(() => {\n const runtimePage = runtimeContent ? getPageContent(runtimeContent, page) : {}\n return { ...defaults, ...buildPageContent, ...runtimePage }\n }, [defaults, buildPageContent, runtimeContent, page])\n\n // Text translation function\n const t = useCallback(\n (key: string, fallback?: string): string => {\n return content[key] ?? fallback ?? key\n },\n [content]\n )\n\n // Fetch runtime content\n const refresh = useCallback(async () => {\n if (!runtime || !siteSlug) return\n\n setIsLoading(true)\n setError(null)\n\n try {\n const data = await fetchRuntimeContent(siteSlug, { apiBaseUrl })\n if (data) {\n setRuntimeContent(data)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to fetch content')\n } finally {\n setIsLoading(false)\n }\n }, [runtime, siteSlug, apiBaseUrl])\n\n // Auto-fetch on mount if runtime mode\n useEffect(() => {\n if (runtime && siteSlug) {\n refresh()\n }\n }, [runtime, siteSlug]) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Simple usage: return just the t function\n if (isSimpleUsage) {\n return t\n }\n\n // Advanced usage: return full object\n return { t, content, isLoading, error, refresh }\n}\n","/**\n * useSEO Hook for React\n *\n * Applies SEO meta tags to the document head based on .dcs/seo.yaml configuration.\n */\n\nimport { useEffect, useMemo } from 'react'\nimport {\n resolveSeoForPage,\n buildMetaTags,\n type SeoConfiguration,\n type ResolvedSeo,\n} from '@duffcloudservices/cms-core/browser'\n\n// Declare the global injected by dcsSeoPlugin\ndeclare const __DCS_SEO__: SeoConfiguration | undefined\n\n/**\n * Configuration for useSEO hook\n */\nexport interface UseSEOOptions {\n /** Page slug matching entry in seo.yaml */\n page: string\n /** Override resolved SEO values */\n overrides?: Partial<{\n title: string\n description: string\n image: string\n }>\n}\n\n/**\n * Return type of useSEO hook\n */\nexport interface UseSEOReturn {\n /** Resolved SEO configuration */\n seo: ResolvedSeo | null\n}\n\n/**\n * Safely get build-time SEO configuration.\n */\nfunction getBuildTimeSeo(): SeoConfiguration | undefined {\n try {\n if (__DCS_SEO__ !== undefined && __DCS_SEO__ !== null) {\n return __DCS_SEO__\n }\n } catch {\n // __DCS_SEO__ not defined\n }\n return undefined\n}\n\n/**\n * Update or create a meta tag in the document head\n */\nfunction updateMetaTag(\n attr: 'name' | 'property',\n key: string,\n content: string | undefined\n): void {\n if (!content) return\n\n let element = document.querySelector(`meta[${attr}=\"${key}\"]`)\n if (!element) {\n element = document.createElement('meta')\n element.setAttribute(attr, key)\n document.head.appendChild(element)\n }\n ;(element as HTMLMetaElement).content = content\n}\n\n/**\n * Normalize input to options object\n */\nfunction normalizeOptions(input: string | UseSEOOptions): UseSEOOptions {\n if (typeof input === 'string') {\n return { page: input }\n }\n return input\n}\n\n/**\n * useSEO hook for React components.\n * Automatically applies SEO meta tags to the document head.\n *\n * @example\n * // Simple usage with page slug\n * useSEO('home')\n *\n * @example\n * // Advanced usage with overrides\n * const { seo } = useSEO({\n * page: 'home',\n * overrides: { title: 'Custom Title' }\n * })\n *\n * @param input - Page slug string or configuration options\n * @returns Resolved SEO object\n */\nexport function useSEO(input: string): UseSEOReturn\nexport function useSEO(input: UseSEOOptions): UseSEOReturn\nexport function useSEO(input: string | UseSEOOptions): UseSEOReturn {\n const options = normalizeOptions(input)\n const { page, overrides } = options\n\n const seoConfig = getBuildTimeSeo()\n\n const resolvedSeo = useMemo(() => {\n if (!seoConfig) return null\n const base = resolveSeoForPage(seoConfig, page)\n return {\n ...base,\n ...(overrides?.title && { title: overrides.title }),\n ...(overrides?.description && { description: overrides.description }),\n ...(overrides?.image && { image: overrides.image }),\n }\n }, [seoConfig, page, overrides])\n\n // Apply to document head\n useEffect(() => {\n if (!resolvedSeo) return\n\n // Update document title\n document.title = resolvedSeo.title\n\n // Build and apply meta tags\n const tags = buildMetaTags(resolvedSeo)\n for (const tag of tags) {\n if (tag.property) {\n updateMetaTag('property', tag.property, tag.content)\n } else if (tag.name) {\n updateMetaTag('name', tag.name, tag.content)\n }\n }\n\n // Handle canonical link\n if (resolvedSeo.canonical) {\n let link = document.querySelector('link[rel=\"canonical\"]')\n if (!link) {\n link = document.createElement('link')\n link.setAttribute('rel', 'canonical')\n document.head.appendChild(link)\n }\n link.setAttribute('href', resolvedSeo.canonical)\n }\n }, [resolvedSeo])\n\n return { seo: resolvedSeo }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/dcsPlugins.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * DCS Vite Plugins for React\r\n *\r\n * Reads `.dcs/content.yaml` and `.dcs/seo.yaml` at build time and injects\r\n * them as global variables for use by React hooks.\r\n *\r\n * @example\r\n * ```typescript\r\n * // vite.config.ts\r\n * import react from '@vitejs/plugin-react'\r\n * import { dcsContentPlugin, dcsSeoPlugin } from '@duffcloudservices/cms-react/plugins'\r\n *\r\n * export default defineConfig({\r\n * plugins: [\r\n * react(),\r\n * dcsContentPlugin(),\r\n * dcsSeoPlugin()\r\n * ]\r\n * })\r\n * ```\r\n */\r\n\r\nimport { loadContentYaml, loadSeoYaml } from '@duffcloudservices/cms-core'\r\n\r\n// Use generic plugin type to avoid Vite version conflicts\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype VitePlugin = any\r\n\r\n/**\r\n * Options for dcsContentPlugin\r\n */\r\nexport interface DcsContentPluginOptions {\r\n /** Path to content.yaml relative to project root (default: '.dcs/content.yaml') */\r\n contentPath?: string\r\n /** Enable runtime mode for premium tier customers */\r\n runtime?: boolean\r\n /** Enable debug logging */\r\n debug?: boolean\r\n}\r\n\r\n/**\r\n * Options for dcsSeoPlugin\r\n */\r\nexport interface DcsSeoPluginOptions {\r\n /** Path to seo.yaml relative to project root (default: '.dcs/seo.yaml') */\r\n seoPath?: string\r\n /** Enable debug logging */\r\n debug?: boolean\r\n}\r\n\r\n/**\r\n * Find config file in common locations\r\n */\r\nfunction findConfigFile(\r\n filename: string,\r\n projectRoot: string,\r\n fs: typeof import('fs'),\r\n path: typeof import('path')\r\n): string | undefined {\r\n const possiblePaths = [\r\n path.resolve(projectRoot, filename),\r\n path.resolve(projectRoot, '..', filename),\r\n path.resolve(process.cwd(), filename),\r\n ]\r\n\r\n for (const testPath of possiblePaths) {\r\n if (fs.existsSync(testPath)) {\r\n return testPath\r\n }\r\n }\r\n\r\n return undefined\r\n}\r\n\r\n/**\r\n * Vite plugin that injects .dcs/content.yaml at build time.\r\n */\r\nexport function dcsContentPlugin(options: DcsContentPluginOptions = {}): VitePlugin {\r\n const { contentPath = '.dcs/content.yaml', runtime = false, debug = false } = options\r\n\r\n return {\r\n name: 'dcs-content-react',\r\n\r\n async config(config: { root?: string }) {\r\n // Dynamic imports for Node.js modules\r\n const fs = await import('node:fs')\r\n const path = await import('node:path')\r\n\r\n const projectRoot = config.root || process.cwd()\r\n const foundPath = findConfigFile(contentPath, projectRoot, fs, path)\r\n\r\n if (!foundPath) {\r\n if (debug) {\r\n console.log('[dcs-content] No content.yaml found, using defaults only')\r\n }\r\n return {\r\n define: {\r\n __DCS_CONTENT__: 'undefined',\r\n __DCS_RUNTIME_MODE__: JSON.stringify(runtime),\r\n },\r\n }\r\n }\r\n\r\n try {\r\n const content = await loadContentYaml(foundPath)\r\n if (debug) {\r\n console.log(`[dcs-content] Loaded content from ${foundPath}`)\r\n }\r\n return {\r\n define: {\r\n __DCS_CONTENT__: JSON.stringify(content),\r\n __DCS_RUNTIME_MODE__: JSON.stringify(runtime),\r\n },\r\n }\r\n } catch (err) {\r\n console.warn(`[dcs-content] Error loading ${contentPath}:`, err)\r\n return {\r\n define: {\r\n __DCS_CONTENT__: 'undefined',\r\n __DCS_RUNTIME_MODE__: JSON.stringify(runtime),\r\n },\r\n }\r\n }\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * Vite plugin that injects .dcs/seo.yaml at build time.\r\n */\r\nexport function dcsSeoPlugin(options: DcsSeoPluginOptions = {}): VitePlugin {\r\n const { seoPath = '.dcs/seo.yaml', debug = false } = options\r\n\r\n return {\r\n name: 'dcs-seo-react',\r\n\r\n async config(config: { root?: string }) {\r\n // Dynamic imports for Node.js modules\r\n const fs = await import('node:fs')\r\n const path = await import('node:path')\r\n\r\n const projectRoot = config.root || process.cwd()\r\n const foundPath = findConfigFile(seoPath, projectRoot, fs, path)\r\n\r\n if (!foundPath) {\r\n if (debug) {\r\n console.log('[dcs-seo] No seo.yaml found, SEO features disabled')\r\n }\r\n return {\r\n define: {\r\n __DCS_SEO__: 'undefined',\r\n },\r\n }\r\n }\r\n\r\n try {\r\n const seo = await loadSeoYaml(foundPath)\r\n if (debug) {\r\n console.log(`[dcs-seo] Loaded SEO config from ${foundPath}`)\r\n }\r\n return {\r\n define: {\r\n __DCS_SEO__: JSON.stringify(seo),\r\n },\r\n }\r\n } catch (err) {\r\n console.warn(`[dcs-seo] Error loading ${seoPath}:`, err)\r\n return {\r\n define: {\r\n __DCS_SEO__: 'undefined',\r\n },\r\n }\r\n }\r\n },\r\n }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../../src/plugins/dcsPlugins.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * DCS Vite Plugins for React\n *\n * Reads `.dcs/content.yaml` and `.dcs/seo.yaml` at build time and injects\n * them as global variables for use by React hooks.\n *\n * @example\n * ```typescript\n * // vite.config.ts\n * import react from '@vitejs/plugin-react'\n * import { dcsContentPlugin, dcsSeoPlugin } from '@duffcloudservices/cms-react/plugins'\n *\n * export default defineConfig({\n * plugins: [\n * react(),\n * dcsContentPlugin(),\n * dcsSeoPlugin()\n * ]\n * })\n * ```\n */\n\nimport { loadContentYaml, loadSeoYaml } from '@duffcloudservices/cms-core'\n\n// Use generic plugin type to avoid Vite version conflicts\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype VitePlugin = any\n\n/**\n * Options for dcsContentPlugin\n */\nexport interface DcsContentPluginOptions {\n /** Path to content.yaml relative to project root (default: '.dcs/content.yaml') */\n contentPath?: string\n /** Enable runtime mode for premium tier customers */\n runtime?: boolean\n /** Enable debug logging */\n debug?: boolean\n}\n\n/**\n * Options for dcsSeoPlugin\n */\nexport interface DcsSeoPluginOptions {\n /** Path to seo.yaml relative to project root (default: '.dcs/seo.yaml') */\n seoPath?: string\n /** Enable debug logging */\n debug?: boolean\n}\n\n/**\n * Find config file in common locations\n */\nfunction findConfigFile(\n filename: string,\n projectRoot: string,\n fs: typeof import('fs'),\n path: typeof import('path')\n): string | undefined {\n const possiblePaths = [\n path.resolve(projectRoot, filename),\n path.resolve(projectRoot, '..', filename),\n path.resolve(process.cwd(), filename),\n ]\n\n for (const testPath of possiblePaths) {\n if (fs.existsSync(testPath)) {\n return testPath\n }\n }\n\n return undefined\n}\n\n/**\n * Vite plugin that injects .dcs/content.yaml at build time.\n */\nexport function dcsContentPlugin(options: DcsContentPluginOptions = {}): VitePlugin {\n const { contentPath = '.dcs/content.yaml', runtime = false, debug = false } = options\n\n return {\n name: 'dcs-content-react',\n\n async config(config: { root?: string }) {\n // Dynamic imports for Node.js modules\n const fs = await import('node:fs')\n const path = await import('node:path')\n\n const projectRoot = config.root || process.cwd()\n const foundPath = findConfigFile(contentPath, projectRoot, fs, path)\n\n if (!foundPath) {\n if (debug) {\n console.log('[dcs-content] No content.yaml found, using defaults only')\n }\n return {\n define: {\n __DCS_CONTENT__: 'undefined',\n __DCS_RUNTIME_MODE__: JSON.stringify(runtime),\n },\n }\n }\n\n try {\n const content = await loadContentYaml(foundPath)\n if (debug) {\n console.log(`[dcs-content] Loaded content from ${foundPath}`)\n }\n return {\n define: {\n __DCS_CONTENT__: JSON.stringify(content),\n __DCS_RUNTIME_MODE__: JSON.stringify(runtime),\n },\n }\n } catch (err) {\n console.warn(`[dcs-content] Error loading ${contentPath}:`, err)\n return {\n define: {\n __DCS_CONTENT__: 'undefined',\n __DCS_RUNTIME_MODE__: JSON.stringify(runtime),\n },\n }\n }\n },\n }\n}\n\n/**\n * Vite plugin that injects .dcs/seo.yaml at build time.\n */\nexport function dcsSeoPlugin(options: DcsSeoPluginOptions = {}): VitePlugin {\n const { seoPath = '.dcs/seo.yaml', debug = false } = options\n\n return {\n name: 'dcs-seo-react',\n\n async config(config: { root?: string }) {\n // Dynamic imports for Node.js modules\n const fs = await import('node:fs')\n const path = await import('node:path')\n\n const projectRoot = config.root || process.cwd()\n const foundPath = findConfigFile(seoPath, projectRoot, fs, path)\n\n if (!foundPath) {\n if (debug) {\n console.log('[dcs-seo] No seo.yaml found, SEO features disabled')\n }\n return {\n define: {\n __DCS_SEO__: 'undefined',\n },\n }\n }\n\n try {\n const seo = await loadSeoYaml(foundPath)\n if (debug) {\n console.log(`[dcs-seo] Loaded SEO config from ${foundPath}`)\n }\n return {\n define: {\n __DCS_SEO__: JSON.stringify(seo),\n },\n }\n } catch (err) {\n console.warn(`[dcs-seo] Error loading ${seoPath}:`, err)\n return {\n define: {\n __DCS_SEO__: 'undefined',\n },\n }\n }\n },\n }\n}\n"]}
package/package.json CHANGED
@@ -1,62 +1,61 @@
1
- {
2
- "name": "@duffcloudservices/cms-react",
3
- "version": "0.1.0",
4
- "description": "React hooks and Vite plugins for DCS CMS integration",
5
- "type": "module",
6
- "exports": {
7
- ".": {
8
- "types": "./dist/index.d.ts",
9
- "import": "./dist/index.js"
10
- },
11
- "./plugins": {
12
- "types": "./dist/plugins/index.d.ts",
13
- "import": "./dist/plugins/index.js"
14
- }
15
- },
16
- "main": "./dist/index.js",
17
- "types": "./dist/index.d.ts",
18
- "files": [
19
- "dist"
20
- ],
21
- "scripts": {
22
- "build": "tsup",
23
- "dev": "tsup --watch",
24
- "test": "vitest run",
25
- "test:watch": "vitest",
26
- "type-check": "tsc --noEmit",
27
- "prepublishOnly": "pnpm run build"
28
- },
29
- "peerDependencies": {
30
- "react": "^18.0.0 || ^19.0.0"
31
- },
32
- "dependencies": {
33
- "@duffcloudservices/cms-core": "workspace:*"
34
- },
35
- "devDependencies": {
36
- "@types/node": "^20.11.0",
37
- "@types/react": "^18.3.0",
38
- "react": "^18.3.0",
39
- "tsup": "^8.0.0",
40
- "typescript": "~5.6.3",
41
- "vite": "^6.3.5",
42
- "vitest": "^3.2.3"
43
- },
44
- "keywords": [
45
- "react",
46
- "dcs",
47
- "cms",
48
- "content",
49
- "seo",
50
- "vite"
51
- ],
52
- "author": "Duff Cloud Services",
53
- "license": "MIT",
54
- "repository": {
55
- "type": "git",
56
- "url": "https://github.com/duffn84/dcs-again",
57
- "directory": "packages/cms-react"
58
- },
59
- "publishConfig": {
60
- "access": "public"
61
- }
62
- }
1
+ {
2
+ "name": "@duffcloudservices/cms-react",
3
+ "version": "0.1.2",
4
+ "description": "React hooks and Vite plugins for DCS CMS integration",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
+ },
11
+ "./plugins": {
12
+ "types": "./dist/plugins/index.d.ts",
13
+ "import": "./dist/plugins/index.js"
14
+ }
15
+ },
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "peerDependencies": {
22
+ "react": "^18.0.0 || ^19.0.0"
23
+ },
24
+ "dependencies": {
25
+ "@duffcloudservices/cms-core": "0.4.4"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20.11.0",
29
+ "@types/react": "^18.3.0",
30
+ "react": "^18.3.0",
31
+ "tsup": "^8.0.0",
32
+ "typescript": "~5.6.3",
33
+ "vite": "^6.3.5",
34
+ "vitest": "^3.2.3"
35
+ },
36
+ "keywords": [
37
+ "react",
38
+ "dcs",
39
+ "cms",
40
+ "content",
41
+ "seo",
42
+ "vite"
43
+ ],
44
+ "author": "Duff Cloud Services",
45
+ "license": "MIT",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/duffn84/dcs-again",
49
+ "directory": "packages/cms-react"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "scripts": {
55
+ "build": "tsup",
56
+ "dev": "tsup --watch",
57
+ "test": "vitest run",
58
+ "test:watch": "vitest",
59
+ "type-check": "tsc --noEmit"
60
+ }
61
+ }