@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.
Files changed (91) hide show
  1. package/dist/cmp/Deploy.js +16 -16
  2. package/dist/cmp/Deploy.js.map +1 -1
  3. package/dist/cmp/ReadmeTop.js +13 -11
  4. package/dist/cmp/ReadmeTop.js.map +1 -1
  5. package/dist/helpers/naming.d.ts +3 -1
  6. package/dist/helpers/naming.js +65 -0
  7. package/dist/helpers/naming.js.map +1 -1
  8. package/dist/helpers/serverVars.d.ts +10 -0
  9. package/dist/helpers/serverVars.js +87 -0
  10. package/dist/helpers/serverVars.js.map +1 -0
  11. package/dist/sdkgen.d.ts +3 -2
  12. package/dist/sdkgen.js +6 -1
  13. package/dist/sdkgen.js.map +1 -1
  14. package/dist/tsconfig.tsbuildinfo +1 -1
  15. package/package.json +3 -3
  16. package/project/.sdk/model/target/go-cli.aontu +2 -2
  17. package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +22 -15
  18. package/project/.sdk/src/cmp/go/Config_go.ts +10 -1
  19. package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +54 -35
  20. package/project/.sdk/src/cmp/go-cli/fragment/main.fragment.go +7 -7
  21. package/project/.sdk/src/cmp/go-cli/fragment/words.fragment.go +21 -18
  22. package/project/.sdk/src/cmp/js/Config_js.ts +11 -0
  23. package/project/.sdk/src/cmp/js/fragment/Config.fragment.js +2 -2
  24. package/project/.sdk/src/cmp/js/fragment/Direct.test.fragment.js +4 -0
  25. package/project/.sdk/src/cmp/lua/Config_lua.ts +10 -1
  26. package/project/.sdk/src/cmp/php/Config_php.ts +13 -2
  27. package/project/.sdk/src/cmp/py/Config_py.ts +10 -1
  28. package/project/.sdk/src/cmp/rb/Config_rb.ts +12 -1
  29. package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +25 -18
  30. package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +10 -3
  31. package/project/.sdk/src/cmp/ts/Config_ts.ts +11 -0
  32. package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +2 -2
  33. package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +4 -0
  34. package/project/.sdk/tm/c/utility/prepare_method.c +18 -0
  35. package/project/.sdk/tm/clojure/src/sdk/core.clj +9 -1
  36. package/project/.sdk/tm/cpp/utility/pipeline.hpp +13 -0
  37. package/project/.sdk/tm/csharp/Makefile +6 -6
  38. package/project/.sdk/tm/csharp/utility/PrepareMethod.cs +11 -0
  39. package/project/.sdk/tm/dart/Makefile +3 -3
  40. package/project/.sdk/tm/dart/lib/utility/PrepareMethodUtility.dart +10 -0
  41. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +8 -1
  42. package/project/.sdk/tm/go/Makefile +6 -6
  43. package/project/.sdk/tm/go/test/primary_utility_test.go +5 -0
  44. package/project/.sdk/tm/go/utility/make_options.go +48 -0
  45. package/project/.sdk/tm/go/utility/prepare_method.go +14 -1
  46. package/project/.sdk/tm/haskell/src/SdkRuntime.hs +13 -4
  47. package/project/.sdk/tm/java/Makefile +6 -6
  48. package/project/.sdk/tm/java/utility/PrepareMethod.java +9 -0
  49. package/project/.sdk/tm/js/Makefile +6 -6
  50. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -1
  51. package/project/.sdk/tm/js/src/utility/PrepareMethodUtility.js +9 -0
  52. package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +5 -0
  53. package/project/.sdk/tm/kotlin/Makefile +6 -6
  54. package/project/.sdk/tm/kotlin/utility/Prepare.kt +9 -0
  55. package/project/.sdk/tm/lean/src/SdkUtility.lean +6 -1
  56. package/project/.sdk/tm/lua/Makefile +7 -7
  57. package/project/.sdk/tm/lua/feature/test_feature.lua +29 -1
  58. package/project/.sdk/tm/lua/test/primary_utility_test.lua +4 -0
  59. package/project/.sdk/tm/lua/utility/make_options.lua +39 -0
  60. package/project/.sdk/tm/lua/utility/prepare_method.lua +11 -0
  61. package/project/.sdk/tm/ocaml/sdk_runtime.ml +9 -3
  62. package/project/.sdk/tm/perl/Makefile +6 -6
  63. package/project/.sdk/tm/perl/utility/prepare_method.pm +17 -0
  64. package/project/.sdk/tm/php/Makefile +6 -6
  65. package/project/.sdk/tm/php/feature/TestFeature.php +30 -2
  66. package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +5 -0
  67. package/project/.sdk/tm/php/utility/MakeOptions.php +44 -0
  68. package/project/.sdk/tm/php/utility/PrepareMethod.php +11 -0
  69. package/project/.sdk/tm/py/Makefile +6 -6
  70. package/project/.sdk/tm/py/test/test_primary_utility.py +5 -0
  71. package/project/.sdk/tm/py/utility/make_options.py +42 -0
  72. package/project/.sdk/tm/py/utility/prepare_method.py +10 -0
  73. package/project/.sdk/tm/rb/Makefile +6 -6
  74. package/project/.sdk/tm/rb/test/primary_utility_test.rb +4 -0
  75. package/project/.sdk/tm/rb/utility/make_options.rb +37 -0
  76. package/project/.sdk/tm/rb/utility/prepare_method.rb +10 -1
  77. package/project/.sdk/tm/rust/Makefile +6 -6
  78. package/project/.sdk/tm/rust/utility/prepare_method.rs +12 -0
  79. package/project/.sdk/tm/scala/utility/Prepare.scala +14 -8
  80. package/project/.sdk/tm/swift/Makefile +6 -6
  81. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +8 -0
  82. package/project/.sdk/tm/ts/Makefile +6 -6
  83. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +39 -1
  84. package/project/.sdk/tm/ts/src/utility/PrepareMethodUtility.ts +9 -0
  85. package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +4 -0
  86. package/project/.sdk/tm/zig/core/utility.zig +15 -0
  87. package/src/cmp/Deploy.ts +16 -16
  88. package/src/cmp/ReadmeTop.ts +13 -11
  89. package/src/helpers/naming.ts +71 -0
  90. package/src/helpers/serverVars.ts +105 -0
  91. package/src/sdkgen.ts +6 -1
