From 69086effab43f4de07a4983212ed0b9edb2a201c Mon Sep 17 00:00:00 2001 From: Ethosa Date: Thu, 29 Aug 2024 12:09:46 +0700 Subject: [PATCH 1/3] refactoring --- happyx.nimble | 2 +- src/happyx/core/constants.nim | 4 +- src/happyx/private/macro_utils.nim | 82 +++++++----------------------- src/happyx/spa/components.nim | 70 +++---------------------- src/happyx/spa/renderer.nim | 9 ++-- src/happyx/spa/tag.nim | 23 ++++++--- src/happyx/ssr/form_data.nim | 4 +- src/happyx/ssr/request_models.nim | 1 - src/happyx/ssr/types.nim | 2 +- src/happyx/ssr/websockets.nim | 3 +- 10 files changed, 55 insertions(+), 145 deletions(-) diff --git a/happyx.nimble b/happyx.nimble index 5dfb2aac5..eb9d955ad 100755 --- a/happyx.nimble +++ b/happyx.nimble @@ -2,7 +2,7 @@ description = "Macro-oriented asynchronous web-framework written with ♥" author = "HapticX" -version = "4.4.4" +version = "4.5.0" license = "MIT" srcDir = "src" installExt = @["nim"] diff --git a/src/happyx/core/constants.nim b/src/happyx/core/constants.nim index ed8b44986..7e27d476f 100755 --- a/src/happyx/core/constants.nim +++ b/src/happyx/core/constants.nim @@ -98,8 +98,8 @@ const nim_2_0_0* = (NimMajor, NimMinor, NimPatch) >= (2, 0, 0) # Framework version HpxMajor* = 4 - HpxMinor* = 4 - HpxPatch* = 4 + HpxMinor* = 5 + HpxPatch* = 0 HpxVersion* = $HpxMajor & "." & $HpxMinor & "." & $HpxPatch diff --git a/src/happyx/private/macro_utils.nim b/src/happyx/private/macro_utils.nim index e163d3fac..3297b0652 100644 --- a/src/happyx/private/macro_utils.nim +++ b/src/happyx/private/macro_utils.nim @@ -142,6 +142,18 @@ proc formatNode*(node: NimNode): NimNode = node +proc liveviewParam*(name: string): NimNode = + newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add( + newCall("declared", ident(name)), + ident(name) + ), newNimNode(nnkElifBranch).add( + newCall("declared", newDotExpr(ident"self", ident(name))), + newDotExpr(ident"self", ident(name)) + ), newNimNode(nnkElse).add( + newLit"" + )) + + proc useComponent*(statement: NimNode, inCycle, inComponent: bool, cycleTmpVar: string, compTmpVar: NimNode, cycleVars: var seq[NimNode], returnTagRef: bool = true, constructor: bool = false, @@ -229,69 +241,13 @@ proc useComponent*(statement: NimNode, inCycle, inComponent: bool, objConstr.add(stringId) when not defined(js) and enableLiveViews: objConstr.add( - newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add( - newCall("declared", ident"urlPath"), - ident"urlPath" - ), newNimNode(nnkElifBranch).add( - newCall("declared", newDotExpr(ident"self", ident"urlPath")), - newDotExpr(ident"self", ident"urlPath") - ), newNimNode(nnkElse).add( - newLit"" - )), - newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add( - newCall("declared", ident"hostname"), - ident"hostname" - ), newNimNode(nnkElifBranch).add( - newCall("declared", newDotExpr(ident"self", ident"hostname")), - newDotExpr(ident"self", ident"hostname") - ), newNimNode(nnkElse).add( - newLit"" - )), - newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add( - newCall("declared", ident"query"), - ident"query" - ), newNimNode(nnkElifBranch).add( - newCall("declared", newDotExpr(ident"self", ident"query")), - newDotExpr(ident"self", ident"query") - ), newNimNode(nnkElse).add( - newLit"" - )), - newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add( - newCall("declared", ident"queryArr"), - ident"queryArr" - ), newNimNode(nnkElifBranch).add( - newCall("declared", newDotExpr(ident"self", ident"queryArr")), - newDotExpr(ident"self", ident"queryArr") - ), newNimNode(nnkElse).add( - newLit"" - )), - newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add( - newCall("declared", ident"reqMethod"), - ident"reqMethod" - ), newNimNode(nnkElifBranch).add( - newCall("declared", newDotExpr(ident"self", ident"reqMethod")), - newDotExpr(ident"self", ident"reqMethod") - ), newNimNode(nnkElse).add( - newLit"" - )), - newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add( - newCall("declared", ident"inCookies"), - ident"inCookies" - ), newNimNode(nnkElifBranch).add( - newCall("declared", newDotExpr(ident"self", ident"inCookies")), - newDotExpr(ident"self", ident"inCookies") - ), newNimNode(nnkElse).add( - newLit"" - )), - newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add( - newCall("declared", ident"headers"), - ident"headers" - ), newNimNode(nnkElifBranch).add( - newCall("declared", newDotExpr(ident"self", ident"headers")), - newDotExpr(ident"self", ident"headers") - ), newNimNode(nnkElse).add( - newLit"" - )), + liveviewParam("urlPath"), + liveviewParam("hostname"), + liveviewParam("query"), + liveviewParam("queryArr"), + liveviewParam("reqMethod"), + liveviewParam("inCookies"), + liveviewParam("headers"), ) if statement[1].kind == nnkCall: for i in 1..{script}" + proc js*(host, script: string) = + requestResult[host] = "script:" & fmt"" proc route*(comp: BaseComponent, path: string) = componentsResult[comp.uniqCompId] = "route:" & path proc js*(comp: BaseComponent, script: string) = componentsResult[comp.uniqCompId] = "script:" & fmt"" proc rerender*(query, queryArr, reqMethod, inCookies, headers: auto, hostname, urlPath: string) = - echo "rerender for " & hostname requestResult[hostname] = "rerender:" & liveviewRoutes[urlPath]( query, queryArr, reqMethod, inCookies, headers, nil ).children[1].ugly() diff --git a/src/happyx/spa/tag.nim b/src/happyx/spa/tag.nim index c0385f21d..a2b23eeec 100644 --- a/src/happyx/spa/tag.nim +++ b/src/happyx/spa/tag.nim @@ -441,7 +441,10 @@ proc tagFromString*(source: string): TagRef {.inline.} = let xmlNode = parseHtml(source) result = initTag("div", @[], true) result.xmlTree2Tag(nil, xmlNode) - result = result.children[0].children[0].TagRef + when defined(js): + result = result.children[0].children[0].TagRef + else: + result = result.children[0].children[0] proc addArg*(self: TagRef, arg: string) = @@ -467,11 +470,13 @@ proc addArgIter*(self: TagRef, arg: string) = ## See also `addArg function #addArg,TagRef,string`_ when defined(js): self.setAttribute(cstring(arg), "") + for i in self.children: + i.TagRef.addArgIter(arg) else: if self.args.len == 0: self.args.add(arg) - for i in self.children: - i.TagRef.addArgIter(arg) + for i in self.children: + i.addArgIter(arg) proc toSeqIter*(self: TagRef): seq[TagRef] = @@ -485,7 +490,7 @@ proc toSeqIter*(self: TagRef): seq[TagRef] = result.add(i) else: for child in self.children: - for i in child.TagRef.toSeqIter: + for i in child.toSeqIter: result.add(i) return result @@ -506,7 +511,10 @@ func lvl*(self: TagRef): int = var tag = self when defined(js): while not tag.parentElement.isNil: - tag = tag.parentElement.TagRef + when defined(js): + tag = tag.parentElement.TagRef + else: + tag = tag.parentElement if not tag.onlyChildren: inc result else: @@ -527,7 +535,10 @@ func `[]`*(self: TagRef, attrName: string): string = func `[]`*(self: TagRef, index: int): TagRef = ## Returns tag by index - self.children[index].TagRef + when defined(js): + self.children[index].TagRef + else: + self.children[index] func `[]=`*(self: TagRef, attrName: string, attrValue: string) = diff --git a/src/happyx/ssr/form_data.nim b/src/happyx/ssr/form_data.nim index 8e5eb6b45..36309df62 100644 --- a/src/happyx/ssr/form_data.nim +++ b/src/happyx/ssr/form_data.nim @@ -37,9 +37,7 @@ type FormDataItem* = object proc parseFormData*(formData: string): (StringTableRef, TableRef[string, FormDataItem]) = ## Parses `form-data` into `StringTableRef` result = (newStringTable(), newTable[string, FormDataItem]()) - let - lineSeparator = "\r\n" - lines = formData.split("\r\n") + let lines = formData.split("\r\n") var key = "" data = "" diff --git a/src/happyx/ssr/request_models.nim b/src/happyx/ssr/request_models.nim index a1dada98f..d6fadc729 100644 --- a/src/happyx/ssr/request_models.nim +++ b/src/happyx/ssr/request_models.nim @@ -84,7 +84,6 @@ import # stdlib std/macros, std/macrocache, - std/strtabs, std/strutils, std/strformat, # Happyx diff --git a/src/happyx/ssr/types.nim b/src/happyx/ssr/types.nim index 55f0b4914..70017d9fb 100644 --- a/src/happyx/ssr/types.nim +++ b/src/happyx/ssr/types.nim @@ -1,7 +1,7 @@ import std/logging, std/tables, - ../spa/[tag, renderer], + ../spa/renderer, ../core/constants when enableHttpx: diff --git a/src/happyx/ssr/websockets.nim b/src/happyx/ssr/websockets.nim index 51c5b6f49..54180c6d2 100644 --- a/src/happyx/ssr/websockets.nim +++ b/src/happyx/ssr/websockets.nim @@ -1,7 +1,6 @@ import std/macros, - ../core/constants, - ../private/macro_utils + ../core/constants proc handleWebsockets*(wsClosedConnection: NimNode): tuple[wsStmtList, insertWsList: NimNode] = From 0b2ea21cc2729b474375b9f19a0bf27649dd2dd1 Mon Sep 17 00:00:00 2001 From: Ethosa Date: Thu, 29 Aug 2024 12:51:30 +0700 Subject: [PATCH 2/3] solve #333 --- src/happyx/routing/mounting.nim | 25 ++++++++++++++++++++++--- src/happyx/ssr/server.nim | 3 +++ tests/testc6.nim | 11 +++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/happyx/routing/mounting.nim b/src/happyx/routing/mounting.nim index 499cf9632..de2e9d29d 100644 --- a/src/happyx/routing/mounting.nim +++ b/src/happyx/routing/mounting.nim @@ -21,7 +21,8 @@ import std/macrocache, std/strformat, # HappyX - ../core/[exceptions] + ../core/[exceptions], + ./decorators when not declared(CacheTable.hasKey): import ../private/macro_utils @@ -35,10 +36,22 @@ proc findAndReplaceMount*(body: NimNode) = ## ## Don't use it in product ## - var offset = 0 + var + offset = 0 + nextRouteDecorators: seq[NimNode] = @[] for i in 0.. 1: + nextRouteDecorators.add(body[idx].copy()) + elif body[idx].kind == nnkCommand and body[idx][0] == ident"mount": if body[idx][1].kind == nnkInfix and body[idx][1][0] == ident"->": # handle mount let @@ -63,10 +76,16 @@ proc findAndReplaceMount*(body: NimNode) = elif statement[1].kind in [nnkStrLit, nnkTripleStrLit]: statement[1] = newLit($route & $statement[1]) # Add mount routes + for decorator in nextRouteDecorators: + inc offset + body.insert(i, decorator) if (statement.kind in [nnkCall, nnkCommand] and $statement[0] != "mount") or (statement.kind == nnkPrefix and $statement[0] == "@"): inc offset body.insert(i, statement) + nextRouteDecorators = @[] + else: + nextRouteDecorators = @[] macro mount*(mountName, body: untyped): untyped = diff --git a/src/happyx/ssr/server.nim b/src/happyx/ssr/server.nim index 33ef571f1..fc091e84a 100755 --- a/src/happyx/ssr/server.nim +++ b/src/happyx/ssr/server.nim @@ -758,6 +758,9 @@ macro routes*(server: Server, body: untyped = newStmtList()): untyped = ), statement[2] )) nextRouteDecorators = @[] + # mount ... + elif statement.kind == nnkCommand and statement[0] == ident"mount" and statement[1].kind == nnkInfix and statement[1][0] == ident"->": + nextRouteDecorators = @[] # reqMethod "/...": # ... elif statement[0].kind == nnkIdent and statement[0] != ident"mount" and statement[1].kind in {nnkStrLit, nnkTripleStrLit, nnkInfix}: diff --git a/tests/testc6.nim b/tests/testc6.nim index e92da8a29..989f2afc3 100644 --- a/tests/testc6.nim +++ b/tests/testc6.nim @@ -26,10 +26,21 @@ decorator HelloWorld: statementList[0].del(statementList[0].len-1) +mount Test: + get "/": + echo 1 + + get "/test": + echo 1 + + serve("127.0.0.1", 5000): "/": return "Hello, world!" + @HelloWorld(1, 2, 3, req) + mount "/test" -> Test + @HelloWorld(1, 2, 3, req) "/test-deco": return "Hello, world!" From 694aad915bccf183822ec565fe9d3ab0a92ed944 Mon Sep 17 00:00:00 2001 From: Ethosa Date: Thu, 29 Aug 2024 12:53:55 +0700 Subject: [PATCH 3/3] little fix --- src/happyx/ssr/websockets.nim | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/happyx/ssr/websockets.nim b/src/happyx/ssr/websockets.nim index 54180c6d2..2f5c5633a 100644 --- a/src/happyx/ssr/websockets.nim +++ b/src/happyx/ssr/websockets.nim @@ -3,6 +3,10 @@ import ../core/constants +when enableHttpBeast: + import ../private/macro_utils + + proc handleWebsockets*(wsClosedConnection: NimNode): tuple[wsStmtList, insertWsList: NimNode] = ## This is helpful function to work with websockets let wsClientI = ident"wsClient"