Skip to content

Commit 908c67d

Browse files
committed
refactor(chrono)!: remake stage area workflow
1 parent 2a6f19e commit 908c67d

File tree

13 files changed

+264
-169
lines changed

13 files changed

+264
-169
lines changed

packages/chrono/playground/PlayApp.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ async function run() {
3636
name: 'commit',
3737
method: 'commit',
3838
},
39+
{
40+
name: 'status',
41+
method: 'status',
42+
},
43+
{
44+
name: 'list',
45+
method: 'list',
46+
},
3947
]
4048

4149
const command = options.find((o) => o.name === commandName)

packages/chrono/src/ChronoApp.ts

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,24 @@ import LocalStageItemRepository from './repositories/implementations/LocalStageI
1111

1212
import InitUseCase from './use-cases/InitUseCase'
1313
import CatFileUseCase from './use-cases/CatFileUseCase'
14-
import HashFileUseCase from './use-cases/HashFileUseCase'
15-
import RemoveStageItemUseCase from './use-cases/RemoveStageItemUseCase'
16-
import AddStageItemUseCase from './use-cases/AddStageItemUseCase'
14+
import HashFileUseCase from './use-cases/HashEntryUseCase'
15+
import RemoveUseCase from './use-cases/RemoveUseCase'
1716
import CommitUseCase from './use-cases/CommitUseCase'
17+
import StatusUseCase from './use-cases/StatusUseCase'
18+
import IEntryRepository from './repositories/IEntryRepository'
19+
import LocalEntryRepository from './repositories/implementations/LocalEntryRepository'
20+
import AddUseCase from './use-cases/AddUseCase'
21+
import ListFilesUseCase from './use-cases/ListFilesUseCase'
22+
import HashEntryService from './services/HashEntryService'
1823