@@ -52,6 +52,11 @@ module ProjectNameUtilities
52
52
  "system" => {},
53
53
  "test" => { "active" => false, "entity" => { "`$OPEN`" => true } },
54
54
  "clean" => { "keys" => "key,token,id" },
55
+ # Server-variable values for a templated base URL (OpenAPI server
56
+ # variables): {name} placeholders in "base" are substituted from this
57
+ # map at construction. Spec defaults arrive via the generated config;
58
+ # user values override them.
59
+ "server" => { "`$CHILD`" => "" },
55
60
  }
56
61
 
57
62
  sys_fetch = VoxgigStruct.getpath(opts, "system.fetch")
@@ -60,6 +65,38 @@ module ProjectNameUtilities
60
65
  validated = VoxgigStruct.validate(merged, optspec)
61
66
  opts = validated.is_a?(Hash) ? validated : {}
62
67
 
68
+ # Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
69
+ # Every placeholder must resolve to a non-empty value: from
70
+ # options["server"] (user), else the config default. A placeholder that
71
+ # resolves to "" is a construction ERROR in live mode — the URL cannot
72
+ # work — but in test mode substitutes the deterministic value
73
+ # "test-<name>" so offline tests need no configuration.
74
+ base = opts["base"]
75
+ if base.is_a?(String) && base.include?("{")
76
+ testmode = VoxgigStruct.getpath(opts, "test.active") == true ||
77
+ VoxgigStruct.getpath(opts, "feature.test.active") == true
78
+ server = opts["server"].is_a?(Hash) ? opts["server"] : {}
79
+ sdkname = VoxgigStruct.getpath(config, "main.name")
80
+ sdkname = "SDK" unless sdkname.is_a?(String) && !sdkname.empty?
81
+ opts["base"] = base.gsub(/\{([A-Za-z0-9_]+)\}/) do
82
+ name = Regexp.last_match(1)
83
+ val = server[name]
84
+ val = "" unless val.is_a?(String)
85
+ if val.empty?
86
+ if testmode
87
+ "test-#{name}"
88
+ else
89
+ raise ArgumentError,
90
+ "#{sdkname}: the server variable '#{name}' is required: " \
91
+ "the API base URL is '#{base}' — pass " \
92
+ "{ \"server\" => { \"#{name}\" => \"...\" } } in the SDK options"
93
+ end
94
+ else
95
+ val
96
+ end
97
+ end
98
+ end
99
+
63
100
  if sys_fetch
64
101
  opts["system"] = {} unless opts["system"].is_a?(Hash)
65
102
  opts["system"]["fetch"] = sys_fetch
@@ -1,5 +1,14 @@
1
1
  # ProjectName SDK utility: prepare_method
2
+ require_relative 'struct/voxgig_struct'
2
3
  module ProjectNameUtilities
3
4
  METHOD_MAP = { "create"=>"POST", "update"=>"PUT", "load"=>"GET", "list"=>"GET", "remove"=>"DELETE", "patch"=>"PATCH" }
