Usage
Property injection only — never put logger decorators on a constructor parameter. The host class must be DI-managed (@Service or a @Controller registered on the module).
- Log important operations and lifecycle events (seed skip/complete, job start/finish, uninstall cleanup)
- Include enough context to debug (ids, plugin name) — not full request bodies with secrets
- Do not log passwords, tokens, API keys, or other sensitive fields
- Prefer @InjectBuiltinLogger over a custom console wrapper
- Pair with @AuditLogMiddleware for user-facing admin actions — logger is for process/runtime diagnostics
TSXservice
1import { InjectBuiltinLogger, Service } from "@quan-erp/shared-backend-core";
2import type { Loggable } from "@quan-erp/shared-backend-core";
3
4@Service()
5export class OrderService {
6 @InjectBuiltinLogger()
7 logger: Loggable;
8
9 async create() {
10 this.logger.log("Creating order");
11 // …
12 this.logger.log("Order created");
13 }
14}TSXseed feedback
1import {
2 InjectBuiltinLogger,
3 OnInit,
4 Service,
5} from "@quan-erp/shared-backend-core";
6import type { Loggable } from "@quan-erp/shared-backend-core";
7
8@Service()
9export class SeedService {
10 @InjectBuiltinLogger()
11 logger: Loggable;
12
13 @OnInit()
14 async init() {
15 if (alreadySeeded) {
16 this.logger.log("Seeding skipped (already initialized)");
17 return;
18 }
19 // … seed …
20 this.logger.log("Module seeded successfully");
21 }
22}Builtin logger
@InjectBuiltinLogger() is shorthand for @InjectLogger(BuiltinLogger). Type the property as Loggable (or BuiltinLogger). Works on services and controllers.
- @InjectBuiltinLogger() — inject the platform BuiltinLogger
- Import from @quan-erp/shared-backend-core
- Keep messages short and searchable (include plugin/job names)
TSXbuiltin
1import {
2 BuiltinLogger,
3 InjectBuiltinLogger,
4 InjectLogger,
5 Service,
6} from "@quan-erp/shared-backend-core";
7import type { Loggable } from "@quan-erp/shared-backend-core";
8
9@Service()
10export class OrderService {
11 @InjectBuiltinLogger()
12 logger: Loggable;
13
14 // equivalent
15 @InjectLogger(BuiltinLogger)
16 builtinLogger: BuiltinLogger;
17}Creating custom logger
Implement Loggable (or your own logger API), mark it @Service(), register it on the plugin @Module providers, then inject with @InjectLogger(YourLogger). Prefer BuiltinLogger unless you need custom formatting or sinks.
- 1. Define a @Service() class that implements Loggable (log / error / …)
- 2. Add the class to @Module({ providers: [...] })
- 3. Inject with property @InjectLogger(MyPluginLogger) — never constructor injection
TSXmy-plugin.logger.ts
1import { Service } from "@quan-erp/shared-backend-core";
2import type { Loggable } from "@quan-erp/shared-backend-core";
3
4@Service()
5export class MyPluginLogger implements Loggable {
6 private prefix = "[my-plugin]";
7
8 log(message: string, ...args: unknown[]) {
9 console.log(this.prefix, message, ...args);
10 }
11
12 error(message: string, ...args: unknown[]) {
13 console.error(this.prefix, message, ...args);
14 }
15
16 warn(message: string, ...args: unknown[]) {
17 console.warn(this.prefix, message, ...args);
18 }
19}TSXmodule providers
1import { Module } from "@quan-erp/shared-backend-core";
2import { OrderController } from "./order.controller.js";
3import { OrderService } from "./order.service.js";
4import { MyPluginLogger } from "./my-plugin.logger.js";
5
6@Module({
7 name: "my-plugin",
8 providers: [OrderService, MyPluginLogger],
9 controllers: [OrderController],
10 entities: [],
11})
12export class MyPluginModule {}TSXinject & use
1import { InjectLogger, Service } from "@quan-erp/shared-backend-core";
2import { MyPluginLogger } from "./my-plugin.logger.js";
3
4@Service()
5export class OrderService {
6 @InjectLogger(MyPluginLogger)
7 logger: MyPluginLogger;
8
9 async create(orderId: string) {
10 this.logger.log(`Creating order ${orderId}`);
11 try {
12 // …
13 this.logger.log(`Order ${orderId} created`);
14 } catch (err) {
15 this.logger.error(`Failed to create order ${orderId}`, err);
16 throw err;
17 }
18 }
19}