@@ -603,6 +603,103 @@ export const LOG_LEVEL_STRINGS = ['| DEBUG |', '| INFO |', '🥺 WARN 🥺', '
603603 * Emitted as separate log lines (before + msg + after) so the dots appear. */
604604const LOG_BUFFER_BUSTER_PADDING = ` $ { '. '.repeat(10000)}/`
605605
606+ /** Resolved settings for log-level checks (from sync object or after await DataStore.settings). */
607+ let cachedPluginSettingsForLog : any = null
608+ /** True once background await has been scheduled (avoid duplicate work). */
609+ let pluginSettingsAwaitPrimeStartedForLog : boolean = false
610+
611+ /** Trace settings resolution via console.log. Enable with env NP_INSTRUMENT_PLUGIN_SETTINGS=1 (Node/Jest only). */
612+ const ENABLE_GET_PLUGIN_SETTINGS_INSTRUMENTATION : boolean =
613+ typeof process !== 'undefined' && process . env && process . env . NP_INSTRUMENT_PLUGIN_SETTINGS === '1'
614+ let getPluginSettingsInstrumentationResolutionLogged : boolean = false
615+
616+ /**
617+ * Emit diagnostics for plugin settings loading. Uses console.log so CLO/logDebug gating does not hide it.
618+ * @param {string } phase
619+ * @param {any } detail
620+ * @returns {void }
621+ */
622+ function logGetPluginSettingsInstrumentation ( phase : string , detail ?: any ) : void {
623+ if ( ! ENABLE_GET_PLUGIN_SETTINGS_INSTRUMENTATION ) {
624+ return
625+ }
626+ try {
627+ if ( typeof console !== 'undefined' && typeof console . log === 'function' ) {
628+ console . log ( `[getPluginSettingsForLogging] ${ phase } ` , detail !== undefined ? detail : '' )
629+ }
630+ } catch ( _e ) {
631+ // ignore
632+ }
633+ }
634+
635+ /**
636+ * Fire-and-forget: `await DataStore.settings` and cache. Callers use sync getPluginSettingsForLogging / shouldOutputForLogLevel.
637+ * @returns {void }
638+ */
639+ function primePluginSettingsCacheViaAwait ( ) : void {
640+ if ( pluginSettingsAwaitPrimeStartedForLog ) {
641+ return
642+ }
643+ pluginSettingsAwaitPrimeStartedForLog = true
644+ void ( async ( ) : Promise < void > => {
645+ try {
646+ if ( typeof DataStore === 'undefined' ) {
647+ return
648+ }
649+ // $FlowIgnore[not-a-promise] NP WebView exposes settings as awaitable; may be object or Thenable.
650+ const resolved = await DataStore . settings
651+ if ( resolved != null && typeof resolved === 'object' ) {
652+ cachedPluginSettingsForLog = resolved
653+ }
654+ if ( ENABLE_GET_PLUGIN_SETTINGS_INSTRUMENTATION && ! getPluginSettingsInstrumentationResolutionLogged ) {
655+ getPluginSettingsInstrumentationResolutionLogged = true
656+ logGetPluginSettingsInstrumentation ( 'await DataStore.settings resolved' , {
657+ typeofResolved : typeof resolved ,
658+ hasLogLevel : resolved != null && typeof resolved === 'object' && '_logLevel' in resolved ,
659+ _logLevel : resolved != null && typeof resolved === 'object' ? resolved . _logLevel : '(n/a)' ,
660+ } )
661+ }
662+ } catch ( err ) {
663+ pluginSettingsAwaitPrimeStartedForLog = false
664+ logGetPluginSettingsInstrumentation ( 'await DataStore.settings threw/rejected' , err )
665+ }
666+ } ) ( )
667+ }
668+
669+ /**
670+ * Return plugin settings for log-level checks.
671+ * - If `DataStore.settings` is already a plain object (not a thenable), use it synchronously.
672+ * - Otherwise schedule one background await and return null until cache fills (same default log level as “no settings”).
673+ *
674+ * @returns {?Object }
675+ */
676+ function getPluginSettingsForLogging ( ) : any {
677+ if ( typeof DataStore === 'undefined' ) {
678+ logGetPluginSettingsInstrumentation ( 'DataStore undefined' , { returning : null } )
679+ return null
680+ }
681+
682+ if ( cachedPluginSettingsForLog != null ) {
683+ return cachedPluginSettingsForLog
684+ }
685+
686+ const raw = DataStore . settings
687+ if ( raw == null ) {
688+ logGetPluginSettingsInstrumentation ( 'DataStore.settings is null/undefined' , { raw, returning : null } )
689+ return null
690+ }
691+
692+ // Plugin / legacy: plain settings object (not Promise / thenable). Exclude null (typeof null === 'object').
693+ if ( typeof raw === 'object' && raw !== null && typeof raw . then !== 'function' ) {
694+ cachedPluginSettingsForLog = raw
695+ return raw
696+ }
697+
698+ // WebView / async: await DataStore.settings once in the background.
699+ primePluginSettingsCacheViaAwait ( )
700+ return null
701+ }
702+
606703/**
607704 * Test _logLevel against logType to decide whether to output
608705 * @param {string } logType
@@ -611,7 +708,7 @@ const LOG_BUFFER_BUSTER_PADDING = `${'.'.repeat(10000)}/`
611708export const shouldOutputForLogLevel = ( logType : string ) : boolean => {
612709 let userLogLevel = 1
613710 const thisMessageLevel = LOG_LEVELS . indexOf ( logType . toUpperCase ( ) )
614- const pluginSettings = typeof DataStore !== 'undefined' ? DataStore . settings : null
711+ const pluginSettings = getPluginSettingsForLogging ( )
615712 // Note: Performing a null change against a value that is `undefined` will be true
616713 // Sure wish NotePlan would not return `undefined` but instead null, then the previous implementataion would not have failed
617714
@@ -643,7 +740,7 @@ export const shouldOutputForLogLevel = (logType: string): boolean => {
643740 * @returns
644741 */
645742export const shouldOutputForFunctionName = ( pluginInfo : any ) : boolean => {
646- const pluginSettings = typeof DataStore !== 'undefined' ? DataStore . settings : null
743+ const pluginSettings = getPluginSettingsForLogging ( )
647744 if ( pluginSettings && pluginSettings . hasOwnProperty ( '_logFunctionRE' ) ) {
648745 const logFunctionRE = pluginSettings [ '_logFunctionRE' ]
649746 if ( logFunctionRE ) {
@@ -799,7 +896,7 @@ export function logTimer(functionName: string, startTime: Date, explanation: str
799896 // console.log(msg)
800897 log ( functionName , msg , 'DEBUG' )
801898 } else {
802- const pluginSettings = typeof DataStore !== 'undefined' ? DataStore . settings : null
899+ const pluginSettings = getPluginSettingsForLogging ( )
803900 // const timerSetting = pluginSettings['_logTimer'] ?? false
804901 if ( pluginSettings && pluginSettings . hasOwnProperty ( '_logTimer' ) && pluginSettings [ '_logTimer' ] === true ) {
805902 // const msg = `${dt().padEnd(19)} | ⏱️ ${functionName} | ${output}`
0 commit comments