depfy
v1.0.1
Published
minimalistic dependency injection mechanism
Downloads
3
Maintainers
Readme
Minimalistic dependency injection mechanism
- Very easy to use
- Perfect for
VanillaJS
- All providers are asynchronous
- Full type system support in
TypeScript
(for convenience inIDE
) - Ability to replace providers (mocks)
Example for TypeScript
/// types.ts
export type User = {
id: number;
email: string;
username: string;
};
/// config.provider.ts
import * as depfy from "depfy";
export default depfy.injectable({
name: "Main config",
async factory() {
return {
db_host: process.env["DB_HOST"],
db_port: process.env["DB_PORT"],
db_username: process.env["DB_USERNAME"],
db_password: process.env["DB_PASSWORD"],
db_database: process.env["DB_DATABASE"],
};
},
});
/// database.provider.ts
import * as depfy from "depfy";
import ConfigProvider from "./config.provider";
export default depfy.injectable({
name: "Database",
dependencies: {
config: ConfigProvider,
},
async factory({ dependencies }) {
const { db_host, db_port, db_password, db_username, db_database } =
dependencies.config;
/// TODO: add orm database (maybe knex?)
/// create instance connect database
const connect = null;
return connect;
},
});
/// user.interface-service.ts
import * as depfy from "depfy";
import { User } from "./types";
export default depfy.replaceable<{
findAll(): Promise<User[]>;
insert(payload: Omit<User, "id">): Promise<User>;
}>();
/// user.mock-service.ts
import * as depfy from "depfy";
import UserInterfaceServiceProvider from "./user.interface-service";
import { User } from "./types";
export default depfy.replacement({
name: "Mock [User service]",
replaceable: UserInterfaceServiceProvider,
async factory() {
return new (class {
private users: User[] = [];
private idCounter = 0;
public async findAll() {
return this.users;
}
public async insert(payload: Omit<User, "id">) {
const id = this.idCounter++;
const user: User = {
id,
...payload,
};
this.users.push(user);
return user;
}
})();
},
});
/// user.service.ts
import * as depfy from "depfy";
import UserInterfaceServiceProvider from "./user.interface-service";
import DatabaseProvider from "./database.provider";
import { User } from "./types";
export default depfy.injectable({
name: "User service",
replaceable: UserInterfaceServiceProvider,
dependencies: {
database: DatabaseProvider,
},
async factory({ dependencies }) {
// if (!dependencies.database) {
// throw new Error("dependencies.database is not implemented");
// }
return {
async findAll(): Promise<User[]> {
throw new Error("dependencies.database is not implemented");
},
async insert(payload: Omit<User, "id">): Promise<User> {
throw new Error("dependencies.database is not implemented");
},
};
},
});
/// app.provider.ts
import * as depfy from "depfy";
import UserServiceProvider from "./user.service";
export default depfy.injectable({
name: "App",
dependencies: {
userService: UserServiceProvider,
},
factory({ dependencies }) {
return {
userService: dependencies.userService,
};
},
});
import * as depfy from "depfy";
import AppProvider from "./app.provider";
import UserMockServiceProvider from "./user.mock-service";
type AppContext = depfy.InferResolver<typeof AppProvider>;
async function bootstrap_prod() {
const appContex: AppContext = await depfy.resolver({
dependency: AppProvider,
});
return appContex;
}
async function bootstrap_dev() {
const appContex: AppContext = await depfy.resolver({
dependency: AppProvider,
replacements: [UserMockServiceProvider],
});
return appContex;
}
async function bootstrap() {
const isDev = process.env.NODE_ENV === "development";
const appContext = await (isDev ? bootstrap_dev : bootstrap_prod)();
const { root: app } = appContext;
{
await app.userService.insert({
email: "[email protected]",
username: "1",
});
const users = await app.userService.findAll();
console.log(users);
}
}
bootstrap();
Example for JavaScript
/// types.js
/**
* @typedef {Object} User
* @property {number} id
* @property {string} email
* @property {string} username
*/
/// config.provider.js
const depfy = require("depfy");
module.exports = depfy.injectable({
name: "Main config",
async factory() {
return {
db_host: process.env["DB_HOST"],
db_port: process.env["DB_PORT"],
db_username: process.env["DB_USERNAME"],
db_password: process.env["DB_PASSWORD"],
db_database: process.env["DB_DATABASE"],
};
},
});
/// database.provider.js
const depfy = require("depfy");
const ConfigProvider = require("./config.provider");
module.exports = depfy.injectable({
name: "Database",
dependencies: {
config: ConfigProvider,
},
async factory({ dependencies }) {
const { db_host, db_port, db_password, db_username, db_database } =
dependencies.config;
/// TODO: add orm database (maybe knex?)
/// create instance connect database
const connect = null;
return connect;
},
});
/// user.service.js
const depfy = require("depfy");
const DatabaseProvider = require("./database.provider");
module.exports = depfy.injectable({
name: "User service",
dependencies: {
database: DatabaseProvider,
},
async factory({ dependencies }) {
// if (!dependencies.database) {
// throw new Error("dependencies.database is not implemented");
// }
return {
/**
* @returns {Promise<User[]>}
*/
async findAll() {
throw new Error("dependencies.database is not implemented");
},
/**
* @param {Omit<User, 'id'>} payload
* @returns {Promise<User>}
*/
async insert(payload) {
throw new Error("dependencies.database is not implemented");
},
};
},
});
/// user.mock-service.js
const depfy = require("depfy");
const UserServiceProvider = require("./user.service");
module.exports = depfy.replacement({
name: "Mock [User service]",
replaceable: UserServiceProvider,
async factory() {
/** @type { User[] } */
const users = [];
let idCounter = 0;
return {
async findAll() {
return users;
},
insert(payload) {
const id = idCounter++;
const user = {
id,
...payload,
};
users.push(user);
return user;
},
};
},
});
/// app.provider.js
const depfy = require("depfy");
const UserServiceProvider = require("./user.service");
module.exports = depfy.injectable({
name: "App",
dependencies: {
userService: UserServiceProvider,
},
factory({ dependencies }) {
return {
userService: dependencies.userService,
};
},
});
/// main.js
const depfy = require("depfy");
const AppProvider = require("./app.provider");
const UserMockServiceProvider = require("./user.mock-service");
async function bootstrap_prod() {
const appContex = await depfy.resolver({
dependency: AppProvider,
});
return appContex;
}
async function bootstrap_dev() {
const appContex = await depfy.resolver({
dependency: AppProvider,
replacements: [UserMockServiceProvider],
});
return appContex;
}
async function bootstrap() {
const isDev = process.env.NODE_ENV === "development";
const appContext = await (isDev ? bootstrap_dev : bootstrap_prod)();
const { root: app } = appContext;
{
await app.userService.insert({
email: "[email protected]",
username: "1",
});
const users = await app.userService.findAll();
console.log(users);
}
}
bootstrap();