@duffcloudservices/cms-angular 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -112,7 +112,7 @@ Service for text content management.
112
112
  **Methods:**
113
113
  - `t(page, key, fallback?)`: Get text by page and key
114
114
  - `getPageContent(page)`: Get all content for a page
115
- - `fetchRuntimeContent(siteSlug, apiBaseUrl?)`: Fetch runtime content (premium)
115
+ - `fetchRuntimeContent(siteSlug, apiBaseUrl?)`: Fetch runtime content (premium). The `siteSlug` argument is deprecated and ignored for routing — the site is resolved server-side from the request Host or the dedicated Container App's `DCS_SITE_SLUG`; it is retained only for source compatibility.
116
116
 
117
117
  **Signals:**
118
118
  - `content`: Current content configuration
package/dist/index.d.ts CHANGED
@@ -40,7 +40,11 @@ declare class DcsContentService {
40
40
  /**
41
41
  * Fetch runtime content from DCS API (premium tier only).
42
42
  *
43
- * @param siteSlug - The site's slug identifier
43
+ * @param siteSlug - The site's slug identifier.
44
+ * @deprecated The site is now resolved server-side from the request Host or
45
+ * the dedicated Container App's `DCS_SITE_SLUG`. This argument is retained
46
+ * for source compatibility but is ignored for routing (no longer placed in
47
+ * the URL path).
44
48
  * @param apiBaseUrl - Optional API base URL override
45
49
  */
46
50
  fetchRuntimeContent(siteSlug: string, apiBaseUrl?: string): Promise<void>;
package/dist/index.js CHANGED
@@ -60,7 +60,11 @@ var DcsContentService = class {
60
60
  /**
61
61
  * Fetch runtime content from DCS API (premium tier only).
62
62
  *
63
- * @param siteSlug - The site's slug identifier
63
+ * @param siteSlug - The site's slug identifier.
64
+ * @deprecated The site is now resolved server-side from the request Host or
65
+ * the dedicated Container App's `DCS_SITE_SLUG`. This argument is retained
66
+ * for source compatibility but is ignored for routing (no longer placed in
67
+ * the URL path).
64
68
  * @param apiBaseUrl - Optional API base URL override
65
69
  */
66
70
  async fetchRuntimeContent(siteSlug, apiBaseUrl) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/content.service.ts","../src/services/seo.service.ts","../src/providers.ts"],"names":["Injectable"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * DcsContentService for Angular\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 { Injectable, signal, computed } from '@angular/core'\nimport {\n resolveTextKey,\n getPageContent,\n fetchRuntimeContent,\n type ContentConfiguration,\n} from '@duffcloudservices/cms-core/browser'\n\n// Declare the global injected by build script\ndeclare const __DCS_CONTENT__: ContentConfiguration | undefined\n\n/**\n * Angular service for DCS text content management.\n */\n@Injectable({ providedIn: 'root' })\nexport class DcsContentService {\n /** Build-time content (injected via index.html script) */\n private readonly buildContent = this.getBuildTimeContent()\n\n /** Runtime content (fetched if runtime mode enabled) */\n private readonly runtimeContent = signal<ContentConfiguration | null>(null)\n\n /** Loading state for runtime fetch */\n readonly isLoading = signal(false)\n\n /** Error state for runtime fetch */\n readonly error = signal<string | null>(null)\n\n /** Current content (runtime overrides build-time) */\n readonly content = computed(() => this.runtimeContent() ?? this.buildContent)\n\n /**\n * Safely get build-time content configuration.\n */\n private 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\n }\n return undefined\n }\n\n /**\n * Get text for a specific page and key.\n *\n * @param page - Page slug matching entry in content.yaml\n * @param key - Text key to retrieve\n * @param fallback - Fallback value if key not found\n * @returns The resolved text value\n */\n t(page: string, key: string, fallback?: string): string {\n const c = this.content()\n if (!c) return fallback ?? key\n return resolveTextKey(c, page, key) ?? fallback ?? key\n }\n\n /**\n * Get all content for a specific page (merged global + page).\n *\n * @param page - Page slug\n * @returns Merged content object\n */\n getPageContent(page: string): Record<string, string> {\n const c = this.content()\n if (!c) return {}\n return getPageContent(c, page)\n }\n\n /**\n * Fetch runtime content from DCS API (premium tier only).\n *\n * @param siteSlug - The site's slug identifier\n * @param apiBaseUrl - Optional API base URL override\n */\n async fetchRuntimeContent(siteSlug: string, apiBaseUrl?: string): Promise<void> {\n this.isLoading.set(true)\n this.error.set(null)\n\n try {\n const data = await fetchRuntimeContent(siteSlug, { apiBaseUrl })\n if (data) {\n this.runtimeContent.set(data)\n }\n } catch (err) {\n this.error.set(err instanceof Error ? err.message : 'Failed to fetch content')\n } finally {\n this.isLoading.set(false)\n }\n }\n}\n","/**\n * DcsSeoService for Angular\n *\n * Applies SEO meta tags to the document head based on .dcs/seo.yaml configuration.\n */\n\nimport { Injectable, inject } from '@angular/core'\nimport { Meta, Title } from '@angular/platform-browser'\nimport {\n resolveSeoForPage,\n buildMetaTags,\n type SeoConfiguration,\n type ResolvedSeo,\n} from '@duffcloudservices/cms-core/browser'\n\n// Declare the global injected by build script\ndeclare const __DCS_SEO__: SeoConfiguration | undefined\n\n/**\n * Angular service for DCS SEO management.\n */\n@Injectable({ providedIn: 'root' })\nexport class DcsSeoService {\n private readonly meta = inject(Meta)\n private readonly title = inject(Title)\n\n /** Build-time SEO config (injected via index.html script) */\n private readonly seoConfig = this.getBuildTimeSeo()\n\n /**\n * Safely get build-time SEO configuration.\n */\n private 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 * Apply SEO for a specific page.\n *\n * @param page - Page slug matching entry in seo.yaml\n * @param overrides - Optional overrides for title, description, or image\n * @returns The resolved SEO configuration\n */\n setPageSeo(\n page: string,\n overrides?: { title?: string; description?: string; image?: string }\n ): ResolvedSeo | null {\n if (!this.seoConfig) return null\n\n const seo = resolveSeoForPage(this.seoConfig, page)\n const resolved: ResolvedSeo = {\n ...seo,\n ...(overrides?.title && { title: overrides.title }),\n ...(overrides?.description && { description: overrides.description }),\n ...(overrides?.image && { image: overrides.image }),\n }\n\n // Set document title\n this.title.setTitle(resolved.title)\n\n // Build and apply meta tags\n const tags = buildMetaTags(resolved)\n for (const tag of tags) {\n if (tag.property) {\n this.meta.updateTag({ property: tag.property, content: tag.content })\n } else if (tag.name) {\n this.meta.updateTag({ name: tag.name, content: tag.content })\n }\n }\n\n // Handle canonical link\n if (resolved.canonical) {\n this.updateCanonicalLink(resolved.canonical)\n }\n\n return resolved\n }\n\n /**\n * Update or create canonical link element.\n */\n private updateCanonicalLink(href: string): void {\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', href)\n }\n\n /**\n * Get the raw SEO configuration.\n */\n getSeoConfig(): SeoConfiguration | undefined {\n return this.seoConfig\n }\n}\n","/**\n * Angular providers for DCS CMS integration.\n */\n\nimport { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core'\nimport { DcsContentService } from './services/content.service'\nimport { DcsSeoService } from './services/seo.service'\n\n/**\n * Provide DCS CMS services for Angular application.\n *\n * @example\n * ```typescript\n * // app.config.ts\n * import { ApplicationConfig } from '@angular/core'\n * import { provideDcs } from '@duffcloudservices/cms-angular'\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideDcs(),\n * ],\n * }\n * ```\n */\nexport function provideDcs(): EnvironmentProviders {\n return makeEnvironmentProviders([DcsContentService, DcsSeoService])\n}\n"]}
