Restructure files
This commit is contained in:
6
packages/adapters/package.json
Normal file
6
packages/adapters/package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "opvault-adapters",
|
||||
"dependencies": {
|
||||
"opvault.js": "*"
|
||||
}
|
||||
}
|
117
packages/adapters/src/showDirectoryPicker.ts
Normal file
117
packages/adapters/src/showDirectoryPicker.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import { Buffer } from "buffer"
|
||||
import type { IAdapter, IFileSystem } from "opvault.js/src/adapter"
|
||||
|
||||
function normalize(path: string) {
|
||||
return path.replace(/^\//, "")
|
||||
}
|
||||
|
||||
function splitPath(path: string) {
|
||||
const segments = normalize(path).split("/")
|
||||
const filename = segments.pop()!
|
||||
return [segments, filename] as const
|
||||
}
|
||||
|
||||
export class FileSystem implements IFileSystem {
|
||||
constructor(private handle: FileSystemDirectoryHandle) {}
|
||||
|
||||
private async getDirectoryHandle(segments: string[]) {
|
||||
if (!segments.length || (segments.length === 1 && !segments[0])) {
|
||||
return this.handle
|
||||
}
|
||||
const [first, ...pathSegments] = segments
|
||||
const handle = await pathSegments.reduce(
|
||||
async (accum, next) => (await accum).getDirectoryHandle(next),
|
||||
this.handle.getDirectoryHandle(first)
|
||||
)
|
||||
return handle
|
||||
}
|
||||
|
||||
private async getFileHandle(path: string) {
|
||||
const [segments, filename] = splitPath(path)
|
||||
const dirHandle = await this.getDirectoryHandle(segments)
|
||||
const fileHandle = await dirHandle.getFileHandle(filename)
|
||||
return fileHandle
|
||||
}
|
||||
|
||||
async readFile(path: string) {
|
||||
const handle = await this.getFileHandle(path)
|
||||
const file = await handle.getFile()
|
||||
return file.text()
|
||||
}
|
||||
|
||||
async exists(path: string): Promise<boolean> {
|
||||
if (path === "/") {
|
||||
return true
|
||||
}
|
||||
|
||||
const [segments, filename] = splitPath(path)
|
||||
let { handle } = this
|
||||
for (const segment of segments) {
|
||||
try {
|
||||
handle = await handle.getDirectoryHandle(segment)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
(await success(() => handle.getFileHandle(filename))) ||
|
||||
(await success(() => handle.getDirectoryHandle(filename)))
|
||||
)
|
||||
}
|
||||
|
||||
async readBuffer(path: string): Promise<Buffer> {
|
||||
const handle = await this.getFileHandle(path)
|
||||
const file = await handle.getFile()
|
||||
return Buffer.from(await file.arrayBuffer())
|
||||
}
|
||||
|
||||
async writeFile(path: string, data: string): Promise<void> {
|
||||
const handle = await this.getFileHandle(path)
|
||||
const writable = await handle.createWritable()
|
||||
await writable.write(data)
|
||||
await writable.close()
|
||||
}
|
||||
|
||||
async readdir(path: string): Promise<string[]> {
|
||||
const segments = normalize(path).split("/")
|
||||
const dirHandle = await this.getDirectoryHandle(segments)
|
||||
const keys: string[] = []
|
||||
for await (const key of dirHandle.keys()) {
|
||||
keys.push(key)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
async isDirectory(path: string) {
|
||||
const [segments, filename] = splitPath(path)
|
||||
const dirHandle = await this.getDirectoryHandle(segments)
|
||||
for await (const [key, handle] of dirHandle.entries()) {
|
||||
if (key !== filename) continue
|
||||
|
||||
if (handle instanceof FileSystemDirectoryHandle) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function success(fn: () => Promise<any>) {
|
||||
try {
|
||||
await fn()
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Browser adapter.
|
||||
*/
|
||||
export const getBrowserAdapter = (handle: FileSystemDirectoryHandle): IAdapter => ({
|
||||
fs: new FileSystem(handle),
|
||||
subtle: crypto.subtle,
|
||||
})
|
53
packages/adapters/src/webkitdirectory.ts
Normal file
53
packages/adapters/src/webkitdirectory.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { Buffer } from "buffer"
|
||||
import type { IAdapter, IFileSystem } from "opvault.js/src/adapter"
|
||||
|
||||
export class FileSystem implements IFileSystem {
|
||||
private paths = new Set<string>()
|
||||
private pathMap = new Map<string, File>()
|
||||
|
||||
constructor(list: FileList) {
|
||||
for (const file of list) {
|
||||
this.pathMap.set(file.webkitRelativePath, file)
|
||||
this.paths.add(file.webkitRelativePath)
|
||||
}
|
||||
}
|
||||
|
||||
async readFile(path: string) {
|
||||
return this.pathMap.get(path)!.text()
|
||||
}
|
||||
|
||||
async exists(path: string): Promise<boolean> {
|
||||
return this.pathMap.has(path)
|
||||
}
|
||||
|
||||
async readBuffer(path: string): Promise<Buffer> {
|
||||
const arrayBuffer = await this.pathMap.get(path)!.arrayBuffer()
|
||||
return Buffer.from(arrayBuffer)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
async writeFile(path: string, data: string): Promise<void> {
|
||||
throw new Error("fs.writeFile is not supported with webkitdirectory")
|
||||
}
|
||||
|
||||
async readdir(path: string): Promise<string[]> {
|
||||
const paths = [...this.paths]
|
||||
return paths
|
||||
.filter(_ => _.startsWith(`${path}/`))
|
||||
.map(_ => _.slice(path.length + 1))
|
||||
.map(_ => _.split("/")[0])
|
||||
}
|
||||
|
||||
async isDirectory(path: string) {
|
||||
const paths = [...this.paths]
|
||||
return paths.some(_ => _.startsWith(`${path}/`)) && !paths.includes(path)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Browser adapter.
|
||||
*/
|
||||
export const getBrowserAdapter = (list: FileList): IAdapter => ({
|
||||
fs: new FileSystem(list),
|
||||
subtle: crypto.subtle,
|
||||
})
|
Reference in New Issue
Block a user