@voxgig/sdkgen 3.4.7 → 3.5.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/bin/voxgig-sdkgen +78 -10
- package/dist/action/action.d.ts +5 -2
- package/dist/action/action.js +113 -6
- package/dist/action/action.js.map +1 -1
- package/dist/action/check.d.ts +15 -0
- package/dist/action/check.js +347 -0
- package/dist/action/check.js.map +1 -0
- package/dist/action/dispatch.d.ts +8 -0
- package/dist/action/dispatch.js +74 -0
- package/dist/action/dispatch.js.map +1 -0
- package/dist/action/docs.d.ts +4 -0
- package/dist/action/docs.js +236 -0
- package/dist/action/docs.js.map +1 -0
- package/dist/action/doctor.d.ts +5 -2
- package/dist/action/doctor.js +526 -74
- package/dist/action/doctor.js.map +1 -1
- package/dist/action/feature.js +96 -17
- package/dist/action/feature.js.map +1 -1
- package/dist/action/kind.d.ts +30 -0
- package/dist/action/kind.js +258 -0
- package/dist/action/kind.js.map +1 -0
- package/dist/action/package.d.ts +25 -0
- package/dist/action/package.js +852 -0
- package/dist/action/package.js.map +1 -0
- package/dist/action/resolve.d.ts +18 -0
- package/dist/action/resolve.js +280 -0
- package/dist/action/resolve.js.map +1 -0
- package/dist/action/target.d.ts +7 -1
- package/dist/action/target.js +240 -97
- package/dist/action/target.js.map +1 -1
- package/dist/cmp/Docs.d.ts +4 -0
- package/dist/cmp/Docs.js +98 -0
- package/dist/cmp/Docs.js.map +1 -0
- package/dist/cmp/ExternalDocs.d.ts +2 -0
- package/dist/cmp/ExternalDocs.js +43 -0
- package/dist/cmp/ExternalDocs.js.map +1 -0
- package/dist/helpers/definition.d.ts +5 -0
- package/dist/helpers/definition.js +72 -0
- package/dist/helpers/definition.js.map +1 -0
- package/dist/helpers/featureSource.d.ts +8 -2
- package/dist/helpers/featureSource.js +61 -12
- package/dist/helpers/featureSource.js.map +1 -1
- package/dist/helpers/junk.d.ts +11 -0
- package/dist/helpers/junk.js +149 -0
- package/dist/helpers/junk.js.map +1 -0
- package/dist/helpers/manifest.d.ts +50 -0
- package/dist/helpers/manifest.js +328 -0
- package/dist/helpers/manifest.js.map +1 -0
- package/dist/helpers/modelcheck.d.ts +22 -0
- package/dist/helpers/modelcheck.js +203 -0
- package/dist/helpers/modelcheck.js.map +1 -0
- package/dist/helpers/semver.d.ts +4 -0
- package/dist/helpers/semver.js +174 -0
- package/dist/helpers/semver.js.map +1 -0
- package/dist/helpers/shipped.d.ts +4 -0
- package/dist/helpers/shipped.js +36 -0
- package/dist/helpers/shipped.js.map +1 -0
- package/dist/helpers/stdrep.d.ts +9 -1
- package/dist/helpers/stdrep.js +22 -0
- package/dist/helpers/stdrep.js.map +1 -1
- package/dist/sdkgen.d.ts +15 -3
- package/dist/sdkgen.js +233 -67
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +10 -2
- package/dist/utility.js +17 -0
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aontu +69 -0
- package/package.json +3 -2
- package/project/.sdk/model/feature/audit.aontu +1 -0
- package/project/.sdk/model/feature/cache.aontu +1 -0
- package/project/.sdk/model/feature/clienttrack.aontu +1 -0
- package/project/.sdk/model/feature/debug.aontu +1 -0
- package/project/.sdk/model/feature/idempotency.aontu +1 -0
- package/project/.sdk/model/feature/log.aontu +1 -0
- package/project/.sdk/model/feature/metrics.aontu +1 -0
- package/project/.sdk/model/feature/netsim.aontu +1 -0
- package/project/.sdk/model/feature/paging.aontu +1 -0
- package/project/.sdk/model/feature/proxy.aontu +1 -0
- package/project/.sdk/model/feature/ratelimit.aontu +1 -0
- package/project/.sdk/model/feature/rbac.aontu +1 -0
- package/project/.sdk/model/feature/retry.aontu +1 -0
- package/project/.sdk/model/feature/streaming.aontu +1 -0
- package/project/.sdk/model/feature/telemetry.aontu +1 -0
- package/project/.sdk/model/feature/test.aontu +1 -0
- package/project/.sdk/model/feature/timeout.aontu +1 -0
- package/project/.sdk/model/target/c.aontu +1 -0
- package/project/.sdk/model/target/clojure.aontu +1 -0
- package/project/.sdk/model/target/cpp.aontu +1 -0
- package/project/.sdk/model/target/dart.aontu +1 -0
- package/project/.sdk/model/target/elixir.aontu +1 -0
- package/project/.sdk/model/target/go-cli.aontu +1 -0
- package/project/.sdk/model/target/go-mcp.aontu +1 -0
- package/project/.sdk/model/target/go.aontu +1 -0
- package/project/.sdk/model/target/haskell.aontu +1 -0
- package/project/.sdk/model/target/java.aontu +1 -0
- package/project/.sdk/model/target/js.aontu +1 -0
- package/project/.sdk/model/target/kotlin.aontu +1 -0
- package/project/.sdk/model/target/lean.aontu +1 -0
- package/project/.sdk/model/target/lua.aontu +1 -0
- package/project/.sdk/model/target/ocaml.aontu +1 -0
- package/project/.sdk/model/target/perl.aontu +1 -0
- package/project/.sdk/model/target/php.aontu +1 -0
- package/project/.sdk/model/target/py-data.aontu +1 -0
- package/project/.sdk/model/target/py.aontu +1 -0
- package/project/.sdk/model/target/rb.aontu +1 -0
- package/project/.sdk/model/target/rust.aontu +1 -0
- package/project/.sdk/model/target/scala.aontu +1 -0
- package/project/.sdk/model/target/seneca-provider.aontu +1 -0
- package/project/.sdk/model/target/zig.aontu +1 -0
- package/project/.sdk/src/cmp/c/Config_c.ts +44 -0
- package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +3 -1
- package/project/.sdk/src/cmp/clojure/Config_clojure.ts +37 -42
- package/project/.sdk/src/cmp/clojure/utility_clojure.ts +42 -0
- package/project/.sdk/src/cmp/cpp/Config_cpp.ts +18 -0
- package/project/.sdk/src/cmp/csharp/Config_csharp.ts +125 -52
- package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +3 -1
- package/project/.sdk/src/cmp/csharp/utility_csharp.ts +94 -6
- package/project/.sdk/src/cmp/dart/Config_dart.ts +43 -5
- package/project/.sdk/src/cmp/dart/fragment/Config.data.fragment.dart +74 -0
- package/project/.sdk/src/cmp/dart/fragment/Config.fragment.dart +6 -9
- package/project/.sdk/src/cmp/dart/fragment/Main.fragment.dart +16 -5
- package/project/.sdk/src/cmp/dart/utility_dart.ts +18 -0
- package/project/.sdk/src/cmp/elixir/Config_elixir.ts +128 -13
- package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +3 -1
- package/project/.sdk/src/cmp/elixir/utility_elixir.ts +6 -0
- package/project/.sdk/src/cmp/haskell/Config_haskell.ts +35 -52
- package/project/.sdk/src/cmp/haskell/Package_haskell.ts +1 -0
- package/project/.sdk/src/cmp/haskell/Test_haskell.ts +1 -1
- package/project/.sdk/src/cmp/haskell/utility_haskell.ts +15 -5
- package/project/.sdk/src/cmp/java/Config_java.ts +21 -0
- package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +15 -0
- package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +42 -39
- package/project/.sdk/src/cmp/perl/Config_perl.ts +15 -0
- package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +3 -1
- package/project/.sdk/src/cmp/rust/Config_rust.ts +44 -0
- package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +4 -2
- package/project/.sdk/src/cmp/scala/Config_scala.ts +15 -0
- package/project/.sdk/src/cmp/swift/Config_swift.ts +17 -0
- package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +3 -1
- package/project/.sdk/src/cmp/zig/Config_zig.ts +44 -0
- package/project/.sdk/src/cmp/zig/TestEntity_zig.ts +9 -2
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +3 -1
- package/project/.sdk/tm/c/core/sdk.h +1 -0
- package/project/.sdk/tm/c/utility/make_options.c +5 -1
- package/project/.sdk/tm/clojure/src/sdk/core.clj +51 -3
- package/project/.sdk/tm/cpp/core/types.hpp +4 -1
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +5 -1
- package/project/.sdk/tm/csharp/test/PipelineTest.cs +15 -0
- package/project/.sdk/tm/csharp/utility/MakeOptions.cs +67 -1
- package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +43 -0
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +58 -2
- package/project/.sdk/tm/haskell/{test/TestJson.hs → src/SdkJson.hs} +8 -4
- package/project/.sdk/tm/haskell/src/SdkRuntime.hs +55 -2
- package/project/.sdk/tm/haskell/test/Runner.hs +1 -1
- package/project/.sdk/tm/haskell/test/StructCorpus.hs +1 -1
- package/project/.sdk/tm/java/core/SdkClient.java +3 -1
- package/project/.sdk/tm/java/utility/MakeOptions.java +5 -1
- package/project/.sdk/tm/kotlin/core/SdkClient.kt +3 -1
- package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +5 -1
- package/project/.sdk/tm/ocaml/Makefile +3 -2
- package/project/.sdk/tm/ocaml/sdk_json.ml +106 -0
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +56 -0
- package/project/.sdk/tm/ocaml/test/struct_corpus.ml +4 -86
- package/project/.sdk/tm/perl/utility/make_options.pm +5 -1
- package/project/.sdk/tm/rust/utility/make_options.rs +79 -1
- package/project/.sdk/tm/scala/core/SdkClient.scala +3 -1
- package/project/.sdk/tm/scala/utility/Make.scala +5 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +5 -1
- package/project/.sdk/tm/zig/core/utility.zig +85 -1
- package/project/sdkgen-package.json +57 -0
- package/src/action/action.ts +136 -6
- package/src/action/check.ts +495 -0
- package/src/action/dispatch.ts +105 -0
- package/src/action/docs.ts +310 -0
- package/src/action/doctor.ts +692 -81
- package/src/action/feature.ts +109 -17
- package/src/action/kind.ts +375 -0
- package/src/action/package.ts +1173 -0
- package/src/action/resolve.ts +362 -0
- package/src/action/target.ts +290 -108
- package/src/cmp/Docs.ts +125 -0
- package/src/cmp/ExternalDocs.ts +54 -0
- package/src/helpers/definition.ts +82 -0
- package/src/helpers/featureSource.ts +83 -13
- package/src/helpers/junk.ts +168 -0
- package/src/helpers/manifest.ts +474 -0
- package/src/helpers/modelcheck.ts +262 -0
- package/src/helpers/semver.ts +211 -0
- package/src/helpers/shipped.ts +41 -0
- package/src/helpers/stdrep.ts +70 -0
- package/src/sdkgen.ts +294 -66
- package/src/types.ts +33 -3
- package/src/utility.ts +17 -0
|
@@ -98,18 +98,96 @@ pub fn make_options_util(ctx: &Rc<Context>) -> Value {
|
|
|
98
98
|
]),
|
|
99
99
|
),
|
|
100
100
|
("clean", jo(vec![("keys", Value::str("key,token,id"))])),
|
|
101
|
+
// Server-variable values for a templated base URL (OpenAPI server
|
|
102
|
+
// variables): {name} placeholders in "base" are substituted from this
|
|
103
|
+
// map at construction. Spec defaults arrive via the generated config;
|
|
104
|
+
// user values override them. Mirrors go's make_options optspec.
|
|
105
|
+
("server", jo(vec![("`$CHILD`", Value::str(""))])),
|
|
101
106
|
]);
|
|
102
107
|
|
|
103
108
|
// Preserve system.fetch before merge/validate (validation strips it).
|
|
104
109
|
let sys_fetch = getpath(&["system", "fetch"], &opts);
|
|
105
110
|
|
|
106
|
-
|
|
111
|
+
// CLONE the config side: `config` is a per-thread singleton
|
|
112
|
+
// (core::config::shared_config) and merge uses its nested maps as merge
|
|
113
|
+
// TARGETS, so without this one client's options (headers, server, ...) are
|
|
114
|
+
// written into the shared config and inherited by every client after it.
|
|
115
|
+
let merged = vs::merge(
|
|
116
|
+
&ja(vec![Value::empty_map(), vs::clone(&cfgopts), opts.clone()]), None);
|
|
107
117
|
if let Ok(validated) = vs::validate(&merged, &optspec, None) {
|
|
108
118
|
if let Value::Map(_) = validated {
|
|
109
119
|
opts = validated;
|
|
110
120
|
}
|
|
111
121
|
}
|
|
112
122
|
|
|
123
|
+
// Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
|
|
124
|
+
// Every placeholder must resolve to a non-empty value: from options.server
|
|
125
|
+
// (user), else the Config default. A placeholder that resolves to "" is a
|
|
126
|
+
// construction ERROR in live mode - the URL cannot work - but in test mode
|
|
127
|
+
// substitutes the deterministic value "test-<name>" so offline tests need
|
|
128
|
+
// no configuration. The SDK constructor has no error return, so a missing
|
|
129
|
+
// required variable PANICS: construction-time misconfiguration.
|
|
130
|
+
//
|
|
131
|
+
// Scanned by hand rather than with vs::re_replace, whose replacement is a
|
|
132
|
+
// fixed string and cannot vary per placeholder.
|
|
133
|
+
if let Value::Str(base) = getp(&opts, "base") {
|
|
134
|
+
if base.contains('{') {
|
|
135
|
+
let testmode = matches!(getpath(&["test", "active"], &opts), Value::Bool(true))
|
|
136
|
+
|| matches!(
|
|
137
|
+
getpath(&["feature", "test", "active"], &opts),
|
|
138
|
+
Value::Bool(true)
|
|
139
|
+
);
|
|
140
|
+
let server = getp(&opts, "server");
|
|
141
|
+
let sdkname = match getpath(&["main", "name"], &config) {
|
|
142
|
+
Value::Str(s) if !s.is_empty() => s,
|
|
143
|
+
_ => "SDK".to_string(),
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
let mut resolved = String::with_capacity(base.len());
|
|
147
|
+
let bytes: Vec<char> = base.chars().collect();
|
|
148
|
+
let mut i = 0usize;
|
|
149
|
+
while i < bytes.len() {
|
|
150
|
+
if '{' != bytes[i] {
|
|
151
|
+
resolved.push(bytes[i]);
|
|
152
|
+
i += 1;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
// A placeholder only when it closes and the name is
|
|
156
|
+
// [A-Za-z0-9_]+; anything else is literal text.
|
|
157
|
+
let mut j = i + 1;
|
|
158
|
+
while j < bytes.len() && (bytes[j].is_ascii_alphanumeric() || '_' == bytes[j]) {
|
|
159
|
+
j += 1;
|
|
160
|
+
}
|
|
161
|
+
if j >= bytes.len() || '}' != bytes[j] || j == i + 1 {
|
|
162
|
+
resolved.push(bytes[i]);
|
|
163
|
+
i += 1;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
let name: String = bytes[i + 1..j].iter().collect();
|
|
167
|
+
let val = match getp(&server, &name) {
|
|
168
|
+
Value::Str(s) => s,
|
|
169
|
+
_ => String::new(),
|
|
170
|
+
};
|
|
171
|
+
if val.is_empty() {
|
|
172
|
+
if testmode {
|
|
173
|
+
resolved.push_str(&format!("test-{}", name));
|
|
174
|
+
} else {
|
|
175
|
+
panic!(
|
|
176
|
+
"{}: the server variable '{}' is required: the API base \
|
|
177
|
+
URL is '{}' - pass server: {{ \"{}\": \"...\" }} in the \
|
|
178
|
+
SDK options",
|
|
179
|
+
sdkname, name, base, name
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
resolved.push_str(&val);
|
|
184
|
+
}
|
|
185
|
+
i = j + 1;
|
|
186
|
+
}
|
|
187
|
+
setp(&opts, "base", Value::str(&resolved));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
113
191
|
// Restore system.fetch.
|
|
114
192
|
if !sys_fetch.is_noval() {
|
|
115
193
|
let sys = getp(&opts, "system");
|
|
@@ -16,7 +16,9 @@ abstract class SdkClient(options0: JMap[String, Object]) {
|
|
|
16
16
|
protected var rootctx: Context = null
|
|
17
17
|
|
|
18
18
|
locally {
|
|
19
|
-
|
|
19
|
+
// The process-wide config (sdkgen rung L2): read-only on the request path,
|
|
20
|
+
// so every client shares one rather than rebuilding it.
|
|
21
|
+
val config = Config.sharedConfig()
|
|
20
22
|
|
|
21
23
|
val ctxmap = new LinkedHashMap[String, Object]()
|
|
22
24
|
ctxmap.put("client", this)
|
|
@@ -216,7 +216,11 @@ object MakeOptions {
|
|
|
216
216
|
|
|
217
217
|
val mergeList = new ArrayList[Object]()
|
|
218
218
|
mergeList.add(new LinkedHashMap[String, Object]())
|
|
219
|
-
|
|
219
|
+
// CLONE the config side: `config` is a process-wide singleton
|
|
220
|
+
// (Config.sharedConfig) and merge uses its nested maps as merge TARGETS, so
|
|
221
|
+
// without this one client's options (headers, server, ...) are written into
|
|
222
|
+
// the shared config and inherited by every client constructed afterwards.
|
|
223
|
+
mergeList.add(Struct.clone(cfgopts))
|
|
220
224
|
mergeList.add(opts)
|
|
221
225
|
val merged = Struct.merge(mergeList)
|
|
222
226
|
|
|
@@ -98,7 +98,11 @@ func makeOptionsUtil(_ ctx: Context) -> VMap {
|
|
|
98
98
|
// validation reshapes the system block).
|
|
99
99
|
let sysFetch = gpath(opts, "system", "fetch")
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
// CLONE the config side: `config` is a process-wide singleton
|
|
102
|
+
// (SdkConfig.sharedConfig) and merge uses its nested maps as merge TARGETS,
|
|
103
|
+
// so without this one client's options (headers, server, ...) are written
|
|
104
|
+
// into the shared config and inherited by every client built afterwards.
|
|
105
|
+
let merged = merge(.list([.map(VMap()), clone(.map(cfgopts)), .map(opts)]))
|
|
102
106
|
let validated = validate(merged, optspec)
|
|
103
107
|
let result = validated.asMap ?? VMap()
|
|
104
108
|
|
|
@@ -35,6 +35,14 @@ fn fmt(comptime f: []const u8, args: anytype) []const u8 {
|
|
|
35
35
|
return std.fmt.allocPrint(h.A(), f, args) catch "";
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// Boolean-or-absent: an option that is unset, null or a non-boolean is false.
|
|
39
|
+
fn is_true(v: Value) bool {
|
|
40
|
+
return switch (v) {
|
|
41
|
+
.bool => |b| b,
|
|
42
|
+
else => false,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
38
46
|
// ============================================================================
|
|
39
47
|
// Utility bundle
|
|
40
48
|
// ============================================================================
|
|
@@ -368,17 +376,93 @@ pub fn make_options_util(ctx: *Context) Value {
|
|
|
368
376
|
.{ "entity", h.jo(&.{.{ "`$OPEN`", h.vbool(true) }}) },
|
|
369
377
|
}) },
|
|
370
378
|
.{ "clean", h.jo(&.{.{ "keys", h.vstr("key,token,id") }}) },
|
|
379
|
+
// Server-variable values for a templated base URL (OpenAPI server
|
|
380
|
+
// variables): {name} placeholders in "base" are substituted from this
|
|
381
|
+
// map at construction. Spec defaults arrive via the generated config;
|
|
382
|
+
// user values override them. Mirrors go's make_options optspec.
|
|
383
|
+
.{ "server", h.jo(&.{.{ "`$CHILD`", h.vstr("") }}) },
|
|
371
384
|
});
|
|
372
385
|
|
|
373
386
|
// Preserve system.fetch before merge/validate (validation strips it).
|
|
374
387
|
const sys_fetch = h.getpath(&.{ "system", "fetch" }, opts);
|
|
375
388
|
|
|
376
|
-
|
|
389
|
+
// CLONE the config side: `config` is a process-wide singleton
|
|
390
|
+
// (config.shared_config) and merge uses its nested maps as merge TARGETS,
|
|
391
|
+
// so without this one client's options (headers, server, ...) are written
|
|
392
|
+
// into the shared config and inherited by every client built after it.
|
|
393
|
+
const merged = vs.merge(h.A(), h.ja(&.{ h.omap(), h.clone(cfgopts), opts }), vs.MAXDEPTH) catch opts;
|
|
377
394
|
const vres = vs.validate(h.A(), merged, optspec) catch null;
|
|
378
395
|
if (vres) |vr| {
|
|
379
396
|
if (vr.err == null and vr.out == .object) opts = vr.out;
|
|
380
397
|
}
|
|
381
398
|
|
|
399
|
+
// Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
|
|
400
|
+
// Every placeholder must resolve to a non-empty value: from options.server
|
|
401
|
+
// (user), else the Config default. A placeholder that resolves to "" is a
|
|
402
|
+
// construction ERROR in live mode - the URL cannot work - but in test mode
|
|
403
|
+
// substitutes the deterministic value "test-<name>" so offline tests need
|
|
404
|
+
// no configuration. The SDK constructor has no error return, so a missing
|
|
405
|
+
// required variable PANICS: construction-time misconfiguration.
|
|
406
|
+
//
|
|
407
|
+
// Scanned by hand: a placeholder is `{` followed by [A-Za-z0-9_]+ and `}`;
|
|
408
|
+
// anything else is literal text, so a stray brace in a URL is left alone.
|
|
409
|
+
switch (h.getp(opts, "base")) {
|
|
410
|
+
.string => |base| {
|
|
411
|
+
if (null != std.mem.indexOfScalar(u8, base, '{')) {
|
|
412
|
+
const testmode =
|
|
413
|
+
is_true(h.getpath(&.{ "test", "active" }, opts)) or
|
|
414
|
+
is_true(h.getpath(&.{ "feature", "test", "active" }, opts));
|
|
415
|
+
const server = h.getp(opts, "server");
|
|
416
|
+
const sdkname: []const u8 = switch (h.getpath(&.{ "main", "name" }, config)) {
|
|
417
|
+
.string => |s| if (0 < s.len) s else "SDK",
|
|
418
|
+
else => "SDK",
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
var out = std.ArrayList(u8).init(h.A());
|
|
422
|
+
var i: usize = 0;
|
|
423
|
+
while (i < base.len) {
|
|
424
|
+
if ('{' != base[i]) {
|
|
425
|
+
out.append(base[i]) catch {};
|
|
426
|
+
i += 1;
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
var j = i + 1;
|
|
430
|
+
while (j < base.len and (std.ascii.isAlphanumeric(base[j]) or '_' == base[j])) {
|
|
431
|
+
j += 1;
|
|
432
|
+
}
|
|
433
|
+
if (j >= base.len or '}' != base[j] or j == i + 1) {
|
|
434
|
+
out.append(base[i]) catch {};
|
|
435
|
+
i += 1;
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
const name = base[i + 1 .. j];
|
|
439
|
+
const val: []const u8 = switch (h.getp(server, name)) {
|
|
440
|
+
.string => |s| s,
|
|
441
|
+
else => "",
|
|
442
|
+
};
|
|
443
|
+
if (0 == val.len) {
|
|
444
|
+
if (testmode) {
|
|
445
|
+
out.appendSlice("test-") catch {};
|
|
446
|
+
out.appendSlice(name) catch {};
|
|
447
|
+
} else {
|
|
448
|
+
std.debug.panic(
|
|
449
|
+
"{s}: the server variable '{s}' is required: the API " ++
|
|
450
|
+
"base URL is '{s}' - pass .server = .{{ .{s} = \"...\" }} " ++
|
|
451
|
+
"in the SDK options",
|
|
452
|
+
.{ sdkname, name, base, name },
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
} else {
|
|
456
|
+
out.appendSlice(val) catch {};
|
|
457
|
+
}
|
|
458
|
+
i = j + 1;
|
|
459
|
+
}
|
|
460
|
+
h.setp(opts, "base", h.vstr(out.toOwnedSlice() catch base));
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
else => {},
|
|
464
|
+
}
|
|
465
|
+
|
|
382
466
|
// Restore system.fetch.
|
|
383
467
|
if (!h.is_noval(sys_fetch)) {
|
|
384
468
|
const sysv = h.getp(opts, "system");
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sdkgen": {
|
|
3
|
+
"package": 1
|
|
4
|
+
},
|
|
5
|
+
"name": "@voxgig/sdkgen",
|
|
6
|
+
"version": "3.5.0",
|
|
7
|
+
"provides": {
|
|
8
|
+
"target": [
|
|
9
|
+
"c",
|
|
10
|
+
"clojure",
|
|
11
|
+
"cpp",
|
|
12
|
+
"csharp",
|
|
13
|
+
"dart",
|
|
14
|
+
"elixir",
|
|
15
|
+
"go",
|
|
16
|
+
"go-cli",
|
|
17
|
+
"go-mcp",
|
|
18
|
+
"haskell",
|
|
19
|
+
"java",
|
|
20
|
+
"js",
|
|
21
|
+
"kotlin",
|
|
22
|
+
"lean",
|
|
23
|
+
"lua",
|
|
24
|
+
"ocaml",
|
|
25
|
+
"perl",
|
|
26
|
+
"php",
|
|
27
|
+
"py",
|
|
28
|
+
"py-data",
|
|
29
|
+
"rb",
|
|
30
|
+
"rust",
|
|
31
|
+
"scala",
|
|
32
|
+
"seneca-provider",
|
|
33
|
+
"swift",
|
|
34
|
+
"ts",
|
|
35
|
+
"zig"
|
|
36
|
+
],
|
|
37
|
+
"feature": [
|
|
38
|
+
"audit",
|
|
39
|
+
"cache",
|
|
40
|
+
"clienttrack",
|
|
41
|
+
"debug",
|
|
42
|
+
"idempotency",
|
|
43
|
+
"log",
|
|
44
|
+
"metrics",
|
|
45
|
+
"netsim",
|
|
46
|
+
"paging",
|
|
47
|
+
"proxy",
|
|
48
|
+
"ratelimit",
|
|
49
|
+
"rbac",
|
|
50
|
+
"retry",
|
|
51
|
+
"streaming",
|
|
52
|
+
"telemetry",
|
|
53
|
+
"test",
|
|
54
|
+
"timeout"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/action/action.ts
CHANGED
|
@@ -12,6 +12,40 @@ import type {
|
|
|
12
12
|
} from '../types'
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
const indexEntry = (name: string) => `@"${name}.aontu"`
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
// An index line that is an ACTIVE include, and the name it includes — or
|
|
19
|
+
// undefined for a blank line, a comment, or anything else.
|
|
20
|
+
//
|
|
21
|
+
// Parsed rather than compared as a string, because both spellings around an
|
|
22
|
+
// include are legal aontu and mean opposite things:
|
|
23
|
+
//
|
|
24
|
+
// @"go.aontu" -> active, name 'go'
|
|
25
|
+
// @"go.aontu" # pinned -> active, name 'go' (trailing comment)
|
|
26
|
+
// @"go.aontu" -> active, name 'go' (indented)
|
|
27
|
+
// # @"go.aontu" -> NOT active
|
|
28
|
+
//
|
|
29
|
+
// A substring test (what this used to be) reads the commented-out form as
|
|
30
|
+
// present, so `target add go` on a project that had switched the target off
|
|
31
|
+
// by hand appended nothing and reported success while the target stayed
|
|
32
|
+
// absent from the model. A whole-line equality test fixes that but then
|
|
33
|
+
// misses the trailing-comment form, and appends a SECOND active include.
|
|
34
|
+
const INDEX_ENTRY_RE = /^\s*@"([^"]+)\.aontu"\s*(?:#.*)?$/
|
|
35
|
+
|
|
36
|
+
function indexEntryName(line: string): string | undefined {
|
|
37
|
+
const m = line.match(INDEX_ENTRY_RE)
|
|
38
|
+
return null == m ? undefined : m[1]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
// Is this name already included by the index?
|
|
43
|
+
function hasIndexEntry(content: string, name: string): boolean {
|
|
44
|
+
return content.split('\n')
|
|
45
|
+
.some((line: string) => indexEntryName(line) === name)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
15
49
|
// Append `@"<name>.aontu"` import lines for each name not already present in
|
|
16
50
|
// the index content. Checking against the accumulating result (not the
|
|
17
51
|
// original) means duplicate names in the same call are added at most once.
|
|
@@ -19,9 +53,8 @@ function appendIndexEntries(content: string, names: string[]): string {
|
|
|
19
53
|
let out = content
|
|
20
54
|
|
|
21
55
|
for (const n of names) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
out += '\n' + entry
|
|
56
|
+
if (!hasIndexEntry(out, n)) {
|
|
57
|
+
out += '\n' + indexEntry(n)
|
|
25
58
|
}
|
|
26
59
|
}
|
|
27
60
|
|
|
@@ -29,6 +62,25 @@ function appendIndexEntries(content: string, names: string[]): string {
|
|
|
29
62
|
}
|
|
30
63
|
|
|
31
64
|
|
|
65
|
+
// Drop the `@"<name>.aontu"` line for each name — the inverse of
|
|
66
|
+
// appendIndexEntries, matching line-exact for the same reasons.
|
|
67
|
+
//
|
|
68
|
+
// Nothing calls this yet: a `remove` action is the fast-follow this exists
|
|
69
|
+
// for (see docs/design/sdkgen-packages.md), and it is written here beside its
|
|
70
|
+
// inverse so the two cannot drift on how an entry is recognised.
|
|
71
|
+
function removeIndexEntries(content: string, names: string[]): string {
|
|
72
|
+
const drop = new Set(names)
|
|
73
|
+
|
|
74
|
+
return content
|
|
75
|
+
.split('\n')
|
|
76
|
+
.filter((line: string) => {
|
|
77
|
+
const name = indexEntryName(line)
|
|
78
|
+
return undefined === name || !drop.has(name)
|
|
79
|
+
})
|
|
80
|
+
.join('\n')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
32
84
|
const UpdateIndex = cmp(function UpdateIndex(props: any) {
|
|
33
85
|
Content(appendIndexEntries(props.content, props.names))
|
|
34
86
|
})
|
|
@@ -45,7 +97,20 @@ function parseAddNames(args: any[]): string[] {
|
|
|
45
97
|
}
|
|
46
98
|
|
|
47
99
|
|
|
48
|
-
|
|
100
|
+
// The current index file for each kind, which `UpdateIndex` appends to.
|
|
101
|
+
//
|
|
102
|
+
// `seed` IS THE UPGRADE PATH. A project scaffolded before a kind existed has
|
|
103
|
+
// no `model/<kind>/<kind>-index.aontu` — every project alive today is in
|
|
104
|
+
// exactly that position for `docs` — and reading it unguarded made the FIRST
|
|
105
|
+
// `docs add` in any existing project fail on ENOENT before it wrote anything.
|
|
106
|
+
//
|
|
107
|
+
// Seeded per call rather than defaulted for every kind: a missing
|
|
108
|
+
// `target-index.aontu` in a scaffolded project is a broken project, and
|
|
109
|
+
// quietly recreating it would hide that. A kind the project has never used is
|
|
110
|
+
// a different thing, and only its own action knows which case it is in.
|
|
111
|
+
function loadContent(
|
|
112
|
+
actx: ActionContext, which: string | string[], seed?: Record<string, string>,
|
|
113
|
+
) {
|
|
49
114
|
which = Array.isArray(which) ? which : [which]
|
|
50
115
|
|
|
51
116
|
const content: any = {}
|
|
@@ -55,8 +120,9 @@ function loadContent(actx: ActionContext, which: string | string[]) {
|
|
|
55
120
|
|
|
56
121
|
which.map((w: string) => {
|
|
57
122
|
const indexfile = Path.join(modelfolder, w, w + '-index.aontu')
|
|
58
|
-
|
|
59
|
-
content[`${w}_index`] =
|
|
123
|
+
|
|
124
|
+
content[`${w}_index`] = (null != seed?.[w] && !fs.existsSync(indexfile)) ?
|
|
125
|
+
seed[w] : fs.readFileSync(indexfile, 'utf8')
|
|
60
126
|
})
|
|
61
127
|
|
|
62
128
|
return content
|
|
@@ -64,9 +130,73 @@ function loadContent(actx: ActionContext, which: string | string[]) {
|
|
|
64
130
|
|
|
65
131
|
|
|
66
132
|
|
|
133
|
+
// ENSURE THE PROJECT'S OWN MODEL INCLUDES A KIND'S INDEX.
|
|
134
|
+
//
|
|
135
|
+
// `model/sdk.aontu` is written once, by create-sdkgen, and includes the
|
|
136
|
+
// indexes of the kinds that existed then. So a project scaffolded before a
|
|
137
|
+
// kind existed — which is every project alive today, for `docs` — never
|
|
138
|
+
// includes its index, and the item's model file is an orphan: it is on disk,
|
|
139
|
+
// `<kind>-index.aontu` includes it, and NOTHING includes that. `main.kit.docs`
|
|
140
|
+
// is then absent from the compiled model, so `package list`, `package update`
|
|
141
|
+
// and `doctor` cannot see the item at all.
|
|
142
|
+
//
|
|
143
|
+
// Appending one include line is additive and idempotent, and it is the only
|
|
144
|
+
// way an existing project can adopt a new kind without hand-editing. The
|
|
145
|
+
// entry is parsed, not substring-matched, for the reason `hasIndexEntry`
|
|
146
|
+
// documents: a commented-out include means the project switched it OFF, and
|
|
147
|
+
// re-adding it would override that.
|
|
148
|
+
function ensureModelInclude(actx: ActionContext, kind: string): boolean {
|
|
149
|
+
const fs = actx.fs()
|
|
150
|
+
const url = actx.url
|
|
151
|
+
|
|
152
|
+
if (!fs.existsSync(url)) {
|
|
153
|
+
// Said out loud rather than skipped silently: without the include the
|
|
154
|
+
// item is invisible to the next model compile, and a quiet no-op here
|
|
155
|
+
// would look exactly like success.
|
|
156
|
+
actx.log.warn({
|
|
157
|
+
point: 'model-include-absent', kind, file: url,
|
|
158
|
+
note: url + ' not found, so ' + indexEntry(kind + '/' + kind + '-index') +
|
|
159
|
+
' could not be added — add it by hand, or nothing will see any ' +
|
|
160
|
+
kind + ' item'
|
|
161
|
+
})
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const name = kind + '/' + kind + '-index'
|
|
166
|
+
const content = String(fs.readFileSync(url, 'utf8'))
|
|
167
|
+
|
|
168
|
+
if (hasIndexEntry(content, name)) {
|
|
169
|
+
return false
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (actx.opts?.dryrun) {
|
|
173
|
+
actx.log.info({
|
|
174
|
+
point: 'model-include-dryrun', kind, file: url, entry: indexEntry(name),
|
|
175
|
+
note: '** DRY RUN ** would add ' + indexEntry(name) + ' to ' + url
|
|
176
|
+
})
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
fs.writeFileSync(url,
|
|
181
|
+
content + (content.endsWith('\n') ? '' : '\n') +
|
|
182
|
+
indexEntry(name) + '\n')
|
|
183
|
+
|
|
184
|
+
actx.log.info({
|
|
185
|
+
point: 'model-include-added', kind, file: url, entry: indexEntry(name),
|
|
186
|
+
note: url + ': added ' + indexEntry(name) +
|
|
187
|
+
' — without it the project model never sees any ' + kind + ' item'
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
return true
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
67
194
|
export {
|
|
68
195
|
UpdateIndex,
|
|
196
|
+
ensureModelInclude,
|
|
69
197
|
appendIndexEntries,
|
|
198
|
+
removeIndexEntries,
|
|
199
|
+
hasIndexEntry,
|
|
70
200
|
parseAddNames,
|
|
71
201
|
loadContent
|
|
72
202
|
}
|