work on typings, start implementing PosixSource

This commit is contained in:
joshuaboud 2022-08-23 18:18:21 -03:00
parent 87e4c72898
commit 9644b86dd4
No known key found for this signature in database
GPG Key ID: 17EFB59E2A8BF50E
7 changed files with 165 additions and 95 deletions

View File

@ -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<SourceType extends Source<Location>>(factory: (ctx: SourceContext) => SourceType) {
return factory;
return {
items
}
}

View File

@ -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<ItemType extends Location, FileType extends Location = ItemType, DirectoryType extends Location = ItemType, LinkType extends Location = ItemType> {
displayTransform(item: Readonly<ItemType>): ItemDisplay<ItemType>;
list(path?: string): Promise<ItemType[]>;
lookup(path: string): Promise<ItemType>;
createFile?(path: string, opts?: Readonly<Source.CreateOptions>): Promise<FileType>;
createDirectory?(path: string, opts?: Readonly<Source.CreateOptions>): Promise<DirectoryType>;
createLink?(path: string, targetLocation: string, opts?: Readonly<Source.CreateOptions>): Promise<LinkType>;
delete?(item: ItemType, opts?: Readonly<Source.DeleteOptions>): Promise<ItemType>;
moveToTrash?(item: ItemType, opts?: Readonly<Source.DeleteOptions>): Promise<ItemType>;
read?(item: FileType): Promise<Uint8Array>;
write?(item: FileType, data: Uint8Array): Promise<FileType>;
getPermissions?(item: Location): Promise<Location & ItemPermissions>;
setPermissions?(item: Location & Partial<ItemPermissions>, newPermissions?: Partial<ItemPermissions>): Promise<Location & ItemPermissions>;
download?(item: Location, options: Source.DownloadOptions): Promise<Location>;
download?(items: Location[], options: Source.DownloadOptions): Promise<Location>;
upload?(dataTransfer: DataTransfer): Promise<Location | Location[]>;
}
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<ItemType, FileType, DirectoryType, LinkType>}) => ctor;

View File

@ -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<ItemPosixLink, 'source'> | Omit<ItemPosi
}
}
}
export async function list(path?: string) {
}

View File

@ -1,20 +1,74 @@
import { defineSource } from "../../../composables/SourceAdapter";
import { Source } from "../../../types/Source";
import { ItemPosix } from "./types";
import { ItemDisplay } from '@/types/FrontEnd';
import { defineSource, Source, SourceStatic } from '@/lib/Source';
import { SourceError } from '@/lib/Error';
import { ItemPosix, LsType } from './types';
export default defineSource(({ notifications }) => {
return class SourcePosix implements Source<ItemPosix> {
constructor(private root: string, private host: string) { }
private async getRecords(location: string): Promise<string[]> {
return [
""
]
export class SourcePosixError extends SourceError { }
export default defineSource(class SourcePosix implements Source<ItemPosix> {
static readonly sourceTypeId = "fs";
constructor(private root: string, private host: string) { }
displayTransform(item: ItemPosix): ItemDisplay<ItemPosix> {
const sourceItem = item;
let displayType: ItemDisplay<ItemPosix>['displayType'];
let isLink: ItemDisplay<ItemPosix>['isLink'];
let isBrokenLink: ItemDisplay<ItemPosix>['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<ItemPosix> {
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<ItemPosix> {
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,
}
}
})
});

View File

@ -7,7 +7,8 @@ export namespace ItemDisplay {
export interface ItemDisplay<SourceItemType extends Location> {
sourceItem: SourceItemType;
name: string;
displayType: 'file' | 'directory';
isLink: true;
displayType: 'directory' | 'file';
isLink: boolean;
isBrokenLink: boolean;
mimetype?: ItemDisplay.mimetype;
}

View File

@ -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<ItemType extends Location, FileType extends Location = ItemType, DirectoryType extends Location = ItemType, LinkType extends Location = ItemType> {
displayTransform(item: ItemType): ItemDisplay<ItemType>;
async list(path?: string): Promise<ItemType[]>;
async lookup(path: string): Promise<ItemType>;
async createFile?(path: string, opts?: Source.CreateOptions): Promise<FileType>;
async createDirectory?(path: string, opts?: Source.CreateOptions): Promise<DirectoryType>;
async createLink?(path: string, targetLocation: string, opts?: Source.CreateOptions): Promise<LinkType>;
async delete?(item: ItemType, opts?: Source.DeleteOptions): Promise<ItemType>;
async moveToTrash?(item: ItemType, opts?: Source.DeleteOptions): Promise<ItemType>;
async read?(item: FileType): Promise<Uint8Array>;
async write?(item: FileType, data: Uint8Array): Promise<FileType>;
async getPermissions?(item: Location): Promise<Location & ItemPermissions>;
async setPermissions?(item: Location & Partial<ItemPermissions>, newPermissions?: Partial<ItemPermissions>): Promise<Location & ItemPermissions>;
async download?(item: Location, options: Source.DownloadOptions): Promise<Location>;
async download?(items: Location[], options: Source.DownloadOptions): Promise<Location>;
async upload?(dataTransfer: DataTransfer): Promise<Location | Location[]>;
}

View File

@ -1,3 +0,0 @@
declare global {
var cockpit = {};
}