Currently, all packages that perform actions requiring a connection follow this repetitive pattern:
class SomeClass
{
async doSomething(): Promise<void>
{
this.#logger?.debug(this.#logPrefix, 'Starting doing something');
try
{
this.#validateConnection(); // Throws `NotConnected` if not connected
await this.#performAction();
this.#logger?.debug(this.#logPrefix, 'Finished doing something');
}
catch (error)
{
this.#logger?.error(this.#logPrefix, 'Doing something failed with error', error);
throw error;
}
}
}
About 95% of this code is boilerplate: logging, try/catch, and connection validation. As the number of packages grows, we should centralize this pattern to reduce duplication.
There are two common approaches:
- TypeScript decorators – clean but experimental; not aligned with our goal of using only native JS constructs.
- Wrapper function – safe and fully compatible with current TS/JS standards.
We propose extending the connection package with a base class that provides a reusable execute method, centralizing the connection and logging patterns:
class Connectable
{
#logger: Logger;
#connected: false;
constructor(logger: Logger)
{
this.#logger = logger;
}
async connect(action: () => Promise<T>)
{
// implement pattern with action execution
}
async disconnect(action: () => Promise<T>)
{
// implement pattern with action execution
}
async execute(actionName: string, action: () => Promise<T>): Promise<T>
{
// implement pattern with action execution
}
}
This can can be used like this:
class SomeClass extends Connectable
{
async doSomething(): Promise<void>
{
return this.execute('something', () => this.#performAction());
}
}
This approach:
- Reduces boilerplate in all connection-based packages.
- Centralizes connect and disconnect handling.
- Makes future actions easier to implement with consistent observability.
Currently, all packages that perform actions requiring a connection follow this repetitive pattern:
About 95% of this code is boilerplate: logging, try/catch, and connection validation. As the number of packages grows, we should centralize this pattern to reduce duplication.
There are two common approaches:
We propose extending the connection package with a base class that provides a reusable execute method, centralizing the connection and logging patterns:
This can can be used like this:
This approach: