The first PR(s) should create the interfaces that need to be implemented for the current ticket. In our example, it's the following:
// Both Website & Order Service
export type Order = {
id: string;
status: string;
datePlaced: string;
total: string;
}
// Order Service
export interface OrderRepository {
getOrders(customerId: string): Promise<Order[]>;
}
// Order Service
export class GetOrdersQuery {
constructor(
public readonly customerId: string
) {}
}
// Website
export interface OrderServiceGateway {
(customerId: string): Promise<Order[]>;
}
// Website
export const orders = atom<Order[]>({
key: 'orders',
default: [],
});
PRs that can be done in parallel after First PRs
For brevity, unit tests are not included
export class MySQLOrderRepository implements OrderRepository {
async getOrders(customerId: string): Promise<Order[]> {
const connection = mysql.createConnection({
host: 'myHost',
user: 'myUserName',
password: 'myPassword'
});
const results = await new Promise((resolve, reject) => {
connection.connect((err) => {
connection.query(
`SELECT * FROM orders WHERE customerId=${req.query.id}`,
(err, result, fields) => {
resolve(result);
}
);
});
});
return results.map((order) => ({
id: order.id,
status: order.order_status,
datePlaced: order.date_placed,
total: order.display_total,
}))
}
}
app.get('/orders', (req, res) => {
// Requires the handler to be declared, but it can be empty. "container" is our DI container
const getOrdersHandler = container.get(TYPES.GetOrdersHandler);
const result = getOrdersHandler.handle(
new GetOrdersQuery(req.query['customer-id'])
);
res.send(result)
})
export class GetOrdersHandler {
constructor(private readonly repository: OrderRepository) {}
async handle(query: GetOrdersQuery): Promise<Order[]> {
// Perform any other business logic needed
return this.repository.getOrders(query.customerId)
}
}
export const getOrders: OrderServiceGateway = async (
customerId: string
): Promise<Order[]> => {
const response = await StockApiClient.get(
`orders?customer-id=${customerId}`
);
return response.json()
};
const createSelector = (serviceGateway: OrderServiceGateway) => {
return selector<Order[]>({
key: 'orders',
get: async ({ get }) => {
const customerId = get(currentCustomerId);
return serviceGateway(customerId);
},,
});
}
// Use the getOrders instead of "() => Promise.resolve([])" when it's created
export const ordersSelector = createSelector(() => Promise.resolve([]))
const MyApp: FunctionComponent = () => {
// Set recoil state
const [orders] = useRecoilState(orders);
return (
// Render order list
);
};