diff --git a/TODO.org b/TODO.org index 0d3d1cb..14dba41 100644 --- a/TODO.org +++ b/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] diff --git a/src/server/env.nim b/src/server/env.nim index 3530e78..981a21e 100644 --- a/src/server/env.nim +++ b/src/server/env.nim @@ -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() diff --git a/src/server/errors.nim b/src/server/errors.nim new file mode 100644 index 0000000..f8ebaab --- /dev/null +++ b/src/server/errors.nim @@ -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" diff --git a/src/server/server.nim b/src/server/server.nim index 8a3dbce..b79942a 100644 --- a/src/server/server.nim +++ b/src/server/server.nim @@ -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) )