optimization for large folders with masks
Massimo Melina committed
Apr 10, 2023 at 15:50 UTC
78609b3f8d2339bd85b40e49029c8e5cef5bed4f
1 file changed
+16
-10
src/vfs.ts
+16
-10
@@ -2,7 +2,7 @@
2
3
import fs from 'fs/promises'
4
import { basename, dirname, join, resolve } from 'path'
5
-import { matches, dirStream, dirTraversal, enforceFinal, getOrSet, isDirectory, typedKeys } from './misc'
5
+import { dirStream, dirTraversal, enforceFinal, getOrSet, isDirectory, typedKeys, makeMatcher } from './misc'
6
import Koa from 'koa'
7
import _ from 'lodash'
8
import { defineConfig, setConfig } from './config'
@@ -96,7 +96,7 @@ export async function urlToNode(url: string, ctx?: Koa.Context, parent: VfsNode=
96
isTemp: true,
97
}
98
inheritMasks(ret, parent, name)
99
- applyMasks(ret, parent, name)
99
+ parentMaskApplier(parent)(ret, name)
100
inheritFromParent(parent, ret)
101
if (child) // yes
102
return urlToNode(rest, ctx, ret, getRest)
@@ -171,6 +171,7 @@ export function statusCodeForMissingPerm(node: VfsNode, perm: keyof VfsPerm, ctx
171
export async function* walkNode(parent:VfsNode, ctx?: Koa.Context, depth:number=0, prefixPath:string='', requiredPerm?: keyof VfsPerm): AsyncIterableIterator<VfsNode> {
172
const { children, source } = parent
173
const took = prefixPath ? undefined : new Set()
174
+ const maskApplier = parentMaskApplier(parent)
175
if (children)
176
for (const child of children) {
177
const nodeName = getNodeName(child)
@@ -225,7 +226,7 @@ export async function* walkNode(parent:VfsNode, ctx?: Koa.Context, depth:number=
226
// item will be changed, so be sure to pass a temp node
227
function canSee(item: VfsNode) {
228
// we basename for depth>0 where we already have the rest of the path in the parent's url, and would be duplicated
228
- applyMasks(item, parent, basename(getNodeName(item)))
229
+ maskApplier(item, basename(getNodeName(item)))
230
inheritFromParent(parent, item)
231
if (ctx && !hasPermission(item, 'can_see', ctx)) return
232
item.isTemp = true
@@ -238,13 +239,18 @@ export function masksCouldGivePermission(masks: Masks | undefined, perm: keyof V
239
props[perm] || masksCouldGivePermission(props.masks, perm))
240
}
241
241
-function applyMasks(item: VfsNode, parent: VfsNode, virtualBasename: string) {
242
- const { masks } = parent
243
- if (!masks) return
244
- for (const [k,v] of Object.entries(masks))
245
- if (k.startsWith('**/') && matches(virtualBasename, k.slice(3))
246
- || !k.includes('/') && matches(virtualBasename, k))
247
- _.defaults(item, v)
242
+function parentMaskApplier(parent: VfsNode) {
243
+ const matchers = Object.entries(parent.masks || {}).map(([k, v]) => {
244
+ k = k.startsWith('**/') ? k.slice(3) : !k.includes('/') ? k : ''
245
+ if (!k) return
246
+ const m = makeMatcher(k)
247
+ return [m, v] as [typeof m, typeof v]
248
+ })
249
+ return (item: VfsNode, virtualBasename: string) => {
250
+ for (const entry of matchers)
251
+ if (entry?.[0]?.(virtualBasename))
252
+ _.defaults(item, entry[1])
253
+ }
254
}
255
256
function inheritMasks(item: VfsNode, parent: VfsNode, virtualBasename:string) {