Problem: Compose Decorators Dynamically Based on Configuration
Problem statement
Your platform operates in multiple environments: development, staging, and production. Each environment needs a different level of instrumentation for a critical async service:
development: Log inputs and outputsstaging: Log + time executionproduction: Timing only
You’ll first build the two decorators—withLogging and withTiming—and then write a function that composes them dynamically based on a configuration object—without hardcoding or repeating decorator logic.
This pattern is common in large Node.js systems, where instrumentation and monitoring are applied selectively.
Goal
Implement two reusable decorators:
withLogging(fn): logs arguments and return values.withTiming(fn): measures execution time.
Implement a
decorate(fn, config)function that:Receives a function and a configuration object, e.g.,
{ logging: true, timing: true }.Dynamically composes the relevant decorators.
Returns a new decorated function that behaves according to config.
Constraints
Do not modify the base service function.
The decorator composition must happen inside
decorate().The order of application must be:
withTiming(withLogging(fn))when both are enabled.You must not use
ifstatements inside the decorators themselves.
Sample output
The examples below illustrate what the output should look like:
const env = 'staging'; // Try with different values: 'development', 'staging', 'production'const config = {development: { logging: true },staging: { logging: true, timing: true },production: { timing: true }}[env];const decoratedProcessOrder = decorate(processOrder, config);(async () => {await decoratedProcessOrder(123);})();/* Expected output:with env = 'development':[LOG] Called with args: [123][LOG] Returned: { id: 123, status: 'processed' }with env = 'staging':[LOG] Called with args: [123][LOG] Returned: { id: 123, status: 'processed' }[TIMER] processOrder took 82mswith env = 'production':[TIMER] processOrder took 81ms */
Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.
Problem: Compose Decorators Dynamically Based on Configuration
Problem statement
Your platform operates in multiple environments: development, staging, and production. Each environment needs a different level of instrumentation for a critical async service:
development: Log inputs and outputsstaging: Log + time executionproduction: Timing only
You’ll first build the two decorators—withLogging and withTiming—and then write a function that composes them dynamically based on a configuration object—without hardcoding or repeating decorator logic.
This pattern is common in large Node.js systems, where instrumentation and monitoring are applied selectively.
Goal
Implement two reusable decorators:
withLogging(fn): logs arguments and return values.withTiming(fn): measures execution time.
Implement a
decorate(fn, config)function that:Receives a function and a configuration object, e.g.,
{ logging: true, timing: true }.Dynamically composes the relevant decorators.
Returns a new decorated function that behaves according to config.
Constraints
Do not modify the base service function.
The decorator composition must happen inside
decorate().The order of application must be:
withTiming(withLogging(fn))when both are enabled.You must not use
ifstatements inside the decorators themselves.
Sample output
The examples below illustrate what the output should look like:
const env = 'staging'; // Try with different values: 'development', 'staging', 'production'const config = {development: { logging: true },staging: { logging: true, timing: true },production: { timing: true }}[env];const decoratedProcessOrder = decorate(processOrder, config);(async () => {await decoratedProcessOrder(123);})();/* Expected output:with env = 'development':[LOG] Called with args: [123][LOG] Returned: { id: 123, status: 'processed' }with env = 'staging':[LOG] Called with args: [123][LOG] Returned: { id: 123, status: 'processed' }[TIMER] processOrder took 82mswith env = 'production':[TIMER] processOrder took 81ms */
Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.