Skip to content

Fix decorator injection from the documented subpath - #4

Open
refucktor wants to merge 1 commit into
BackendStack21:mainfrom
refucktor:fix/decorator-subpath-metadata
Open

Fix decorator injection from the documented subpath#4
refucktor wants to merge 1 commit into
BackendStack21:mainfrom
refucktor:fix/decorator-subpath-metadata

Conversation

@refucktor

@refucktor refucktor commented Jul 20, 2026

Copy link
Copy Markdown

Problem

The documented import pattern uses the container from fast-injection and decorators from fast-injection/decorators. In the published package, those entrypoints were bundled independently. Each bundle created its own decorator metadata store, so @inject(...) saved dependency information in a store the container could not read.

As a result, registered classes resolved without their decorated constructor dependencies. For example, constructor(@inject(Database) private db: Database) received undefined for db, causing a runtime error when the service used it.

Fix

Build the package entrypoints with Bun code splitting so the main entrypoint and decorator subpath share the same metadata module at runtime.

Also add a package-boundary regression test that builds a temporary package and runs a consumer using the documented imports. This catches future builds that accidentally isolate decorator metadata again.

Verification

  • bun test
  • bun run lint
  • bun run build

- Build package entrypoints with shared chunks so decorators and the container use the same metadata store
- Cover direct and consumer package imports with decorator injection tests
- Define rootDir so declaration generation succeeds with TypeScript 5.9
@refucktor

Copy link
Copy Markdown
Author

This is the documented pattern, taken directly from the website:

import { Container } from "fast-injection";
import { singleton, inject } from "fast-injection/decorators";

// Define services with decorators
@singleton()
class Database {
  query(sql: string) {
    return "Query result for: " + sql;
  }
}

@singleton()
class UserService {
  constructor(@inject(Database) private db: Database) {}

  getUser(id: string) {
    return this.db.query(`SELECT * FROM users WHERE id = ${id}`);
  }
}

// Create container and register services
const container = new Container();
container.register(Database);
container.register(UserService);

// Resolve with automatic dependency injection
const userService = container.resolve(UserService);

// This part was added by me to test the resolution and it fails
console.info("=== Example: Dependency Injection with Decorators ===");
const user = userService.getUser("123");
console.log(user);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant