@duffcloudservices/cms 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duffcloudservices/cms",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "Vue 3 composables and Vite plugins for DCS CMS integration",
5
5
  "type": "module",
6
6
  "exports": {
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "js-yaml": "^4.1.0",
61
- "@duffcloudservices/cms-core": "0.8.0"
61
+ "@duffcloudservices/cms-core": "0.8.1"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@types/js-yaml": "^4.0.9",
@@ -84,9 +84,18 @@
84
84
  </template>
85
85
 
86
86
  <script setup lang="ts">
87
- import { platformFetch } from '@duffcloudservices/cms-core'
88
87
  import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue'
89
88
 
89
+ /*
90
+ * NO cms-core VALUE imports in this file. The `./components` export ships RAW SFC
91
+ * source (tsup builds no .vue), so consumer sites type-check this file directly —
92
+ * and cms-core is a transitive dep pnpm's strict layout never exposes to them.
93
+ * A value import here is TS2307 in every fleet site's type-check gate (measured on
94
+ * the 0.13.0 canary, 2026-08-10; kept/boogie-babies/bryans/mi-handyman all red).
95
+ * `import type` is erased and safe. The C-298 layer-2 guard this file needs from
96
+ * platformFetch is inlined below at its single call site instead.
97
+ */
98
+
90
99
  /* ------------------------------------------------------------------ */
91
100
  /* Props */
92
101
  /* ------------------------------------------------------------------ */
@@ -235,15 +244,22 @@ onMounted(async () => {
235
244
  const base =
236
245
  (import.meta.env as Record<string, string | undefined>)
237
246
  .VITE_API_BASE_URL ?? 'https://portal.duffcloudservices.com'
238
- // C-298 layer 2: the `catch { /* non-critical */ }` below is a swallow site; the
239
- // wrapper's console error is what makes an HTML body visible at all here.
240
- const res = await platformFetch(
241
- `${base}/api/v1/release-notes/latest`,
242
- { headers: { Accept: 'application/json' } },
243
- )
247
+ // C-298 layer 2, INLINED (see the no-cms-core-value-imports note at the top of
248
+ // this <script>): the `catch { /* non-critical */ }` below is a swallow site, so
249
+ // a non-JSON (HTML-shell) body must go LOUD here before it can be swallowed.
250
+ const url = `${base}/api/v1/release-notes/latest`
251
+ const res = await fetch(url, { headers: { Accept: 'application/json' } })
244
252
  if (res.ok) {
245
- const data = await res.json()
246
- if (data.version) resolvedVersion.value = data.version
253
+ const ct = res.headers?.get?.('content-type') ?? ''
254
+ if (!/\bjson\b/i.test(ct)) {
255
+ console.error(
256
+ `[dcs-cms] PreviewRibbon: ${url} returned content-type "${ct}" — ` +
257
+ 'an HTML body here means a platform misroute (C-298); refusing to parse it.',
258
+ )
259
+ } else {
260
+ const data = await res.json()
261
+ if (data.version) resolvedVersion.value = data.version
262
+ }
247
263
  }
248
264
  } catch {
249
265
  /* non-critical */
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { readFileSync, readdirSync } from 'node:fs'
3
+ import { join } from 'node:path'
4
+
5
+ /**
6
+ * The `./components` export ships RAW SFC source (tsup builds no .vue), so every
7
+ * consumer site type-checks these files directly — against a dependency tree where
8
+ * cms-core is TRANSITIVE and pnpm's strict layout never exposes it. A VALUE import
9
+ * of cms-core in any raw-shipped .vue is therefore TS2307 in every fleet site's
10
+ * type-check gate, invisible to this package's own checks (cms-core resolves fine
11
+ * HERE — that is exactly why only a consumer-shaped gate or this test can see it).
12
+ *
13
+ * Measured on the 0.13.0 canary (2026-08-10): one value import in PreviewRibbon.vue
14
+ * would have redded CI on kept (the payer), boogie-babies, bryans and mi-handyman.
15
+ * `import type` is erased at compile time and stays allowed.
16
+ */
17
+ describe('raw-source .vue exports must not value-import cms-core', () => {
18
+ const dir = __dirname
19
+ const vueFiles = readdirSync(dir).filter((f) => f.endsWith('.vue'))
20
+
21
+ it('finds the raw-shipped component set (non-vacuity)', () => {
22
+ expect(vueFiles.length).toBeGreaterThan(0)
23
+ expect(vueFiles).toContain('PreviewRibbon.vue')
24
+ })
25
+
26
+ for (const file of vueFiles) {
27
+ it(`${file} has no cms-core value import`, () => {
28
+ const src = readFileSync(join(dir, file), 'utf8')
29
+ const valueImports = Array.from(src.matchAll(/^\s*import\s+(?!type\b)[^;'"]*['"]@duffcloudservices\/cms-core['"]/gm))
30
+ expect(
31
+ valueImports.map((m) => m[0].trim()),
32
+ `${file} value-imports cms-core — this ships as raw source and breaks every consumer site's type-check (see header comment)`,
33
+ ).toEqual([])
34
+ })
35
+ }
36
+
37
+ it('kill-test: the guard regex catches the 0.13.0 defect shape', () => {
38
+ const bad = "import { platformFetch } from '@duffcloudservices/cms-core'"
39
+ const good = "import type { PlatformFetchOptions } from '@duffcloudservices/cms-core'"
40
+ const re = /^\s*import\s+(?!type\b)[^;'"]*['"]@duffcloudservices\/cms-core['"]/gm
41
+ expect(Array.from(bad.matchAll(re)).length).toBe(1)
42
+ expect(Array.from(good.matchAll(re)).length).toBe(0)
43
+ })
44
+ })