Implement org file server
This commit is contained in:
22
TODO.org
22
TODO.org
@@ -1,20 +1,34 @@
|
||||
#+TITLE: Todo
|
||||
|
||||
* Todos
|
||||
|
||||
** TODO Creating a server
|
||||
** ACTIVE Creating a server :BACK_END:
|
||||
:LOGBOOK:
|
||||
CLOCK: [2022-05-29 Sun 11:24]
|
||||
CLOCK: [2022-05-30 Mon 07:52]--[2022-05-30 Mon 09:00] => 1:08
|
||||
CLOCK: [2022-05-29 Sun 11:24]--[2022-05-29 Sun 16:44] => 5:20
|
||||
:END:
|
||||
|
||||
- [[https://nim-lang.org/docs/asynchttpserver.html][std/asynchttpserver]]
|
||||
- [[https://github.com/h3rald/nimhttpd/blob/master/src/nimhttpd.nim][nimhttpd/nimhttpd.nim at master · h3rald/nimhttpd]]
|
||||
|
||||
** TODO Creating hot reload
|
||||
** TODO Headline content parser
|
||||
** TODO Store the line numbers :PARSER:
|
||||
** TODO Tag parser :PARSER:
|
||||
** TODO Build Redux :FRONT_END:
|
||||
:PROPERTIES:
|
||||
:CREATED: [2022-05-16 Mon 22:12]
|
||||
:END:
|
||||
|
||||
- [[https://blog.bitsrc.io/build-our-own-react-redux-using-usereducer-and-usecontext-hooks-a5574b526475][Build Your Own React-Redux Using useReducer and useContext Hooks | by Chidume Nnamdi | Bits and Pieces]]
|
||||
|
||||
** TODO Creating hot reload :DEV_ENVIRONMENT:
|
||||
|
||||
- [ ] [[https://dev.to/alemagio/implement-your-own-hot-reload-2435][Implement your own hot-reload - DEV Community]]
|
||||
- [ ] [[https://maheshsenniappan.medium.com/creating-a-module-bundler-with-hot-module-replacement-b439f0cc660f][Creating a module bundler with Hot Module Replacement | by Mahesh Senniappan | Medium]]
|
||||
- [ ] [[https://maheshsenniappan.medium.com/creating-a-module-bundler-with-hot-module-replacement-b439f0cc660f][Creating a module bundler with Hot Module Replacement | by Mahesh Senniappan | Medium]]
|
||||
** TODO Cordova App
|
||||
|
||||
https://hub.docker.com/r/xurei/docker-cordova
|
||||
|
||||
** DONE A nim compiler with watcher for js files
|
||||
:PROPERTIES:
|
||||
:CREATED: [2022-05-18 Wed 14:22]
|
||||
|
||||
@@ -1,24 +1,72 @@
|
||||
import std/[
|
||||
mimetypes,
|
||||
os,
|
||||
strformat,
|
||||
]
|
||||
import fp/[
|
||||
map,
|
||||
]
|
||||
import ./errors
|
||||
|
||||
const PORT_DEFAULT* = 1337
|
||||
const HTML_ROOT* = "../js"
|
||||
const DIST_ROOT* = HTML_ROOT.joinPath("dist")
|
||||
|
||||
type Env* = ref object
|
||||
port*: int
|
||||
mimeTypes*: MimeDb
|
||||
htmlRoot*: string
|
||||
distRoot*: string
|
||||
type
|
||||
orgPath* = string
|
||||
orgId* = string
|
||||
# OrgEnv* = ref object
|
||||
# paths*: seq[tuple[
|
||||
# path: orgPath,
|
||||
# id: orgId,
|
||||
# ]]
|
||||
|
||||
proc initEnv*(): auto =
|
||||
type
|
||||
debugLevel* = enum
|
||||
log
|
||||
|
||||
type
|
||||
Env* = ref object
|
||||
port*: int
|
||||
mimeTypes*: MimeDb
|
||||
debugLevel*: debugLevel
|
||||
|
||||
htmlRoot*: string
|
||||
distRoot*: string
|
||||
|
||||
orgEnv*: Map[orgId, orgPath]
|
||||
|
||||
proc debugLog*(env: Env, content: string): void =
|
||||
case env.debugLevel:
|
||||
of log: echo(content)
|
||||
|
||||
proc logErr*(env: Env, err: orgEnvErr, t1: string): void {.inline.} =
|
||||
debugLog(env, stringify(err, t1))
|
||||
|
||||
proc initEnv*(): Env =
|
||||
Env(
|
||||
port: PORT_DEFAULT,
|
||||
mimeTypes: newMimetypes(),
|
||||
debugLevel: log,
|
||||
|
||||
htmlRoot: HTML_ROOT,
|
||||
distRoot: DIST_ROOT,
|
||||
|
||||
orgEnv: @[
|
||||
("Main", "~/Documents/Org/Main/".expandTilde()),
|
||||
("Work", "~/Documents/Org/Work/".expandTilde()),
|
||||
].asMap()
|
||||
)
|
||||
|
||||
echo newMimetypes().getMimetype("txt")
|
||||
proc `$`*(x: Env): string =
|
||||
&"""Env(
|
||||
port: {x.port},
|
||||
debugLevel: {x.debugLevel},
|
||||
htmlRoot: {x.htmlRoot},
|
||||
distRoot: {x.distRoot},
|
||||
orgEnv: {x.orgEnv},
|
||||
)
|
||||
"""
|
||||
|
||||
when isMainModule:
|
||||
echo initEnv()
|
||||
|
||||
24
src/server/errors.nim
Normal file
24
src/server/errors.nim
Normal file
@@ -0,0 +1,24 @@
|
||||
import std/[
|
||||
strformat,
|
||||
sugar,
|
||||
]
|
||||
|
||||
type
|
||||
orgEnvErr* = enum
|
||||
invalidWorkspaceId
|
||||
fileNotFound
|
||||
|
||||
const errorPrefix = "Error: "
|
||||
|
||||
const invalidWorkspaceIdMessage = "Could not find org workspace with id: "
|
||||
const fileNotFoundMessage = "Could not find org file: "
|
||||
|
||||
func stringify*(x: orgEnvErr, t1: string): string =
|
||||
let msg = case x:
|
||||
of invalidWorkspaceId: invalidWorkspaceIdMessage & t1
|
||||
of fileNotFound: fileNotFoundMessage & t1
|
||||
errorPrefix & msg
|
||||
|
||||
when isMainModule:
|
||||
doAssert: invalidWorkspaceId.stringify($0) == errorPrefix & invalidWorkspaceIdMessage & $0
|
||||
doAssert: fileNotFound.stringify("/path/to/file") == errorPrefix & fileNotFoundMessage & "/path/to/file"
|
||||
@@ -11,10 +11,14 @@ import std/[
|
||||
sugar,
|
||||
]
|
||||
import fp/[
|
||||
map,
|
||||
option,
|
||||
maybe,
|
||||
resultM,
|
||||
]
|
||||
import fusion/matching
|
||||
import ./env
|
||||
import ./errors
|
||||
import ./utils
|
||||
# (GET, (scheme: "", username: "", password: "", hostname: "", port: "", path: "/", query: "", anchor: "", opaque: false, isIpv6: false), {"accept": @["*/*"], "host": @["localhost:45201"], "user-agent": @["curl/7.82.0"]})
|
||||
|
||||
@@ -55,6 +59,44 @@ proc sendStaticFile(env: Env, path: seq[string]): NimHttpResponse =
|
||||
})
|
||||
)
|
||||
|
||||
proc sendOrgFile(env: Env, id: orgId, path: seq[string]): NimHttpResponse =
|
||||
type errT = tuple[err: orgEnvErr, id: orgId, path: string]
|
||||
type StringResult = Result[orgPath, errT]
|
||||
type FileResult = Result[string, errT]
|
||||
|
||||
let content = env.orgEnv
|
||||
.get(id)
|
||||
.fold(
|
||||
() => StringResult.err((invalidWorkspaceId, id, "")),
|
||||
(x: orgPath) => StringResult.ok(x),
|
||||
)
|
||||
.map((x: orgPath) => $x.joinPath(path.join("/")))
|
||||
.flatMap((path: orgPath) => (
|
||||
catch(readFile(path)).fold(
|
||||
_ => FileResult.err((fileNotFound, id, path)),
|
||||
(content: string) => FileResult.ok(content),
|
||||
)
|
||||
))
|
||||
.tapErr((err: errT) => logErr(env, err[0], &"{err[1]}, path: {err[2]}"))
|
||||
|
||||
content.fold(
|
||||
(e: errT) => (
|
||||
code: Http404,
|
||||
content: "File not Found",
|
||||
headers: newHttpHeaders({
|
||||
"Content-Type": "application/json"
|
||||
})
|
||||
),
|
||||
(content: string) => (
|
||||
code: Http200,
|
||||
content: content,
|
||||
headers: newHttpHeaders({
|
||||
"Content-Type": "application/json"
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
proc handleRoute(env: Env, req: Request): NimHttpResponse =
|
||||
# Handle main route
|
||||
if req.url.path == "/":
|
||||
@@ -65,9 +107,11 @@ proc handleRoute(env: Env, req: Request): NimHttpResponse =
|
||||
|
||||
# Router
|
||||
return (
|
||||
case path:
|
||||
of ["dist", .._]:
|
||||
case (req.reqMethod, path):
|
||||
of (HttpGet, ["dist", .._]):
|
||||
sendStaticFile(env, path)
|
||||
of (HttpGet, ["org", @id, all @rest]):
|
||||
sendOrgFile(env, id, rest)
|
||||
else:
|
||||
sendNotFound(env, path)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user