Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add module jsfetch #12531

Merged
merged 125 commits into from
Mar 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
125 commits
Select commit Hold shift + click to select a range
263f0ed
Add module jsfetch for fetch support for JavaScript target https://de…
juancarlospaco Oct 27, 2019
20e9b2c
ReSync devel
juancarlospaco Oct 29, 2019
4f3ea12
ReSync with Devel
juancarlospaco Nov 9, 2019
6d063d9
ReSync with Devel
juancarlospaco Dec 31, 2019
8ca76c8
ReSync
juancarlospaco Apr 6, 2020
46b398f
ReSync
juancarlospaco Apr 6, 2020
983b575
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Apr 10, 2020
975932e
FetchOptions object to just pass 2 arguments to fetch()
juancarlospaco Apr 10, 2020
b497c1f
https://github.com/nim-lang/Nim/pull/12531#discussion_r406985988
juancarlospaco Apr 11, 2020
3e513a6
https://github.com/nim-lang/Nim/pull/12531#discussion_r406987058
juancarlospaco Apr 11, 2020
cf31e28
https://github.com/nim-lang/Nim/pull/12531#discussion_r406987058
juancarlospaco Apr 11, 2020
391d299
https://github.com/nim-lang/Nim/pull/12531#discussion_r406987058
juancarlospaco Apr 11, 2020
aa248eb
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Apr 12, 2020
fd1b4e6
Resync and clean out
juancarlospaco Apr 12, 2020
7c21575
Doc Comment
juancarlospaco Apr 12, 2020
41ecadd
Doc Comment
juancarlospaco Apr 12, 2020
df9df33
ReSync, add convenience proc
juancarlospaco Apr 16, 2020
8d71a34
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Apr 16, 2020
94d65a1
Merge branch 'devel' into jsfetch
ringabout Nov 27, 2020
fa6d607
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Dec 11, 2020
60fb0e1
Fix conflict on changelog
juancarlospaco Dec 11, 2020
c84a0a0
Merge branch 'jsfetch' of https://github.com/juancarlospaco/Nim into …
juancarlospaco Dec 11, 2020
8ddb073
Fix conflict on changelog
juancarlospaco Dec 11, 2020
ea89ef3
Working
juancarlospaco Dec 12, 2020
0298a03
Working
juancarlospaco Dec 12, 2020
fa9ca34
Working
juancarlospaco Dec 12, 2020
5f73f43
Convenience func is convenient
juancarlospaco Dec 12, 2020
970444a
importcpp to importjs
juancarlospaco Dec 12, 2020
bfa4500
runnableExamples only work on web browser console, but they work
juancarlospaco Dec 12, 2020
d253ca5
naming
juancarlospaco Dec 12, 2020
f009084
trypo
juancarlospaco Dec 12, 2020
67e4a1e
tipo
juancarlospaco Dec 12, 2020
5278aa1
Headers really is a thing for itself
juancarlospaco Dec 12, 2020
c7760d8
Headers really is a thing for itself
juancarlospaco Dec 12, 2020
5e2f926
Headers really is a thing for itself
juancarlospaco Dec 12, 2020
2930508
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Dec 12, 2020
b12a6c2
Headers really is a thing for itself
juancarlospaco Dec 13, 2020
2d7e946
Headers really is a thing for itself
juancarlospaco Dec 13, 2020
84c688a
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Jan 18, 2021
73588a7
Merge branch 'jsfetch' of https://github.com/juancarlospaco/Nim into …
juancarlospaco Jan 18, 2021
030a940
This is not dead yet
juancarlospaco Jan 18, 2021
20e61d0
Fix
juancarlospaco Jan 18, 2021
027db75
Fix
juancarlospaco Jan 18, 2021
fab7190
Fix
juancarlospaco Jan 18, 2021
fd104ff
Fix
juancarlospaco Jan 18, 2021
6777e22
Fix
juancarlospaco Jan 18, 2021
6773532
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Jan 20, 2021
8aad4f2
Clean out
juancarlospaco Jan 20, 2021
c3d30ab
Clean out
juancarlospaco Jan 20, 2021
833f0c1
move it
juancarlospaco Jan 20, 2021
d6bda3b
move it
juancarlospaco Jan 20, 2021
8564714
Update lib/std/jsfetch.nim
juancarlospaco Jan 25, 2021
316cfa9
Update lib/std/jsfetch.nim
juancarlospaco Jan 25, 2021
2775066
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Jan 25, 2021
8be32d9
Improvements and fixes
juancarlospaco Jan 25, 2021
9f842eb
Improvements and fixes
juancarlospaco Jan 25, 2021
aa3af12
Improvements and fixes
juancarlospaco Jan 25, 2021
2a9841b
doc
juancarlospaco Jan 25, 2021
a2efb22
https://github.com/nim-lang/Nim/pull/12531#discussion_r563766815
juancarlospaco Jan 25, 2021
fd5c57f
https://github.com/nim-lang/Nim/pull/12531#discussion_r563766815
juancarlospaco Jan 25, 2021
7416b9f
Dollars
juancarlospaco Jan 25, 2021
bc592ed
Dollars
juancarlospaco Jan 25, 2021
76cb084
Update lib/std/jsheaders.nim
juancarlospaco Jan 26, 2021
2107249
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Jan 29, 2021
0f306a1
https://github.com/nim-lang/Nim/pull/12531/files#r564156627
juancarlospaco Jan 29, 2021
e9aef5c
Merge branch 'jsfetch' of https://github.com/juancarlospaco/Nim into …
juancarlospaco Jan 29, 2021
73ef1f5
https://github.com/nim-lang/Nim/pull/12531#discussion_r564160044
juancarlospaco Jan 29, 2021
afed536
https://github.com/nim-lang/Nim/pull/12531#discussion_r564160044
juancarlospaco Jan 29, 2021
3d8cb6a
https://github.com/nim-lang/Nim/pull/12531#discussion_r564160044
juancarlospaco Jan 29, 2021
b0a6f77
https://github.com/nim-lang/Nim/pull/12531#discussion_r564160044
juancarlospaco Jan 29, 2021
fd7a95b
https://github.com/nim-lang/Nim/pull/12531#discussion_r564160044
juancarlospaco Jan 29, 2021
caf515a
https://github.com/nim-lang/Nim/pull/12531#discussion_r564160044
juancarlospaco Jan 29, 2021
66bcc62
https://github.com/nim-lang/Nim/pull/12531#discussion_r564160044
juancarlospaco Jan 29, 2021
de90631
https://github.com/nim-lang/Nim/pull/12531#discussion_r564160044
juancarlospaco Jan 29, 2021
709ba35
Update lib/std/jsfetch.nim
juancarlospaco Jan 30, 2021
f7e6e29
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Feb 24, 2021
9914e9d
Merge branch 'jsfetch' of https://github.com/juancarlospaco/Nim into …
juancarlospaco Feb 24, 2021
b2bb48d
Use new .then
juancarlospaco Feb 25, 2021
45ad131
I removed the toCstring because with the new .then() is more intuitiv…
juancarlospaco Feb 25, 2021
b84410c
Clean out
juancarlospaco Feb 25, 2021
ec76fc4
import std/
juancarlospaco Feb 25, 2021
d918a0a
Response procs so it can be explicitly created and tested
juancarlospaco Feb 25, 2021
daada08
Response procs so it can be explicitly created and tested
juancarlospaco Feb 25, 2021
0f3ad78
Clean out
juancarlospaco Feb 25, 2021
9fd32ba
Let the Body hit the floor
juancarlospaco Feb 25, 2021
7c315c8
Improve the code
juancarlospaco Feb 25, 2021
0a24d26
Improve the code
juancarlospaco Feb 25, 2021
f53d6e5
Improve the code
juancarlospaco Feb 25, 2021
c9c824e
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Feb 25, 2021
bba17db
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Feb 25, 2021
cebbe8c
Progressive progress
juancarlospaco Feb 25, 2021
bd90b9b
cstring instead
juancarlospaco Feb 25, 2021
eea6fcb
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Feb 27, 2021
842dc5c
this --> self
juancarlospaco Feb 27, 2021
bb2abf7
this --> self
juancarlospaco Feb 27, 2021
2eea903
Dollars, more Dollars for everyone
juancarlospaco Feb 27, 2021
60a350e
Dollars, more Dollars for everyone
juancarlospaco Feb 27, 2021
112ae07
https://github.com/nim-lang/Nim/pull/17189#issuecomment-787127954
juancarlospaco Feb 27, 2021
4950d00
Clean out
juancarlospaco Feb 27, 2021
a0ebcf9
.then .catch
juancarlospaco Feb 27, 2021
60e5329
.then .catch
juancarlospaco Feb 27, 2021
36b5717
text response
juancarlospaco Feb 27, 2021
23c0be5
text response
juancarlospaco Feb 27, 2021
17bfea0
ref object of JsRoot
juancarlospaco Feb 27, 2021
669d6fa
nimExperimentalJsfetch
juancarlospaco Feb 27, 2021
7e8f773
Otherwise doc is empty
juancarlospaco Feb 27, 2021
04ed53b
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Mar 5, 2021
b48a997
Update lib/std/jsformdata.nim
juancarlospaco Mar 6, 2021
b8e1798
Update lib/std/jsfetch.nim
juancarlospaco Mar 7, 2021
8789424
Update lib/std/jsfetch.nim
juancarlospaco Mar 7, 2021
8986262
Merge branch 'devel' of https://github.com/nim-lang/Nim into jsfetch
juancarlospaco Mar 7, 2021
e329f71
Merge branch 'jsfetch' of https://github.com/juancarlospaco/Nim into …
juancarlospaco Mar 7, 2021
6b845e5
Sync and feedback
juancarlospaco Mar 7, 2021
fe7a552
Sync and feedback
juancarlospaco Mar 7, 2021
7040c48
Sync and feedback
juancarlospaco Mar 7, 2021
85d5846
Sync and feedback
juancarlospaco Mar 7, 2021
642c0ff
Sync and feedback
juancarlospaco Mar 7, 2021
ade2c5f
Sync and feedback
juancarlospaco Mar 7, 2021
8c95566
tiny
juancarlospaco Mar 7, 2021
96abbb1
tiny
juancarlospaco Mar 7, 2021
53e05a4
tiny
juancarlospaco Mar 7, 2021
222d654
tiny
juancarlospaco Mar 7, 2021
e5859db
tiny
juancarlospaco Mar 7, 2021
3b28469
Update lib/std/jsfetch.nim
juancarlospaco Mar 7, 2021
e0d8342
Update changelog.md
juancarlospaco Mar 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ provided by the operating system.

