Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .uigraph.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ architectureDiagrams:
- name: Peer File Transfer
path: .uigraph/diagrams/peer-file-transfer/peer-file-transfer.mmd
contextPath: .uigraph/diagrams/peer-file-transfer/context.json
- name: CLI Command Dispatch
path: .uigraph/diagrams/cli-command-dispatch/cli-command-dispatch.mmd
contextPath: .uigraph/diagrams/cli-command-dispatch/context.json
- name: FTP Server Flow
path: .uigraph/diagrams/ftp-server-flow/ftp-server-flow.mmd
contextPath: .uigraph/diagrams/ftp-server-flow/context.json
- name: Web Auth and Session
path: .uigraph/diagrams/web-auth-session/web-auth-session.mmd
contextPath: .uigraph/diagrams/web-auth-session/context.json
- name: Web Upload Flow
path: .uigraph/diagrams/web-upload-flow/web-upload-flow.mmd
contextPath: .uigraph/diagrams/web-upload-flow/context.json
- name: Build and Package Pipeline
path: .uigraph/diagrams/build-package-pipeline/build-package-pipeline.mmd
contextPath: .uigraph/diagrams/build-package-pipeline/context.json

docs:
- name: CLI Commands
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
flowchart TD
build[npm run build] --> clean[Delete dist and dist-web]
clean --> serverBuild[build-server]
serverBuild --> dist[dist/server bundle]
clean --> webBuild[build-web]
webBuild --> distWeb[Web static output]
dist --> bin[bin entry]
distWeb --> bin
bin --> pkg[npm package]
pkg --> publish[npm publish]
63 changes: 63 additions & 0 deletions .uigraph/diagrams/build-package-pipeline/context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"nodes": {
"build": {
"name": "npm run build",
"data": {
"Script": { "type": "Text Input", "value": "node ./build.cjs" },
"Spawns": { "type": "Text Input", "value": "Every script starting with build-" }
}
},
"clean": {
"name": "Delete outputs",
"data": {
"Deletes": { "type": "Tag Input", "value": ["dist", "dist-web"] }
}
},
"serverBuild": {
"name": "Server build",
"data": {
"Script": { "type": "Text Input", "value": "build-server: tsc -p ./server" },
"Emits": { "type": "Text Input", "value": "dist/server" }
}
},
"dist": {
"name": "Server bundle",
"data": {
"Entry": { "type": "Text Input", "value": "dist/server/index.js" }
}
},
"webBuild": {
"name": "Web build",
"data": {
"Script": { "type": "Text Input", "value": "build-web: tsc -p ./web, vite build --emptyOutDir" }
}
},
"distWeb": {
"name": "Web static output",
"data": {
"Served From": { "type": "Text Input", "value": "dist-web by the web server" }
}
},
"bin": {
"name": "bin entry",
"type": "shape",
"shape": "rectangle",
"data": {
"Bin": { "type": "Text Input", "value": "./dist/server/index.js" }
}
},
"pkg": {
"name": "npm package",
"data": {
"Name": { "type": "Text Input", "value": "netserv" },
"Type": { "type": "Text Input", "value": "commonjs" }
}
},
"publish": {
"name": "npm publish",
"data": {
"Registry": { "type": "Text Input", "value": "npmjs.org" }
}
}
}
}
10 changes: 10 additions & 0 deletions .uigraph/diagrams/cli-command-dispatch/cli-command-dispatch.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
flowchart TD
bin[netserv CLI] --> arg[NoArg dispatch]
arg --> web[web command]
arg --> ftp[ftp command]
arg --> get[get command]
arg --> send[send command]
web --> webServe[Express on LAN]
ftp --> ftpServe[ftp-srv listener]
get --> getServer[Upload receiver]
send --> sendUpload[Multipart sender]
82 changes: 82 additions & 0 deletions .uigraph/diagrams/cli-command-dispatch/context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"nodes": {
"bin": {
"name": "netserv CLI",
"data": {
"Source": { "type": "Text Input", "value": "dist/server/index.js" },
"Command": { "type": "Text Input", "value": "node dist/server/index.js" }
}
},
"arg": {
"name": "Command dispatcher",
"data": {
"Source": { "type": "Text Input", "value": "server/arg.ts" },
"Library": { "type": "Text Input", "value": "noarg" }
}
},
"web": {
"name": "Web server command",
"data": {
"Source": { "type": "Text Input", "value": "server/web/index.ts" },
"Flags": {
"type": "Tag Input",
"value": ["Target Dir", "password", "host", "port", "qr", "writable"]
},
"Default Port": { "type": "Number Input", "value": 8000 }
}
},
"ftp": {
"name": "FTP server command",
"data": {
"Source": { "type": "Text Input", "value": "server/ftp/index.ts" },
"Flags": {
"type": "Tag Input",
"value": ["host", "port", "username", "password", "root"]
},
"Default Port": { "type": "Number Input", "value": 2221 }
}
},
"get": {
"name": "Get receiver command",
"data": {
"Source": { "type": "Text Input", "value": "server/get/index.ts" },
"Flags": { "type": "Tag Input", "value": ["output", "code"] }
}
},
"send": {
"name": "Send uploader command",
"data": {
"Source": { "type": "Text Input", "value": "server/send/index.ts" },
"Arguments": { "type": "Tag Input", "value": ["host", "port", "target"] }
}
},
"webServe": {
"name": "Express web server",
"data": {
"Binds": { "type": "Text Input", "value": "One listen call per IPv4 interface" },
"QR": { "type": "Text Input", "value": "Terminal QR code when --qr (default)" }
}
},
"ftpServe": {
"name": "ftp-srv instance",
"data": {
"Binds": { "type": "Text Input", "value": "Every IPv4 interface when no --host" },
"Mode": { "type": "Text Input", "value": "Anonymous without credentials" }
}
},
"getServer": {
"name": "Upload receiver",
"data": {
"Listen": { "type": "Text Input", "value": "portfinder from 8080" },
"Output": { "type": "Text Input", "value": "Config output directory" }
}
},
"sendUpload": {
"name": "Multipart uploader",
"data": {
"Body": { "type": "Text Input", "value": "Multipart with file read streams" },
"Token": { "type": "Text Input", "value": "Fetched from GET /token/{size}" }
}
}
}
}
93 changes: 93 additions & 0 deletions .uigraph/diagrams/ftp-server-flow/context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"nodes": {
"cmd": {
"name": "FTP command",
"data": {
"Source": { "type": "Text Input", "value": "server/ftp/index.ts" },
"Flags": {
"type": "Tag Input",
"value": ["host", "port", "username", "password", "root"]
}
}
},
"srv": {
"name": "ftp-srv server",
"data": {
"Source": { "type": "Text Input", "value": "server/ftp/server.ts" },
"Mode": { "type": "Text Input", "value": "Anonymous when no credentials" }
}
},
"client": {
"name": "FTP client",
"data": {
"Protocol": { "type": "Text Input", "value": "ftp://host:port" }
}
},
"started": {
"name": "Server started",
"type": "shape",
"shape": "diamond",
"data": {
"Failure": { "type": "Text Input", "value": "Removes listeners and closes server" }
}
},
"retry": {
"name": "Retry after 1s",
"data": {
"Loop": { "type": "Text Input", "value": "Restarts per interface until it binds" }
}
},
"login": {
"name": "Login event handler",
"data": {
"Source": { "type": "Text Input", "value": "server/ftp/server.ts" },
"Args": { "type": "Tag Input", "value": ["connection", "username", "password"] }
}
},
"anon": {
"name": "Credentials configured",
"type": "shape",
"shape": "diamond",
"data": {
"Exits When": { "type": "Text Input", "value": "Root directory does not exist" }
}
},
"verify": {
"name": "Credential check",
"type": "shape",
"shape": "diamond",
"data": {
"Comparison": { "type": "Text Input", "value": "Exact match against configured values" }
}
},
"reject": {
"name": "Reject connection",
"data": {
"Error": { "type": "Text Input", "value": "Invalid username or password" }
}
},
"resolve": {
"name": "Resolve served root",
"data": {
"Resolution": { "type": "Text Input", "value": "path.resolve(config.root || '.')" }
}
},
"root": {
"name": "Served directory",
"type": "shape",
"shape": "cylinder",
"data": {
"Check": { "type": "Text Input", "value": "Must exist, otherwise process exits" }
}
}
},
"edges": {
"srv-started": { "label": "listen on host:2221" },
"started-retry": { "label": "connect failed" },
"started-login": { "label": "ready" },
"anon-resolve": { "label": "no" },
"anon-verify": { "label": "yes" },
"verify-reject": { "label": "mismatch" },
"verify-resolve": { "label": "match" }
}
}
12 changes: 12 additions & 0 deletions .uigraph/diagrams/ftp-server-flow/ftp-server-flow.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
flowchart TD
cmd[ftp command] --> srv[ftp-srv server]
client[FTP client] --> srv
srv -->|listen on host:2221| started{Server started}
started -->|connect failed| retry[Retry in 1 second]
started -->|ready| login{Login event}
login --> anon{Credentials configured}
anon -->|no| resolve[Resolve served root]
anon -->|yes| verify{Check username and password}
verify -->|mismatch| reject[Reject connection]
verify -->|match| resolve
resolve --> root[(Served directory)]
97 changes: 97 additions & 0 deletions .uigraph/diagrams/web-auth-session/context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"nodes": {
"browser": {
"name": "Browser",
"data": {
"UI Branch": { "type": "Text Input", "value": "web/" }
}
},
"authRouter": {
"name": "Auth router",
"data": {
"Mount": { "type": "Text Input", "value": "/auth" },
"Routes": { "type": "Tag Input", "value": ["GET /init", "POST /login"] }
}
},
"login": {
"name": "Login handler",
"type": "shape",
"shape": "diamond",
"data": {
"Source": { "type": "Text Input", "value": "server/web/controller/auth.ts" },
"Equality": { "type": "Text Input", "value": "Direct comparison with configured password" }
}
},
"login401": {
"name": "401 Invalid password",
"data": {
"Also Returns": { "type": "Text Input", "value": "400 when no password or login disabled" }
}
},
"issue": {
"name": "Issue session",
"data": {
"Token": { "type": "Text Input", "value": "JWT expiresIn 1d" },
"Cookie": { "type": "Text Input", "value": "jwt, httpOnly, maxAge 1 year" }
}
},
"init": {
"name": "Init handler",
"type": "shape",
"shape": "diamond",
"data": {
"Response": { "type": "Text Input", "value": "writable, authEnabled, jwt" },
"Bypass": { "type": "Text Input", "value": "jwt null when login disabled" }
}
},
"rotate": {
"name": "Rotate session",
"data": {
"Behavior": { "type": "Text Input", "value": "Fresh token and reset cookie" }
}
},
"clear": {
"name": "Clear session",
"data": {
"Behavior": { "type": "Text Input", "value": "Clears cookie, reports jwt null" }
}
},
"guard": {
"name": "Auth gate",
"type": "shape",
"shape": "diamond",
"data": {
"Source": { "type": "Text Input", "value": "checkAuthMiddleware in controller/auth.ts" },
"Rejection": { "type": "Text Input", "value": "401 without a valid JWT cookie" }
}
},
"open": {
"name": "Password mode off",
"data": {
"Behavior": { "type": "Text Input", "value": "Requests pass and routes stay open" }
}
},
"guard401": {
"name": "401 No/invalid JWT",
"data": {
"Cookie State": { "type": "Text Input", "value": "Absent or failed verification" }
}
},
"api": {
"name": "API router",
"data": {
"Mount": { "type": "Text Input", "value": "/api" },
"Routes": { "type": "Tag Input", "value": ["dir", "file", "rename", "delete", "new-folder", "upload"] }
}
}
},
"edges": {
"login-login401": { "label": "empty or wrong" },
"login-issue": { "label": "correct" },
"init-rotate": { "label": "valid cookie" },
"init-clear": { "label": "invalid" },
"guard-open": { "label": "password mode off" },
"guard-guard401": { "label": "no or invalid cookie" },
"guard-api": { "label": "valid" }
}
}
Loading
Loading