@voxgig/sdkgen 1.3.18 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cmp/Deploy.js +16 -16
- package/dist/cmp/Deploy.js.map +1 -1
- package/dist/cmp/ReadmeTop.js +13 -11
- package/dist/cmp/ReadmeTop.js.map +1 -1
- package/dist/helpers/naming.d.ts +3 -1
- package/dist/helpers/naming.js +65 -0
- package/dist/helpers/naming.js.map +1 -1
- package/dist/helpers/serverVars.d.ts +10 -0
- package/dist/helpers/serverVars.js +87 -0
- package/dist/helpers/serverVars.js.map +1 -0
- package/dist/sdkgen.d.ts +3 -2
- package/dist/sdkgen.js +6 -1
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/project/.sdk/model/target/go-cli.aontu +2 -2
- package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +22 -15
- package/project/.sdk/src/cmp/go/Config_go.ts +10 -1
- package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +54 -35
- package/project/.sdk/src/cmp/go-cli/fragment/main.fragment.go +7 -7
- package/project/.sdk/src/cmp/go-cli/fragment/words.fragment.go +21 -18
- package/project/.sdk/src/cmp/js/Config_js.ts +11 -0
- package/project/.sdk/src/cmp/js/fragment/Config.fragment.js +2 -2
- package/project/.sdk/src/cmp/js/fragment/Direct.test.fragment.js +4 -0
- package/project/.sdk/src/cmp/lua/Config_lua.ts +10 -1
- package/project/.sdk/src/cmp/php/Config_php.ts +13 -2
- package/project/.sdk/src/cmp/py/Config_py.ts +10 -1
- package/project/.sdk/src/cmp/rb/Config_rb.ts +12 -1
- package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +25 -18
- package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +10 -3
- package/project/.sdk/src/cmp/ts/Config_ts.ts +11 -0
- package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +2 -2
- package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +4 -0
- package/project/.sdk/tm/c/utility/prepare_method.c +18 -0
- package/project/.sdk/tm/clojure/src/sdk/core.clj +9 -1
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +13 -0
- package/project/.sdk/tm/csharp/Makefile +6 -6
- package/project/.sdk/tm/csharp/utility/PrepareMethod.cs +11 -0
- package/project/.sdk/tm/dart/Makefile +3 -3
- package/project/.sdk/tm/dart/lib/utility/PrepareMethodUtility.dart +10 -0
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +8 -1
- package/project/.sdk/tm/go/Makefile +6 -6
- package/project/.sdk/tm/go/test/primary_utility_test.go +5 -0
- package/project/.sdk/tm/go/utility/make_options.go +48 -0
- package/project/.sdk/tm/go/utility/prepare_method.go +14 -1
- package/project/.sdk/tm/haskell/src/SdkRuntime.hs +13 -4
- package/project/.sdk/tm/java/Makefile +6 -6
- package/project/.sdk/tm/java/utility/PrepareMethod.java +9 -0
- package/project/.sdk/tm/js/Makefile +6 -6
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -1
- package/project/.sdk/tm/js/src/utility/PrepareMethodUtility.js +9 -0
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +5 -0
- package/project/.sdk/tm/kotlin/Makefile +6 -6
- package/project/.sdk/tm/kotlin/utility/Prepare.kt +9 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +6 -1
- package/project/.sdk/tm/lua/Makefile +7 -7
- package/project/.sdk/tm/lua/feature/test_feature.lua +29 -1
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +4 -0
- package/project/.sdk/tm/lua/utility/make_options.lua +39 -0
- package/project/.sdk/tm/lua/utility/prepare_method.lua +11 -0
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +9 -3
- package/project/.sdk/tm/perl/Makefile +6 -6
- package/project/.sdk/tm/perl/utility/prepare_method.pm +17 -0
- package/project/.sdk/tm/php/Makefile +6 -6
- package/project/.sdk/tm/php/feature/TestFeature.php +30 -2
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +5 -0
- package/project/.sdk/tm/php/utility/MakeOptions.php +44 -0
- package/project/.sdk/tm/php/utility/PrepareMethod.php +11 -0
- package/project/.sdk/tm/py/Makefile +6 -6
- package/project/.sdk/tm/py/test/test_primary_utility.py +5 -0
- package/project/.sdk/tm/py/utility/make_options.py +42 -0
- package/project/.sdk/tm/py/utility/prepare_method.py +10 -0
- package/project/.sdk/tm/rb/Makefile +6 -6
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +4 -0
- package/project/.sdk/tm/rb/utility/make_options.rb +37 -0
- package/project/.sdk/tm/rb/utility/prepare_method.rb +10 -1
- package/project/.sdk/tm/rust/Makefile +6 -6
- package/project/.sdk/tm/rust/utility/prepare_method.rs +12 -0
- package/project/.sdk/tm/scala/utility/Prepare.scala +14 -8
- package/project/.sdk/tm/swift/Makefile +6 -6
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +8 -0
- package/project/.sdk/tm/ts/Makefile +6 -6
- package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +39 -1
- package/project/.sdk/tm/ts/src/utility/PrepareMethodUtility.ts +9 -0
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +4 -0
- package/project/.sdk/tm/zig/core/utility.zig +15 -0
- package/src/cmp/Deploy.ts +16 -16
- package/src/cmp/ReadmeTop.ts +13 -11
- package/src/helpers/naming.ts +71 -0
- package/src/helpers/serverVars.ts +105 -0
- package/src/sdkgen.ts +6 -1
|
@@ -16,18 +16,32 @@ import {
|
|
|
16
16
|
} from '@voxgig/apidef'
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
// Published
|
|
20
|
-
// eng/go
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// go.
|
|
19
|
+
// Published boru/eng/go version. The engine module
|
|
20
|
+
// github.com/boru-lang/boru/eng/go is not yet tagged under the boru path (the
|
|
21
|
+
// eng/go/v0.0.1 tag predates the aql->boru rename and still declares the old
|
|
22
|
+
// aql-lang/aql module path), so we pin a commit pseudo-version. Bump here —
|
|
23
|
+
// to a real eng/go/v<X.Y.Z> once one is published, or a newer pseudo-version —
|
|
24
|
+
// when adopting a newer engine.
|
|
25
|
+
const BORU_ENG_VERSION = 'v0.0.2-0.20260804163932-0d66b55c5110'
|
|
26
|
+
|
|
27
|
+
// go.sum entries for BORU_ENG_VERSION and its transitive deps. The sibling
|
|
24
28
|
// SDK dep needs no entry (path replace). Deterministic because the version
|
|
25
29
|
// is pinned above — regenerate with `go mod tidy` and update BOTH constants
|
|
26
|
-
// together when bumping
|
|
27
|
-
const
|
|
28
|
-
github.com/
|
|
29
|
-
github.com/
|
|
30
|
-
github.com/
|
|
30
|
+
// together when bumping BORU_ENG_VERSION.
|
|
31
|
+
const BORU_ENG_GOSUM = `github.com/boru-lang/boru/eng/go v0.0.2-0.20260804163932-0d66b55c5110 h1:iwMbEPhByhVhJgt6xhyhT+jXMiARvbG4wHIrc4OPcvU=
|
|
32
|
+
github.com/boru-lang/boru/eng/go v0.0.2-0.20260804163932-0d66b55c5110/go.mod h1:KQLjjCq4QVAfdSuhmQ58ZFA9JK7LV2+A/aLRb3m4s5k=
|
|
33
|
+
github.com/cockroachdb/apd/v3 v3.2.3 h1:4Zx+I3R35bFXMnltzmjP79i2cravE4jTRL6ps9Aux80=
|
|
34
|
+
github.com/cockroachdb/apd/v3 v3.2.3/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc=
|
|
35
|
+
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
|
36
|
+
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|
37
|
+
github.com/tabnas/debug/go v0.2.3 h1:cptiwHcHKw+lqtZuKp6gX7yY1NunJLS5PHD7ykVcIvM=
|
|
38
|
+
github.com/tabnas/debug/go v0.2.3/go.mod h1:EXSNFdN6Ct9pcAUk8ZGozNbIltb3Hw0wcne+5vWQyns=
|
|
39
|
+
github.com/tabnas/json/go v0.4.0 h1:1BxLHyCullkKXkvui/SuZ4s6OMrFVDuEB13IX/5S1eM=
|
|
40
|
+
github.com/tabnas/json/go v0.4.0/go.mod h1:MJzyziKcvZk3OZCaSDxhMdf/Wkq2UJ0uLGWFtp9zsJs=
|
|
41
|
+
github.com/tabnas/jsonic/go v0.4.0 h1:y5k/P21C3q3jWaA+VxEhXxzZ8xJgpgAehMBEseDN31g=
|
|
42
|
+
github.com/tabnas/jsonic/go v0.4.0/go.mod h1:eDpkddhkuTFuIXMkSqTZl7cU7M23swbMpkXR1W5bApQ=
|
|
43
|
+
github.com/tabnas/parser/go v0.4.0 h1:M8+qRT4KaCtr4OCpg9NDNUXJIdbbweqeqbpEpVGNEqU=
|
|
44
|
+
github.com/tabnas/parser/go v0.4.0/go.mod h1:WrlfEVyZ1QjEIowWiyEu3K1iHj7wxuPut5zoH9Trehk=
|
|
31
45
|
`
|
|
32
46
|
|
|
33
47
|
|
|
@@ -64,7 +78,7 @@ const Main = cmp(function Main(props: any) {
|
|
|
64
78
|
// EVERYTHING here is MODEL-DRIVEN: verbs, examples and how-to sections are
|
|
65
79
|
// gated on whether an active entity actually exposes that op
|
|
66
80
|
// (op.<name>.active !== false) — never document an operation no entity
|
|
67
|
-
// supports. The CLI implements three
|
|
81
|
+
// supports. The CLI implements three boru words (list / load / update; see
|
|
68
82
|
// words.fragment.go + runOp).
|
|
69
83
|
// ==========================================================================
|
|
70
84
|
const bin = `${model.name}-cli`
|
|
@@ -129,7 +143,7 @@ const Main = cmp(function Main(props: any) {
|
|
|
129
143
|
ex.push('# 3. Provide credentials once, via the environment')
|
|
130
144
|
ex.push(`export ${apiKeyEnv}=sk_live_xxx`)
|
|
131
145
|
ex.push('')
|
|
132
|
-
ex.push('# 4. Each command line is ONE
|
|
146
|
+
ex.push('# 4. Each command line is ONE boru expression, run against the API:')
|
|
133
147
|
if (firstHas('list')) ex.push(`./${bin} list ${firstEntity}`)
|
|
134
148
|
if (firstHas('load')) {
|
|
135
149
|
ex.push(`./${bin} load 1 ${firstEntity} # {id:1} shorthand`)
|
|
@@ -158,7 +172,7 @@ const Main = cmp(function Main(props: any) {
|
|
|
158
172
|
\`\`\`
|
|
159
173
|
|
|
160
174
|
\`list <entity>\` returns the first page of records. \`<entity>\` is a bareword —
|
|
161
|
-
it is auto-quoted as an
|
|
175
|
+
it is auto-quoted as an boru atom, so no quotes are needed.`)
|
|
162
176
|
|
|
163
177
|
if (firstHas('load')) howtos.push(`### Load a single record
|
|
164
178
|
|
|
@@ -194,7 +208,7 @@ Both are injectable by a secrets vault, so the key never has to be typed inline.
|
|
|
194
208
|
howtos.push(`### Explore interactively with the REPL
|
|
195
209
|
|
|
196
210
|
Run with no arguments to open a REPL (prompt \`${model.name}>\`). Each line is
|
|
197
|
-
evaluated as its own
|
|
211
|
+
evaluated as its own boru expression:
|
|
198
212
|
|
|
199
213
|
\`\`\`text
|
|
200
214
|
$ ./${bin}
|
|
@@ -218,10 +232,10 @@ below — this SDK exposes ${entityCount} ${entityNoun}.`)
|
|
|
218
232
|
|
|
219
233
|
File({ name: 'README.md' }, () => Content(`# ${model.name}-cli
|
|
220
234
|
|
|
221
|
-
|
|
222
|
-
SDK. Each command line is parsed as a single [
|
|
235
|
+
boru-driven command-line client **and** interactive REPL for the ${model.Name}
|
|
236
|
+
SDK. Each command line is parsed as a single [boru](https://github.com/boru-lang/boru)
|
|
223
237
|
expression and evaluated against the live API; run it with no arguments to drop
|
|
224
|
-
into a REPL. Built on \`github.com/
|
|
238
|
+
into a REPL. Built on \`github.com/boru-lang/boru/eng/go\` and the sibling Go SDK
|
|
225
239
|
at \`../go\`.
|
|
226
240
|
|
|
227
241
|
## Examples
|
|
@@ -248,7 +262,7 @@ ${exampleBlock}
|
|
|
248
262
|
export ${apiKeyEnv}=sk_live_xxx
|
|
249
263
|
\`\`\`
|
|
250
264
|
|
|
251
|
-
3. **Run a query.** Evaluate an
|
|
265
|
+
3. **Run a query.** Evaluate an boru expression against the API (or run with no
|
|
252
266
|
arguments to open the REPL):
|
|
253
267
|
|
|
254
268
|
\`\`\`sh
|
|
@@ -258,7 +272,7 @@ ${exampleBlock}
|
|
|
258
272
|
4. **Go interactive.** Run the binary with no arguments to open the REPL, then
|
|
259
273
|
type \`/help\` for the word and entity lists and \`/quit\` to leave.
|
|
260
274
|
|
|
261
|
-
That is the whole loop: *build → set key → evaluate
|
|
275
|
+
That is the whole loop: *build → set key → evaluate boru expressions*.
|
|
262
276
|
|
|
263
277
|
## How-to guides
|
|
264
278
|
|
|
@@ -268,13 +282,13 @@ ${howtoBlock}
|
|
|
268
282
|
|
|
269
283
|
### Words
|
|
270
284
|
|
|
271
|
-
The CLI registers these
|
|
285
|
+
The CLI registers these boru words, each bound to the SDK:
|
|
272
286
|
|
|
273
287
|
| Word | Signatures | Returns |
|
|
274
288
|
|----------|-----------------------------------------------|--------------------------------|
|
|
275
289
|
${verbRows}
|
|
276
290
|
|
|
277
|
-
- \`<entity>\` is a bareword, auto-quoted as an
|
|
291
|
+
- \`<entity>\` is a bareword, auto-quoted as an boru atom (e.g. \`${firstEntity}\`).
|
|
278
292
|
- \`<query>\` is either a **Map** (\`{id:1}\`) or a **Scalar** (\`1\`, treated as
|
|
279
293
|
\`{id:1}\`). A scalar is always wrapped as \`{id:<value>}\`.
|
|
280
294
|
|
|
@@ -293,7 +307,7 @@ Unset variables fall back to the SDK's built-in defaults.
|
|
|
293
307
|
|
|
294
308
|
### REPL commands
|
|
295
309
|
|
|
296
|
-
Meta-commands use the \`/\` prefix (everything else on a line is evaluated as
|
|
310
|
+
Meta-commands use the \`/\` prefix (everything else on a line is evaluated as boru):
|
|
297
311
|
|
|
298
312
|
- \`/quit\` / \`/q\` / \`/exit\` — exit the REPL
|
|
299
313
|
- \`/help\` / \`/h\` / \`/?\` — show the word list, entity list and meta commands
|
|
@@ -321,25 +335,25 @@ ${entityList}
|
|
|
321
335
|
|
|
322
336
|
## Explanation
|
|
323
337
|
|
|
324
|
-
### Why
|
|
338
|
+
### Why boru?
|
|
325
339
|
|
|
326
|
-
The whole command line is one [
|
|
340
|
+
The whole command line is one [boru](https://github.com/boru-lang/boru) expression,
|
|
327
341
|
not a fixed \`verb --flag\` grammar. That means the same binary works one-shot
|
|
328
342
|
(\`./${bin} <expr>\`) and interactively (the REPL), and expressions compose the
|
|
329
|
-
same way in both. \`list\` / \`load\` / \`update\` are ordinary
|
|
343
|
+
same way in both. \`list\` / \`load\` / \`update\` are ordinary boru *words* bound to
|
|
330
344
|
the SDK — adding SDK operations is adding words, not re-parsing flags.
|
|
331
345
|
|
|
332
346
|
### How it is wired
|
|
333
347
|
|
|
334
348
|
\`main.go\` builds the SDK client (configured from the environment), creates an
|
|
335
|
-
|
|
349
|
+
boru registry, and \`words.go\` registers \`list\` / \`load\` / \`update\` as native
|
|
336
350
|
words that dispatch on the entity atom and call the sibling Go SDK at \`../go\`.
|
|
337
351
|
Results are unwrapped from their \`Entity\` wrappers to plain data before being
|
|
338
352
|
printed.
|
|
339
353
|
|
|
340
354
|
### Output format
|
|
341
355
|
|
|
342
|
-
Each result value is printed as its
|
|
356
|
+
Each result value is printed as its boru string form (a JSON-like rendering of
|
|
343
357
|
the record or list of records). One-shot mode prints to stdout; errors go to
|
|
344
358
|
stderr with a non-zero exit code.
|
|
345
359
|
|
|
@@ -350,25 +364,30 @@ this repo, or upstream at
|
|
|
350
364
|
\`github.com/voxgig/sdkgen/project/.sdk/src/cmp/go-cli/\`.
|
|
351
365
|
`))
|
|
352
366
|
|
|
353
|
-
// go.mod — sibling SDK via relative replace;
|
|
354
|
-
// public Go module proxy. The go directive must be >=
|
|
355
|
-
// (go 1.24.7
|
|
367
|
+
// go.mod — sibling SDK via relative replace; boru/eng/go from the
|
|
368
|
+
// public Go module proxy. The go directive must be >= boru/eng/go's own
|
|
369
|
+
// (go 1.24.7) — keep in step with BORU_ENG_VERSION.
|
|
356
370
|
File({ name: 'go.mod' }, () => Content(`module ${cliModule}
|
|
357
371
|
|
|
358
372
|
go 1.24.7
|
|
359
373
|
|
|
360
374
|
require ${sdkModule} v0.0.0
|
|
361
|
-
require github.com/
|
|
375
|
+
require github.com/boru-lang/boru/eng/go ${BORU_ENG_VERSION}
|
|
362
376
|
|
|
363
|
-
require
|
|
377
|
+
require (
|
|
378
|
+
github.com/cockroachdb/apd/v3 v3.2.3 // indirect
|
|
379
|
+
github.com/tabnas/json/go v0.4.0 // indirect
|
|
380
|
+
github.com/tabnas/jsonic/go v0.4.0 // indirect
|
|
381
|
+
github.com/tabnas/parser/go v0.4.0 // indirect
|
|
382
|
+
)
|
|
364
383
|
|
|
365
384
|
replace ${sdkModule} => ../go
|
|
366
385
|
`))
|
|
367
386
|
|
|
368
|
-
// go.sum — required for `go build` to accept the
|
|
387
|
+
// go.sum — required for `go build` to accept the boru/eng/go dependency
|
|
369
388
|
// (the path-replaced sibling SDK needs no entry). Pinned alongside
|
|
370
|
-
//
|
|
371
|
-
File({ name: 'go.sum' }, () => Content(
|
|
389
|
+
// BORU_ENG_VERSION above.
|
|
390
|
+
File({ name: 'go.sum' }, () => Content(BORU_ENG_GOSUM))
|
|
372
391
|
|
|
373
392
|
// Makefile — `make build` for the current machine, `make build-all` to
|
|
374
393
|
// cross-compile for the three desktop OSes (linux, darwin, windows) on
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Command ProjectName-cli is a CLI + REPL for the ProjectName SDK,
|
|
2
|
-
// built on the
|
|
3
|
-
// single
|
|
2
|
+
// built on the boru engine. Positional arguments are joined into a
|
|
3
|
+
// single boru expression and evaluated; with no arguments, falls into
|
|
4
4
|
// a REPL. Generated by sdkgen go-cli target.
|
|
5
5
|
package main
|
|
6
6
|
|
|
@@ -11,8 +11,8 @@ import (
|
|
|
11
11
|
"os"
|
|
12
12
|
"strings"
|
|
13
13
|
|
|
14
|
-
eng "github.com/
|
|
15
|
-
"github.com/
|
|
14
|
+
eng "github.com/boru-lang/boru/eng/go"
|
|
15
|
+
"github.com/boru-lang/boru/eng/go/parser"
|
|
16
16
|
sdk "GOMODULE"
|
|
17
17
|
)
|
|
18
18
|
|
|
@@ -28,10 +28,10 @@ func main() {
|
|
|
28
28
|
|
|
29
29
|
// usage prints the CLI help (for --help / -h). No client or network setup.
|
|
30
30
|
func usage(out io.Writer) {
|
|
31
|
-
fmt.Fprintf(out, "%s-cli —
|
|
31
|
+
fmt.Fprintf(out, "%s-cli — boru-driven CLI + REPL for the %s SDK\n\n", prompt, prompt)
|
|
32
32
|
fmt.Fprintln(out, "Usage:")
|
|
33
|
-
fmt.Fprintf(out, " %s-cli [--help] [<
|
|
34
|
-
fmt.Fprintln(out, "With arguments, they are joined into a single
|
|
33
|
+
fmt.Fprintf(out, " %s-cli [--help] [<boru expression>]\n\n", prompt)
|
|
34
|
+
fmt.Fprintln(out, "With arguments, they are joined into a single boru expression and")
|
|
35
35
|
fmt.Fprintln(out, "evaluated against the API. With no arguments, starts an interactive REPL.")
|
|
36
36
|
fmt.Fprintln(out)
|
|
37
37
|
fmt.Fprintln(out, "Words: list / load / update <query?> <entity>")
|
|
@@ -5,11 +5,11 @@ import (
|
|
|
5
5
|
"fmt"
|
|
6
6
|
"strings"
|
|
7
7
|
|
|
8
|
-
eng "github.com/
|
|
8
|
+
eng "github.com/boru-lang/boru/eng/go"
|
|
9
9
|
sdk "GOMODULE"
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
-
// registerSDKWords installs three native
|
|
12
|
+
// registerSDKWords installs three native boru words bound to the SDK:
|
|
13
13
|
// list / load / update. Each is declared with two overloads matching
|
|
14
14
|
// the signature [query?:(Node or Scalar) entity:atom]:
|
|
15
15
|
//
|
|
@@ -18,31 +18,34 @@ import (
|
|
|
18
18
|
// `load {id:1} book`, `load 1 book`)
|
|
19
19
|
//
|
|
20
20
|
// The entity slot is /q-quoted so a bareword `book` parses as the
|
|
21
|
-
// Atom "book" rather than dispatching as an undefined word.
|
|
21
|
+
// Atom "book" rather than dispatching as an undefined word. Both
|
|
22
|
+
// overloads are all-forward (BarrierAllForward), so args are collected
|
|
23
|
+
// from the tokens following the word.
|
|
22
24
|
func registerSDKWords(r *eng.Registry, client *sdk.ProjectNameSDK) {
|
|
23
25
|
for _, op := range []string{"list", "load", "update"} {
|
|
24
26
|
op := op
|
|
25
|
-
single := eng.
|
|
27
|
+
single := eng.Signature{
|
|
26
28
|
Args: []*eng.Type{eng.TAtom},
|
|
27
29
|
QuoteArgs: map[int]bool{0: true},
|
|
28
|
-
|
|
30
|
+
Impl: eng.Go(func(args []eng.Value, _ map[string]eng.Value, _ []eng.Value, _ *eng.Registry) ([]eng.Value, error) {
|
|
29
31
|
return runOp(client, op, nil, args[0])
|
|
30
|
-
},
|
|
31
|
-
Returns:
|
|
32
|
+
}),
|
|
33
|
+
Returns: []*eng.Type{eng.TAny},
|
|
34
|
+
BarrierPos: eng.BarrierAllForward,
|
|
32
35
|
}
|
|
33
|
-
dual := eng.
|
|
36
|
+
dual := eng.Signature{
|
|
34
37
|
Args: []*eng.Type{eng.TAny, eng.TAtom},
|
|
35
38
|
QuoteArgs: map[int]bool{1: true},
|
|
36
|
-
|
|
39
|
+
Impl: eng.Go(func(args []eng.Value, _ map[string]eng.Value, _ []eng.Value, _ *eng.Registry) ([]eng.Value, error) {
|
|
37
40
|
q := args[0]
|
|
38
41
|
return runOp(client, op, &q, args[1])
|
|
39
|
-
},
|
|
40
|
-
Returns:
|
|
42
|
+
}),
|
|
43
|
+
Returns: []*eng.Type{eng.TAny},
|
|
44
|
+
BarrierPos: eng.BarrierAllForward,
|
|
41
45
|
}
|
|
42
46
|
r.RegisterNativeFunc(eng.NativeFunc{
|
|
43
|
-
Name:
|
|
44
|
-
|
|
45
|
-
Signatures: []eng.NativeSig{single, dual},
|
|
47
|
+
Name: op,
|
|
48
|
+
Signatures: []eng.Signature{single, dual},
|
|
46
49
|
})
|
|
47
50
|
}
|
|
48
51
|
}
|
|
@@ -91,22 +94,22 @@ func entityFor(client *sdk.ProjectNameSDK, name string) (sdk.ProjectNameEntity,
|
|
|
91
94
|
return nil, fmt.Errorf("unknown entity %q", name)
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
// queryToMap converts
|
|
97
|
+
// queryToMap converts a boru Value (Map or Scalar) into the
|
|
95
98
|
// `map[string]any` shape the SDK expects. Maps are unwrapped via
|
|
96
99
|
// eng.ToNative. Scalars are wrapped as {"id": <value>} so the
|
|
97
100
|
// shorthand `load 1 book` becomes `load {id:1} book`.
|
|
98
101
|
func queryToMap(v eng.Value) (map[string]any, error) {
|
|
99
|
-
if v.
|
|
102
|
+
if v.Parent.ConformsTo(eng.TMap) {
|
|
100
103
|
m, ok := eng.ToNative(v).(map[string]any)
|
|
101
104
|
if !ok {
|
|
102
105
|
return nil, fmt.Errorf("query map could not be unwrapped")
|
|
103
106
|
}
|
|
104
107
|
return m, nil
|
|
105
108
|
}
|
|
106
|
-
if v.
|
|
109
|
+
if v.Parent.ConformsTo(eng.TScalar) {
|
|
107
110
|
return map[string]any{"id": eng.ToNative(v)}, nil
|
|
108
111
|
}
|
|
109
|
-
return nil, fmt.Errorf("query must be a Map or Scalar, got %s", v.
|
|
112
|
+
return nil, fmt.Errorf("query must be a Map or Scalar, got %s", v.Parent)
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
// extractData walks an SDK result and replaces any sdk.Entity wrapper
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
indent,
|
|
13
13
|
isAuthActive,
|
|
14
14
|
resolveAuthPrefix,
|
|
15
|
+
serverVariables,
|
|
15
16
|
} from '@voxgig/sdkgen'
|
|
16
17
|
|
|
17
18
|
|
|
@@ -53,6 +54,14 @@ const Config = cmp(async function Config(props: any) {
|
|
|
53
54
|
`
|
|
54
55
|
: ''
|
|
55
56
|
|
|
57
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
58
|
+
// runtime can substitute {name} placeholders in base (see makeOptions).
|
|
59
|
+
const svars = serverVariables(model)
|
|
60
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
61
|
+
'server: {\n' +
|
|
62
|
+
svars.map((v: any) => ` ${JSON.stringify(v.name)}: ${JSON.stringify(v.dflt)},\n`).join('') +
|
|
63
|
+
' },\n\n '
|
|
64
|
+
|
|
56
65
|
File({ name: 'Config.' + target.ext }, () => {
|
|
57
66
|
|
|
58
67
|
Fragment({
|
|
@@ -60,6 +69,8 @@ const Config = cmp(async function Config(props: any) {
|
|
|
60
69
|
|
|
61
70
|
replace: {
|
|
62
71
|
|
|
72
|
+
"'SERVERBLOCK'": serverBlock,
|
|
73
|
+
|
|
63
74
|
"'AUTHBLOCK'": authBlock,
|
|
64
75
|
|
|
65
76
|
"'HEADERS'": indent(JSON.stringify(headers, null, 2), 4).trim(),
|
|
@@ -19,7 +19,7 @@ class Config {
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
main = {
|
|
22
|
-
name: '
|
|
22
|
+
name: '$$const.Name$$',
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
|
|
@@ -31,7 +31,7 @@ class Config {
|
|
|
31
31
|
options = {
|
|
32
32
|
base: '$$main.kit.info.servers.0.url$$',
|
|
33
33
|
|
|
34
|
-
'AUTHBLOCK'headers: 'HEADERS',
|
|
34
|
+
'SERVERBLOCK''AUTHBLOCK'headers: 'HEADERS',
|
|
35
35
|
|
|
36
36
|
entity: {
|
|
37
37
|
// #EntityConfigs
|
|
@@ -17,6 +17,10 @@ describe('EntityNameDirect', async () => {
|
|
|
17
17
|
|
|
18
18
|
test('direct-exists', async () => {
|
|
19
19
|
const sdk = new ProjectNameSDK({
|
|
20
|
+
// Concrete base: a live construction must satisfy any server
|
|
21
|
+
// variables a templated base URL declares; overriding base with a
|
|
22
|
+
// literal (as the direct flow tests do) sidesteps the requirement.
|
|
23
|
+
base: 'http://localhost:8080',
|
|
20
24
|
system: { fetch: async () => ({}) }
|
|
21
25
|
})
|
|
22
26
|
assert('function' === typeof sdk.direct)
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
each,
|
|
12
12
|
isAuthActive,
|
|
13
13
|
resolveAuthPrefix,
|
|
14
|
+
serverVariables,
|
|
14
15
|
} from '@voxgig/sdkgen'
|
|
15
16
|
|
|
16
17
|
|
|
@@ -46,6 +47,14 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
47
|
let baseUrl = ''
|
|
47
48
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
49
|
|
|
50
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
51
|
+
// runtime can substitute {name} placeholders in base (see make_options).
|
|
52
|
+
const svars = serverVariables(model)
|
|
53
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
54
|
+
' server = {\n' +
|
|
55
|
+
svars.map((v: any) => ` [${JSON.stringify(v.name)}] = ${JSON.stringify(v.dflt)},\n`).join('') +
|
|
56
|
+
' },\n'
|
|
57
|
+
|
|
49
58
|
const authBlock = authActive
|
|
50
59
|
? ` auth = {
|
|
51
60
|
prefix = "${authPrefix}",
|
|
@@ -73,7 +82,7 @@ local function make_config()
|
|
|
73
82
|
Content(` },
|
|
74
83
|
options = {
|
|
75
84
|
base = "${baseUrl}",
|
|
76
|
-
${authBlock} headers = ${formatLuaTable(headers, 3)},
|
|
85
|
+
${serverBlock}${authBlock} headers = ${formatLuaTable(headers, 3)},
|
|
77
86
|
entity = {
|
|
78
87
|
`)
|
|
79
88
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
each,
|
|
12
12
|
isAuthActive,
|
|
13
13
|
resolveAuthPrefix,
|
|
14
|
+
serverVariables,
|
|
14
15
|
} from '@voxgig/sdkgen'
|
|
15
16
|
|
|
16
17
|
|
|
@@ -46,6 +47,16 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
47
|
let baseUrl = ''
|
|
47
48
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
49
|
|
|
50
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
51
|
+
// runtime can substitute {name} placeholders in base (see MakeOptions).
|
|
52
|
+
// `$` is escaped so a default can never open a PHP interpolation.
|
|
53
|
+
const svars = serverVariables(model)
|
|
54
|
+
const phps = (s: string) => JSON.stringify(s).replace(/\$/g, '\\$')
|
|
55
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
56
|
+
' "server" => [\n' +
|
|
57
|
+
svars.map((v: any) => ` ${phps(v.name)} => ${phps(v.dflt)},\n`).join('') +
|
|
58
|
+
' ],\n'
|
|
59
|
+
|
|
49
60
|
const authBlock = authActive
|
|
50
61
|
? ` "auth" => [
|
|
51
62
|
"prefix" => "${authPrefix}",
|
|
@@ -84,7 +95,7 @@ class ${model.const.Name}Config
|
|
|
84
95
|
Content(` ],
|
|
85
96
|
"options" => [
|
|
86
97
|
"base" => "${baseUrl}",
|
|
87
|
-
${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
98
|
+
${serverBlock}${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
88
99
|
"entity" => (object)[],
|
|
89
100
|
],
|
|
90
101
|
"entity" => (object)[],
|
|
@@ -94,7 +105,7 @@ ${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
|
94
105
|
Content(` ],
|
|
95
106
|
"options" => [
|
|
96
107
|
"base" => "${baseUrl}",
|
|
97
|
-
${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
108
|
+
${serverBlock}${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
98
109
|
"entity" => [
|
|
99
110
|
`)
|
|
100
111
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
each,
|
|
12
12
|
isAuthActive,
|
|
13
13
|
resolveAuthPrefix,
|
|
14
|
+
serverVariables,
|
|
14
15
|
} from '@voxgig/sdkgen'
|
|
15
16
|
|
|
16
17
|
|
|
@@ -46,6 +47,14 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
47
|
let baseUrl = ''
|
|
47
48
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
49
|
|
|
50
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
51
|
+
// runtime can substitute {name} placeholders in base (see make_options).
|
|
52
|
+
const svars = serverVariables(model)
|
|
53
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
54
|
+
' "server": {\n' +
|
|
55
|
+
svars.map((v: any) => ` ${JSON.stringify(v.name)}: ${JSON.stringify(v.dflt)},\n`).join('') +
|
|
56
|
+
' },\n'
|
|
57
|
+
|
|
49
58
|
const authBlock = authActive
|
|
50
59
|
? ` "auth": {
|
|
51
60
|
"prefix": "${authPrefix}",
|
|
@@ -74,7 +83,7 @@ def make_config():
|
|
|
74
83
|
Content(` },
|
|
75
84
|
"options": {
|
|
76
85
|
"base": "${baseUrl}",
|
|
77
|
-
${authBlock} "headers": ${formatPyDict(headers, 3)},
|
|
86
|
+
${serverBlock}${authBlock} "headers": ${formatPyDict(headers, 3)},
|
|
78
87
|
"entity": {
|
|
79
88
|
`)
|
|
80
89
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
each,
|
|
12
12
|
isAuthActive,
|
|
13
13
|
resolveAuthPrefix,
|
|
14
|
+
serverVariables,
|
|
14
15
|
} from '@voxgig/sdkgen'
|
|
15
16
|
|
|
16
17
|
|
|
@@ -46,6 +47,16 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
47
|
let baseUrl = ''
|
|
47
48
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
49
|
|
|
50
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
51
|
+
// runtime can substitute {name} placeholders in base (see make_options).
|
|
52
|
+
// `#` is escaped so a default can never open a Ruby interpolation.
|
|
53
|
+
const svars = serverVariables(model)
|
|
54
|
+
const rbs = (s: string) => JSON.stringify(s).replace(/#/g, '\\#')
|
|
55
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
56
|
+
' "server" => {\n' +
|
|
57
|
+
svars.map((v: any) => ` ${rbs(v.name)} => ${rbs(v.dflt)},\n`).join('') +
|
|
58
|
+
' },\n'
|
|
59
|
+
|
|
49
60
|
const authBlock = authActive
|
|
50
61
|
? ` "auth" => {
|
|
51
62
|
"prefix" => "${authPrefix}",
|
|
@@ -74,7 +85,7 @@ module ${model.const.Name}Config
|
|
|
74
85
|
Content(` },
|
|
75
86
|
"options" => {
|
|
76
87
|
"base" => "${baseUrl}",
|
|
77
|
-
${authBlock} "headers" => ${formatRubyHash(headers, 4)},
|
|
88
|
+
${serverBlock}${authBlock} "headers" => ${formatRubyHash(headers, 4)},
|
|
78
89
|
"entity" => {
|
|
79
90
|
`)
|
|
80
91
|
|
|
@@ -75,8 +75,30 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
75
75
|
|
|
76
76
|
const genCtx: GenCtx = { model, entity, rustcrate, flow: basicflow, PROJUPPER }
|
|
77
77
|
|
|
78
|
-
const
|
|
79
|
-
|
|
78
|
+
const opNames = Array.from(new Set(allSteps.map((s: any) => s.op).filter(Boolean)))
|
|
79
|
+
const opsList = opNames.map(o => `"${o}"`).join(', ')
|
|
80
|
+
|
|
81
|
+
// Same hazard as the csharp target: an entity whose basic flow has no ops
|
|
82
|
+
// would emit `for op in []`, and rustc cannot infer the element type of an
|
|
83
|
+
// empty array literal — E0282, type annotations needed. The loop is dead
|
|
84
|
+
// code in that case, and so is the `mode` binding only it reads (which
|
|
85
|
+
// would then warn as unused). Emit neither.
|
|
86
|
+
const skipBlock = 0 === opNames.length ? '' : ` // Per-op sdk-test-control.json skip — the basic test exercises a flow
|
|
87
|
+
// with multiple ops; skipping any op skips the whole flow.
|
|
88
|
+
let mode = if setup.live { "live" } else { "unit" };
|
|
89
|
+
for op in [${opsList}] {
|
|
90
|
+
let (skip, reason) = is_control_skipped("entityOp", &format!("${entity.name}.{}", op), mode);
|
|
91
|
+
if skip {
|
|
92
|
+
let reason = if reason.is_empty() {
|
|
93
|
+
"skipped via sdk-test-control.json".to_string()
|
|
94
|
+
} else {
|
|
95
|
+
reason
|
|
96
|
+
};
|
|
97
|
+
eprintln!("skip: {}", reason);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
`
|
|
80
102
|
|
|
81
103
|
const method = rustVarName(entity.name)
|
|
82
104
|
const evar = rustVarName(entity.name)
|
|
@@ -158,22 +180,7 @@ fn ${evar}_entity_stream() {
|
|
|
158
180
|
#[test]
|
|
159
181
|
fn ${evar}_entity_basic() {
|
|
160
182
|
let setup = ${evar}_basic_setup(Value::Noval);
|
|
161
|
-
//
|
|
162
|
-
// with multiple ops; skipping any op skips the whole flow.
|
|
163
|
-
let mode = if setup.live { "live" } else { "unit" };
|
|
164
|
-
for op in [${opsList}] {
|
|
165
|
-
let (skip, reason) = is_control_skipped("entityOp", &format!("${entity.name}.{}", op), mode);
|
|
166
|
-
if skip {
|
|
167
|
-
let reason = if reason.is_empty() {
|
|
168
|
-
"skipped via sdk-test-control.json".to_string()
|
|
169
|
-
} else {
|
|
170
|
-
reason
|
|
171
|
-
};
|
|
172
|
-
eprintln!("skip: {}", reason);
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// The basic flow consumes synthetic IDs from the fixture. In live mode
|
|
183
|
+
${skipBlock} // The basic flow consumes synthetic IDs from the fixture. In live mode
|
|
177
184
|
// without an *_ENTID env override, those IDs hit the live API and 4xx.
|
|
178
185
|
if setup.synthetic_only {
|
|
179
186
|
eprintln!("skip: live entity test uses synthetic IDs from fixture — set ${PROJUPPER}_TEST_${ENTUPPER}_ENTID JSON to run live");
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
File, Content, Folder,
|
|
26
26
|
} from '@voxgig/sdkgen'
|
|
27
27
|
|
|
28
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames } from '@voxgig/sdkgen'
|
|
28
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames, swiftSafeTypeName } from '@voxgig/sdkgen'
|
|
29
29
|
|
|
30
30
|
import {
|
|
31
31
|
KIT,
|
|
@@ -114,9 +114,16 @@ import Foundation
|
|
|
114
114
|
.filter((f: any) => f.active !== false)
|
|
115
115
|
|
|
116
116
|
// Entity data model: one property per field. req:false -> optional.
|
|
117
|
+
//
|
|
118
|
+
// Swift has no intra-module namespacing, so a spec schema named
|
|
119
|
+
// after one of our own runtime types (e.g. `Response`) would be a
|
|
120
|
+
// redeclaration and fail the build. swiftSafeTypeName appends
|
|
121
|
+
// `Type` on collision only — `Response` -> `ResponseType` — so
|
|
122
|
+
// non-colliding SDKs generate byte-identical output to before.
|
|
123
|
+
const TypeName = swiftSafeTypeName(Name)
|
|
117
124
|
emitStruct(
|
|
118
|
-
`/// ${
|
|
119
|
-
|
|
125
|
+
`/// ${TypeName} is the typed data model for the ${ent.name} entity.`,
|
|
126
|
+
TypeName,
|
|
120
127
|
fields.map((f: any) => ({ name: f.name, type: f.type, optional: false === f.req }))
|
|
121
128
|
)
|
|
122
129
|
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
indent,
|
|
13
13
|
isAuthActive,
|
|
14
14
|
resolveAuthPrefix,
|
|
15
|
+
serverVariables,
|
|
15
16
|
} from '@voxgig/sdkgen'
|
|
16
17
|
|
|
17
18
|
|
|
@@ -53,6 +54,14 @@ const Config = cmp(async function Config(props: any) {
|
|
|
53
54
|
`
|
|
54
55
|
: ''
|
|
55
56
|
|
|
57
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
58
|
+
// runtime can substitute {name} placeholders in base (see makeOptions).
|
|
59
|
+
const svars = serverVariables(model)
|
|
60
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
61
|
+
'server: {\n' +
|
|
62
|
+
svars.map((v: any) => ` ${JSON.stringify(v.name)}: ${JSON.stringify(v.dflt)},\n`).join('') +
|
|
63
|
+
' },\n\n '
|
|
64
|
+
|
|
56
65
|
File({ name: 'Config.' + target.ext }, () => {
|
|
57
66
|
|
|
58
67
|
Fragment({
|
|
@@ -60,6 +69,8 @@ const Config = cmp(async function Config(props: any) {
|
|
|
60
69
|
|
|
61
70
|
replace: {
|
|
62
71
|
|
|
72
|
+
"'SERVERBLOCK'": serverBlock,
|
|
73
|
+
|
|
63
74
|
"'AUTHBLOCK'": authBlock,
|
|
64
75
|
|
|
65
76
|
"'HEADERS'": indent(JSON.stringify(headers, null, 2), 4).trim(),
|