Skip to content

Commit

Permalink
modified shutdown timer to prevent crashes, added js module support v…
Browse files Browse the repository at this point in the history
…ia forcing MIME type.
  • Loading branch information
Niminem committed Oct 29, 2023
1 parent 7b27c32 commit bb7ab19
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 16 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
*.exe
*.exe
*.txt
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ nim c -r --threads:on --gc:orc main.nim
```
When compiling for Windows, also compile with the `--app:gui` flag. This will prevent the app opening up with the terminal.

#### Final Thoughts Before Developing With Neel
Keep the following in mind when developing you Neel App:
* All of your frontend assets are embedded into the binary at compile-time. For now you'll need to recompile when modifying/changing static frontend assets.
* To prevent crashes when users spam refresh or constantly switch between different pages, we implemented a sort of countdown timer for shutting down. Approximately 10 seconds after closing the app window, the server and program is killed if a websocket hasn't reconnected within that time period. Just keep that in mind before doing CTL+C in the terminal during testing.

## Examples

A simple Neel app that picks a random filename out of a given folder (something impossible from a browser):
Expand Down
39 changes: 24 additions & 15 deletions src/neel.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import std/[macros, os, strutils, osproc, json, threadpool, browsers, uri, tables]
from std/sequtils import keepItIf
import pkg/[mummy, mummy/routers]
export os, strutils, mummy, osproc, json, threadpool, browsers, routers
export os, strutils, osproc, json, threadpool, browsers
export mummy, routers

type NeelError* = object of CatchableError

Expand All @@ -12,7 +13,7 @@ proc getWebFolder*(webDirPath: string) :Table[string,string] {.compileTime.} =
if path == "index.html":
result["/"] = staticRead(webDirPath / path)
else:
result["/" & path] = staticRead(webDirPath / path)
result["/" & path.replace('\\','/')] = staticRead(webDirPath / path)


# ----------------------------------------------------------------------
Expand Down Expand Up @@ -182,7 +183,7 @@ proc findChromeMac*: string =
if alternateDirs != @[]:
result = alternateDirs[0] & "/Contents/MacOS/Google Chrome"
else:
raise newException(NeelError, "could not find Chrome")
raise newException(NeelError, "could not find Chrome using `mdfind`")

except:
raise newException(NeelError, "could not find Chrome in Applications directory")
Expand All @@ -205,14 +206,14 @@ proc findChromeWindows*: string =
discard

if result.len == 0:
raise newException(NeelError, "could not find Chrome in Program Files (x86) directory")
raise newException(NeelError, "could not find Chrome")

proc findChromeLinux*: string =
const chromeNames = ["google-chrome", "google-chrome-stable", "chromium-browser", "chromium"]
for name in chromeNames:
if execCmd("which " & name) == 0:
return name
raise newException(NeelError, "could not find Chrome in PATH")
raise newException(NeelError, "could not find Chrome")

proc findPath*: string =
when hostOS == "macosx":
Expand Down Expand Up @@ -242,19 +243,18 @@ proc openChrome*(portNo: int, chromeFlags: seq[string]) =
macro startApp*(webDirPath: string, portNo: int = 5000,
position: array[2, int] = [500,150], size: array[2, int] = [600,600],
chromeFlags: seq[string] = @[""], appMode: bool = true) =

quote do:
const
assets = getWebFolder(`webDirPath`)
NOCACHE_HEADER = @[("Cache-Control","no-store")]

var openSockets: bool
const Assets = getWebFolder(`webDirPath`)
var openSockets = false

proc handleFrontEndData*(frontEndData :string) {.gcsafe.} =
callNim(frontEndData.parseJson)

proc shutdown =
sleep 1000 # *** NEED BETTER IMPLEMENTATION HERE... ***
proc shutdown = # quick implementation to reduce crashing from users spamming refresh / clicking on new pages
for i in 1 .. 10:
sleep 1000
if openSockets: return
if not openSockets: quit()

if `appMode`:
Expand All @@ -264,9 +264,14 @@ macro startApp*(webDirPath: string, portNo: int = 5000,

proc indexHandler(request: Request) =
let path = parseUri(request.uri).path
request.respond(200, NOCACHE_HEADER, assets[path])
var headers: HttpHeaders
headers["Cache-Control"] = "no-store"
request.respond(200, headers, Assets[path])
proc jsHandler(request: Request) =
request.respond(200, NOCACHE_HEADER,"window.moveTo(" & $`position`[0] & "," & $`position`[1] & ")\n" &
var headers: HttpHeaders
headers["Cache-Control"] = "no-store"
headers["Content-Type"] = "application/javascript"
request.respond(200, headers,"window.moveTo(" & $`position`[0] & "," & $`position`[1] & ")\n" &
"window.resizeTo(" & $`size`[0] & "," & $`size`[1] & ")\n" &
"var ws = new WebSocket(\"ws://localhost:" & $`portNo` & "/ws\")\n" &
"""var connected = false
Expand Down Expand Up @@ -328,7 +333,11 @@ macro startApp*(webDirPath: string, portNo: int = 5000,
proc pathHandler(request: Request) =
let path = parseUri(request.uri).path
try:
request.respond(200,NOCACHE_HEADER,assets[path])
var headers: HttpHeaders
headers["Cache-Control"] = "no-store"
if "js" == path.split('.')[^1]: # forcing MIME-type to support JS modules
headers["Content-Type"] = "application/javascript"
request.respond(200,headers,Assets[path])
except:
raise newException(NeelError, "path: " & path & " doesn't exist")

Expand Down

0 comments on commit bb7ab19

Please sign in to comment.