Araq / ormin

Ormin -- An ORM for Nim.
MIT License
152 stars 18 forks source link

WIP: allow independent client #18

Closed kidandcat closed 4 years ago

kidandcat commented 4 years ago

With this change the generated client by Ormin can be used standalone in JS applications:

This code:

import ormin / [serverws]
import ormin

import json

importModel(DbBackend.sqlite, "chat_model")

#var db {.global.} = open("chat_ormin.db", "", "", "")

protocol "pingclient.nim", "ws://localhost:8080":
  server "pong":
    echo "got pong"

  client "pong":
    proc pong*() {.exportc.}

  server "ping":
    send %"ping"

  client "ping":
    echo "got ping"

Will generate this:

## Generated by Ormin. DO NOT EDIT!
import karax / [kajax, jwebsockets, jjson]
let conn = newWebSocket("ws://localhost:8080", "ormin")
proc send(msg: JsonNode) =
  conn.send(toJson(msg))

proc pong*() {.exportc.} =
  let req = newJObject()
  req["cmd"] = %0
  req["arg"] = newJNull()
  send(req)

proc recvMsg*(inp: JsonNode) =
  let data = inp["data"]
  let cmd = inp["cmd"].getInt()
  case cmd
  of 1:
    discard
  of 3:
    echo "got ping"
  else:
    discard

Which can just be compiled nim js client.nim and if you add {.exportc.} to your client methods, you can use that client in any JS app.

PD: I don't know how the ast works well, so probably this has a lot of improvements, also I tried to make the second macro param (the WS url) optional, but failed to do so.

Araq commented 4 years ago

Is that a good idea though? The generated code is supposed to be an include file, so adding whatever you need was easy enough.

kidandcat commented 4 years ago

Well, now you have both functionalities, if you do not pass a second argument to protocol (you must pass "" because I don't know how to overload a macro) it will work like now, nothing is imported in the generated file and it should be used by including it.

But if you pass the second argument to protocol macro (the WS url), then the imports are included, plus the ws connection, and the file can now be compiled to JS or used by importing it (instead of including)

So my idea was to not changing the actual behavior, but extend it to allow it to be used in any JS project without any effort.

Araq commented 4 years ago

Well but macro protocol*(name: static[string], wsurl: static[string] = ""; body: untyped): untyped doesn't work with Nim v1. Maybe it appears to work for some test cases, but it really doesn't.

kidandcat commented 4 years ago

There is a better way of overloading a macro? or doing what I pretend? I'm not experienced with Nim macros

Araq commented 4 years ago

The only real option is to name it differently, macro protocolUrl

kidandcat commented 4 years ago

Anyway I found is very easy to create a client.nim:

with something like:

import karax, ....

proc send(data: JsonNode)

include pingclient

and you just need to compile it, because it will not change, just the generated pingclient.nim

So is not a need to add more complexity to the codebase of ormin for this funcionality which you can implement in 5 LoC, I just wanted a fast compiling flow, but it can be achieved with this client.nim so I'm closing this