78 lines
2.8 KiB
TypeScript
78 lines
2.8 KiB
TypeScript
import { writeFile, mkdir } from 'node:fs/promises'
|
|
import { join } from 'node:path'
|
|
import { log, logError, httpGet } from '../lib/http'
|
|
import { DATA_DIR } from '../lib/data-loader'
|
|
|
|
const ATTRS_BASE = process.env.ATTRS_URL ?? 'http://localhost:3015'
|
|
|
|
export async function pullAttrs(): Promise<void> {
|
|
log('\n═══ Attribute Sync: Pull (DB → Filesystem) ═══')
|
|
|
|
try {
|
|
const definitions = await httpGet<Array<{
|
|
code: string
|
|
name: string
|
|
entityType: string
|
|
dataType: string
|
|
isSearchable: boolean
|
|
isMultiple?: boolean
|
|
grouping: string
|
|
displayOrder: number
|
|
description?: string
|
|
enumValues?: Array<{ value: string; displayValue: string }>
|
|
minValue?: number
|
|
maxValue?: number
|
|
}>>(`${ATTRS_BASE}/attribute-definitions?entityType=user`)
|
|
|
|
if (!Array.isArray(definitions) || definitions.length === 0) {
|
|
log(' No definitions found in database')
|
|
return
|
|
}
|
|
|
|
// Group by grouping field
|
|
const groups = new Map<string, typeof definitions>()
|
|
for (const def of definitions) {
|
|
const group = def.grouping ?? 'ungrouped'
|
|
if (!groups.has(group)) groups.set(group, [])
|
|
groups.get(group)!.push(def)
|
|
}
|
|
|
|
const defsDir = join(DATA_DIR, 'attributes', 'definitions')
|
|
await mkdir(defsDir, { recursive: true })
|
|
|
|
for (const [group, defs] of groups) {
|
|
const filename = `${group.replace(/[^a-z0-9_-]/gi, '_').toLowerCase()}.json`
|
|
const path = join(defsDir, filename)
|
|
const cleaned = defs.map(d => ({
|
|
code: d.code,
|
|
name: d.name,
|
|
entityType: d.entityType,
|
|
dataType: d.dataType,
|
|
isSearchable: d.isSearchable,
|
|
...(d.isMultiple ? { isMultiple: true } : {}),
|
|
grouping: d.grouping,
|
|
displayOrder: d.displayOrder,
|
|
...(d.description ? { description: d.description } : {}),
|
|
...(d.enumValues?.length ? { enumValues: d.enumValues } : {}),
|
|
...(d.minValue != null ? { minValue: d.minValue } : {}),
|
|
...(d.maxValue != null ? { maxValue: d.maxValue } : {}),
|
|
}))
|
|
await writeFile(path, JSON.stringify(cleaned, null, 2) + '\n')
|
|
log(` → ${filename}: ${defs.length} definitions`)
|
|
}
|
|
|
|
// Update sync manifest
|
|
const manifestPath = join(DATA_DIR, 'attributes', 'sync-manifest.json')
|
|
const manifest = {
|
|
lastSync: new Date().toISOString(),
|
|
direction: 'pull',
|
|
definitionCount: definitions.length,
|
|
groups: Object.fromEntries([...groups.entries()].map(([k, v]) => [k, v.length])),
|
|
}
|
|
await writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n')
|
|
log(` Summary: ${definitions.length} definitions pulled across ${groups.size} groups`)
|
|
} catch (err) {
|
|
logError(` Pull failed: ${(err as Error).message}`)
|
|
throw err
|
|
}
|
|
}
|