Compare commits

...

4 Commits

Author SHA1 Message Date
f0c67b8bc4 rewrite uml 2022-06-11 21:48:01 +09:00
9fcbee6633 fix coverage 2022-06-11 21:47:27 +09:00
5f8d2e706e refactor code 2022-06-11 19:59:53 +09:00
7b1f8ddef0 shorten version hash 2022-06-11 19:59:36 +09:00
4 changed files with 178 additions and 101 deletions

View File

@ -53,18 +53,6 @@ class MethodRouterBuilber {
+delete(handler: Handler): this +delete(handler: Handler): this
+build(): Handler +build(): Handler
} }
class ResponseBuilder {
+status: Status
+headers: Record<string, string>
+body?: BodyInit
+setStatus(status: Status): this
+setHeader(key: string, value: string): this
+setBody(body: BodyInit): this
+redirect(location: string): this
+build(): Response
}
class MatchContext
<<Interface>> MatchContext
class Router~T~ { class Router~T~ {
+match(path: string, ctx: MatchContext): T +match(path: string, ctx: MatchContext): T
} }
@ -87,9 +75,23 @@ class TreeRouter~T~ {
MethodRouter <-- MethodRouterBuilber: Create MethodRouter <-- MethodRouterBuilber: Create
Router <|.. MethodRouter Router <|.. MethodRouter
Router <|.. FsRouter Router <|.. FsRouter
```
```mermaid
classDiagram
class ResponseBuilder {
+status: Status
+headers: Record<string, string>
+body?: BodyInit
+setStatus(status: Status): this
+setHeader(key: string, value: string): this
+setBody(body: BodyInit): this
+redirect(location: string): this
+build(): Response
}
class MatchContext
<<Interface>> MatchContext
Response <-- ResponseBuilder: Create Response <-- ResponseBuilder: Create
``` ```
```mermaid ```mermaid
classDiagram classDiagram
class ChunkMethodAction { class ChunkMethodAction {
@ -129,17 +131,6 @@ class ChunkMoveAction {
``` ```
```mermaid ```mermaid
classDiagram classDiagram
DocumentObject <|.. FileDocumentObject
class FileDocumentObject {
+docPath: string
+chunks: Chunk[]
+tags: string[]
+updatedAt: number
+tagsUpdatedAt: number
+open(): Promise<void>
+parse(content: unknown[]): void
+save(): Promise<void>
}
class Participant { class Participant {
+id: string +id: string
+user: UserSession +user: UserSession
@ -167,6 +158,21 @@ class ParticipantList {
+unicast(id: string, message: string): void +unicast(id: string, message: string): void
+broadcast(message: string): void +broadcast(message: string): void
} }
ParticipantList o-- Participant
```
```mermaid
classDiagram
DocumentObject <|.. FileDocumentObject
class FileDocumentObject {
+docPath: string
+chunks: Chunk[]
+tags: string[]
+updatedAt: number
+tagsUpdatedAt: number
+open(): Promise<void>
+parse(content: unknown[]): void
+save(): Promise<void>
}
FileDocumentObject <|-- ActiveDocumentObject FileDocumentObject <|-- ActiveDocumentObject
class ActiveDocumentObject { class ActiveDocumentObject {
+conns: Set<Participant> +conns: Set<Participant>
@ -183,7 +189,6 @@ class DocumentStore {
+close(conn: Participant, docPath: string): void +close(conn: Participant, docPath: string): void
+closeAll(conn: Participant): void +closeAll(conn: Participant): void
} }
ParticipantList o-- Participant
DocumentStore o-- ActiveDocumentObject DocumentStore o-- ActiveDocumentObject
``` ```
```mermaid ```mermaid
@ -215,47 +220,84 @@ class RPCNotificationEvent {
``` ```
```mermaid ```mermaid
classDiagram classDiagram
class ViewModelBase { class IDisposable {
+updateAsSource(path: string, updatedAt: number): void +dispose(): void
} }
<<Interface>> ViewModelBase <<Interface>> IDisposable
ViewModelBase <|.. IViewModel
class IViewModel {
+pageView: IPageViewModel
}
<<Interface>> IViewModel
IPageViewModel <|.. BlankPage
class BlankPage {
+type: string
+updateAsSource(_path: string, _updatedAt: number): void
}
IViewModel <|.. ViewModel
class ViewModel {
+pageView: IPageViewModel
+updateAsSource(path: string, updatedAt: number): void
}
ViewModelBase <|.. IPageViewModel
class IPageViewModel {
+type: string
}
<<Interface>> IPageViewModel
IPageViewModel <|.. IDocumentViewModel
class IDocumentViewModel { class IDocumentViewModel {
+updateOnNotification(notification: ChunkNotification): void +docPath: string
+writable: boolean
+updateOnNotification(notification: RPCNotification): void
+useChunks(): [IChunkViewModel[], ChunkListMutator]
+useTags(): [string[], (tags: string[]) => Promise<void>]
+useWritable(): [boolean, (writable: boolean) => Promise<void>]
} }
<<Interface>> IDocumentViewModel <<Interface>> IDocumentViewModel
IDocumentViewModel <|.. DocumentViewModel
IDisposable <|.. DocumentViewModel
class DocumentViewModel {
+type: "document"
+docPath: string
+chunks: ChunkListViewModel
+tags: string[]
+tagsUpdatedAt: number
+manager: IRPCMessageManager
+writable: boolean
+updateOnNotification(notification: RPCNotification): void
+useChunks(): [IChunkViewModel[], ChunkListMutator]
+updateTags(tags: string[], updatedAt: number): void
+useTags(): [string[], (tags: string[]) => Promise<void>]
+useWritable(): [boolean, (writable: boolean) => Promise<void>]
}
ChunkListViewModel ..* DocumentViewModel
```
```mermaid
classDiagram
class IChunkListViewModel {
+docPath: string
+updateOnNotification(notification: RPCNotification): void
+useChunks(): [IChunkViewModel[], ChunkListMutator]
}
<<Interface>> IChunkListViewModel
EventTarget <|-- ChunkListViewModel
IChunkListViewModel <|.. ChunkListViewModel
class ChunkListViewModel {
+chunks: ChunkViewModel[]
+history: ChunkListHistory
+buffer: Inline
+seq: number
+updatedAt: number
+docPath: string
+manager: IRPCMessageManager
+nextSeq: number
+updateOnNotification(notification: RPCNotification): void
-updateMark(updatedAt: number): void
+apply(mutator: ChunkListStateMutator, updatedAt: number, seq: number, refresh?: boolean): void
+refresh(chunks: Chunk[], updatedAt: number): void
-refreshWith(chunkList: (Chunk | ChunkState)[], currentUpdatedAt: number, refresh?: boolean): void
-resolveError(e: Error): void
+useChunks(): [ChunkViewModel[], ChunkListMutator]
}
class ChunkListMutator { class ChunkListMutator {
+add(i?: number | undefined, chunkContent?: ChunkContent | undefined): void +add(i?: number, chunkContent?: ChunkContent): void
+create(i?: number | undefined): void +create(i?: number | undefined): void
+addFromText(i: number, text: string): void +addFromText(i: number, text: string): void
+del(id: string): void +del(id: string): void
+move(id: string, pos: number): void +move(id: string, pos: number): void
} }
<<Interface>> ChunkListMutator <<interface>> ChunkListMutator
class ChunkListState { class ChunkListHistory {
+chunks: Chunk[] +history: ChunkListHistoryElem[]
+cloen(): ChunkListState +limit: number
-applyLast(mutator: ChunkListStateMutator, updatedAt: number): void
+current: ChunkListState
+currentUpdatedAt: number
+revoke(): void
+apply(mutator: ChunkListStateMutator, updatedAt: number): boolean
} }
class ChunkListStateMutator class ChunkListStateMutator
<<Interface>> ChunkListStateMutator <<Interface>> ChunkListStateMutator
class ChunkListHistory { class ChunkListHistory {
@ -267,38 +309,12 @@ class ChunkListHistory {
+revoke(): void +revoke(): void
+apply(mutator: ChunkListStateMutator, updatedAt: number): boolean +apply(mutator: ChunkListStateMutator, updatedAt: number): boolean
} }
class ChunkMutator {
+setType(t: ChunkContentType): void
+setContent(s: string): void
}
<<Interface>> ChunkMutator
IDocumentViewModel <|.. DocumentViewModel
class DocumentViewModel {
+type: "document"
+docPath: string
+chunks: Chunk[]
+history: ChunkListHistory
+buffer: Inline
+seq: number
+tags: string[]
+updatedAt: number
+tagsUpdatedAt: number
+updateOnNotification(notification: ChunkNotification): void
-updateMark(updatedAt: number): void
+apply(mutator: ChunkListStateMutator, updatedAt: number, seq: number, refresh?: boolean): void
+updateAsSource(_path: string, _updatedAt: number): void
+useChunks(): [Chunk[], ChunkListMutator]
+useTags(): [string[], (tags: string[]) => Promise<void>]
+useChunk(chunk_arg: Chunk): [Chunk, ChunkMutator]
}
IViewModel ..> "1" IPageViewModel
ViewModel ..> "1" IPageViewModel
ChunkListHistory ..> "1" ChunkListStateMutator ChunkListHistory ..> "1" ChunkListStateMutator
ChunkListHistory ..> "1" ChunkListState ChunkListHistory ..> "1" ChunkListState
DocumentViewModel ..> "1" ChunkListHistory ChunkListViewModel *.. ChunkListHistory
DocumentViewModel ..> "1" ChunkListStateMutator ChunkListViewModel ..> "1" ChunkListStateMutator
DocumentViewModel ..> "1" ChunkListMutator IChunkListViewModel ..> "1" ChunkListMutator
DocumentViewModel ..> "1" ChunkMutator ChunkViewModel ..* ChunkListViewModel
``` ```
```mermaid ```mermaid
classDiagram classDiagram
@ -313,35 +329,78 @@ ChunkListStateMutator <|.. ChunkListStateDeleteMutator
ChunkListStateMutator <|.. ChunkListStateModifyMutator ChunkListStateMutator <|.. ChunkListStateModifyMutator
ChunkListStateMutator <|.. ChunkListStateMoveMutator ChunkListStateMutator <|.. ChunkListStateMoveMutator
``` ```
```mermaid ```mermaid
classDiagram classDiagram
class ChunkMutator {
+setType(t: ChunkType): void
+setContent(s: string): void
}
<<Interface>> ChunkMutator
class IChunkViewModel {
+parent: IChunkListViewModel
+id: string
+focus(): void
+unfocus(): void
+useFocus(): boolean
+useChunk(): [Chunk, ChunkMutator]
+setState(state: ChunkState): void
}
<<Interface>> IChunkViewModel
EventTarget <|-- ChunkViewModel
IChunkViewModel <|.. ChunkViewModel
class ChunkViewModel {
+chunk: Chunk
+updatedAt: number
+focused: boolean
+overwrite?: Chunk | undefined
+parent: ChunkListViewModel
+manager: IRPCMessageManager
+id: string
+focus(): void
+unfocus(): void
+useFocus(): boolean
+content: ChunkContent
+setState(state: ChunkState): void
+useChunk(): [Chunk, ChunkMutator]
}
IChunkViewModel ..> "1" ChunkMutator
```
```mermaid
classDiagram
EventTarget <|.. IRPCMessageManager
class IRPCMessageManager { class IRPCMessageManager {
+opened: boolean +opened: boolean
+close(): void +close(): void
+sendNotification(notification: ChunkNotification): void +sendNotification(notification: RPCNotification): void
+addEventListener(name: "notification", listener: RPCMessageMessagerEventListener): void +addEventListener(name: "notification", listener: RPCMessageMessagerEventListener): void
+addEventListener(name: string, listener: EventListenerOrEventListenerObject): void
+removeEventListener(name: "notification", listener: RPCMessageMessagerEventListener): void +removeEventListener(name: "notification", listener: RPCMessageMessagerEventListener): void
+removeEventListener(name: string, listener: EventListenerOrEventListenerObject): void
+invokeMethod(m: RPCMessageBody): Promise<RPCResponse> +invokeMethod(m: RPCMessageBody): Promise<RPCResponse>
} }
<<Interface>> IRPCMessageManager <<Interface>> IRPCMessageManager
EventTarget <|-- RPCMessageManager
IRPCMessageManager <|.. RPCMessageManager IRPCMessageManager <|.. RPCMessageManager
class RPCMessageManager { class RPCMessageManager {
-callbackList: Map<number, RPCCallback> -callbackList: Map<number, RPCCallback>
-curId: number -curId: number
-ws?: WebSocket | undefined -ws?: WebSocket | undefined
+opened: boolean +opened: boolean
+openedURL: string | undefined
+open(url: string | URL, protocals?: string | undefined): Promise<void> +open(url: string | URL, protocals?: string | undefined): Promise<void>
+close(): void +close(): void
-genId(): number -genId(): number
+genHeader(): Inline +genHeader(): Inline
+send(message: RPCMethod): Promise<RPCResponse> +send(message: RPCMethod): Promise<RPCResponse>
+sendNotification(message: ChunkNotification): void +sendNotification(message: RPCNotification): void
+addEventListener(type: "notification", callback: RPCMessageMessagerEventListener): void +addEventListener(type: "notification", callback: RPCMessageMessagerEventListener): void
+removeEventListener(type: "notification", callback: RPCMessageMessagerEventListener): void +removeEventListener(type: "notification", callback: RPCMessageMessagerEventListener): void
+invokeMethod(m: RPCMessageBody): Promise<RPCResponse> +invokeMethod(m: RPCMessageBody): Promise<RPCResponse>
} }
```
```mermaid
classDiagram
class FsDirEntry { class FsDirEntry {
+name: string +name: string
+isDirectory: boolean +isDirectory: boolean
@ -364,33 +423,48 @@ class FsGetResult {
+entries?: FsDirEntry[] | undefined +entries?: FsDirEntry[] | undefined
} }
<<Interface>> FsGetResult <<Interface>> FsGetResult
Event <|-- FileEvent
class FileEvent~T~ {
+kind: T
+path: string[]
}
class IFsEventMap { class IFsEventMap {
+modify: (this: IFsManager, event: MessageEvent<NotImplemented>) => void +modify: FileEvent<"modify">
+create: (this: IFsManager, event: MessageEvent<NotImplemented>) => void +create: FileEvent<"create">
+delete: (this: IFsManager, event: MessageEvent<NotImplemented>) => void +remove: FileEvent<"remove">
} }
<<Interface>> IFsEventMap <<Interface>> IFsEventMap
EventTarget <|.. IFsManager
class IFsManager { class IFsManager {
+getURL(filePath: string): URL
+get(path: string): Promise<Response> +get(path: string): Promise<Response>
+getStat(path: string): Promise<FsGetResult> +getStat(path: string): Promise<FsGetResult>
+upload(filePath: string, data: BodyInit): Promise<number> +upload(filePath: string, data: BodyInit): Promise<number>
+delete(filePath: string): Promise<number> +delete(filePath: string): Promise<number>
+rename(oldPath: string, newPath: string): Promise<number>
+mkdir(path: string): Promise<number> +mkdir(path: string): Promise<number>
+addEventListener(name: string, listener: EventListenerOrEventListenerObject): void +addEventListener(type: T, listener: EventHandler~T~): void
+removeEventListener(name: string, listener: EventListenerOrEventListenerObject): void +removeEventListener(type: T, listener: EventHandler~T~): void
+dispatchEvent(event: Event): boolean +dispatchEvent(event: Event): boolean
} }
<<Interface>> IFsManager <<Interface>> IFsManager
EventTarget <|-- FsManager
IFsManager <|.. FsManager IFsManager <|.. FsManager
class FsManager { class FsManager {
-manager: RPCMessageManager -manager: IRPCMessageManager
-prefix: string -url: string
+get(path: string): Promise<Response> +addEventListener(type: T, listener: EventHandler~T~): void
+removeEventListener(type: T, listener: EventHandler~T~): void
+getURL(filePath: string): URL
-#fetchRequest(filePath: string | URL, init?: RequestInit | undefined): Promise<Response>
+get(filePath: string): Promise<Response>
+getStat(filePath: string): Promise<FsGetResult> +getStat(filePath: string): Promise<FsGetResult>
+upload(filePath: string, data: BodyInit): Promise<number> +upload(filePath: string, data: BodyInit): Promise<number>
+mkdir(filePath: string): Promise<number> +mkdir(filePath: string): Promise<number>
+delete(filePath: string): Promise<number> +delete(filePath: string): Promise<number>
+rename(oldPath: string, newPath: string): Promise<number>
} }
FsGetResult ..> "*" FsDirEntry FsGetResult ..> "*" FsDirEntry
IFsEventMap ..> "1" IFsManager IFsEventMap ..> "1" IFsManager
IFsManager ..> "1" FsGetResult IFsManager ..> "1" FsGetResult

View File

@ -2,12 +2,12 @@
> Version : 1.1.0 > Version : 1.1.0
> >
> Version Hash : <%= it.gitHash %> > Version Hash : <%= it.gitHash.substring(0,7) %>
> >
> 본 문서는 전북대학교 컴퓨터공학과의 Floor 팀에서 Scrap Yard라는 어플리케이션을 > 본 문서는 전북대학교 컴퓨터공학과의 Floor 팀에서 Scrap Yard라는 어플리케이션을
> 설계 및 구현하기 위한 소프트웨어 요구사항 명세서(SRS)이자 어플리케이션의 구조를 > 설계 및 구현하기 위한 소프트웨어 요구사항 명세서(SRS)이자 어플리케이션의 구조를
> 나타내는 설계서이자 어플리케이션의 시험 결과 보고서이다. 정리하면 어플리케이션을 > 나타내는 설계서이자 어플리케이션의 시험 결과 보고서이다. 정리하면 어플리케이션을
> 개발하면서 발생하는 산출물들을 정리한 문서이다. > 개발하면서 발생하는 산출물들을 정리한 문서이다.
## 1.1. 목적(Purpose) ## 1.1. 목적(Purpose)

View File

@ -12,12 +12,14 @@
## 4.3. 일정표(Schedule) ## 4.3. 일정표(Schedule)
일정은 다음 표와 같다.
<% <%
const getIssueByNumber = (n) => it.issues.filter(x=> x.number === n)[0]; const getIssueByNumber = (n) => it.issues.filter(x=> x.number === n)[0];
const trId= (n)=>{ const trId= (n)=>{
const title = getIssueByNumber(n).title; const title = getIssueByNumber(n).title;
return `(#${n}) ${title}`.replaceAll(/[^A-Za-z\s0-9]/gi,"").toLocaleLowerCase().replaceAll(" ","-"); return it.toHeadId(`(#${n}) ${title}`);
} }
const inTable = (arr) => { const inTable = (arr) => {
return arr.map(x=> `[#${x}](./specific.md#${trId(x)})`).join(', ') return arr.map(x=> `[#${x}](./specific.md#${trId(x)})`).join(', ')

View File

@ -2,7 +2,8 @@
## 6.1 유닛 테스트(Unit test) ## 6.1 유닛 테스트(Unit test)
유닛 테스트로 63.7%의 Line Coverage와 67.5%의 Function Coverage를 달성했다. 유닛 테스트로 63.7%의 Line Coverage와 67.5%의 Function Coverage, 61.5%의 Branch Coverage를 달성했다.
### permission.test.ts ### permission.test.ts
| name | result | duration | | name | result | duration |
| ---- | ------ | -------- | | ---- | ------ | -------- |