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}