Skip to content

Commit

Permalink
refactor into multiple files
Browse files Browse the repository at this point in the history
  • Loading branch information
jkdmyrs committed Sep 10, 2023
1 parent e5ce0ad commit 864df1f
Show file tree
Hide file tree
Showing 17 changed files with 182 additions and 75 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.timeclock/*
5 changes: 5 additions & 0 deletions src/app/Invoice/InvoiceHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { IInvoiceHandler } from "../../domain/Invoice/IInvoiceHandler.ts";

export class InvoiceHandler implements IInvoiceHandler {

}
43 changes: 43 additions & 0 deletions src/app/Punch/PunchHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { IPunchHandler } from "../../domain/Punch/IPunchHandler.ts";
import { Punch } from "../../domain/Punch/Punch.ts";
import { PunchType } from "../../domain/Punch/PunchType.ts";
import { executeShellCommandAsync } from "../../infra/IO/Shell.ts";
import * as FileManager from "../../infra/IO/Files.ts";
import { Shift } from "../../domain/Shift/Shift.ts";
import { ShiftHandler } from "../Shift/ShiftHandler.ts";

export class PunchHandler implements IPunchHandler {
constructor() {
}

async createPunchAsync(punch: Punch): Promise<void> {
if (punch.type === PunchType.Sart) {
await this.createStartPunchAsync(punch);
} else {
await this.createEndPunchAsync(punch);
}
await this.commitPunchAsync(punch);
}

private async commitPunchAsync(punch: Punch) {
const msg = punch.type == PunchType.Sart ? "START" : "END";
(await executeShellCommandAsync("git", ["commit", "-m", `\"TIMECLOCK PUNCH ${msg} - ${punch.user}\"`])).verifyZeroReturnCode();
}

private async createStartPunchAsync(punch: Punch) {
await FileManager.createDirectoryAsync(punch.punchDir);
await Deno.writeTextFile(punch.punchFilePath, Date.now().toString());
(await executeShellCommandAsync("git", ["add", punch.punchFilePath])).verifyZeroReturnCode();
}

private async createEndPunchAsync(punch: Punch) {
const nowUtcMs = Date.now().toString();
const punchStartUtcMs = await Deno.readTextFile(punch.punchFilePath);
const shift: Shift = new Shift(punch.user, punchStartUtcMs, nowUtcMs);

await Deno.remove(punch.punchFilePath);
(await executeShellCommandAsync("git", ["add", punch.punchFilePath])).verifyZeroReturnCode();

await new ShiftHandler().createShiftAsync(shift);
}
}
13 changes: 13 additions & 0 deletions src/app/Shift/ShiftHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { IShiftHandler } from "../../domain/Shift/IShiftHandler.ts";
import { Shift } from "../../domain/Shift/Shift.ts";
import * as FileManager from "../../infra/IO/Files.ts";
import { executeShellCommandAsync } from "../../infra/IO/Shell.ts";

export class ShiftHandler implements IShiftHandler {

public async createShiftAsync(shift: Shift): Promise<void> {
await FileManager.createDirectoryAsync(shift.shiftDir);
await Deno.writeTextFile(shift.shiftFilePath, shift.diffHours.toString());
(await executeShellCommandAsync("git", ["add", shift.shiftFilePath])).verifyZeroReturnCode();
}
}
24 changes: 24 additions & 0 deletions src/app/timeclock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Punch } from "../domain/Punch/Punch.ts";
import { PunchType } from "../domain/Punch/PunchType.ts";
import { executeShellCommandAsync } from "../infra/IO/Shell.ts";
import { PunchHandler } from "./Punch/PunchHandler.ts";

async function validateCleanWorkingTreeAsync() {
const statusOutput = (await executeShellCommandAsync("git", ["status"])).verifyZeroReturnCode();
if (!statusOutput.stdout.includes("nothing to commit, working tree clean")) {
throw "punches must occur on a clean working tree";
}
}
const _punchHandler = new PunchHandler();
async function main() {
const user: string = Deno.args[0];
const isEndPunch: boolean = Deno.args.some(x => x === "--end");
const punchType: PunchType = isEndPunch ? PunchType.End : PunchType.Sart;

const punch = new Punch(punchType, user);

await validateCleanWorkingTreeAsync();
await _punchHandler.createPunchAsync(punch);
}

await main();
1 change: 1 addition & 0 deletions src/domain/Constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const ONE_HOUR_IN_MS: number = 3600000;
3 changes: 3 additions & 0 deletions src/domain/Invoice/IInvoiceHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IInvoiceHandler {

}
3 changes: 3 additions & 0 deletions src/domain/Invoice/Invoice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class Invoice {

}
5 changes: 5 additions & 0 deletions src/domain/Punch/IPunchHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Punch } from "./Punch.ts";

export interface IPunchHandler {
createPunchAsync(punch: Punch): Promise<void>;
}
15 changes: 15 additions & 0 deletions src/domain/Punch/Punch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PunchType } from "./PunchType.ts";

export class Punch {
type: PunchType;
user: string;
punchDir: string;
punchFilePath: string;

constructor(punchType: PunchType, user: string) {
this.type = punchType;
this.user = user;
this.punchDir = `./.timeclock/punches/${user}`;
this.punchFilePath = `${this.punchDir}/punch`;
}
}
4 changes: 4 additions & 0 deletions src/domain/Punch/PunchType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum PunchType {
Sart,
End
}
5 changes: 5 additions & 0 deletions src/domain/Shift/IShiftHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Shift } from "./Shift.ts";

export interface IShiftHandler {
createShiftAsync(shift: Shift): Promise<void>;
}
16 changes: 16 additions & 0 deletions src/domain/Shift/Shift.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as DomainConstants from "../Constants.ts";

export class Shift {
user: string;
diffHours: number
shiftDir: string;
shiftFilePath: string;

constructor(user: string, punchStartUtcMs: string, punchEndUtcMs: string) {
this.user = user;
const diffMs: number = Number.parseInt(punchEndUtcMs) - Number.parseInt(punchStartUtcMs);
this.diffHours = diffMs/DomainConstants.ONE_HOUR_IN_MS;
this.shiftDir = `./.timeclock/shifts/${user}`;
this.shiftFilePath = `${this.shiftDir}/shift_${crypto.randomUUID()}`;
}
}
10 changes: 10 additions & 0 deletions src/infra/IO/Files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {exists} from "https://deno.land/std@0.201.0/fs/mod.ts";

export async function createDirectoryAsync(path: string) {
const dirExists = await exists(path);
if (!dirExists) {
await Deno.mkdir(path, {
recursive: true
});
}
}
6 changes: 6 additions & 0 deletions src/infra/IO/Shell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ShellOutput } from "./ShellOutput.ts";

export async function executeShellCommandAsync(command: string, args: string[]): Promise<ShellOutput> {
const output = await new Deno.Command(command, { args: args }).output();
return new ShellOutput(output);
}
28 changes: 28 additions & 0 deletions src/infra/IO/ShellOutput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export class ShellOutput {
private _output: Deno.CommandOutput;

constructor(output: Deno.CommandOutput) {
this._output = output;
}

public get code(): number {
return this._output.code;
}

public get stderr(): string {
return new TextDecoder().decode(this._output.stderr);
}

public get stdout(): string {
return new TextDecoder().decode(this._output.stdout);
}

public verifyZeroReturnCode(): ShellOutput {
if (this._output.code !== 0) {
// todo - enhance error handling
console.log(this.stdout, this.stderr);
throw `non-zero RC: ${this._output.code}`;
}
return this;
}
}
75 changes: 0 additions & 75 deletions src/timeclock.ts

This file was deleted.

0 comments on commit 864df1f

Please sign in to comment.