Files
MikrotikManager/backend/scripts/writer-profile/catalogue.mts
T

31 lines
2.8 KiB
TypeScript

import assert from 'node:assert/strict'
import {Fixed44CatalogueValueBridgeData} from './catalogue-value-bridge.js'
import {FIXED44_CATALOGUE_BUILD_SQL} from './fixed44-build-sql.js'
import {BUILD44_PROVENANCE,FIXED44_ROLE_TEMPLATE} from './fixed44-build-definition.js'
import {canonical,sha} from './application-writer-profile-canonical.js'
export function approvedDefinition(value:unknown){
assert(value&&typeof value==='object');const v=value as Record<string,unknown>
assert.deepEqual(Object.keys(v).sort(),['format','provenance','template']);assert.equal(v.format,'application-writer-source44-definition-approval-v1')
assert.equal(canonical(v.provenance),canonical(BUILD44_PROVENANCE));assert.equal(canonical(v.template),canonical(FIXED44_ROLE_TEMPLATE))
return BUILD44_PROVENANCE.templateSha256
}
/** Real incremental DATA verifier on caller's retained transaction. No pool or attestor. */
export async function collectSource44Catalogue(s:{query:(sql:string,values?:unknown[])=>Promise<{rows:Record<string,unknown>[]} >},installation:{roleBindings:ConstructorParameters<typeof Fixed44CatalogueValueBridgeData>[0]}){
const settings=(await s.query("SELECT pg_catalog.current_setting('search_path') AS path,pg_catalog.current_setting('TimeZone') AS zone,pg_catalog.current_setting('DateStyle') AS dates")).rows
assert.equal(settings.length,1);assert(['path','zone','dates'].every(k=>typeof settings[0][k]==='string'))
let cursor=false,primary:unknown,failed=false
try{
await s.query("SELECT pg_catalog.set_config('search_path','pg_catalog, public',true),pg_catalog.set_config('TimeZone','UTC',true),pg_catalog.set_config('DateStyle','ISO, YMD',true)")
const bindings=installation.roleBindings,values=['operator','runtime','capture','publisher','control'].map(k=>bindings[k as keyof typeof bindings].name)
const bridge=new Fixed44CatalogueValueBridgeData(bindings)
await s.query('DECLARE mm_publisher44 NO SCROLL CURSOR WITHOUT HOLD FOR '+FIXED44_CATALOGUE_BUILD_SQL,values);cursor=true
for(;;){const page=(await s.query('FETCH FORWARD 128 FROM mm_publisher44')).rows;bridge.acceptPage(page);if(page.length===0)break}
const result=bridge.finish();await s.query('CLOSE mm_publisher44');cursor=false
return {catalogSha256:sha(canonical({values:result.values.snapshotSha256,catalogue:result.catalogue})),definitionSha256:result.catalogue.definitionSha256,leafCount:result.catalogue.leafRelations}
}catch(error){primary=error;failed=true;throw error}
finally{
try{if(cursor)await s.query('CLOSE mm_publisher44');await s.query("SELECT pg_catalog.set_config('search_path',$1,true),pg_catalog.set_config('TimeZone',$2,true),pg_catalog.set_config('DateStyle',$3,true)",[settings[0].path,settings[0].zone,settings[0].dates])}
catch(error){if(failed)throw new AggregateError([primary,error],'Catalogue and context cleanup failed');throw error}
}
}