Skip to content

Commit 02bf691

Browse files
committed
Fix for async DataStore.settings._logLevel in JSX
1 parent f0654d4 commit 02bf691

1 file changed

Lines changed: 100 additions & 3 deletions

File tree

‎helpers/dev.js‎

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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. */
604604
const 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)}/`
611708
export 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
*/
645742
export 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

Comments
 (0)