Skip to content

Commit

Permalink
Merge branch 'main' into Notes-100--Comment-Edit-bldrs-ai#1186
Browse files Browse the repository at this point in the history
  • Loading branch information
OlegMoshkovich authored Jun 19, 2024
2 parents 836dc42 + c68605d commit a71be42
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bldrs",
"version": "1.0.1073",
"version": "1.0.1060",
"main": "src/index.jsx",
"license": "AGPL-3.0",
"homepage": "https://github.com/bldrs-ai/Share",
Expand Down
6 changes: 5 additions & 1 deletion src/BaseRoutes.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {useEffect} from 'react'
import {Outlet, Route, Routes, useLocation, useNavigate} from 'react-router-dom'
import ShareRoutes from './ShareRoutes'
import {checkOPFSAvailability} from './OPFS/utils'
import {checkOPFSAvailability, setUpGlobalDebugFunctions} from './OPFS/utils'
import debug from './utils/debug'
import {navWith} from './utils/navigate'
import useStore from './store/useStore'
Expand Down Expand Up @@ -47,6 +47,10 @@ export default function BaseRoutes({testElt = null}) {
const checkAvailability = async () => {
const available = await checkOPFSAvailability()

if (available) {
setUpGlobalDebugFunctions()
}

setIsOpfsAvailable(available)
}

Expand Down
57 changes: 57 additions & 0 deletions src/OPFS/OPFS.worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,69 @@ self.addEventListener('message', async (event) => {
['commitHash', 'originalFilePath', 'owner', 'repo', 'branch'])

await deleteModelFromOPFS(commitHash, originalFilePath, owner, repo, branch)
} else if (event.data.command === 'clearCache') {
await clearCache()
} else if (event.data.command === 'snapshotCache') {
await snapshotCache()
}
} catch (error) {
self.postMessage({error: error.message})
}
})

/**
* Return directory snapshot of OPFS cache
*/
async function snapshotCache() {
const opfsRoot = await navigator.storage.getDirectory()

const directoryStructure = await traverseDirectory(opfsRoot)

// Send the directory structure as a message to the main thread
self.postMessage({completed: true, event: 'snapshot', directoryStructure: directoryStructure})
}

/**
* Given a directory handle, traverse the directory
*/
async function traverseDirectory(dirHandle, path = '') {
let entries = ''
for await (const [name, handle] of dirHandle.entries()) {
if (handle.kind === 'directory') {
entries += `${path}/${name}/\n`
entries += await traverseDirectory(handle, `${path}/${name}`)
} else if (handle.kind === 'file') {
entries += `${path}/${name}\n`
}
}
return entries
}

/**
* Clear OPFS cache
*/
async function clearCache() {
const opfsRoot = await navigator.storage.getDirectory()
await deleteAllEntries(opfsRoot)

// Send the directory structure as a message to the main thread
self.postMessage({completed: true, event: 'clear'})
}

/**
* Delete all entries for a given directory handle
*/
async function deleteAllEntries(dirHandle) {
for await (const [name, handle] of dirHandle.entries()) {
if (handle.kind === 'directory') {
await deleteAllEntries(handle)
await dirHandle.removeEntry(name, {recursive: true})
} else if (handle.kind === 'file') {
await dirHandle.removeEntry(name)
}
}
}

/**
*
*/
Expand Down
28 changes: 28 additions & 0 deletions src/OPFS/OPFSService.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,34 @@ export function opfsReadModel(modelKey) {
})
}

/**
* Clears the OPFS cache
*/
export function opfsClearCache() {
if (!workerRef) {
debug().error('Worker not initialized')
return
}

workerRef.postMessage({
command: 'clearCache',
})
}

/**
* Retrives a directory snapshot of the opfs cache.
*/
export function opfsSnapshotCache() {
if (!workerRef) {
debug().error('Worker not initialized')
return
}

workerRef.postMessage({
command: 'snapshotCache',
})
}