1
+ {"version":3,"sources":["../src/services/content.service.ts","../src/services/seo.service.ts","../src/providers.ts"],"names":["Injectable"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * DcsContentService for Angular\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 { Injectable, signal, computed } from '@angular/core'\nimport {\n resolveTextKey,\n getPageContent,\n fetchRuntimeContent,\n type ContentConfiguration,\n} from '@duffcloudservices/cms-core/browser'\n\n// Declare the global injected by build script\ndeclare const __DCS_CONTENT__: ContentConfiguration | undefined\n\n/**\n * Angular service for DCS text content management.\n */\n@Injectable({ providedIn: 'root' })\nexport class DcsContentService {\n /** Build-time content (injected via index.html script) */\n private readonly buildContent = this.getBuildTimeContent()\n\n /** Runtime content (fetched if runtime mode enabled) */\n private readonly runtimeContent = signal<ContentConfiguration | null>(null)\n\n /** Loading state for runtime fetch */\n readonly isLoading = signal(false)\n\n /** Error state for runtime fetch */\n readonly error = signal<string | null>(null)\n\n /** Current content (runtime overrides build-time) */\n readonly content = computed(() => this.runtimeContent() ?? this.buildContent)\n\n /**\n * Safely get build-time content configuration.\n */\n private 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\n }\n return undefined\n }\n\n /**\n * Get text for a specific page and key.\n *\n * @param page - Page slug matching entry in content.yaml\n * @param key - Text key to retrieve\n * @param fallback - Fallback value if key not found\n * @returns The resolved text value\n */\n t(page: string, key: string, fallback?: string): string {\n const c = this.content()\n if (!c) return fallback ?? key\n return resolveTextKey(c, page, key) ?? fallback ?? key\n }\n\n /**\n * Get all content for a specific page (merged global + page).\n *\n * @param page - Page slug\n * @returns Merged content object\n */\n getPageContent(page: string): Record<string, string> {\n const c = this.content()\n if (!c) return {}\n return getPageContent(c, page)\n }\n\n /**\n * Fetch runtime content from DCS API (premium tier only).\n *\n * @param siteSlug - The site's slug identifier.\n * @deprecated The site is now resolved server-side from the request Host or\n * the dedicated Container App's `DCS_SITE_SLUG`. This argument is retained\n * for source compatibility but is ignored for routing (no longer placed in\n * the URL path).\n * @param apiBaseUrl - Optional API base URL override\n */\n async fetchRuntimeContent(siteSlug: string, apiBaseUrl?: string): Promise<void> {\n this.isLoading.set(true)\n this.error.set(null)\n\n try {\n const data = await fetchRuntimeContent(siteSlug, { apiBaseUrl })\n if (data) {\n this.runtimeContent.set(data)\n }\n } catch (err) {\n this.error.set(err instanceof Error ? err.message : 'Failed to fetch content')\n } finally {\n this.isLoading.set(false)\n }\n }\n}\n","/**\n * DcsSeoService for Angular\n *\n * Applies SEO meta tags to the document head based on .dcs/seo.yaml configuration.\n */\n\nimport { Injectable, inject } from '@angular/core'\nimport { Meta, Title } from '@angular/platform-browser'\nimport {\n resolveSeoForPage,\n buildMetaTags,\n type SeoConfiguration,\n type ResolvedSeo,\n} from '@duffcloudservices/cms-core/browser'\n\n// Declare the global injected by build script\ndeclare const __DCS_SEO__: SeoConfiguration | undefined\n\n/**\n * Angular service for DCS SEO management.\n */\n@Injectable({ providedIn: 'root' })\nexport class DcsSeoService {\n private readonly meta = inject(Meta)\n private readonly title = inject(Title)\n\n /** Build-time SEO config (injected via index.html script) */\n private readonly seoConfig = this.getBuildTimeSeo()\n\n /**\n * Safely get build-time SEO configuration.\n */\n private 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 * Apply SEO for a specific page.\n *\n * @param page - Page slug matching entry in seo.yaml\n * @param overrides - Optional overrides for title, description, or image\n * @returns The resolved SEO configuration\n */\n setPageSeo(\n page: string,\n overrides?: { title?: string; description?: string; image?: string }\n ): ResolvedSeo | null {\n if (!this.seoConfig) return null\n\n const seo = resolveSeoForPage(this.seoConfig, page)\n const resolved: ResolvedSeo = {\n ...seo,\n ...(overrides?.title && { title: overrides.title }),\n ...(overrides?.description && { description: overrides.description }),\n ...(overrides?.image && { image: overrides.image }),\n }\n\n // Set document title\n this.title.setTitle(resolved.title)\n\n // Build and apply meta tags\n const tags = buildMetaTags(resolved)\n for (const tag of tags) {\n if (tag.property) {\n this.meta.updateTag({ property: tag.property, content: tag.content })\n } else if (tag.name) {\n this.meta.updateTag({ name: tag.name, content: tag.content })\n }\n }\n\n // Handle canonical link\n if (resolved.canonical) {\n this.updateCanonicalLink(resolved.canonical)\n }\n\n return resolved\n }\n\n /**\n * Update or create canonical link element.\n */\n private updateCanonicalLink(href: string): void {\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', href)\n }\n\n /**\n * Get the raw SEO configuration.\n */\n getSeoConfig(): SeoConfiguration | undefined {\n return this.seoConfig\n }\n}\n","/**\n * Angular providers for DCS CMS integration.\n */\n\nimport { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core'\nimport { DcsContentService } from './services/content.service'\nimport { DcsSeoService } from './services/seo.service'\n\n/**\n * Provide DCS CMS services for Angular application.\n *\n * @example\n * ```typescript\n * // app.config.ts\n * import { ApplicationConfig } from '@angular/core'\n * import { provideDcs } from '@duffcloudservices/cms-angular'\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideDcs(),\n * ],\n * }\n * ```\n */\nexport function provideDcs(): EnvironmentProviders {\n return makeEnvironmentProviders([DcsContentService, DcsSeoService])\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duffcloudservices/cms-angular",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Angular services and build scripts for DCS CMS integration",
5
5
  "type": "module",
6
6
  "exports": {
@@ -27,7 +27,7 @@
27
27
  "@angular/platform-browser": "^17.0.0 || ^18.0.0 || ^19.0.0"
28
28
  },
29
29
  "dependencies": {
30
- "@duffcloudservices/cms-core": "0.4.4"
30
+ "@duffcloudservices/cms-core": "0.5.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@angular/common": "^19.0.0",