code wiki / _hdl_build / nx_cms_api.nx
nx_cms_api.nx source
↩ module page · 58 lines · 2514 B
1// nx_cms_api.nx -- CMS REST + GraphQL-style content API (the rest-graphql-api class). Serves the real
2// nx_cms_store content as RFC 8259 JSON via nx_json_emit, with FIELD SELECTION (the GraphQL essence:
3// the caller asks for exactly the fields it wants; REST = ask for all, GraphQL = ask for a subset) and
4// correct string escaping (the security axis -- a value containing a quote or newline can never break
5// out of the JSON, unlike naive string concatenation). Read side; composes cst_get + json_emit.
6// module: nishi-core.cms.api
7// depends: nishi-core.cms.store + nishi-core.data.json_emit + nishi-core.io.syscalls
8// capability: CMS
9// license_tier: ORIGINAL
10import "nx_cms_store.nx"
11import "nx_json_emit.nx"
12import "nx_syscalls.nx"
13
14func capi_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
15
16// emit a JSON object into an existing writer, projecting only the named fields that are
17// PRESENT in the store (absent fields are skipped gracefully -- a GraphQL/REST must not 500
18// on a field that doesn't exist). names is an array of *u8 (one per requested field).
19func cms_api_emit_obj(w: *JsonWriter, store: *u8, n: i64, names: *i64, nf: i64) -> i64 {
20 let valbuf: *u8 = sys_mmap(2048)
21 json_begin_object(w)
22 var i: i64 = 0
23 while i < nf {
24 let name: *u8 = (names[i]) as *u8
25 let vl: i64 = cst_get(store, n, name, valbuf, 2048)
26 if vl >= 0 {
27 json_emit_key(w, name, capi_slen(name))
28 json_emit_string(w, valbuf, vl)
29 }
30 i = i + 1
31 }
32 json_end_object(w)
33 return 0
34}
35
36// REST/GraphQL single-record endpoint: project the named fields of one store into a JSON object.
37// Returns the JSON byte length written to out.
38func cms_api_render_obj(store: *u8, n: i64, names: *i64, nf: i64, out: *u8, cap: i64) -> i64 {
39 let w: *JsonWriter = sys_mmap(128) as *JsonWriter
40 json_writer_init(w, out, cap)
41 cms_api_emit_obj(w, store, n, names, nf)
42 return w.pos
43}
44
45// REST/GraphQL list endpoint: a JSON array of projected objects, one per store.
46// stores[i] = *u8 store ptr, counts[i] = its byte length.
47func cms_api_render_list(stores: *i64, counts: *i64, ns: i64, names: *i64, nf: i64, out: *u8, cap: i64) -> i64 {
48 let w: *JsonWriter = sys_mmap(128) as *JsonWriter
49 json_writer_init(w, out, cap)
50 json_begin_array(w)
51 var i: i64 = 0
52 while i < ns {
53 cms_api_emit_obj(w, (stores[i]) as *u8, counts[i], names, nf)
54 i = i + 1
55 }
56 json_end_array(w)
57 return w.pos
58}