1924
export default class ChronoApp {
2025
private readonly objectRepository: IObjectRepository
2126
private readonly blobRepository: IBlobRepository
2227

2328
private readonly stageItemRepository: IStageItemRepository
29+
private readonly entryRepository: IEntryRepository
30+
31+
private readonly hashEntryService: HashEntryService
2432

2533
constructor(
2634
private readonly drive: IDrive,
@@ -30,6 +38,13 @@ export default class ChronoApp {
3038
this.blobRepository = new LocalBlobRepository(drive, hash)
3139

3240
this.stageItemRepository = new LocalStageItemRepository(drive)
41+
this.entryRepository = new LocalEntryRepository(drive, hash)
42+
43+
this.hashEntryService = new HashEntryService(
44+
drive,
45+
this.objectRepository,
46+
this.blobRepository
47+
)
3348
}
3449

3550
public async init() {
@@ -51,30 +66,42 @@ export default class ChronoApp {
5166
}
5267

5368
public async addEntry(path: string) {
54-
const useCase = new AddStageItemUseCase(
69+
const useCase = new AddUseCase(
5570
this.drive,
56-
this.stageItemRepository,
5771
this.objectRepository,
58-
this.blobRepository
72+
this.blobRepository,
73+
this.entryRepository
5974
)
6075

6176
return useCase.execute({ path })
6277
}
6378

6479
public async removeEntry(path: string) {
65-
const useCase = new RemoveStageItemUseCase(this.stageItemRepository)
80+
const useCase = new RemoveUseCase(this.drive, this.entryRepository)
6681

6782
return useCase.execute({ path })
6883
}
6984

85+
public async list() {
86+
const useCase = new ListFilesUseCase(this.entryRepository)
87+
88+
return useCase.execute()
89+
}
90+
7091
public async commit(message: string, body?: string) {
7192
const useCase = new CommitUseCase(
7293
this.drive,
7394
this.objectRepository,
7495
this.blobRepository,
75-
this.stageItemRepository
96+
this.entryRepository
7697
)
7798

7899
return useCase.execute({ message, body })
79100
}
101+
102+
public async status() {
103+
const useCase = new StatusUseCase(this.drive, this.entryRepository)
104+
105+
return useCase.execute()
106+
}
80107
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export enum ChronoEntryStatus {
2+
Unmodified = 0,
3+
Modified = 1,
4+
Added = 2,
5+
Deleted = 3,
6+
Renamed = 4,
7+
Copied = 5,
8+
}
9+
10+
export default class ChronoEntry {
11+
public path: string
12+
public hash: string
13+
public status: ChronoEntryStatus
14+
15+
public static STATUS = ChronoEntryStatus
16+
17+
constructor(
18+
path: string,
19+
hash: string,
20+
status: ChronoEntryStatus = ChronoEntryStatus.Unmodified
21+
) {
22+
this.path = path
23+
this.hash = hash
24+
this.status = status
25+
}
26+
27+
public static from({ path, hash, status }: Pick<ChronoEntry, 'path' | 'hash' | 'status'>) {
28+
return new ChronoEntry(path, hash, status)
29+
}
30+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import ChronoEntry from '../entities/ChronoEntry'
2+
3+
export default interface IEntryRepository {
4+
findAll(): Promise<ChronoEntry[]>
5+
saveAll(entries: ChronoEntry[]): Promise<void>
6+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import ChronoEntry from '../../entities/ChronoEntry'
2+
import IDrive from '../../gateways/IDrive'
3+
import IHash from '../../gateways/IHash'
4+
import HelperService from '../../services/HelperService'
5+
import IEntryRepository from '../IEntryRepository'
6+
7+
export default class LocalEntryRepository implements IEntryRepository {
8+
constructor(
9+
private readonly drive: IDrive,
10+
private readonly hash: IHash
11+
) {}
12+
13+
public findAll: IEntryRepository['findAll'] = async () => {
14+
const contents = await this.drive.read('.chrono/index')
15+
16+
const json = JSON.parse(contents ? HelperService.decode(contents) : '[]')
17+
18+
return json.map((i: any) => new ChronoEntry(i.path, i.hash, i.status))
19+
}
20+
21+
public saveAll: IEntryRepository['saveAll'] = async (entries) => {
22+
await this.drive.write(
23+
'.chrono/index',
24+
HelperService.encode(JSON.stringify(entries, null, 4))
25+
)
26+
}
27+
}

packages/chrono/src/use-cases/AddStageItemUseCase.spec.ts

Lines changed: 0 additions & 54 deletions
This file was deleted.

packages/chrono/src/use-cases/AddStageItemUseCase.ts

Lines changed: 0 additions & 93 deletions
This file was deleted.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import ChronoEntry from '../entities/ChronoEntry'
2+
import IDrive from '../gateways/IDrive'
3+
4+
import IBlobRepository from '../repositories/IBlobRepository'
5+
import IEntryRepository from '../repositories/IEntryRepository'
6+
import IObjectRepository from '../repositories/IObjectRepository'
7+
8+
import HashEntryService from '../services/HashEntryService'
9+
10+
interface Params {
11+
path: string
12+
}
13+
14+
export default class AddUseCase {
15+
constructor(
16+
private readonly drive: IDrive,
17+
private readonly objectRepository: IObjectRepository,
18+
private readonly blobRepository: IBlobRepository,
19+
private readonly entryRepository: IEntryRepository
20+
) {}
21+
22+
public async addEntry(path: string) {
23+
const hashService = new HashEntryService(
24+
this.drive,
25+
this.objectRepository,
26+
this.blobRepository
27+
)
28+
29+
// list all workspace entries
30+
const entries = await this.entryRepository.findAll()
31+
32+
const entry = entries.find((entry) => entry.path === path)
33+
34+
if (entry) return entry
35+
36+
const { objectHash } = await hashService.hashEntry(path)
37+
38+
const newEntry = new ChronoEntry(path, objectHash, ChronoEntry.STATUS.Added)
39+
40+
entries.push(newEntry)
41+
42+
await this.entryRepository.saveAll(entries)
43+
44+
return newEntry
45+
}
46+
47+
public async execute({ path }: Params) {
48+
const result = [] as ChronoEntry[]
49+
50+
if (await this.drive.isFile(path)) {
51+
const entry = await this.addEntry(path)
52+
53+
result.push(entry)
54+
55+
return result
56+
}
57+
58+
const files = await this.drive.readdir(path, {
59+
recursive: true,
60+
onlyFiles: true,
61+
})
62+
63+
for await (const file of files) {
64+
const entry = await this.addEntry(`${path}/${file}`)
65+
66+
result.push(entry)
67+
}
68+
69+
return result
70+
}
71+
}

packages/chrono/src/use-cases/InitUseCase.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ export default class InitUseCase {
1818
await this.drive.mkdir('.chrono/stage')
1919

2020
await this.drive.write('.chrono/head', HelperService.encode(''))
21-
await this.drive.write('.chrono/stage/index', HelperService.encode(''))
21+
await this.drive.write('.chrono/index', HelperService.encode('[]'))
2222
}
2323
}

0 commit comments

Comments
 (0)