Files
justvitamin/scripts/assign-image-filenames.ts
Omair Saleh 056c47581f feat: editorial review dashboard + elite-grade pilot batch (5 SKUs)
Ships the second dashboard surface — a Pattern Library + Preview Theatre — that
presents the 4-section PDP pilot batch back to Umar, compliance, and the board
in an editorial format. Adds the full data layer that drives it: 5 source-backed
per-SKU drafts at QA 100/100, 15 competitor PDP semantic extracts, PubMed
evidence packs, EFSA claims library extension, JV brand voice guide, hand-curated
product FAQs, and the Matrixify-ready CSV exports for Lewis.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 18:50:09 +08:00

57 lines
2.7 KiB
TypeScript

#!/usr/bin/env bun
import { readdirSync } from 'fs'
import { join } from 'path'
import { ROOT, readJson, writeJson } from './lib/intel-utils'
const contentRoot = join(ROOT, 'data', 'content')
const productsRoot = join(contentRoot, 'products')
const workflowRoot = join(contentRoot, 'workflow')
const outRoot = join(ROOT, 'content_population_exports')
const fields = [
['pdpResults', 'results'],
['pdpResultsMobile', 'results-mobile'],
['pdpHowWeCompare', 'how-we-compare']
]
function filename(sku: string, suffix: string) { return `${sku.toLowerCase()}-${suffix}.png` }
const rows: any[] = []
const files = readdirSync(productsRoot).filter(file => file.endsWith('.json'))
let assigned = 0
for (const file of files) {
const path = join(productsRoot, file)
const product = readJson(path, null)
if (!product) continue
product.metafields = product.metafields || {}
for (const [field, suffix] of fields) {
const before = product.metafields[field] || ''
const after = before || filename(product.sku, suffix)
product.metafields[field] = after
if (!before) assigned += 1
rows.push({ sku: product.sku, field, filename: after, status: before ? 'preserved_existing' : 'assigned_pending_asset_upload' })
}
product.approval = { ...(product.approval || {}), images: product.approval?.images || 'needed' }
product.updatedAt = new Date().toISOString()
writeJson(path, product)
const workflowPath = join(workflowRoot, `${product.sku}.json`)
const workflow = readJson(workflowPath, null)
if (workflow?.fields) {
for (const [field] of fields) {
if (workflow.fields[field] && workflow.fields[field].status === 'blocked_asset') {
workflow.fields[field].status = 'pending_asset_upload'
}
}
workflow.events = Array.isArray(workflow.events) ? workflow.events : []
if (assigned) {
workflow.events.unshift({ at: new Date().toISOString(), type: 'asset_filenames_assigned', actor: 'script', summary: 'Deterministic PDP image filenames assigned; upload/production still required.' })
}
workflow.updatedAt = new Date().toISOString()
writeJson(workflowPath, workflow)
}
}
const headers = ['sku', 'field', 'filename', 'status']
const esc = (value: any) => /[",\n\r]/.test(String(value ?? '')) ? `"${String(value ?? '').replace(/"/g, '""')}"` : String(value ?? '')
await Bun.write(join(outRoot, 'planned_image_filenames.csv'), [headers.join(','), ...rows.map(row => headers.map(h => esc(row[h])).join(','))].join('\n') + '\n')
writeJson(join(outRoot, 'planned_image_filenames.json'), { generatedAt: new Date().toISOString(), assigned, totalRows: rows.length, rows })
console.log(`Planned image filename rows: ${rows.length}`)
console.log(`New filenames assigned: ${assigned}`)