@@ -6,6 +6,25 @@ import { Plugin, PluginContext } from '@objectstack/core';
66
77export type { Plugin , PluginContext } ;
88
9+ /**
10+ * Protocol extension for DB-based metadata hydration.
11+ * `loadMetaFromDb` is implemented by ObjectStackProtocolImplementation but
12+ * is NOT (yet) part of the canonical ObjectStackProtocol wire-contract in
13+ * `@objectstack/spec`, since it is a server-side bootstrap concern only.
14+ */
15+ interface ProtocolWithDbRestore {
16+ loadMetaFromDb ( ) : Promise < { loaded : number ; errors : number } > ;
17+ }
18+
19+ /** Type guard — checks whether the service exposes `loadMetaFromDb`. */
20+ function hasLoadMetaFromDb ( service : unknown ) : service is ProtocolWithDbRestore {
21+ return (
22+ typeof service === 'object' &&
23+ service !== null &&
24+ typeof ( service as Record < string , unknown > ) [ 'loadMetaFromDb' ] === 'function'
25+ ) ;
26+ }
27+
928export class ObjectQLPlugin implements Plugin {
1029 name = 'com.objectstack.engine.objectql' ;
1130 type = 'objectql' ;
@@ -352,13 +371,24 @@ export class ObjectQLPlugin implements Plugin {
352371 * - The underlying driver/table does not exist yet (first-run scenario).
353372 */
354373 private async restoreMetadataFromDb ( ctx : PluginContext ) : Promise < void > {
374+ // Phase 1: Resolve protocol service (separate from DB I/O for clearer diagnostics)
375+ let protocol : ProtocolWithDbRestore ;
355376 try {
356- const protocol = ctx . getService ( 'protocol' ) as any ;
357- if ( ! protocol || typeof protocol . loadMetaFromDb !== 'function' ) {
377+ const service = ctx . getService ( 'protocol' ) ;
378+ if ( ! service || ! hasLoadMetaFromDb ( service ) ) {
358379 ctx . logger . debug ( 'Protocol service does not support loadMetaFromDb, skipping DB restore' ) ;
359380 return ;
360381 }
382+ protocol = service ;
383+ } catch ( e : unknown ) {
384+ ctx . logger . debug ( 'Protocol service unavailable, skipping DB restore' , {
385+ error : e instanceof Error ? e . message : String ( e ) ,
386+ } ) ;
387+ return ;
388+ }
361389
390+ // Phase 2: DB hydration
391+ try {
362392 const { loaded, errors } = await protocol . loadMetaFromDb ( ) ;
363393
364394 if ( loaded > 0 || errors > 0 ) {
@@ -368,7 +398,7 @@ export class ObjectQLPlugin implements Plugin {
368398 }
369399 } catch ( e : unknown ) {
370400 // Non-fatal: first-run or in-memory driver may not have sys_metadata yet
371- ctx . logger . debug ( 'DB metadata restore skipped (non-fatal)' , {
401+ ctx . logger . debug ( 'DB metadata restore failed (non-fatal)' , {
372402 error : e instanceof Error ? e . message : String ( e ) ,
373403 } ) ;
374404 }
0 commit comments