import { autoService, singleton, location } from 'knifecycle'; import { noop } from '../utils/utils.js'; import { type LogService } from './log.js'; export type CounterService = () => Promise; export interface CounterServiceConfig { COUNTER?: { firstCount: number }; } export type CounterServiceDependencies = CounterServiceConfig & { log?: LogService; }; const DEFAULT_COUNTER = { firstCount: 1, }; /** * Instantiate the counter service * @name initCounter * @function * @param {Object} services * The services to inject * @param {Object} [services.COUNTER=DEFAULT_COUNTER] * An optional configuration object * @param {Object} [services.log=noop] * An optional logging function * @return {Promise} * A promise of the counter function * @example * import { * initCounter, * initLog, * } from 'common-services'; * * const log = await initLog({ * logger: DEFAULT_LOGGER * }); * * const counter = await initCounter({ * COUNTER: { firstCount: 1 }, * log, * }); */ async function initCounter({ COUNTER = DEFAULT_COUNTER, log = noop, }: CounterServiceDependencies): Promise { let currentCount = COUNTER.firstCount; log('debug', '📇 - Counter service initialized.'); return counter; /** * Returns the current count and increment the counter * @return {Promise} * A promise of the current count * @example * console.log([ * counter(), * counter(), * counter(), * ]); * // Prints: 1,2,3 */ async function counter() { log('debug', '📇 - Picked a count:', currentCount); return currentCount++; } } /* Architecture Note #1.9: Counter The `counter` service provide a simple, local and mockable counter. The count are returned asynchronously in order to be easily maintained across several instances if needed later via another service with the same surface API. */ export default location( singleton(autoService(initCounter), true), import.meta.url, );