AppView in a box as a Vite plugin thing hatk.dev

fix: coerce booleans in SQLite params, run label rules on PDS writes, support label hot-reload

- SQLite adapter coerces boolean params to 0/1
- pdsCreateRecord and pdsPutRecord now run label rules after local indexing
- clearLabels() added for hot-reload support in server-init

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+26 -3
+2 -1
packages/hatk/src/database/adapters/sqlite.ts
··· 12 12 const expandedParams: unknown[] = [] 13 13 const translated = sql.replace(/\$(\d+)/g, (_match, numStr) => { 14 14 const idx = parseInt(numStr) - 1 // $1 → index 0 15 - expandedParams.push(params[idx]) 15 + const val = params[idx] 16 + expandedParams.push(typeof val === 'boolean' ? (val ? 1 : 0) : val) 16 17 return '?' 17 18 }) 18 19
+6
packages/hatk/src/labels.ts
··· 112 112 } 113 113 } 114 114 115 + /** Clear all registered label definitions and rules (for hot-reload). */ 116 + export function clearLabels(): void { 117 + labelDefs.length = 0 118 + rules.length = 0 119 + } 120 + 115 121 /** Register a single label module from a scanned server/ module. */ 116 122 export function registerLabelModule( 117 123 name: string,
+15
packages/hatk/src/pds-proxy.ts
··· 8 8 import { getLexiconArray } from './database/schema.ts' 9 9 import { insertRecord, deleteRecord as dbDeleteRecord } from './database/db.ts' 10 10 import { emit } from './logger.ts' 11 + import { runLabelRules } from './labels.ts' 11 12 12 13 export class ProxyError extends Error { 13 14 constructor( ··· 167 168 168 169 try { 169 170 await insertRecord(input.collection, String(pdsRes.body.uri), String(pdsRes.body.cid), viewer.did, input.record) 171 + await runLabelRules({ 172 + uri: String(pdsRes.body.uri), 173 + cid: String(pdsRes.body.cid), 174 + did: viewer.did, 175 + collection: input.collection, 176 + value: input.record, 177 + }) 170 178 } catch (err: unknown) { 171 179 emit('pds-proxy', 'local_index_error', { 172 180 op: 'createRecord', ··· 237 245 238 246 try { 239 247 await insertRecord(input.collection, String(pdsRes.body.uri), String(pdsRes.body.cid), viewer.did, input.record) 248 + await runLabelRules({ 249 + uri: String(pdsRes.body.uri), 250 + cid: String(pdsRes.body.cid), 251 + did: viewer.did, 252 + collection: input.collection, 253 + value: input.record, 254 + }) 240 255 } catch (err: unknown) { 241 256 emit('pds-proxy', 'local_index_error', { op: 'putRecord', error: err instanceof Error ? err.message : String(err) }) 242 257 }
+3 -2
packages/hatk/src/server-init.ts
··· 3 3 import { scanServerDir } from './scanner.ts' 4 4 import { registerFeed, listFeeds } from './feeds.ts' 5 5 import { registerXrpcHandler, listXrpc } from './xrpc.ts' 6 - import { registerLabelModule, getLabelDefinitions } from './labels.ts' 6 + import { registerLabelModule, getLabelDefinitions, clearLabels } from './labels.ts' 7 7 import { registerOgHandler } from './opengraph.ts' 8 8 import { registerHook } from './hooks.ts' 9 9 import { runSetupHandler } from './setup.ts' ··· 47 47 registerHook(entry.mod.event, entry.mod.handler) 48 48 } 49 49 50 - // 5. Register labels 50 + // 5. Register labels (clear first for hot-reload) 51 + clearLabels() 51 52 for (const entry of scanned.labels) { 52 53 registerLabelModule(entry.name, entry.mod) 53 54 }