Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DSDK-178] [TS] [SDK] Setup InversifyJS and SOLID conventions #9

Merged
merged 4 commits into from
Jan 25, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions packages/core/scripts/add-module.mjs
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
#!/usr/bin/env zx
import "zx/globals";
import { basename } from "node:path";
const features = argv._;
const modules = argv._;

if (!features.length) {
if (!modules.length) {
console.error(`Usage: ${basename(__filename)} <feature1> [<feature2> ...]`);
process.exit(1);
}

within(async () => {
cd("src/internal");
for (const feature of features) {
const rootFolderName = `${feature}`;
const featureUppercased =
feature.charAt(0).toUpperCase() + feature.slice(1);
for (const mod of modules) {
const rootFolderName = `${mod}`;
const featureUppercased = mod.charAt(0).toUpperCase() + mod.slice(1);
await $`mkdir ${rootFolderName}`;
within(async () => {
cd(rootFolderName);
await $`mkdir data di model service usecase`;
const files = [
`data/${featureUppercased}DataSource.ts`,
`di/${feature}Module.test.ts`,
`di/${feature}Module.ts`,
`di/${feature}Types.ts`,
`di/${mod}Module.test.ts`,
`di/${mod}Module.ts`,
`di/${mod}Types.ts`,
`model/.gitkeep`,
`service/${featureUppercased}Service.ts`,
`service/Default${featureUppercased}Service.test.ts`,
9 changes: 7 additions & 2 deletions packages/core/src/di.ts
Original file line number Diff line number Diff line change
@@ -5,10 +5,15 @@ import configModuleFactory from "./internal/config/di/configModule";

const logger = makeLoggerMiddleware();

export const makeContainer = (mock = false) => {
type MakeContainerProps = {
mock: boolean;
};
export const makeContainer = ({
mock = false,
}: Partial<MakeContainerProps> = {}) => {
const container = new Container();
container.applyMiddleware(logger);
container.load(configModuleFactory(mock));
container.load(configModuleFactory({ mock }));

return container;
};
24 changes: 15 additions & 9 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -2,18 +2,24 @@ import "reflect-metadata";

import { makeContainer } from "./di";
import { types } from "./internal/config/di/configTypes";
import { GetSDKVersionUseCase } from "./internal/config/usecase/GetSdkVersionUseCase";
import { GetSdkVersionUseCase } from "./internal/config/usecase/GetSdkVersionUseCase";

export * from "./api";
export * from "./transport";

const container = makeContainer();
const mockContainer = makeContainer(true);
async function main(): Promise<void> {
const container = makeContainer();
const mockContainer = makeContainer({ mock: true });

const mod = container.get<GetSDKVersionUseCase>(types.GetSDKVersionUseCase);
console.log("module.getSdkVersion", mod.getSdkVersion());
const mod = container.get<GetSdkVersionUseCase>(types.GetSdkVersionUseCase);
console.log("module.getSdkVersion", await mod.getSdkVersion());

const mockModule = mockContainer.get<GetSDKVersionUseCase>(
types.GetSDKVersionUseCase
);
console.log("mockModule.getSdkVersion", mockModule.getSdkVersion());
const mockModule = mockContainer.get<GetSdkVersionUseCase>(
types.GetSdkVersionUseCase
);
console.log("mockModule.getSdkVersion", await mockModule.getSdkVersion());
}

main().catch((err) => {
console.error(err);
});
2 changes: 1 addition & 1 deletion packages/core/src/internal/config/data/DTO.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
// They will usually be the response of an API call that will need to be parsed
// into an object used by the application. (in our example: DTOConfig => Config)

export type ConfigDTO = {
export type ConfigDto = {
valpinkman marked this conversation as resolved.
Show resolved Hide resolved
version: string;
name: string;
yolo: string;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { injectable } from "inversify";
import "reflect-metadata";
import { RemoteConfigDataSource } from "./ConfigDataSource";
import { ConfigDTO } from "./DTO";
import { ConfigDto } from "./Dto";
import { Config } from "../model/Config";

/**
@@ -12,7 +12,7 @@ import { Config } from "../model/Config";
export class RestRemoteConfigDataSource implements RemoteConfigDataSource {
async getConfig() {
// Fake API call
const v = await new Promise<{ json: () => Promise<ConfigDTO> }>(
const v = await new Promise<{ json: () => Promise<ConfigDto> }>(
(resolve) => {
resolve({
json: async () =>
@@ -33,7 +33,7 @@ export class RestRemoteConfigDataSource implements RemoteConfigDataSource {

// Parser for the DTO
// parserResponse: ConfigDTO => Config
private _parseResponse(dto: ConfigDTO): Config {
private _parseResponse(dto: ConfigDto): Config {
const { name, version } = dto;
return { name, version };
}
10 changes: 7 additions & 3 deletions packages/core/src/internal/config/di/configModule.ts
Original file line number Diff line number Diff line change
@@ -8,16 +8,20 @@ import {
RestRemoteConfigDataSource,
} from "../data/RemoteConfigDataSource";
import { DefaultConfigService } from "../service/DefaultConfigService";
import { GetSDKVersionUseCase } from "../usecase/GetSdkVersionUseCase";
import { GetSdkVersionUseCase } from "../usecase/GetSdkVersionUseCase";
import { types } from "./configTypes";

// This module is used to configure the dependency injection container
// This is where we will bind our interfaces to their implementations (or mocks...)
const configModuleFactory = (mock = false) =>
type FactoryProps = {
mock?: boolean;
};

const configModuleFactory = ({ mock = false }: FactoryProps) =>
new ContainerModule((bind, _unbind, _isBound, rebind) => {
bind(types.LocalConfigDataSource).to(FileLocalConfigDataSource);
bind(types.RemoteConfigDataSource).to(RestRemoteConfigDataSource);
bind(types.GetSDKVersionUseCase).to(GetSDKVersionUseCase);
bind(types.GetSdkVersionUseCase).to(GetSdkVersionUseCase);
bind(types.ConfigService).to(DefaultConfigService);

if (mock) {
2 changes: 1 addition & 1 deletion packages/core/src/internal/config/di/configTypes.ts
Original file line number Diff line number Diff line change
@@ -2,5 +2,5 @@ export const types = {
LocalConfigDataSource: Symbol.for("LocalConfigDataSource"),
RemoteConfigDataSource: Symbol.for("RemoteConfigDataSource"),
ConfigService: Symbol.for("ConfigService"),
GetSDKVersionUseCase: Symbol.for("GetSDKVersionUseCase"),
GetSdkVersionUseCase: Symbol.for("GetSdkVersionUseCase"),
};
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { GetSDKVersionUseCase } from "./GetSdkVersionUseCase";
import { GetSdkVersionUseCase } from "./GetSdkVersionUseCase";

const getSdkVersionMock = jest.fn();

let usecase: GetSDKVersionUseCase;
let usecase: GetSdkVersionUseCase;
describe("GetSdkVersionUseCase", () => {
beforeEach(() => {
getSdkVersionMock.mockClear();
const configService = {
getSdkVersion: getSdkVersionMock,
};

usecase = new GetSDKVersionUseCase(configService);
usecase = new GetSdkVersionUseCase(configService);
});

it("should return the sdk version", async () => {
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ import { types } from "../di/configTypes";
* We will have many use cases in our SDK, and each should be contained in its own file.
*/
@injectable()
export class GetSDKVersionUseCase {
export class GetSdkVersionUseCase {
private _configService: ConfigService;
constructor(@inject(types.ConfigService) configService: ConfigService) {
this._configService = configService;