From 9644b86dd40b6e5907aee2b9711221812b6ecf2a Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Tue, 23 Aug 2022 18:18:21 -0300 Subject: [PATCH] work on typings, start implementing PosixSource --- navigator/src/composables/SourceAdapter.ts | 20 +++-- navigator/src/lib/Source.ts | 75 +++++++++++++++++++ navigator/src/lib/sources/POSIX/find.ts | 7 +- navigator/src/lib/sources/POSIX/index.ts | 86 ++++++++++++++++++---- navigator/src/types/FrontEnd.d.ts | 5 +- navigator/src/types/Source.d.ts | 64 ---------------- navigator/src/types/cockpit.d.ts | 3 - 7 files changed, 165 insertions(+), 95 deletions(-) create mode 100644 navigator/src/lib/Source.ts delete mode 100644 navigator/src/types/Source.d.ts delete mode 100644 navigator/src/types/cockpit.d.ts diff --git a/navigator/src/composables/SourceAdapter.ts b/navigator/src/composables/SourceAdapter.ts index b16e983..f99f93e 100644 --- a/navigator/src/composables/SourceAdapter.ts +++ b/navigator/src/composables/SourceAdapter.ts @@ -1,11 +1,15 @@ -import { Source } from "../types/Source"; -import { Location } from "../types/Location"; -import { INotifications } from "../types/Notifications"; +import { ref } from 'vue'; +import { useRoute } from 'vue-router'; +import { Source } from "@/lib/Source"; +import { Location } from "@/types/Location"; +import { INotifications } from "@/types/Notifications"; -export interface SourceContext { - notifications: INotifications; -} +export default function useSourceAdapter() { + let source; + const items = ref([]); + const route = useRoute(); -export function defineSource>(factory: (ctx: SourceContext) => SourceType) { - return factory; + return { + items + } } diff --git a/navigator/src/lib/Source.ts b/navigator/src/lib/Source.ts new file mode 100644 index 0000000..62dee4c --- /dev/null +++ b/navigator/src/lib/Source.ts @@ -0,0 +1,75 @@ +import { ItemDisplay } from '@/types/FrontEnd'; +import { Location } from '@/types/Location'; + +export interface ItemPermissions { + owner: string | number; + group: string | number; + mode: number; +} + +export namespace Source { + export interface CreateOptions { + /** + * If a file/link already exists at the specified path, and is the same type as what is being created, overwrite it. + * Cannot overwrite directories. + */ + overwrite?: boolean; + /** + * If a file/link already exists at the specified path, overwrite it regardless of original type. + * Cannot overwrite directories. + */ + forceOverwrite?: boolean; + /** + * If the path does not exist, create parent directories. + * Analogous to `mkdir -p` + */ + parents?: boolean; + } + export interface DeleteOptions { + /** + * For directories, delete all children. If not specified for non-empty directory, deletion will fail. + */ + recursive?: boolean; + } + export interface DownloadOptions { + /** + * Compress files/directories into archive before downloading + */ + zip?: boolean; + } +} + +export interface Source { + displayTransform(item: Readonly): ItemDisplay; + + list(path?: string): Promise; + lookup(path: string): Promise; + + createFile?(path: string, opts?: Readonly): Promise; + createDirectory?(path: string, opts?: Readonly): Promise; + createLink?(path: string, targetLocation: string, opts?: Readonly): Promise; + + delete?(item: ItemType, opts?: Readonly): Promise; + moveToTrash?(item: ItemType, opts?: Readonly): Promise; + + read?(item: FileType): Promise; + write?(item: FileType, data: Uint8Array): Promise; + + getPermissions?(item: Location): Promise; + setPermissions?(item: Location & Partial, newPermissions?: Partial): Promise; + + download?(item: Location, options: Source.DownloadOptions): Promise; + download?(items: Location[], options: Source.DownloadOptions): Promise; + upload?(dataTransfer: DataTransfer): Promise; +} + +export interface SourceStatic { + readonly sourceTypeId: string; +} + +export const defineSource = < + ItemType extends Location, + FileType extends Location = ItemType, + DirectoryType extends Location = ItemType, + LinkType extends Location = ItemType +>(ctor: SourceStatic & { new (...args: any[]): Source}) => ctor; diff --git a/navigator/src/lib/sources/POSIX/find.ts b/navigator/src/lib/sources/POSIX/find.ts index 9511c25..51c0488 100644 --- a/navigator/src/lib/sources/POSIX/find.ts +++ b/navigator/src/lib/sources/POSIX/find.ts @@ -1,6 +1,5 @@ -import { Source } from "../../../types/Source"; import { ItemPosix, ItemPosixLink, ItemPosixNonLink, LsType } from "./types"; -import { UNIT_SEPARATOR, RECORD_SEPARATOR } from "../../constants"; +import { UNIT_SEPARATOR, RECORD_SEPARATOR } from "@/constants"; const findPrintfDirectives = [ '%p', // full path @@ -149,3 +148,7 @@ function makeItem(record: string): Omit | Omit { - return class SourcePosix implements Source { - constructor(private root: string, private host: string) { } - private async getRecords(location: string): Promise { - return [ - "" - ] +export class SourcePosixError extends SourceError { } + +export default defineSource(class SourcePosix implements Source { + static readonly sourceTypeId = "fs"; + constructor(private root: string, private host: string) { } + displayTransform(item: ItemPosix): ItemDisplay { + const sourceItem = item; + let displayType: ItemDisplay['displayType']; + let isLink: ItemDisplay['isLink']; + let isBrokenLink: ItemDisplay['isBrokenLink']; + + switch (item.type) { + case LsType.DIRECTORY: + isLink = isBrokenLink = false; + displayType = 'directory'; + break; + case LsType.LINK: + isLink = true; + isBrokenLink = false; + switch (item.targetType) { + case LsType.DIRECTORY: + displayType = 'directory'; + break; + case LsType.LINK_BROKEN: + case LsType.LINK_LOOP: + isBrokenLink = true; + /* fall through */ + default: + displayType = 'file'; + break; + } + default: + isLink = isBrokenLink = false; + displayType = 'file'; + break; } - async list(path: string = ""): Promise<(ItemPosix)[]> { - return (await this.getRecords(this.root + path)).map(record => this.makeItem(record)); - } - async lookup(path: string): Promise { - return this.makeItem(this.getRecords(this.root + location)[0]) + + return { + name: item.name, + sourceItem, + displayType, + isLink, + isBrokenLink, + }; + } + async list(path: string = ""): Promise<(ItemPosix)[]> { + return []; + } + async lookup(path: string): Promise { + return { + source: this, + path, + name: 'test', + st_dev: 0, + st_ino: 0, + st_mode: 0, + st_uid: 0, + user: 'jimmy', + st_gid: 0, + group: 'bob', + st_size: 0, + st_atime: 0, + st_mtime: 0, + st_ctime: 0, + st_btime: 0, + type: LsType.REGULAR_FILE, } } -}) +}); diff --git a/navigator/src/types/FrontEnd.d.ts b/navigator/src/types/FrontEnd.d.ts index ac04931..8c824ab 100644 --- a/navigator/src/types/FrontEnd.d.ts +++ b/navigator/src/types/FrontEnd.d.ts @@ -7,7 +7,8 @@ export namespace ItemDisplay { export interface ItemDisplay { sourceItem: SourceItemType; name: string; - displayType: 'file' | 'directory'; - isLink: true; + displayType: 'directory' | 'file'; + isLink: boolean; + isBrokenLink: boolean; mimetype?: ItemDisplay.mimetype; } diff --git a/navigator/src/types/Source.d.ts b/navigator/src/types/Source.d.ts deleted file mode 100644 index b0a6ba7..0000000 --- a/navigator/src/types/Source.d.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { ItemDisplay } from "./FrontEnd"; -import { Location } from "./Location"; - -export interface ItemPermissions { - owner: string | number; - group: string | number; - mode: number; -} - -export namespace Source { - export interface CreateOptions { - /** - * If a file/link already exists at the specified path, and is the same type as what is being created, overwrite it. - * Cannot overwrite directories. - */ - overwrite?: boolean; - /** - * If a file/link already exists at the specified path, overwrite it regardless of original type. - * Cannot overwrite directories. - */ - forceOverwrite?: boolean; - /** - * If the path does not exist, create parent directories. - * Analogous to `mkdir -p` - */ - parents?: boolean; - } - export interface DeleteOptions { - /** - * For directories, delete all children. If not specified for non-empty directory, deletion will fail. - */ - recursive?: boolean; - } - export interface DownloadOptions { - /** - * Compress files/directories into archive before downloading - */ - zip?: boolean; - } -} - -export interface Source { - displayTransform(item: ItemType): ItemDisplay; - - async list(path?: string): Promise; - async lookup(path: string): Promise; - - async createFile?(path: string, opts?: Source.CreateOptions): Promise; - async createDirectory?(path: string, opts?: Source.CreateOptions): Promise; - async createLink?(path: string, targetLocation: string, opts?: Source.CreateOptions): Promise; - - async delete?(item: ItemType, opts?: Source.DeleteOptions): Promise; - async moveToTrash?(item: ItemType, opts?: Source.DeleteOptions): Promise; - - async read?(item: FileType): Promise; - async write?(item: FileType, data: Uint8Array): Promise; - - async getPermissions?(item: Location): Promise; - async setPermissions?(item: Location & Partial, newPermissions?: Partial): Promise; - - async download?(item: Location, options: Source.DownloadOptions): Promise; - async download?(items: Location[], options: Source.DownloadOptions): Promise; - async upload?(dataTransfer: DataTransfer): Promise; -} diff --git a/navigator/src/types/cockpit.d.ts b/navigator/src/types/cockpit.d.ts deleted file mode 100644 index c496ed5..0000000 --- a/navigator/src/types/cockpit.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare global { - var cockpit = {}; -}