/**
* Sets a callback function to handle messages from the worker.
*
Expand Down
38 changes: 38 additions & 0 deletions src/OPFS/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
opfsWriteModelFileHandle,
opfsDoesFileExist,
opfsDeleteModel,
opfsSnapshotCache,
opfsClearCache,
} from '../OPFS/OPFSService.js'
import {assertDefined} from '../utils/assert'
import debug from '../utils/debug'
Expand Down Expand Up @@ -186,6 +188,16 @@ function makePromise(callback, originalFilePath, commitHash, owner, repo, branch
resolve(false) // Resolve the promise with false
} else if (event.data.event === eventStatus) {
workerRef.removeEventListener('message', listener) // Remove the event listener

if (event.data.event === 'clear') {
// eslint-disable-next-line no-console
console.log('OPFS cache cleared.')
}

if (event.data.directoryStructure) {
// eslint-disable-next-line no-console
console.log(`OPFS Directory Structure:\n${ event.data.directoryStructure}`)
}
resolve(true) // Resolve the promise with true
}
}
Expand Down Expand Up @@ -220,6 +232,24 @@ export function doesFileExistInOPFS(
return makePromise(opfsDoesFileExist, originalFilePath, commitHash, owner, repo, branch, 'exist')
}

/**
* Prints a snapshot of the OPFS directory structure
*
* @return {boolean}
*/
export function snapshotOPFS() {
return makePromise(opfsSnapshotCache, null, null, null, null, null, 'snapshot')
}

/**
* Deletes entirety of OPFS cache
*
* @return {boolean}
*/
export function clearOPFSCache() {
return makePromise(opfsClearCache, null, null, null, null, null, 'clear')
}

/**
* Deletes a file from opfs if it exists.
* Returns true if file was found and deleted, false otherwise.
Expand Down Expand Up @@ -317,3 +347,11 @@ export async function checkOPFSAvailability() {
return false
}
}

/**
*
*/
export function setUpGlobalDebugFunctions() {
window.snapshotOPFS = snapshotOPFS
window.clearOPFSCache = clearOPFSCache
}
44 changes: 43 additions & 1 deletion src/OPFS/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
downloadToOPFS,
doesFileExistInOPFS,
deleteFileFromOPFS,
checkOPFSAvailability} from './utils'
checkOPFSAvailability,
snapshotOPFS,
clearOPFSCache} from './utils'


jest.mock('../OPFS/OPFSService.js')
Expand Down Expand Up @@ -295,4 +297,44 @@ describe('OPFS Test Suite', () => {
expect(result).toBe(false)
})
})

describe('snapshotOPFS', () => {
it('should resolve true if the snapshot was retrieved', async () => {
const mockWorker = {
addEventListener: jest.fn((_, handler) => {
// Simulate successful file deletion
process.nextTick(() => handler({data: {completed: true, event: 'snapshot', directoryStructure: []}}))
}),
removeEventListener: jest.fn(),
}
OPFSService.initializeWorker.mockReturnValue(mockWorker)

const result = await snapshotOPFS()

expect(result).toBe(true)
expect(OPFSService.initializeWorker).toHaveBeenCalled()
expect(mockWorker.addEventListener).toHaveBeenCalled()
expect(mockWorker.removeEventListener).toHaveBeenCalledTimes(1)
})
})

describe('clearOPFS', () => {
it('should resolve true if the OPFS cache was cleared', async () => {
const mockWorker = {
addEventListener: jest.fn((_, handler) => {
// Simulate successful file deletion
process.nextTick(() => handler({data: {completed: true, event: 'clear'}}))
}),
removeEventListener: jest.fn(),
}
OPFSService.initializeWorker.mockReturnValue(mockWorker)

const result = await clearOPFSCache()

expect(result).toBe(true)
expect(OPFSService.initializeWorker).toHaveBeenCalled()
expect(mockWorker.addEventListener).toHaveBeenCalled()
expect(mockWorker.removeEventListener).toHaveBeenCalledTimes(1)
})
})
})

0 comments on commit a71be42

Please sign in to comment.