moved vfs to config
Massimo Melina committed
Dec 27, 2021 at 17:10 UTC
0e9ac4443fe13bf3b4fe0d3d153035b6f745ee7e
5 files changed
+42
-69
README.md
+3
-4
@@ -28,6 +28,7 @@ General configuration is read by default from file `config.yaml`.
28
When not specified, default values will be used.
29
Supported entries are:
30
- `port` where to accept http connections. Default is 80.
31
+- `vfs` the files and folders you want to expose. For details see the dedicated following section.
32
- `mime` command what mime-type to be returned with some files.
33
E.g.: `"*.jpg": image/jpeg`
34
You can specify multiple entries, or separate multiple file masks with a p|pe.
@@ -35,10 +36,8 @@ Supported entries are:
36
37
## Virtual File System (VFS)
38
38
-The virtual file system is a tree of nodes.
39
-By default, it's in the file `vfs.yaml`.
40
-You can decide a different file by passing it as first parameter at command line.
41
-A node is folder, unless you provide for it a source that's not a folder itself.
39
+The virtual file system is a tree of files and folders, collectively called *nodes*.
40
+By default a node is folder, unless you provide for it a source that's a file.
41
Valid keys in a node are:
42
- `name`: how to display it. If not provided HFS will infer it from the source.
43
- `source`: where to get its content from. Absolute or relative file path, or even http url.
config.yaml
+20
@@ -1,3 +1,23 @@
1
port: 80
2
mime:
3
"*.jpg|*.png|*.mp3|*.txt": auto
4
+vfs:
5
+ children:
6
+ - name: f1
7
+ children:
8
+ - name: f2
9
+ children:
10
+ - source: tests/alfa.txt
11
+ - name: pic
12
+ mime: png
13
+ source: tests/page/gpl.png
14
+ - name: page
15
+ default: index.html
16
+ source: tests/page
17
+ - name: proxy
18
+ source: https://raw.githubusercontent.com/nodejs/node/master/README.md
19
+ - name: for-admins
20
+ perm:
21
+ admin: r
22
+ children:
23
+ - source: tests/alfa.txt
package.json
+1
-1
@@ -10,7 +10,7 @@
10
"license": "GPL-3.0",
11
"author": "Massimo Melina <a@rejetto.com>",
12
"scripts": {
13
- "watch-server": "nodemon --ignore tests/ --watch src -e ts,tsx --exec ts-node src/index.ts vfs.yaml",
13
+ "watch-server": "nodemon --ignore tests/ --watch src -e ts,tsx --exec ts-node src/index.ts",
14
"start": "node dist",
15
"start-frontend": "cd frontend && npm run start",
16
"build": "node timestamp && tsc && cp package*.json *.yaml dist && cd dist && npm ci --production",
src/vfs.ts
+18
-45
@@ -1,14 +1,12 @@
1
-import { argv } from './const'
2
-import yaml from 'yaml'
1
import fs from 'fs/promises'
4
-import { FSWatcher, watch } from 'fs'
5
-import { dirname, basename } from 'path'
2
+import { basename } from 'path'
3
import { isMatch } from 'micromatch'
7
-import { complySlashes, enforceFinal, prefix, readFileBusy } from './misc'
4
+import { complySlashes, enforceFinal, prefix } from './misc'
5
import { getCurrentUsernameExpanded } from './perm'
6
import Koa from 'koa'
7
import glob from 'fast-glob'
8
import _ from 'lodash'
9
+import { subscribe } from './config'
10
11
export enum VfsNodeType {
12
root,
@@ -37,51 +35,15 @@ export const MIME_AUTO = 'auto'
35
36
export class Vfs {
37
root: VfsNode = EMPTY
40
- watcher?: FSWatcher
41
- basePath: string
42
-
43
- constructor(path?:string) {
44
- this.basePath = ''
45
- if (path)
46
- this.load(path).then(()=>
47
- this.basePath = dirname(path))
48
- else
49
- this.reset()
38
+
39
+ constructor() {
40
+ this.reset()
41
}
42
43
reset(){
44
this.root = { ...EMPTY }
45
}
46
56
- async load(path: string, watchFile:boolean=true) {
57
- console.debug('loading',path)
58
- try {
59
- const data = await readFileBusy(path)
60
- this.root = yaml.parse(data)
61
- // we should validate content now
62
- }
63
- catch(e) {
64
- console.error(`Load failed for ${path}`,e)
65
- }
66
- this.watcher?.close()
67
- this.watcher = undefined
68
- recur(this.root)
69
- if (!watchFile) return
70
- let doing = false
71
- this.watcher = watch(path, async () => {
72
- if (doing) return
73
- doing = true
74
- try { await this.load(path).catch() }
75
- finally { doing = false }
76
- })
77
-
78
- function recur(node:VfsNode) {
79
- if (node.type !== VfsNodeType.root && !node.name && node.source)
80
- node.name = basename(node.source)
81
- node.children?.forEach(recur)
82
- }
83
- }
84
-
47
async urlToNode(url: string, ctx: Koa.Context) : Promise<VfsNode | undefined> {
48
const users = await getCurrentUsernameExpanded(ctx)
49
let run = this.root
@@ -108,7 +70,18 @@ export class Vfs {
70
71
}
72
111
-export const vfs = new Vfs(argv._[0] || 'vfs.yaml')
73
+export const vfs = new Vfs()
74
+subscribe('vfs', data => {
75
+ // we should validate content now
76
+ recur(data)
77
+ vfs.root = data
78
+
79
+ function recur(node:VfsNode) {
80
+ if (node.type !== VfsNodeType.root && !node.name && node.source)
81
+ node.name = basename(node.source)
82
+ node.children?.forEach(recur)
83
+ }
84
+})
85
86
function findChildByName(name:string, node:VfsNode) {
87
const { rename } = node
vfs.yaml
deleted
-19
@@ -1,19 +0,0 @@
1
-children:
2
- - name: f1
3
- children:
4
- - name: f2
5
- children:
6
- - source: tests/alfa.txt
7
- - name: pic
8
- mime: png
9
- source: tests/page/gpl.png
10
- - name: page
11
- default: index.html
12
- source: tests/page
13
- - name: proxy
14
- source: https://raw.githubusercontent.com/nodejs/node/master/README.md
15
- - name: for-admins
16
- perm:
17
- admin: r
18
- children:
19
- - source: tests/alfa.txt