4
- PrepareMethod = ->(ctx) { METHOD_MAP[ctx.op.name] || "GET" }
5
+
6
+ # The API definition is authoritative: a POST-only or PATCH-based API
7
+ # exposes `update` as POST or PATCH, not the PUT the op name implies.
8
+ # Only fall back to the op-name convention when the point has no method.
9
+ PrepareMethod = ->(ctx) {
10
+ method = VoxgigStruct.getprop(ctx.point, "method")
11
+ next method.upcase if method.is_a?(String) && "" != method
12
+ METHOD_MAP[ctx.op.name] || "GET"
13
+ }
5
14
  end
@@ -13,21 +13,21 @@ clean:
13
13
  # The crates.io registry entry is declared in the model with
14
14
  # state: 'pending' — a real deploy publishes the git tag rust/vX.Y.Z only;
15
15
  # `cargo publish` starts when the registry state flips to 'active'. Run
16
- # headless under the aql key vault, which injects the GitHub token so
16
+ # headless under the boru key vault, which injects the GitHub token so
17
17
  # nothing lands on disk or argv:
18
- # aql vault exec --for=github=<alias> -- make publish
19
- # aql `--dry-run` injects a filler token we detect to rehearse (no tag/push).
18
+ # boru vault exec --for=github=<alias> -- make publish
19
+ # boru `--dry-run` injects a filler token we detect to rehearse (no tag/push).
20
20
  # set -e + tag-last: a failed push never leaves a tag behind.
21
21
  VERSION := $(shell cat VERSION)
22
22
  TAG := rust/v$(VERSION)
23
- AQL_DRY_RUN_FILLER := AQL-DRY-RUN-FILLER-NOT-A-REAL-SECRET
23
+ BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
24
24
  publish:
25
25
  @if git rev-parse -q --verify "refs/tags/$(TAG)" >/dev/null; then \
26
26
  echo "tag $(TAG) already exists — bump VERSION first"; exit 1; fi
27
27
  @set -e; \
28
28
  token="$${GITHUB_TOKEN:-$$GH_TOKEN}"; \
29
- if [ "$$token" = "$(AQL_DRY_RUN_FILLER)" ]; then \
30
- echo "[dry-run] aql filler token detected: would tag $(TAG); nothing pushed."; \
29
+ if [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ]; then \
30
+ echo "[dry-run] boru filler token detected: would tag $(TAG); nothing pushed."; \
31
31
  exit 0; \
32
32
  fi; \
33
33
  git tag -a "$(TAG)" -m "rust v$(VERSION)"; \
@@ -1,10 +1,22 @@
1
1
  use std::rc::Rc;
2
2
 
3
3
  use crate::core::context::Context;
4
+ use crate::core::helpers::getp;
5
+ use crate::utility::voxgigstruct::Value;
4
6
 