- `std/options` changed `$some(3)` to `"some(3)"` instead of `"Some(3)"`
and `$none(int)` to `"none(int)"` instead of `"None[int]"`.
- Added `std/jsfetch` module [Fetch](https://developer.mozilla.org/docs/Web/API/Fetch_API) wrapper for JavaScript target.
- Added `std/jsheaders` module [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) wrapper for JavaScript target.
- Added `std/jsformdata` module [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) wrapper for JavaScript target.


- `system.addEscapedChar` now renders `\r` as `\r` instead of `\c`, to be compatible
with most other languages.
Expand Down
198 changes: 198 additions & 0 deletions lib/std/jsfetch.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
## - Fetch for the JavaScript target: https://developer.mozilla.org/docs/Web/API/Fetch_API
## .. Note:: jsfetch is Experimental. jsfetch module requires `-d:nimExperimentalJsfetch`
when not defined(js):
{.fatal: "Module jsfetch is designed to be used with the JavaScript backend.".}

when defined(nimExperimentalJsfetch) or defined(nimdoc):
import std/[asyncjs, jsheaders, jsformdata]
from std/httpcore import HttpMethod
from std/jsffi import JsObject

type
FetchOptions* = ref object of JsRoot ## Options for Fetch API.
keepalive*: bool
metod* {.importjs: "method".}: cstring
body*, integrity*, referrer*, mode*, credentials*, cache*, redirect*, referrerPolicy*: cstring

FetchModes* = enum ## Mode options.
fmCors = "cors"
fmNoCors = "no-cors"
fmSameOrigin = "same-origin"

FetchCredentials* = enum ## Credential options. See https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
fcInclude = "include"
fcSameOrigin = "same-origin"
fcOmit = "omit"

FetchCaches* = enum ## https://developer.mozilla.org/docs/Web/API/Request/cache
fchDefault = "default"
fchNoStore = "no-store"
fchReload = "reload"
fchNoCache = "no-cache"
fchForceCache = "force-cache"

FetchRedirects* = enum ## Redirects options.
frFollow = "follow"
frError = "error"
frManual = "manual"

FetchReferrerPolicies* = enum ## Referrer Policy options.
frpNoReferrer = "no-referrer"
frpNoReferrerWhenDowngrade = "no-referrer-when-downgrade"
frpOrigin = "origin"
frpOriginWhenCrossOrigin = "origin-when-cross-origin"
frpUnsafeUrl = "unsafe-url"

Body* = ref object of JsRoot ## https://developer.mozilla.org/en-US/docs/Web/API/Body
bodyUsed*: bool

Response* = ref object of JsRoot ## https://developer.mozilla.org/en-US/docs/Web/API/Response
bodyUsed*, ok*, redirected*: bool
typ* {.importjs: "type".}: cstring
url*, statusText*: cstring
status*: cint
headers*: Headers
body*: Body

Request* = ref object of JsRoot ## https://developer.mozilla.org/en-US/docs/Web/API/Request
bodyUsed*, ok*, redirected*: bool
typ* {.importjs: "type".}: cstring
url*, statusText*: cstring
status*: cint
headers*: Headers
body*: Body


func newResponse*(body: cstring | FormData): Response {.importjs: "(new Response(#))".}
## Constructor for `Response`. This does *not* call `fetch()`. Same as `new Response()`.

func newRequest*(url: cstring): Request {.importjs: "(new Request(#))".}
## Constructor for `Request`. This does *not* call `fetch()`. Same as `new Request()`.

func clone*(self: Response | Request): Response {.importjs: "#.$1()".}
## https://developer.mozilla.org/en-US/docs/Web/API/Response/clone

proc text*(self: Response): Future[cstring] {.importjs: "#.$1()".}
## https://developer.mozilla.org/en-US/docs/Web/API/Body/text

proc json*(self: Response): Future[JsObject] {.importjs: "#.$1()".}
## https://developer.mozilla.org/en-US/docs/Web/API/Body/json

proc formData*(self: Body): Future[FormData] {.importjs: "#.$1()".}
## https://developer.mozilla.org/en-US/docs/Web/API/Body/formData

proc unsafeNewFetchOptions*(metod, body, mode, credentials, cache, referrerPolicy: cstring;
keepalive: bool; redirect = "follow".cstring; referrer = "client".cstring; integrity = "".cstring): FetchOptions {.importjs:
"{method: #, body: #, mode: #, credentials: #, cache: #, referrerPolicy: #, keepalive: #, redirect: #, referrer: #, integrity: #}".}
## .. Warning:: Unsafe `newfetchOptions`.

func newfetchOptions*(metod: HttpMethod; body: cstring;
mode: FetchModes; credentials: FetchCredentials; cache: FetchCaches; referrerPolicy: FetchReferrerPolicies;
keepalive: bool; redirect = frFollow; referrer = "client".cstring; integrity = "".cstring): FetchOptions =
## Constructor for `FetchOptions`.
result = FetchOptions(
body: body, mode: $mode, credentials: $credentials, cache: $cache, referrerPolicy: $referrerPolicy,
keepalive: keepalive, redirect: $redirect, referrer: referrer, integrity: integrity,
metod: (case metod
of HttpHead: "HEAD".cstring
of HttpGet: "GET".cstring
of HttpPost: "POST".cstring
of HttpPut: "PUT".cstring
of HttpDelete: "DELETE".cstring
of HttpPatch: "PATCH".cstring
else: "GET".cstring
)
)

proc fetch*(url: cstring | Request): Future[Response] {.importjs: "$1(#)".}
## `fetch()` API, simple `GET` only, returns a `Future[Response]`.

proc fetch*(url: cstring | Request; options: FetchOptions): Future[Response] {.importjs: "$1(#, #)".}
## `fetch()` API that takes a `FetchOptions`, returns a `Future[Response]`.

func toCstring*(self: Request | Response | Body | FetchOptions): cstring {.importjs: "JSON.stringify(#)".}

func `$`*(self: Request | Response | Body | FetchOptions): string = $toCstring(self)


runnableExamples("-d:nimExperimentalJsfetch -r:off"):
import std/[asyncjs, jsconsole, jsheaders, jsformdata]
from std/httpcore import HttpMethod
from std/jsffi import JsObject
from std/sugar import `=>`

block:
let options0: FetchOptions = unsafeNewFetchOptions(
metod = "POST".cstring,
body = """{"key": "value"}""".cstring,
mode = "no-cors".cstring,
credentials = "omit".cstring,
cache = "no-cache".cstring,
referrerPolicy = "no-referrer".cstring,
keepalive = false,
redirect = "follow".cstring,
referrer = "client".cstring,
integrity = "".cstring
)
assert options0.keepalive == false
assert options0.metod == "POST".cstring
assert options0.body == """{"key": "value"}""".cstring
assert options0.mode == "no-cors".cstring
assert options0.credentials == "omit".cstring
assert options0.cache == "no-cache".cstring
assert options0.referrerPolicy == "no-referrer".cstring
assert options0.redirect == "follow".cstring
assert options0.referrer == "client".cstring
assert options0.integrity == "".cstring

block:
let options1: FetchOptions = newFetchOptions(
metod = HttpPost,
body = """{"key": "value"}""".cstring,
mode = fmNoCors,
credentials = fcOmit,
cache = fchNoCache,
referrerPolicy = frpNoReferrer,
keepalive = false,
redirect = frFollow,
referrer = "client".cstring,
integrity = "".cstring
)
assert options1.keepalive == false
assert options1.metod == $HttpPost
assert options1.body == """{"key": "value"}""".cstring
assert options1.mode == $fmNoCors
assert options1.credentials == $fcOmit
assert options1.cache == $fchNoCache
assert options1.referrerPolicy == $frpNoReferrer
assert options1.redirect == $frFollow
assert options1.referrer == "client".cstring
assert options1.integrity == "".cstring

block:
let response: Response = newResponse(body = "-. .. --".cstring)
let request: Request = newRequest(url = "http://nim-lang.org".cstring)

if not defined(nodejs):
block:
proc doFetch(): Future[Response] {.async.} =
fetch "https://httpbin.org/get".cstring

proc example() {.async.} =
let response: Response = await doFetch()
assert response.ok
assert response.status == 200.cint
assert response.headers is Headers
assert response.body is Body

discard example()

when defined(nimExperimentalAsyncjsThen):
block:
proc example2 {.async.} =
await fetch("https://api.github.com/users/torvalds".cstring)
.then((response: Response) => response.json())
.then((json: JsObject) => console.log(json))
.catch((err: Error) => console.log("Request Failed", err))

discard example2()
65 changes: 65 additions & 0 deletions lib/std/jsformdata.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
## - `FormData` for the JavaScript target: https://developer.mozilla.org/en-US/docs/Web/API/FormData
when not defined(js):
{.fatal: "Module jsformdata is designed to be used with the JavaScript backend.".}

type FormData* = ref object of JsRoot ## FormData API.

func newFormData*(): FormData {.importjs: "new FormData()".}

func add*(self: FormData; name: cstring; value: SomeNumber | bool | cstring) {.importjs: "#.append(#, #)".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
## Duplicate keys are allowed and order is preserved.

func add*(self: FormData; name: cstring; value: SomeNumber | bool | cstring, filename: cstring) {.importjs: "#.append(#, #, #)".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
## Duplicate keys are allowed and order is preserved.

func delete*(self: FormData; name: cstring) {.importjs: "#.$1(#)".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/delete
##
## .. Warning:: Deletes *all items* with the same key name.

func getAll*(self: FormData; name: cstring): seq[cstring] {.importjs: "#.$1(#)".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/getAll

func hasKey*(self: FormData; name: cstring): bool {.importjs: "#.has(#)".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/has

func keys*(self: FormData): seq[cstring] {.importjs: "Array.from(#.$1())".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/keys

func values*(self: FormData): seq[cstring] {.importjs: "Array.from(#.$1())".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/values

func pairs*(self: FormData): seq[tuple[key, val: cstring]] {.importjs: "Array.from(#.entries())".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/entries

func put*(self: FormData; name, value, filename: cstring) {.importjs: "#.set(#, #, #)".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/set

func `[]=`*(self: FormData; name, value: cstring) {.importjs: "#.set(#, #)".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/set

func `[]`*(self: FormData; name: cstring): cstring {.importjs: "#.get(#)".}
## https://developer.mozilla.org/en-US/docs/Web/API/FormData/get

func clear*(self: FormData) {.importjs:
"(() => { const frmdt = #; Array.from(frmdt.keys()).forEach((key) => frmdt.delete(key)) })()".}
## Convenience func to delete all items from `FormData`.

func toCstring*(self: FormData): cstring {.importjs: "JSON.stringify(#)".}

func `$`*(self: FormData): string = $toCstring(self)

func len*(self: FormData): int {.importjs: "Array.from(#.entries()).length".}


runnableExamples("-r:off"):
let data: FormData = newFormData()
data["key0"] = "value0".cstring
data.add("key1".cstring, "value1".cstring)
data.delete("key1")
assert data.hasKey("key0")
assert data["key0"] == "value0".cstring
data.clear()
assert data.len == 0
83 changes: 83 additions & 0 deletions lib/std/jsheaders.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
## - HTTP Headers for the JavaScript target: https://developer.mozilla.org/en-US/docs/Web/API/Headers
when not defined(js):
{.fatal: "Module jsheaders is designed to be used with the JavaScript backend.".}

type Headers* = ref object of JsRoot ## HTTP Headers API.

func newHeaders*(): Headers {.importjs: "new Headers()".}
## https://developer.mozilla.org/en-US/docs/Web/API/Headers

func add*(self: Headers; key: cstring; value: cstring) {.importjs: "#.append(#, #)".}
## Allows duplicated keys.
## https://developer.mozilla.org/en-US/docs/Web/API/Headers/append

func delete*(self: Headers; key: cstring) {.importjs: "#.$1(#)".}
## https://developer.mozilla.org/en-US/docs/Web/API/Headers/delete
juancarlospaco marked this conversation as resolved.
Show resolved Hide resolved
##
## .. Warning:: Delete *all* items with `key` from the headers, including duplicated keys.

func hasKey*(self: Headers; key: cstring): bool {.importjs: "#.has(#)".}
## https://developer.mozilla.org/en-US/docs/Web/API/Headers/has

func keys*(self: Headers): seq[cstring] {.importjs: "Array.from(#.$1())".}
## https://developer.mozilla.org/en-US/docs/Web/API/Headers/keys

func values*(self: Headers): seq[cstring] {.importjs: "Array.from(#.$1())".}
## https://developer.mozilla.org/en-US/docs/Web/API/Headers/values

func entries*(self: Headers): seq[tuple[key, value: cstring]] {.importjs: "Array.from(#.$1())".}
## https://developer.mozilla.org/en-US/docs/Web/API/Headers/entries

func `[]`*(self: Headers; key: cstring): cstring {.importjs: "#.get(#)".}
## Get *all* items with `key` from the headers, including duplicated values.
## https://developer.mozilla.org/en-US/docs/Web/API/Headers/get
juancarlospaco marked this conversation as resolved.
Show resolved Hide resolved

func `[]=`*(self: Headers; key: cstring; value: cstring) {.importjs: "#.set(#, #)".}
## Do *not* allow duplicated keys, overwrites duplicated keys.
## https://developer.mozilla.org/en-US/docs/Web/API/Headers/set
juancarlospaco marked this conversation as resolved.
Show resolved Hide resolved

func clear*(self: Headers) {.importjs:
"(() => { const header = #; Array.from(header.keys()).forEach((key) => header.delete(key)) })()".}
## Convenience func to delete all items from `Headers`.

func toCstring*(self: Headers): cstring {.importjs: "JSON.stringify(Array.from(#.entries()))".}
## Returns a `cstring` representation of `Headers`.

func `$`*(self: Headers): string = $toCstring(self)

func len*(self: Headers): int {.importjs: "Array.from(#.entries()).length".}


runnableExamples("-r:off"):

block:
let header: Headers = newHeaders()
header.add("key", "value")
assert header.hasKey("key")
assert header.keys() == @["key".cstring]
assert header.values() == @["value".cstring]
assert header["key"] == "value".cstring
header["other"] = "another".cstring
assert header["other"] == "another".cstring
assert header.entries() == @[("key".cstring, "value".cstring), ("other".cstring, "another".cstring)]
assert header.toCstring() == """[["key","value"],["other","another"]]""".cstring
header.delete("other")
assert header.entries() == @[("key".cstring, "value".cstring)]
header.clear()
assert header.entries() == @[]
assert header.len == 0

block:
let header: Headers = newHeaders()
header.add("key", "a")
header.add("key", "b") ## Duplicated.
header.add("key", "c") ## Duplicated.
assert header["key"] == "a, b, c".cstring
header["key"] = "value".cstring
assert header["key"] == "value".cstring

block:
let header: Headers = newHeaders()
header["key"] = "a"
header["key"] = "b" ## Overwrites.
assert header["key"] == "b".cstring
2 changes: 1 addition & 1 deletion tools/kochdocs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const
webUploadOutput = "web/upload"

var nimExe*: string
const allowList = ["jsbigints.nim"]
const allowList = ["jsbigints.nim", "jsheaders.nim", "jsformdata.nim", "jsfetch.nim"]

template isJsOnly(file: string): bool =
file.isRelativeTo("lib/js") or
Expand Down