Files
orca/src/shared/filesystem-directory-listing-limit.ts
T
NeilandOrca 879aad7dd6 oom(foundation): bound shared readers/limits + add BoundedMap primitive (#10299)
* oom(01): A1-shared-readers — reintroduce #10179 subset

Files: 18 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(02): A2-shared-image-media — reintroduce #10179 subset

Files: 7 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(03): A3-shared-fs-listing — reintroduce #10179 subset

Files: 21 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(04): A4-shared-remote-relay — reintroduce #10179 subset

Files: 8 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(05): A5-shared-misc — reintroduce #10179 subset

Files: 28 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(06): B-shared-wiring — reintroduce #10179 subset

Files: 81 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-24 21:36:57 -07:00

76 lines
2.3 KiB
TypeScript

export const FILESYSTEM_DIRECTORY_MAX_ENTRIES = 100_000
export const FILESYSTEM_DIRECTORY_MAX_RETAINED_BYTES = 12 * 1024 * 1024
export const FILESYSTEM_DIRECTORY_LIMIT_MESSAGE =
'This folder is too large to list safely (limit: 100,000 items or a 12 MB listing).'
export type FilesystemDirectoryListingLimits = {
maxEntries: number
maxRetainedBytes: number
}
type NamedDirectoryEntry = { name: string }
export type FilesystemDirectoryLimitState = {
entries: number
retainedBytes: number
limits: FilesystemDirectoryListingLimits
}
export function resolveFilesystemDirectoryListingLimits(
requested?: Partial<FilesystemDirectoryListingLimits>
): FilesystemDirectoryListingLimits {
return {
maxEntries: clampLimit(requested?.maxEntries, FILESYSTEM_DIRECTORY_MAX_ENTRIES),
maxRetainedBytes: clampLimit(
requested?.maxRetainedBytes,
FILESYSTEM_DIRECTORY_MAX_RETAINED_BYTES
)
}
}
export function createFilesystemDirectoryLimitState(
requested?: Partial<FilesystemDirectoryListingLimits>
): FilesystemDirectoryLimitState {
return {
entries: 0,
retainedBytes: 0,
limits: resolveFilesystemDirectoryListingLimits(requested)
}
}
export function trackFilesystemDirectoryEntry(
state: FilesystemDirectoryLimitState,
entry: NamedDirectoryEntry
): void {
state.entries += 1
state.retainedBytes += estimateFilesystemDirectoryEntryBytes(entry)
if (
state.entries > state.limits.maxEntries ||
state.retainedBytes > state.limits.maxRetainedBytes
) {
throw new Error(FILESYSTEM_DIRECTORY_LIMIT_MESSAGE)
}
}
export function assertFilesystemDirectoryWithinLimit(
entries: readonly NamedDirectoryEntry[],
requested?: Partial<FilesystemDirectoryListingLimits>
): void {
const state = createFilesystemDirectoryLimitState(requested)
for (const entry of entries) {
trackFilesystemDirectoryEntry(state, entry)
}
}
export function estimateFilesystemDirectoryEntryBytes(entry: NamedDirectoryEntry): number {
// Why: this covers worst-case JSON escaping plus each result object's fixed overhead.
return entry.name.length * 6 + 96
}
function clampLimit(value: number | undefined, maximum: number): number {
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0) {
return maximum
}
return Math.min(value, maximum)
}