5
7
  pub fn prepare_method_util(ctx: &Rc<Context>) -> String {
6
8
  let opname = ctx.op.borrow().name.clone();
7
9
 
10
+ // The API definition is authoritative: a POST-only or PATCH-based API
11
+ // exposes `update` as POST or PATCH, not the PUT the op name implies.
12
+ // Only fall back to the op-name convention when the point has no method.
13
+ let point = ctx.point.borrow().clone();
14
+ if let Value::Str(pm) = getp(&point, "method") {
15
+ if !pm.is_empty() {
16
+ return pm.to_uppercase();
17
+ }
18
+ }
19
+
8
20
  match opname.as_str() {
9
21
  "create" => "POST",
10
22
  "update" => "PUT",
@@ -14,14 +14,20 @@ object PreparePath {
14
14
  }
15
15
 
16
16
  object PrepareMethod {
17
- def prepareMethod(ctx: Context): String = ctx.op.name match {
18
- case "create" => "POST"
19
- case "update" => "PUT"
20
- case "load" => "GET"
21
- case "list" => "GET"
22
- case "remove" => "DELETE"
23
- case "patch" => "PATCH"
24
- case _ => "GET"
17
+ // The API definition is authoritative: a POST-only or PATCH-based API
18
+ // exposes `update` as POST or PATCH, not the PUT the op name implies.
19
+ // Only fall back to the op-name convention when the point has no method.
20
+ def prepareMethod(ctx: Context): String = Struct.getprop(ctx.point, "method") match {
21
+ case s: String if s.nonEmpty => s.toUpperCase
22
+ case _ => ctx.op.name match {
23
+ case "create" => "POST"
24
+ case "update" => "PUT"
25
+ case "load" => "GET"
26
+ case "list" => "GET"
27
+ case "remove" => "DELETE"
28
+ case "patch" => "PATCH"
29
+ case _ => "GET"
30
+ }
25
31
  }
26
32
  }
27
33
 
@@ -13,21 +13,21 @@ clean:
13
13
  # --- Release: tag for the SwiftPM registry ---------------------------------
14
14
  # SwiftPM has no upload step - publishing IS the git tag. Publication is
15
15
  # pending (see model/target/swift.aontu publish block); publishing a version
16
- # currently means pushing the tag swift/vX.Y.Z. Run headless under the aql key
16
+ # currently means pushing the tag swift/vX.Y.Z. Run headless under the boru key
17
17
  # vault, which injects the GitHub token so nothing lands on disk or argv:
18
- # aql vault exec --for=github=<alias> -- make publish
19
- # aql `--dry-run` injects a filler token we detect to rehearse (no tag/push).
18
+ # boru vault exec --for=github=<alias> -- make publish
19
+ # boru `--dry-run` injects a filler token we detect to rehearse (no tag/push).
20
20
  # set -e + tag-last: a failed push never leaves a tag behind.
21
21
  VERSION := $(shell cat VERSION)
22
22
  TAG := swift/v$(VERSION)
23
- AQL_DRY_RUN_FILLER := AQL-DRY-RUN-FILLER-NOT-A-REAL-SECRET
23
+ BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
24
24
  publish: test
25
25
  @if git rev-parse -q --verify "refs/tags/$(TAG)" >/dev/null; then \
26
26
  echo "tag $(TAG) already exists - bump VERSION first"; exit 1; fi
27
27
  @set -e; \
28
28
  token="$${GITHUB_TOKEN:-$$GH_TOKEN}"; \
29
- if [ "$$token" = "$(AQL_DRY_RUN_FILLER)" ]; then \
30
- echo "[dry-run] aql filler token detected: would tag $(TAG); nothing pushed."; \
29
+ if [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ]; then \
30
+ echo "[dry-run] boru filler token detected: would tag $(TAG); nothing pushed."; \
31
31
  exit 0; \
32
32
  fi; \
33
33
  git tag -a "$(TAG)" -m "swift v$(VERSION)"; \
@@ -14,6 +14,14 @@ private let methodMap: [String: String] = [
14
14
 
15
15
  func prepareMethodUtil(_ ctx: Context) -> String {
16
16
  let opname = ctx.op!.name
17
+
18
+ // The API definition is authoritative: a POST-only or PATCH-based API
19
+ // exposes `update` as POST or PATCH, not the PUT the op name implies.
20
+ // Only fall back to the op-name convention when the point has no method.
21
+ if let pm = gp(ctx.point, "method").asString, !pm.isEmpty {
22
+ return pm.uppercased()
23
+ }
24
+
17
25
  return methodMap[opname] ?? "GET"
18
26
  }
19
27
 
@@ -17,22 +17,22 @@ clean:
17
17
 
18
18
  # --- Release: publish to npm ----------------------------------------------
19
19
  # Compile, then publish this package to npm and tag ts/vX.Y.Z. Run headless
20
- # under the aql key vault, which injects the npm auth token + the GitHub token
20
+ # under the boru key vault, which injects the npm auth token + the GitHub token
21
21
  # (never on disk or argv):
22
- # aql vault exec --for=npm=<alias> --for=github=<alias> -- make publish
23
- # aql `--dry-run` injects a filler token we detect to rehearse (build only, no
22
+ # boru vault exec --for=npm=<alias> --for=github=<alias> -- make publish
23
+ # boru `--dry-run` injects a filler token we detect to rehearse (build only, no
24
24
  # publish/tag). set -e + tag-last: a failed publish never leaves a tag behind.
25
25
  SHELL := /bin/bash
26
26
  VERSION := $(shell node -p "require('./package.json').version")
27
27
  TAG := ts/v$(VERSION)
28
- AQL_DRY_RUN_FILLER := AQL-DRY-RUN-FILLER-NOT-A-REAL-SECRET
28
+ BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
29
29
  publish: test
30
30
  @if git rev-parse -q --verify "refs/tags/$(TAG)" >/dev/null; then \
31
31
  echo "tag $(TAG) already exists — bump package.json version first"; exit 1; fi
32
32
  @set -e; \
33
33
  token="$${GITHUB_TOKEN:-$$GH_TOKEN}"; \
34
- if [ "$$token" = "$(AQL_DRY_RUN_FILLER)" ]; then \
35
- echo "[dry-run] aql filler token detected: would publish to npm and tag $(TAG); nothing pushed."; \
34
+ if [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ]; then \
35
+ echo "[dry-run] boru filler token detected: would publish to npm and tag $(TAG); nothing pushed."; \
36
36
  exit 0; \
37
37
  fi; \
38
38
  npm stage publish --access public --registry https://registry.npmjs.org; \
@@ -82,16 +82,54 @@ function makeOptions(ctx: Context) {
82
82
  },
83
83
  clean: {
84
84
  keys: 'key,token,id'
85
+ },
86
+ // Server-variable values for a templated base URL (OpenAPI server
87
+ // variables): `{name}` placeholders in `base` are substituted from
88
+ // this map at construction. Spec defaults arrive via the generated
89
+ // Config; user values override them.
90
+ server: {
91
+ '`$CHILD`': ''
85
92
  }
86
93
  }
87
94
 
88
95
  // JavaScript specific option values.
89
96
  optspec.system.fetch = opts.system?.fetch || global.fetch
90
97
 
91
- opts = merge([{}, cfgopts, opts])
98
+ // Clone the config side before merging: `config` is a module-level
99
+ // singleton in ts/js, and merge would otherwise use its nested maps as
100
+ // merge TARGETS — one instance's options (server, headers, ...) would
101
+ // contaminate every instance constructed after it.
102
+ opts = merge([{}, struct.clone(cfgopts), opts])
92
103
 
93
104
  opts = validate(opts, optspec)
94
105
 
106
+ // Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
107
+ // Every placeholder must resolve to a non-empty value: from
108
+ // options.server (user), else the Config default. A placeholder that
109
+ // resolves to '' is a construction ERROR in live mode — the URL cannot
110
+ // work — but in test mode substitutes the deterministic value
111
+ // `test-<name>` so offline tests need no configuration.
112
+ if ('string' === typeof opts.base && opts.base.includes('{')) {
113
+ const testmode = true === opts.test.active ||
114
+ true === (opts.feature && opts.feature.test && opts.feature.test.active)
115
+ const server = opts.server || {}
116
+ opts.base = opts.base.replace(/\{([A-Za-z0-9_]+)\}/g,
117
+ (_m: string, name: string) => {
118
+ let val = server[name]
119
+ val = 'string' === typeof val ? val : ''
120
+ if ('' === val) {
121
+ if (testmode) {
122
+ return 'test-' + name
123
+ }
124
+ throw new Error(
125
+ `${config?.main?.name || 'SDK'}: the server variable '${name}' is required: ` +
126
+ `the API base URL is '${opts.base}' — pass { server: { ${name}: '...' } } ` +
127
+ `in the SDK options`)
128
+ }
129
+ return val
130
+ })
131
+ }
132
+
95
133
  // Resolve the feature add-order: an explicit array order (above) wins;
96
134
  // otherwise order the map test-first, then the remaining names sorted, so
97
135
  // the outcome is deterministic and `test` is always the base transport.
@@ -16,6 +16,15 @@ function prepareMethod(ctx: Context) {
16
16
  patch: 'PATCH',
17
17
  }
18
18
 
19
+ // The API definition is authoritative: a POST-only or PATCH-based API
20
+ // exposes `update` as POST or PATCH, not the PUT the op name implies.
21
+ // Only fall back to the op-name convention when the point has no method.
22
+ const method = ctx.point?.method
23
+
24
+ if (null != method && '' !== method) {
25
+ return method.toUpperCase()
26
+ }
27
+
19
28
  return methodMap[key]
20
29
  }
21
30
 
@@ -229,6 +229,8 @@ describe('PrimaryUtility', async () => {
229
229
  body: 'present',
230
230
  })
231
231
  const reqClient = new (SDK as any)({
232
+ // Concrete base: a live construction must satisfy any server variables a templated base URL declares; a literal base sidesteps the requirement.
233
+ base: 'http://localhost:8080',
232
234
  system: { fetch: mockFetch }
233
235
  })
234
236
  const reqUtility = reqClient.utility()
@@ -410,6 +412,7 @@ describe('PrimaryUtility', async () => {
410
412
  test('fetcher-live', async () => {
411
413
  const calls: any[] = []
412
414
  const liveClient = new (SDK as any)({
415
+ base: 'http://localhost:8080',
413
416
  system: {
414
417
  fetch: async (url: string, init: any) => {
415
418
  calls.push({ url, init })
@@ -431,6 +434,7 @@ describe('PrimaryUtility', async () => {
431
434
 
432
435
  test('fetcher-blocked-test-mode', async () => {
433
436
  const blockedClient = new (SDK as any)({
437
+ base: 'http://localhost:8080',
434
438
  system: { fetch: async () => ({}) }
435
439
  })
436
440
  blockedClient._mode = 'test'
@@ -825,6 +825,21 @@ pub fn param_util(ctx: *Context, paramdef: Value) Value {
825
825
 
826
826
  pub fn prepare_method_util(ctx: *Context) []const u8 {
827
827
  const opname = ctx.op.name;
828
+
829
+ // The API definition is authoritative: a POST-only or PATCH-based API
830
+ // exposes `update` as POST or PATCH, not the PUT the op name implies.
831
+ // Only fall back to the op-name convention when the point has no method.
832
+ switch (h.getp(ctx.point, "method")) {
833
+ .string => |m| {
834
+ if (0 < m.len) {
835
+ const upper = h.A().alloc(u8, m.len) catch return m;
836
+ for (m, 0..) |c, i| upper[i] = std.ascii.toUpper(c);
837
+ return upper;
838
+ }
839
+ },
840
+ else => {},
841
+ }
842
+
828
843
  if (std.mem.eql(u8, opname, "create")) return "POST";
829
844
  if (std.mem.eql(u8, opname, "update")) return "PUT";
830
845
  if (std.mem.eql(u8, opname, "load")) return "GET";
package/src/cmp/Deploy.ts CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  // `publish` sections (see model/sdkgen.aontu):
11
11
  //
12
12
  // publish.tag — git release tag `<prefix>/vX.Y.Z`; every port has
13
- // one, pushed with a token from the aql key vault
13
+ // one, pushed with a token from the boru key vault
14
14
  // (--for recipe + alias, default github/github).
15
15
  // publish.registry — package registry details (name, url, vault
16
16
  // credential recipe or raw env mapping) plus a
@@ -25,7 +25,7 @@ import {
25
25
  // Follows the voxgig/struct root Makefile conventions: per-target deploy
26
26
  // targets, deliberately no all-targets real deploy (each upload is
27
27
  // irreversible), and an everything-at-once DRY run leaning on
28
- // `aql vault exec --dry-run` filler-token cooperation in each target's
28
+ // `boru vault exec --dry-run` filler-token cooperation in each target's
29
29
  // publish recipe.
30
30
  const Deploy = cmp(function Deploy(props: any) {
31
31
  const { ctx$ } = props
@@ -76,7 +76,7 @@ function aliasVarName(name: string): string {
76
76
  }
77
77
 
78
78
 
79
- // The aql vault exec argument string for a target: `--for=<recipe>=<alias>`
79
+ // The boru vault exec argument string for a target: `--for=<recipe>=<alias>`
80
80
  // flags where a preset recipe exists, or a raw `'alias=ENV_VAR,...'`
81
81
  // mapping when any credential lacks a preset (e.g. luarocks). The github
82
82
  // token for the tag push is always included.
@@ -142,10 +142,10 @@ function makeDeployMakefile(model: any, targets: any[]): string {
142
142
  return `
143
143
  deploy-${t.name}:
144
144
  \t@echo "deploy-${t.name}: tag-only port — publishing the git tag."
145
- \taql vault exec ${ghArgs} -- $(MAKE) tag-push-${t.name}
145
+ \tboru vault exec ${ghArgs} -- $(MAKE) tag-push-${t.name}
146
146
 
147
147
  deploy-dry-${t.name}:
148
- \taql vault exec --dry-run ${ghArgs} -- $(MAKE) tag-push-${t.name}
148
+ \tboru vault exec --dry-run ${ghArgs} -- $(MAKE) tag-push-${t.name}
149
149
  ${tagPushRecipe(t.name, 'tag-only port')}
150
150
  `
151
151
  }
@@ -157,20 +157,20 @@ ${tagPushRecipe(t.name, 'tag-only port')}
157
157
  return `
158
158
  deploy-${t.name}:
159
159
  \t@echo "deploy-${t.name}: ${reg.name} publication is pending — publishing the git tag only."
160
- \taql vault exec ${ghArgs} -- $(MAKE) tag-push-${t.name}
160
+ \tboru vault exec ${ghArgs} -- $(MAKE) tag-push-${t.name}
161
161
 
162
162
  deploy-dry-${t.name}:
163
- \taql vault exec --dry-run ${ghArgs} -- $(MAKE) tag-push-${t.name}
163
+ \tboru vault exec --dry-run ${ghArgs} -- $(MAKE) tag-push-${t.name}
164
164
  ${tagPushRecipe(t.name, reg.name + ' publication pending — tag-only deploy')}
165
165
  `
166
166
  }
167
167
 
168
168
  return `
169
169
  deploy-${t.name}:
170
- \taql vault exec ${args} -- $(MAKE) -C ${t.name} publish
170
+ \tboru vault exec ${args} -- $(MAKE) -C ${t.name} publish
171
171
 
172
172
  deploy-dry-${t.name}:
173
- \taql vault exec --dry-run ${args} -- $(MAKE) -C ${t.name} publish
173
+ \tboru vault exec --dry-run ${args} -- $(MAKE) -C ${t.name} publish
174
174
  `
175
175
  }).join('')
176
176
 
@@ -183,7 +183,7 @@ deploy-dry-${t.name}:
183
183
  #
184
184
  # Every port gets a git release tag <target>/vX.Y.Z. Ports with an ACTIVE
185
185
  # registry also publish a package there. Credentials are injected at exec
186
- # time by the aql key vault (https://github.com/aql-lang/aql) — never
186
+ # time by the boru key vault (https://github.com/boru-lang/boru) — never
187
187
  # stored on disk or passed on the command line.
188
188
  #
189
189
  # Publication state (from the model):
@@ -194,7 +194,7 @@ ${summary}
194
194
  # registry upload is irreversible); while a
195
195
  # registry is pending this publishes the
196
196
  # port's git tag only
197
- # make deploy-dry rehearse EVERY target: aql --dry-run
197
+ # make deploy-dry rehearse EVERY target: boru --dry-run
198
198
  # injects a filler token that each publish
199
199
  # recipe detects, so build + test run in full
200
200
  # but nothing is uploaded and no tag is cut
@@ -207,7 +207,7 @@ ${varLines}
207
207
 
208
208
  # Lockstep SDK version, read from the canonical ts manifest.
209
209
  VERSION := $(shell node -p "require('./ts/package.json').version" 2>/dev/null || echo 0.0.0)
210
- AQL_DRY_RUN_FILLER := AQL-DRY-RUN-FILLER-NOT-A-REAL-SECRET
210
+ BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
211
211
 
212
212
  TARGETS := ${targets.map((t: any) => t.name).join(' ')}
213
213
 
@@ -233,7 +233,7 @@ ${deployRules}`
233
233
 
234
234
 
235
235
 
236
- // The root-level tag creation + push recipe for a target: aql --dry-run
236
+ // The root-level tag creation + push recipe for a target: boru --dry-run
237
237
  // filler cooperation, idempotent tag creation, token-authenticated https
238
238
  // push (works from an ssh-remote clone without ssh keys).
239
239
  function tagPushRecipe(name: string, note: string): string {
@@ -241,9 +241,9 @@ function tagPushRecipe(name: string, note: string): string {
241
241
  tag-push-${name}:
242
242
  \t@set -e; tag="${name}/v$(VERSION)"; \\
243
243
  \ttoken="\$\${GITHUB_TOKEN:-$$GH_TOKEN}"; \\
244
- \tif [ "$$token" = "$(AQL_DRY_RUN_FILLER)" ]; then \\
245
- \t echo "[dry-run] aql filler token detected: would create (if missing) and push tag $$tag; nothing pushed."; exit 0; fi; \\
246
- \tif [ -z "$$token" ]; then echo "tag-push-${name}: no GITHUB_TOKEN in env — run via make deploy-${name} (aql vault exec)"; exit 1; fi; \\
244
+ \tif [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ]; then \\
245
+ \t echo "[dry-run] boru filler token detected: would create (if missing) and push tag $$tag; nothing pushed."; exit 0; fi; \\
246
+ \tif [ -z "$$token" ]; then echo "tag-push-${name}: no GITHUB_TOKEN in env — run via make deploy-${name} (boru vault exec)"; exit 1; fi; \\
247
247
  \tif git rev-parse -q --verify "refs/tags/$$tag" >/dev/null; then \\
248
248
  \t echo "tag $$tag already exists — pushing existing tag"; \\
249
249
  \telse git tag -a "$$tag" -m "Release $$tag"; fi; \\
@@ -549,28 +549,30 @@ Pass custom features via the \`extend\` option at construction time.
549
549
  `)
550
550
  }
551
551
 
552
- // 13. Upstream API — contact/servers from the OpenAPI info block
552
+ // 13. Upstream API — always disclose the OpenAPI origin and where the
553
+ // spec(s) live; contact/servers links come from the OpenAPI info block.
553
554
  const upstreamUrl = (info.contact && info.contact.url)
554
555
  || (info.servers && info.servers[0] && info.servers[0].url)
555
556
  || homepage
556
- if (upstreamUrl || docsUrl) {
557
- Content(`## Upstream API
557
+ Content(`## Upstream API
558
558
 
559
559
  This SDK is generated from the upstream OpenAPI specification. It is an
560
560
  unofficial client and is not affiliated with the API provider.
561
561
 
562
+ The OpenAPI spec(s) this SDK was generated from are kept in the
563
+ [\`.sdk/def/\`](.sdk/def/) folder.
564
+
562
565
  `)
563
- if (upstreamUrl) {
564
- Content(`- Upstream API: [${upstreamUrl}](${upstreamUrl})
565
- `)
566
- }
567
- if (docsUrl && docsUrl !== upstreamUrl) {
568
- Content(`- Documentation: [${docsUrl}](${docsUrl})
566
+ if (upstreamUrl) {
567
+ Content(`- Upstream API: [${upstreamUrl}](${upstreamUrl})
569
568
  `)
570
- }
571
- Content(`
569
+ }
570
+ if (docsUrl && docsUrl !== upstreamUrl) {
571
+ Content(`- Documentation: [${docsUrl}](${docsUrl})
572
572
  `)
573
573
  }
574
+ Content(`
575
+ `)
574
576
 
575
577
  // 13b. Security
576
578
  Content(`## Security
@@ -126,6 +126,75 @@ function rbSafeTypeName(Name: string): string {
126
126
  }
127
127
 
128
128
 
129
+ // Swift SDK-OWNED TYPE NAMES — a third hazard, distinct from both sets above.
130
+ //
131
+ // The keyword sets guard local bindings; the Ruby set guards clobbering the
132
+ // LANGUAGE's core. This set guards clobbering OUR OWN runtime, because Swift
133
+ // has no namespacing WITHIN a module: every type the swift templates declare
134
+ // and every generated entity type land in the same module. Two declarations
135
+ // of one name is a hard error, not a silent override:
136
+ //
137
+ // // core/Response.swift (template)
138
+ // public final class Response { ... } // transport wrapper
139
+ // // entity/<Prefix>Types.swift (generated from a spec schema named Response)
140
+ // public struct Response { ... }
141
+ // -> error: invalid redeclaration of 'Response'
142
+ // -> error: 'Response' is ambiguous for type lookup (every core file)
143
+ //
144
+ // Found 2026-08-07: the Hook0 spec has a `Response` schema, which took the
145
+ // whole swift target down. `Response` is merely the first collision to be
146
+ // hit — every name below is equally exposed.
147
+ //
148
+ // Sourced by scanning BOTH `tm/swift/Sources/*/` (templates) and
149
+ // `src/cmp/swift/*.ts` (components) for top-level type declarations —
150
+ // regardless of access level. `internal` is Swift's default and is still
151
+ // module-wide, and `open class BaseFeature` is not `public` either, so an
152
+ // access-level filter under-collects and silently reopens the bug.
153
+ //
154
+ // Nested types (a `typealias Element` inside a struct) and the separate Tests
155
+ // module (`ReadmeExamplesTest`) do NOT share this namespace and are excluded.
156
+ //
157
+ // `swift-sdk-types.test.ts` re-derives this list from the templates and fails
158
+ // on drift, so adding a public type to a swift template cannot silently
159
+ // reopen the bug.
160
+ const SWIFT_SDK_TYPES = new Set<string>([
161
+ // core runtime
162
+ 'Context', 'Control', 'Entity', 'Operation', 'Point', 'Response', 'Result',
163
+ 'SdkConfig', 'Spec', 'Utility',
164
+ // struct library
165
+ 'Injection', 'Injector', 'JSON', 'JSONParseError', 'Modify',
166
+ 'OrderedDictionary', 'Sentinel', 'Value', 'VList', 'VMap', 'WalkApply',
167
+ // function/callback aliases
168
+ 'FetcherFunc', 'Formatter', 'NativeCall0', 'NativeRef', 'SystemFetch',
169
+ // features
170
+ 'AuditFeature', 'BaseFeature', 'CacheFeature', 'ClienttrackFeature',
171
+ 'DebugFeature', 'IdempotencyFeature', 'LogFeature', 'MetricsBucket',
172
+ 'MetricsFeature', 'NetsimFeature', 'PagingFeature', 'ProxyFeature',
173
+ 'RatelimitFeature', 'RbacFeature', 'RetryFeature', 'StreamingFeature',
174
+ 'TelemetryFeature', 'TestFeature', 'TimeoutFeature',
175
+ ])
176
+
177
+
178
+ // Does `Name` collide with a type the swift SDK runtime already declares?
179
+ function isSwiftSdkType(Name: string): boolean {
180
+ return SWIFT_SDK_TYPES.has(Name)
181
+ }
182
+
183
+
184
+ // A module-safe Swift type name for a generated type: unchanged, unless the
185
+ // swift runtime already declares it, in which case `Type` is appended
186
+ // (`Response` -> `ResponseType`). Mirrors rbSafeTypeName deliberately — same
187
+ // suffix, same "only rename on an actual collision" rule, so SDKs that do not
188
+ // collide are byte-identical to before.
189
+ //
190
+ // Applied ONLY to the bare entity data type. Per-op type names already carry
191
+ // their own suffix (`ResponseCreateData`, `ResponseLoadMatch`) and the entity
192
+ // CLASS is separately suffixed (`ResponseEntity`), so neither ever collided.
193
+ function swiftSafeTypeName(Name: string): string {
194
+ return isSwiftSdkType(Name) ? Name + 'Type' : Name
195
+ }
196
+
197
+
129
198
  // Is `name` a reserved word (an illegal identifier) in the target language?
130
199
  function isReservedName(name: string, lang: string): boolean {
131
200
  const set = RESERVED[lang]
@@ -189,6 +258,8 @@ export {
189
258
  exampleVarName,
190
259
  isRbCoreConstant,
191
260
  rbSafeTypeName,
261
+ isSwiftSdkType,
262
+ swiftSafeTypeName,
192
263
  jsProp,
193
264
  jsOptProp,
194
265
  jsKey,