Add browser implementation

This commit is contained in:
proteriax 2021-10-29 12:18:45 -04:00
parent 26f8485761
commit 28c910c9d7
3 changed files with 99 additions and 3 deletions

View File

@ -24,6 +24,7 @@
"@types/react-dom": "^17.0.9",
"@types/sinon": "^10.0.4",
"@types/sinon-chai": "^3.2.5",
"@types/wicg-file-system-access": "^2020.9.4",
"@typescript-eslint/eslint-plugin": "4.33.0",
"@typescript-eslint/parser": "4.33.0",
"chai": "^4.3.4",
@ -66,6 +67,7 @@
"trailingComma": "es5"
},
"dependencies": {
"buffer": "^6.0.3",
"tiny-invariant": "1.1.0",
"tslib": "2.3.1"
}

11
pnpm-lock.yaml generated
View File

@ -13,8 +13,10 @@ specifiers:
'@types/react-dom': ^17.0.9
'@types/sinon': ^10.0.4
'@types/sinon-chai': ^3.2.5
'@types/wicg-file-system-access': ^2020.9.4
'@typescript-eslint/eslint-plugin': 4.33.0
'@typescript-eslint/parser': 4.33.0
buffer: ^6.0.3
chai: ^4.3.4
chai-as-promised: ^7.1.1
chalk: ^4.1.2
@ -49,6 +51,7 @@ specifiers:
typescript: ^4.4.3
dependencies:
buffer: 6.0.3
tiny-invariant: 1.1.0
tslib: 2.3.1
@ -65,6 +68,7 @@ devDependencies:
'@types/react-dom': 17.0.9
'@types/sinon': 10.0.4
'@types/sinon-chai': 3.2.5
'@types/wicg-file-system-access': 2020.9.4
'@typescript-eslint/eslint-plugin': 4.33.0_d753869925cce96d3eb2141eeedafe57
'@typescript-eslint/parser': 4.33.0_eslint@7.32.0+typescript@4.4.3
chai: 4.3.4
@ -1591,6 +1595,10 @@ packages:
resolution: {integrity: sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==}
dev: true
/@types/wicg-file-system-access/2020.9.4:
resolution: {integrity: sha512-o43jUljwP0ZrQ927mPjGdJaBMfS12nf3VPj6Z52fMucxILrSs8tnfLbMDSn6cP3hrrLChc3SYneeEvecknNVtA==}
dev: true
/@typescript-eslint/eslint-plugin/4.33.0_d753869925cce96d3eb2141eeedafe57:
resolution: {integrity: sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==}
engines: {node: ^10.12.0 || >=12.0.0}
@ -1920,7 +1928,6 @@ packages:
/base64-js/1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
dev: true
/binary-extensions/2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
@ -2074,7 +2081,6 @@ packages:
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
dev: true
/builtin-status-codes/3.0.0:
resolution: {integrity: sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=}
@ -3514,7 +3520,6 @@ packages:
/ieee754/1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: true
/ignore/4.0.6:
resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==}

View File

@ -0,0 +1,89 @@
import { promises as fs, existsSync } from "fs"
import { Buffer } from "buffer"
import type { IAdapter, IFileSystem } from "./index"
function splitPath(path: string) {
const segments = path.split("/")
const filename = segments.pop()!
return [segments, filename] as const
}
export class BrowserAdapter implements IFileSystem {
constructor(private handle: FileSystemDirectoryHandle) {}
static async create() {
const handle = await showDirectoryPicker()
return new BrowserAdapter(handle)
}
private async getDirectoryHandle([first, ...pathSegments]: string[]) {
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 existsSync(path: string): Promise<boolean> {
const [segments, filename] = splitPath(path)
let handle = this.handle
for (const segment of segments) {
handle.values()
const next = await handle.getDirectoryHandle()
}
throw new Error("Method not implemented.")
}
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()
}
readdir(path: string): Promise<string[]> {
throw new Error("Method not implemented.")
}
stat(path: string): Promise<{ isDirectory(): boolean }> {
throw new Error("Method not implemented.")
}
}
/**
* Default Node.js adapter. This can be used while using `opvault.js`
* in a Node.js environment.
*/
const nodeAdapter: IAdapter = {
fs: {
readFile: path => fs.readFile(path, "utf-8"),
readBuffer: path => fs.readFile(path),
writeFile: fs.writeFile,
readdir: fs.readdir,
stat: fs.stat,
existsSync,
},
}
export default nodeAdapter