All files / src/utils lazySettings.ts

100% Statements 8/8
100% Branches 2/2
100% Functions 2/2
100% Lines 7/7

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 5128x                                                                             28x 417x   417x 261x 107x     260x      
import { resolve } from '@bayudwiyansatria/core'
 
/**
 * Defers a module's settings lookup until something actually reads them.
 *
 * @remarks
 * Solves an ordering problem ES modules make unavoidable for a consumer:
 *
 * ```ts
 * import { configure, systemDefaults } from '@bayudwiyansatria/core'
 * import { cloudflareDefaults, KVService } from '@bayudwiyansatria/cloudflare'
 *
 * configure({ ...systemDefaults, ...cloudflareDefaults })
 * ```
 *
 * Imports are hoisted, so every module in this package has already initialised
 * by the time `configure()` runs. Accessors are created at module scope on
 * purpose, since one instance is reused across requests — and if that resolved
 * settings eagerly, the import alone would throw `ConfigurationError`, with no
 * ordering a consumer could write to avoid it.
 *
 * First use is inside a request handler, long after startup, so deferring to
 * then works. Memoised, so it is still one lookup per accessor.
 *
 * Passing `override` skips the lookup, which is how a test constructs an
 * accessor with no configuration registered.
 *
 * @typeParam S The settings shape for this module.
 *
 * @param module Name of the module to resolve when first read.
 * @param override Settings supplied by the caller, bypassing resolution.
 * @returns A memoised getter for the settings.
 *
 * @function
 *
 * @author Bayu Dwiyan Satria
 * @version 1.0.0
 * @since 1.0.0
 */
export const lazySettings = <S>(module: string, override?: S): (() => S) => {
  let settled: S | undefined = override
 
  return () => {
    if (settled === undefined) {
      settled = resolve<S>(module)
    }
 
    return settled
  }
}