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