remove doc + saf

This commit is contained in:
m
2026-09-11 11:14:20 +02:00
parent 2d9be3f489
commit 6666c5b469
5 changed files with 38 additions and 527 deletions
+17 -42
View File
@@ -4,13 +4,13 @@ import type {
FileEntry,
Folder,
FolderInfo,
PickDirectoryOptions,
} from './safDirectory.types';
import { __setSafWalkImpl, yieldToMainThread } from './safWalk';
export { listFoldersChunked, yieldToMainThread, DEFAULT_WALK_BUDGET_MS } from './safWalk';
// Bootstrap: wire the real SAF implementation for the Expo runtime.
__setSafWalkImpl({
list: listDirectory,
list: listDirectoryEntries,
info: getFolderInfo,
yield: yieldToMainThread,
});
@@ -20,43 +20,23 @@ export async function pickDirectory(initialUri?: string): Promise<Folder | null>
const directory = await Directory.pickDirectoryAsync(initialUri);
if (!directory || !directory.uri) return null;
return toFolder({ uri: directory.uri, name: directory.name, exists: directory.exists });
} catch {
} catch (error) {
console.warn('[safDirectory] pickDirectory failed:', error);
return null;
}
}
export function listDirectory(directoryUri: string): DirectoryEntry[] {
export function listDirectoryEntries(directoryUri: string): DirectoryEntry[] {
const directory = new Directory(directoryUri);
if (!directory.exists) return [];
try {
return directory.list().map(toEntry);
} catch {
} catch (error) {
console.warn('[safDirectory] listDirectoryEntries failed:', error);
return [];
}
}
export function listFolders(directoryUri: string, options: PickDirectoryOptions = {}): Folder[] {
const { recursive = false, includeRoot = false } = options;
if (!recursive) {
return listDirectory(directoryUri).filter((entry): entry is Folder => entry.isDirectory);
}
const result: Folder[] = [];
if (includeRoot) {
result.push({ ...getFolderInfo(directoryUri), isDirectory: true });
}
const visit = (uri: string) => {
for (const entry of listDirectory(uri)) {
if (entry.isDirectory) {
result.push(entry);
visit(entry.uri);
}
}
};
visit(directoryUri);
return result;
}
export function getFolderInfo(directoryUri: string): FolderInfo {
const directory = new Directory(directoryUri);
return {
@@ -66,6 +46,7 @@ export function getFolderInfo(directoryUri: string): FolderInfo {
};
}
/** Creates a directory. Intentionally lets exceptions propagate (permissions, quota, etc). */
export function createDirectory(directoryUri: string, name: string): Folder {
const directory = new Directory(Paths.join(directoryUri, name));
directory.create({ idempotent: true, intermediates: true });
@@ -73,7 +54,10 @@ export function createDirectory(directoryUri: string, name: string): Folder {
}
export function fileFromUri(uri: string): FileEntry {
const file = new File(uri);
return toFileEntry(new File(uri));
}
function toFileEntry(file: File): FileEntry {
return {
uri: file.uri,
name: file.name,
@@ -87,21 +71,12 @@ export function fileFromUri(uri: string): FileEntry {
}
function toEntry(item: Directory | File): DirectoryEntry {
if (item instanceof Directory) {
return toFolder({ uri: item.uri, name: item.name, exists: item.exists });
}
return {
uri: item.uri,
name: item.name,
isDirectory: false,
extension: item.extension,
exists: item.exists,
size: item.size,
type: item.type,
lastModified: item.lastModified,
};
return item instanceof Directory
? toFolder({ uri: item.uri, name: item.name, exists: item.exists })
: toFileEntry(item);
}
// Perf: avoids constructing a Directory when all fields are already provided by the caller.
function toFolder({ uri, name, exists }: { uri: string; name?: string; exists?: boolean }): Folder {
const directory = exists === undefined ? new Directory(uri) : null;
return {
@@ -110,4 +85,4 @@ function toFolder({ uri, name, exists }: { uri: string; name?: string; exists?:
isDirectory: true,
exists: exists ?? directory?.exists,
};
}
}
+1
View File
@@ -2,6 +2,7 @@ export type Folder = {
uri: string;
name: string;
isDirectory: true;
/** `undefined` when neither caller nor Directory fallback provided a value. */
exists?: boolean;
};
+20 -8
View File
@@ -52,19 +52,31 @@ export async function listFoldersChunked(
}
let lastYield = Date.now();
const visit = async (uri: string) => {
if (Date.now() - lastYield >= budgetMs) {
lastYield = Date.now();
await impl.yield();
}
// Stack of Folders identified by uri; push in reverse so the first-listed
// descendant is popped first, preserving the DFS pre-order of the recursive
// traversal (a folder's subtree is fully explored before its later siblings).
const stack: Folder[] = impl
.list(directoryUri)
.filter((entry): entry is Folder => entry.isDirectory)
.reverse();
while (stack.length > 0) {
if (Date.now() - lastYield >= budgetMs) {
lastYield = Date.now();
await impl.yield();
}
for (const entry of impl.list(uri)) {
if (entry.isDirectory) {
result.push(entry);
await visit(entry.uri);
}
const folder = stack.pop()!;
result.push(folder);
const children = impl
.list(folder.uri)
.filter((entry): entry is Folder => entry.isDirectory);
for (let i = children.length - 1; i >= 0; i--) {
stack.push(children[i]);
}
};
await visit(directoryUri);
}
return result;
}