doxa-maps/internal/check-snippet-engine.mjs
Doxa Maps cafee0d432 The default embed snippet preloads MapLibre, the engine it draws with; Mapbox gets its own snippet
Every map profile's copy-paste snippet began with a preload of
api.mapbox.com's mapbox-gl.js, while its own profile-config said provider
"maplibre", and since 2026-09-28 only an explicit provider "mapbox" selects
Mapbox. So an unedited paste downloaded the Mapbox engine on every view,
never used it, and made a Mapbox request from a keyless page. Its only
guard was a stale comment asking the partner to delete the line.

- embed.script now preloads MapLibre's script and stylesheet, pinned the
  way useMapInstance loads them so the preloads are reused, and its note
  points a host who wants Mapbox at the variant.
- embed.scriptMapbox is that variant: the Mapbox preloads and the same
  element with "provider":"mapbox".
- check:snippet-engine (gates:post, with a self-test) reads the built
  manifest: no default snippet names api.mapbox.com, every map snippet
  preloads MapLibre, and every Mapbox variant preloads Mapbox and sets its
  provider. Planted: the old snippet and a provider-less variant both fail.
2026-09-29 09:18:39 +00:00

77 lines
4.3 KiB
JavaScript

#!/usr/bin/env node
/**
* check-snippet-engine.mjs — the copy-paste snippet preloads the engine it will actually use.
*
* THE DEFECT (FIX-DEFAULT-EMBED-SNIPPET-PRELOADS-THE-MAPBOX-ENGINE). Every map profile's default snippet
* began with a preload of api.mapbox.com's mapbox-gl.js, while the same snippet's profile-config said
* provider "maplibre" — and since 2026-09-28 only an explicit provider "mapbox" selects Mapbox. So an
* unedited paste downloaded the Mapbox engine on every view, never used it, and made a Mapbox request
* from a keyless page. Its only guard was a comment asking the partner to delete the line.
*
* Reads the BUILT manifest (public/<tree>/manifest.json) and asserts, for every profile:
* a map profile embed.script names no api.mapbox.com URL and preloads MapLibre (its script pin);
* embed.scriptMapbox preloads the Mapbox engine AND sets "provider":"mapbox"
* any other profile embed.script names no api.mapbox.com URL, and there is no scriptMapbox
* `--self-test` plants the old snippet and a variant that forgot its provider; both must fail.
* Exit 0 pass · 1 fail · 2 no manifest.
*/
import { readFileSync, existsSync } from 'node:fs'
import { resolve, dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { TREE_NAME } from './_tree-name.mjs'
import { CDN } from '../library/constants/cdn.js'
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
const MANIFEST = join(ROOT, 'public', TREE_NAME, 'manifest.json')
const MAPBOX_HOST = 'api.mapbox.com'
export function checkSnippets(manifest) {
const errs = []
let maps = 0
for (const b of manifest.bundles || []) {
for (const p of b.profiles || []) {
const id = `${b.bundle}/${p.profile}`
const script = String(p.embed?.script || '')
if (script.includes(MAPBOX_HOST)) errs.push(`${id}: the default snippet names ${MAPBOX_HOST} — an unedited paste would fetch an engine it never uses`)
if (p.isMap) {
maps++
if (!script.includes(CDN.maplibreGlJs.url)) errs.push(`${id}: the default snippet does not preload MapLibre, the engine it draws with`)
const mb = String(p.embed?.scriptMapbox || '')
if (!mb) errs.push(`${id}: no embed.scriptMapbox, so a host that chooses Mapbox has no snippet for it`)
else {
if (!mb.includes(CDN.mapboxGlJs.url)) errs.push(`${id}: scriptMapbox does not preload the Mapbox engine`)
if (!mb.includes('"provider":"mapbox"')) errs.push(`${id}: scriptMapbox does not set "provider":"mapbox", so it would still draw with MapLibre`)
}
} else if (p.embed?.scriptMapbox) errs.push(`${id}: a non-map profile carries a Mapbox snippet`)
}
}
return { errs, maps }
}
if (!existsSync(MANIFEST)) { console.error(`SNIPPET-ENGINE: no ${TREE_NAME}/manifest.json — build the tree first`); process.exit(2) }
const manifest = JSON.parse(readFileSync(MANIFEST, 'utf8'))
if (process.argv.includes('--self-test')) {
const clone = () => JSON.parse(JSON.stringify(manifest))
const firstMap = (m) => m.bundles.flatMap((b) => b.profiles).find((p) => p.isMap)
const oldShape = clone(); { const p = firstMap(oldShape); p.embed.script = `<link rel="preload" as="script" href="${CDN.mapboxGlJs.url}">\n` + p.embed.script.replace(/<link rel="preload"[^\n]*\n/g, '') }
const noProvider = clone(); { const p = firstMap(noProvider); p.embed.scriptMapbox = p.embed.scriptMapbox.replace('"provider":"mapbox"', '"provider":"maplibre"') }
const cases = [['the built tree passes', manifest, 0], ['the old Mapbox-preloading default fails', oldShape, 1], ['a Mapbox variant without its provider fails', noProvider, 1]]
let ok = true
for (const [name, m, want] of cases) {
const n = checkSnippets(m).errs.length
const pass = want === 0 ? n === 0 : n >= want
if (!pass) ok = false
console.log(` ${pass ? '✓' : '✗'} ${name} -> ${n} error(s)`)
}
console.log(ok ? 'SNIPPET-ENGINE SELF-TEST: PASS' : 'SNIPPET-ENGINE SELF-TEST: FAIL')
process.exit(ok ? 0 : 1)
}
const { errs, maps } = checkSnippets(manifest)
if (errs.length) {
console.error(`SNIPPET-ENGINE: FAIL — ${errs.length} problem(s)`)
for (const e of errs.slice(0, 20)) console.error(' ✗ ' + e)
process.exit(1)
}
console.log(`SNIPPET-ENGINE: PASS — ${maps} map snippet(s) preload MapLibre and name no ${MAPBOX_HOST}; each has a Mapbox variant that sets its provider`)