By Lesauf | August 2, 2025
Welcome to the third part of my series on vibe-coding an eCommerce API! In this series, I’ll walk you through the process of designing and implementing a robust, scalable API for an eCommerce platform. You can find the second part here.
The project architecture is already in place. You can see the current version of the code here.
Now if you noticed in src/infrastructure/http/routes/productRoutes.ts
,
there is a section in line 17 that create dependencies that will be used by the router and controller.
// Create dependencies
const productRepository = new InMemoryProductRepository();
const getProductUseCase = new GetProductUseCase(productRepository);
const productPresenter = new ProductPresenter();
const productController = new ProductController(getProductUseCase, productPresenter);
This is good and working, but we can somehow automate it and I want to use Tsyringe. Awilix works well, but I prefer Tsyringe use of decorators.
Prompt: integrate Tsyringe
Implement Tsyringe for Dependency Injection in ProductRouter
Junie created a new file in src/infrastucture/container/index.ts
/**
* Dependency Injection Container Configuration
*
* This file configures the Tsyringe dependency injection container.
* It registers all the dependencies that will be injected throughout the application.
*/
import { container } from 'tsyringe';
import { ProductRepositoryInterface } from '@domain/repositories/ProductRepositoryInterface';
import { InMemoryProductRepository } from '@infrastructure/database/repositories/InMemoryProductRepository';
// Register repositories
container.registerSingleton<ProductRepositoryInterface>(
'ProductRepositoryInterface',
InMemoryProductRepository
);
export { container };
replaced all the previous manual Dependencies Injection in productRoutes.ts
with a one-liner
// Resolve dependencies using Tsyringe container
const productController = container.resolve(ProductController);
and added an @Injectable()
decorator to ProductController.ts
, ProductPresenter.ts
, InMemoryProductRepository.ts
and GetProductUseCase.ts
so they can be injected wherever needed. This simplify the dependencies management in the project,
as there will be more and more classes added.
Let me try a run of the project to see how it goes with npm run dev
. I get this error:
Error: Cannot find module '@interfaces/controllers/ProductController'
Require stack:
- /home/lesauf/Dev/ecommerce-api/src/infrastructure/http/routes/productRoutes.ts
- /home/lesauf/Dev/ecommerce-api/src/infrastructure/http/server.ts
I suspect it is related to tsconfig path
and rootDir
options, but lets ask Junie to check:
Prompt: Fix typescript paths
I get this error
Error: Cannot find module '@interfaces/controllers/ProductController'
Require stack:
- /home/lesauf/Dev/ecommerce-api/src/infrastructure/http/routes/productRoutes.ts
- /home/lesauf/Dev/ecommerce-api/src/infrastructure/http/server.ts
Can you fix it using the paths already defined in tsconfig.json?
It solution was to install the module-alias
package with paths defined in package.json; I don’t like it. I would prefer
to use the paths already defined in tsconfig.json if possible. After a quick Google search, I found that there is a solution with
tsconfig-paths and ts-node. Let me ask Junie to use it.
Prompt: fix typescript paths using tsconfig-paths
I get this error
Error: Cannot find module '@interfaces/controllers/ProductController'
Require stack:
- /home/lesauf/Dev/ecommerce-api/src/infrastructure/http/routes/productRoutes.ts
- /home/lesauf/Dev/ecommerce-api/src/infrastructure/http/server.ts
Can you fix it using the paths already defined in tsconfig.json using tsconfig-paths?
Much better, but now it uses a tsconfig-paths-bootstrap.js
file in dist
folder.
// This file configures tsconfig-paths to work with the compiled JavaScript files
const tsConfigPaths = require('tsconfig-paths');
const path = require('path');
const fs = require('fs');
// The compiled JavaScript files are in the dist directory
const baseUrl = path.join(process.cwd(), 'dist');
// Define the path mappings explicitly
const paths = {
'@domain/*': [path.join(baseUrl, 'domain/*')],
'@application/*': [path.join(baseUrl, 'application/*')],
'@infrastructure/*': [path.join(baseUrl, 'infrastructure/*')],
'@interfaces/*': [path.join(baseUrl, 'interfaces/*')],
'@config/*': [path.join(baseUrl, 'config/*')]
};
// Register the paths
const result = tsConfigPaths.register({
baseUrl,
paths
});
console.log('Path aliases registered with explicit mapping');
console.log('Base URL:', baseUrl);
console.log('Paths:', JSON.stringify(paths, null, 2));
// Verify that critical files exist
const criticalPaths = [
path.join(baseUrl, 'infrastructure/database/repositories/InMemoryProductRepository.js'),
path.join(baseUrl, 'interfaces/controllers/ProductController.js')
];
criticalPaths.forEach(filePath => {
console.log(`Checking if file exists: ${filePath} - ${fs.existsSync(filePath) ? 'YES' : 'NO'}`);
});
I do not like that, I would much prefer a solution that uses the already defined paths in tsconfig.json. Let me revert and make a more clearer prompt.
Prompt: fix typescript paths using tsconfig-paths and existing paths in tsconfig.json
I get this error
Error: Cannot find module '@interfaces/controllers/ProductController'
Require stack:
- /home/lesauf/Dev/ecommerce-api/src/infrastructure/http/routes/productRoutes.ts
- /home/lesauf/Dev/ecommerce-api/src/infrastructure/http/server.ts
Can you fix it using the paths already defined in tsconfig.json using tsconfig-paths? I would like a simple solution that uses the already defined paths in tsconfig.json, without having to define them again.
Now, I like his solution better. It updated the start
and dev
scripts in package.json
:
{
"start": "node -r ./tsconfig-paths-bootstrap.js dist/index.js",
"dev": "ts-node-dev --respawn --transpile-only -r tsconfig-paths/register src/index.ts"
}
Here is tsconfig-paths-bootstrap.js
created at the root of the project to register the paths when running the built files:
/**
* tsconfig-paths-bootstrap.js
*
* This file registers the path aliases defined in tsconfig.json for runtime resolution
* when running the compiled JavaScript code.
*/
const tsConfigPaths = require('tsconfig-paths');
const tsConfig = require('./tsconfig.json');
// The compiled JavaScript files will be in the dist directory
const baseUrl = './dist';
// Register the path mappings
tsConfigPaths.register({
baseUrl,
paths: tsConfig.compilerOptions.paths
});
The project runs smoothly and the /health
endpoint display a "status": "ok"
.