@voxgig/sdkgen 4.31.1 → 4.32.1
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 +1 -1
- package/dist/helpers/definitionPlan.d.ts +5 -0
- package/dist/helpers/definitionPlan.js +44 -7
- package/dist/helpers/definitionPlan.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/project/.sdk/tm/c/utility/make_url.c +11 -0
- package/project/.sdk/tm/c/utility/prepare_headers.c +53 -3
- package/project/.sdk/tm/c/utility/prepare_query.c +4 -1
- package/project/.sdk/tm/c/utility/transform_request.c +31 -8
- package/project/.sdk/tm/clojure/src/sdk/core.clj +62 -15
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +72 -15
- package/project/.sdk/tm/csharp/utility/MakeUrl.cs +8 -0
- package/project/.sdk/tm/csharp/utility/PrepareHeaders.cs +34 -4
- package/project/.sdk/tm/csharp/utility/PrepareQuery.cs +14 -0
- package/project/.sdk/tm/csharp/utility/TransformRequest.cs +31 -5
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +86 -24
- package/project/.sdk/tm/go/utility/make_url.go +8 -0
- package/project/.sdk/tm/go/utility/prepare_headers.go +36 -7
- package/project/.sdk/tm/go/utility/prepare_query.go +11 -0
- package/project/.sdk/tm/go/utility/transform_request.go +31 -5
- package/project/.sdk/tm/java/utility/MakeUrl.java +8 -0
- package/project/.sdk/tm/java/utility/PrepareHeaders.java +30 -6
- package/project/.sdk/tm/java/utility/PrepareQuery.java +10 -0
- package/project/.sdk/tm/java/utility/TransformRequest.java +30 -5
- package/project/.sdk/tm/js/src/Response.js +14 -1
- package/project/.sdk/tm/js/src/utility/MakeUrlUtility.js +7 -0
- package/project/.sdk/tm/js/src/utility/PrepareHeadersUtility.js +18 -0
- package/project/.sdk/tm/js/src/utility/PrepareQueryUtility.js +3 -1
- package/project/.sdk/tm/js/src/utility/TransformRequestUtility.js +17 -3
- package/project/.sdk/tm/js/test/definition-runner.js +74 -13
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +25 -0
- package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +8 -0
- package/project/.sdk/tm/kotlin/utility/Prepare.kt +34 -4
- package/project/.sdk/tm/kotlin/utility/ResultTransform.kt +18 -6
- package/project/.sdk/tm/lua/utility/make_url.lua +8 -0
- package/project/.sdk/tm/lua/utility/prepare_headers.lua +35 -6
- package/project/.sdk/tm/lua/utility/prepare_query.lua +10 -0
- package/project/.sdk/tm/lua/utility/transform_request.lua +37 -6
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +63 -13
- package/project/.sdk/tm/perl/utility/make_url.pm +6 -0
- package/project/.sdk/tm/perl/utility/prepare_headers.pm +21 -3
- package/project/.sdk/tm/perl/utility/prepare_query.pm +8 -0
- package/project/.sdk/tm/perl/utility/transform_request.pm +19 -7
- package/project/.sdk/tm/php/utility/MakeUrl.php +7 -0
- package/project/.sdk/tm/php/utility/PrepareHeaders.php +33 -4
- package/project/.sdk/tm/php/utility/PrepareQuery.php +11 -0
- package/project/.sdk/tm/php/utility/TransformRequest.php +28 -5
- package/project/.sdk/tm/py/pkg/utility/make_url.py +7 -0
- package/project/.sdk/tm/py/pkg/utility/prepare_headers.py +27 -6
- package/project/.sdk/tm/py/pkg/utility/prepare_query.py +8 -0
- package/project/.sdk/tm/py/pkg/utility/transform_request.py +21 -5
- package/project/.sdk/tm/rb/utility/make_url.rb +7 -0
- package/project/.sdk/tm/rb/utility/prepare_headers.rb +21 -3
- package/project/.sdk/tm/rb/utility/prepare_query.rb +8 -0
- package/project/.sdk/tm/rb/utility/transform_request.rb +18 -5
- package/project/.sdk/tm/rust/utility/make_url.rs +10 -1
- package/project/.sdk/tm/rust/utility/prepare_headers.rs +43 -7
- package/project/.sdk/tm/rust/utility/prepare_query.rs +18 -1
- package/project/.sdk/tm/rust/utility/transform_request.rs +29 -7
- package/project/.sdk/tm/scala/utility/Make.scala +9 -0
- package/project/.sdk/tm/scala/utility/Prepare.scala +42 -3
- package/project/.sdk/tm/scala/utility/Transform.scala +30 -6
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Make.swift +7 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +28 -2
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +23 -5
- package/project/.sdk/tm/ts/src/Response.ts +14 -1
- package/project/.sdk/tm/ts/src/utility/MakeUrlUtility.ts +7 -0
- package/project/.sdk/tm/ts/src/utility/PrepareHeadersUtility.ts +16 -0
- package/project/.sdk/tm/ts/src/utility/PrepareQueryUtility.ts +3 -1
- package/project/.sdk/tm/ts/src/utility/TransformRequestUtility.ts +16 -3
- package/project/.sdk/tm/ts/test/definition-runner.ts +75 -13
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +25 -0
- package/project/.sdk/tm/zig/core/utility.zig +80 -20
- package/project/sdkgen-package.json +1 -1
- package/src/helpers/definitionPlan.ts +49 -7
|
@@ -764,6 +764,15 @@ pub fn make_url_util(ctx: *Context) E![]const u8 {
|
|
|
764
764
|
h.vstr(spec.suffix),
|
|
765
765
|
}), "/", true) catch "";
|
|
766
766
|
|
|
767
|
+
// A route the definition ends with a slash keeps it: a server such as a
|
|
768
|
+
// Django REST one redirects or refuses the route without it.
|
|
769
|
+
const orig = h.getp(ctx.point, "orig");
|
|
770
|
+
if (orig == .string and std.mem.endsWith(u8, orig.string, "/") and spec.suffix.len == 0 and
|
|
771
|
+
!std.mem.endsWith(u8, url, "/"))
|
|
772
|
+
{
|
|
773
|
+
url = std.mem.concat(h.A(), u8, &.{ url, "/" }) catch url;
|
|
774
|
+
}
|
|
775
|
+
|
|
767
776
|
const resmatch = h.omap();
|
|
768
777
|
|
|
769
778
|
if (spec.params == .object) {
|
|
@@ -1043,12 +1052,37 @@ pub fn prepare_headers_util(ctx: *Context) Value {
|
|
|
1043
1052
|
const options: Value = if (ctx.client) |client| client.options_map() else ctx.options;
|
|
1044
1053
|
|
|
1045
1054
|
const headers = h.getp(options, "headers");
|
|
1046
|
-
if (h.is_noval(headers))
|
|
1047
|
-
|
|
1048
|
-
return switch (h.clone(headers)) {
|
|
1055
|
+
const out: Value = if (h.is_noval(headers)) h.omap() else switch (h.clone(headers)) {
|
|
1049
1056
|
.object => h.clone(headers),
|
|
1050
1057
|
else => h.omap(),
|
|
1051
1058
|
};
|
|
1059
|
+
|
|
1060
|
+
// A header parameter travels as a header, under the name the definition
|
|
1061
|
+
// gives it, and only from this call's own arguments. It replaces a default
|
|
1062
|
+
// of the same name, whatever its case.
|
|
1063
|
+
const aheader: Value = h.getpath(&.{ "args", "header" }, ctx.point);
|
|
1064
|
+
if (aheader == .array) {
|
|
1065
|
+
for (aheader.array.data.items) |hd| {
|
|
1066
|
+
const name = h.getp(hd, "name");
|
|
1067
|
+
if (name != .string or name.string.len == 0) continue;
|
|
1068
|
+
const orig = h.getp(hd, "orig");
|
|
1069
|
+
const wire: []const u8 = if (orig == .string and orig.string.len != 0) orig.string else name.string;
|
|
1070
|
+
var val = h.getp(ctx.reqmatch, name.string);
|
|
1071
|
+
if (h.is_noval(val)) val = h.getp(ctx.reqdata, name.string);
|
|
1072
|
+
if (h.is_noval(val)) continue;
|
|
1073
|
+
const key = std.ascii.allocLowerString(h.A(), wire) catch wire;
|
|
1074
|
+
while (true) {
|
|
1075
|
+
var kit = out.object.iterator();
|
|
1076
|
+
const same: ?[]const u8 = while (kit.next()) |kv| {
|
|
1077
|
+
if (std.ascii.eqlIgnoreCase(kv.key_ptr.*, key)) break kv.key_ptr.*;
|
|
1078
|
+
} else null;
|
|
1079
|
+
_ = out.object.fetchOrderedRemove(same orelse break);
|
|
1080
|
+
}
|
|
1081
|
+
h.setp(out, key, h.vstr(h.stringify(val)));
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
return out;
|
|
1052
1086
|
}
|
|
1053
1087
|
|
|
1054
1088
|
pub fn prepare_body_util(ctx: *Context) Value {
|
|
@@ -1094,6 +1128,16 @@ pub fn prepare_path_util(ctx: *Context) []const u8 {
|
|
|
1094
1128
|
return vs.join(h.A(), parts, "/", true) catch "";
|
|
1095
1129
|
}
|
|
1096
1130
|
|
|
1131
|
+
// Whether a list of argument definitions names this key.
|
|
1132
|
+
fn names_key(defs: Value, key: []const u8) bool {
|
|
1133
|
+
if (defs != .array) return false;
|
|
1134
|
+
for (defs.array.data.items) |d| {
|
|
1135
|
+
const name = h.getp(d, "name");
|
|
1136
|
+
if (name == .string and std.mem.eql(u8, name.string, key)) return true;
|
|
1137
|
+
}
|
|
1138
|
+
return false;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1097
1141
|
pub fn prepare_query_util(ctx: *Context) Value {
|
|
1098
1142
|
const point = ctx.point;
|
|
1099
1143
|
const reqmatch: Value = switch (ctx.reqmatch) {
|
|
@@ -1107,6 +1151,8 @@ pub fn prepare_query_util(ctx: *Context) Value {
|
|
|
1107
1151
|
// A path parameter travels in the path. The generated config lists them
|
|
1108
1152
|
// as args.params, which prepare_params reads; params is the older list.
|
|
1109
1153
|
const aparams: Value = h.getpath(&.{ "args", "params" }, point);
|
|
1154
|
+
// A header parameter travels in the headers, which prepare_headers fills.
|
|
1155
|
+
const aheader: Value = h.getpath(&.{ "args", "header" }, point);
|
|
1110
1156
|
// A query parameter travels under the name the definition gives it, its
|
|
1111
1157
|
// orig, which the model may have renamed for the caller.
|
|
1112
1158
|
const aquery: Value = h.getpath(&.{ "args", "query" }, point);
|
|
@@ -1126,15 +1172,7 @@ pub fn prepare_query_util(ctx: *Context) Value {
|
|
|
1126
1172
|
}
|
|
1127
1173
|
}
|
|
1128
1174
|
}
|
|
1129
|
-
if (!contained
|
|
1130
|
-
for (aparams.array.data.items) |pd| {
|
|
1131
|
-
const name = h.getp(pd, "name");
|
|
1132
|
-
if (name == .string and std.mem.eql(u8, name.string, key)) {
|
|
1133
|
-
contained = true;
|
|
1134
|
-
break;
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1175
|
+
if (!contained) contained = names_key(aparams, key) or names_key(aheader, key);
|
|
1138
1176
|
var wire: []const u8 = key;
|
|
1139
1177
|
if (aquery == .array) {
|
|
1140
1178
|
for (aquery.array.data.items) |qd| {
|
|
@@ -1406,13 +1444,33 @@ pub fn result_body_util(ctx: *Context) ?*SdkResult {
|
|
|
1406
1444
|
// `$action` selects the point (see make_point_util); it is never an API
|
|
1407
1445
|
// field, so the body is a copy without it. The caller's map is left untouched.
|
|
1408
1446
|
fn strip_action(reqdata: Value) Value {
|
|
1447
|
+
return omit_keys(reqdata, h.vnull(), true);
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
// A header argument travels as a header, which prepare_headers_util sends, so
|
|
1451
|
+
// the body is built from the request data without it.
|
|
1452
|
+
fn dropped(key: []const u8, point: Value, action: bool) bool {
|
|
1453
|
+
if (action) return std.mem.eql(u8, key, "$action");
|
|
1454
|
+
const aheader: Value = h.getpath(&.{ "args", "header" }, point);
|
|
1455
|
+
if (aheader != .array) return false;
|
|
1456
|
+
for (aheader.array.data.items) |hd| {
|
|
1457
|
+
const name = h.getp(hd, "name");
|
|
1458
|
+
if (name == .string and std.mem.eql(u8, name.string, key)) return true;
|
|
1459
|
+
}
|
|
1460
|
+
return false;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
fn omit_keys(reqdata: Value, point: Value, action: bool) Value {
|
|
1409
1464
|
if (reqdata != .object) return reqdata;
|
|
1410
|
-
|
|
1411
|
-
const body = h.omap();
|
|
1465
|
+
var found = false;
|
|
1412
1466
|
var it = reqdata.object.iterator();
|
|
1413
|
-
while (it.next()) |kv|
|
|
1467
|
+
while (it.next()) |kv| found = found or dropped(kv.key_ptr.*, point, action);
|
|
1468
|
+
if (!found) return reqdata;
|
|
1469
|
+
const body = h.omap();
|
|
1470
|
+
var bit = reqdata.object.iterator();
|
|
1471
|
+
while (bit.next()) |kv| {
|
|
1414
1472
|
const key = kv.key_ptr.*;
|
|
1415
|
-
if (!
|
|
1473
|
+
if (!dropped(key, point, action)) h.setp(body, key, kv.value_ptr.*);
|
|
1416
1474
|
}
|
|
1417
1475
|
return body;
|
|
1418
1476
|
}
|
|
@@ -1423,16 +1481,18 @@ pub fn transform_request_util(ctx: *Context) Value {
|
|
|
1423
1481
|
|
|
1424
1482
|
if (spec) |sp| sp.step = "reqform";
|
|
1425
1483
|
|
|
1484
|
+
const reqdata = omit_keys(ctx.reqdata, point, false);
|
|
1485
|
+
|
|
1426
1486
|
const transform = h.to_map(h.getp(point, "transform"));
|
|
1427
|
-
if (h.is_noval(transform)) return strip_action(
|
|
1487
|
+
if (h.is_noval(transform)) return strip_action(reqdata);
|
|
1428
1488
|
|
|
1429
1489
|
const reqform = h.getp(transform, "req");
|
|
1430
|
-
if (h.is_noval(reqform)) return strip_action(
|
|
1490
|
+
if (h.is_noval(reqform)) return strip_action(reqdata);
|
|
1431
1491
|
|
|
1432
|
-
const store = h.jo(&.{.{ "reqdata",
|
|
1492
|
+
const store = h.jo(&.{.{ "reqdata", reqdata }});
|
|
1433
1493
|
// transform now reports collected injection errors beside the value; .out
|
|
1434
1494
|
// is what it used to return on its own, errors or not.
|
|
1435
|
-
const tres = vs.transform(h.A(), store, reqform) catch return strip_action(
|
|
1495
|
+
const tres = vs.transform(h.A(), store, reqform) catch return strip_action(reqdata);
|
|
1436
1496
|
return strip_action(tres.out);
|
|
1437
1497
|
}
|
|
1438
1498
|
|
|
@@ -5,6 +5,7 @@ import { KIT, nom } from '@voxgig/apidef'
|
|
|
5
5
|
import { entityCollection } from './opShape'
|
|
6
6
|
import { pointSegments } from './pointPath'
|
|
7
7
|
import { pointFacts } from './resolved'
|
|
8
|
+
import { isAuthSuppressed, resolveAuthIn, resolveAuthName } from '../utility'
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
// What a generated definition test checks an operation against: the API
|
|
@@ -23,6 +24,7 @@ type DefinitionPoint = {
|
|
|
23
24
|
action?: string
|
|
24
25
|
args: { name: string, wire: string, value: any }[]
|
|
25
26
|
select: Record<string, any>
|
|
27
|
+
headers: { name: string, wire: string, value: any }[]
|
|
26
28
|
query: string[]
|
|
27
29
|
auth: Credential[][] | null
|
|
28
30
|
status: number
|
|
@@ -31,6 +33,10 @@ type DefinitionPoint = {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
// The operations every target generates a method for. The model may hold
|
|
37
|
+
// others, such as a patch beside an update, which no SDK can be called with.
|
|
38
|
+
const GENERATED_OPS = ['load', 'list', 'create', 'update', 'remove']
|
|
39
|
+
|
|
34
40
|
const MAX_ITEMS = 3
|
|
35
41
|
const MAX_DEPTH = 8
|
|
36
42
|
const MAX_SAMPLE = 32 * 1024
|
|
@@ -41,13 +47,19 @@ function definitionPlan(ctx$: any): DefinitionPoint[] {
|
|
|
41
47
|
const plan: DefinitionPoint[] = []
|
|
42
48
|
const unchecked = false === model?.main?.[KIT]?.config?.auth?.active ||
|
|
43
49
|
false === model?.main?.[KIT]?.info?.auth
|
|
50
|
+
// A generated SDK sends one credential, under the scheme apidef chose for it.
|
|
51
|
+
const own = model?.main?.[KIT]?.info?.security?.scheme
|
|
52
|
+
// The header the SDK puts any key in, as its prepareAuth does, though the
|
|
53
|
+
// definition declares no scheme: LearnWorlds declares it as a parameter.
|
|
54
|
+
const ownHeader = !isAuthSuppressed(model) && 'header' === resolveAuthIn(model) ?
|
|
55
|
+
resolveAuthName(model).toLowerCase() : null
|
|
44
56
|
|
|
45
57
|
for (const entity of Object.values(entityCollection(model)) as any[]) {
|
|
46
58
|
if (false === entity.active) continue
|
|
47
59
|
|
|
48
60
|
for (const [op, operation] of Object.entries(entity.op || {}) as any[]) {
|
|
49
61
|
// An inactive operation stays in the model but gets no method.
|
|
50
|
-
if (false === operation?.active) continue
|
|
62
|
+
if (false === operation?.active || !GENERATED_OPS.includes(op)) continue
|
|
51
63
|
|
|
52
64
|
const points = (operation?.points || []).filter((p: any) => false !== p.a)
|
|
53
65
|
|
|
@@ -71,9 +83,21 @@ function definitionPlan(ctx$: any): DefinitionPoint[] {
|
|
|
71
83
|
return { name: arg.n, wire, value: scalar(def?.example ?? def?.schema?.example) ?? 'p' + (i + 1) }
|
|
72
84
|
})
|
|
73
85
|
|
|
86
|
+
// A header argument is sent too, and must arrive as a header under
|
|
87
|
+
// the definition's name, never in the query.
|
|
88
|
+
const headers = (point.g?.header || [])
|
|
89
|
+
.filter((arg: any) => false !== arg.a &&
|
|
90
|
+
![ownHeader, 'content-type'].includes(String(arg.or || arg.n).toLowerCase()))
|
|
91
|
+
.map((arg: any, i: number) => {
|
|
92
|
+
const wire = String(arg.or || arg.n)
|
|
93
|
+
const def = params.find((p: any) => 'header' === p?.in &&
|
|
94
|
+
wire.toLowerCase() === String(p?.name).toLowerCase())
|
|
95
|
+
return { name: arg.n, wire, value: scalar(arg.ex ?? def?.example ?? def?.schema?.example) ?? 'h' + (i + 1) }
|
|
96
|
+
})
|
|
97
|
+
|
|
74
98
|
const selected: Record<string, any> = {}
|
|
75
99
|
for (const key of select.exist || []) {
|
|
76
|
-
if (args.some((a: any) => a.name === key)) continue
|
|
100
|
+
if (args.some((a: any) => a.name === key) || headers.some((h: any) => h.name === key)) continue
|
|
77
101
|
const def = params.find((p: any) => key === p?.name)
|
|
78
102
|
selected[key] = scalar(def?.example ?? def?.schema?.example) ?? 'v1'
|
|
79
103
|
}
|
|
@@ -101,10 +125,11 @@ function definitionPlan(ctx$: any): DefinitionPoint[] {
|
|
|
101
125
|
...(null == select.$action ? {} : { action: select.$action }),
|
|
102
126
|
args,
|
|
103
127
|
select: selected,
|
|
128
|
+
headers,
|
|
104
129
|
query: params.filter((p: any) => 'query' === p?.in).map((p: any) => p.name),
|
|
105
|
-
auth: unchecked ? null : credentialSets(facts),
|
|
130
|
+
auth: unchecked ? null : credentialSets(facts, own),
|
|
106
131
|
status: success?.status ?? 200,
|
|
107
|
-
sample: null == media ? null : boundedSample(sampleOf(media)),
|
|
132
|
+
sample: null == media ? null : boundedSample(fitting(sampleOf(media), media.schema)),
|
|
108
133
|
idField: entity.id?.field || 'id',
|
|
109
134
|
})
|
|
110
135
|
}
|
|
@@ -168,6 +193,20 @@ function sampleOf(media: any): any {
|
|
|
168
193
|
}
|
|
169
194
|
|
|
170
195
|
|
|
196
|
+
// An example whose top level contradicts its own schema proves nothing, such
|
|
197
|
+
// as GitHub's page of deployment rule apps written as a list of its halves.
|
|
198
|
+
function fitting(sample: any, schema: any): any {
|
|
199
|
+
const type = Array.isArray(schema?.type) ?
|
|
200
|
+
schema.type.find((t: string) => 'null' !== t) : schema?.type
|
|
201
|
+
const object = 'object' === type || (null == type && null != schema?.properties)
|
|
202
|
+
const array = 'array' === type || (null == type && null != schema?.items)
|
|
203
|
+
if (object && (Array.isArray(sample) || null == sample || 'object' !== typeof sample)) {
|
|
204
|
+
return undefined
|
|
205
|
+
}
|
|
206
|
+
return array && !Array.isArray(sample) ? undefined : sample
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
|
|
171
210
|
// Schema-shaped data where the definition gives no example: every property,
|
|
172
211
|
// one item per array, the first branch of a union.
|
|
173
212
|
function synthesize(schema: any, depth: number): any {
|
|
@@ -222,15 +261,18 @@ function boundedSample(sample: any): any {
|
|
|
222
261
|
|
|
223
262
|
|
|
224
263
|
// Alternatives of credentials, every one of a set needed together. Empty is a
|
|
225
|
-
// public operation; null is one whose schemes no SDK option can express.
|
|
226
|
-
|
|
264
|
+
// public operation; null is one whose schemes no SDK option can express. Only
|
|
265
|
+
// those the SDK's one scheme meets count, so Petstore's OAuth pets are null.
|
|
266
|
+
function credentialSets(facts: any, own?: string): Credential[][] | null {
|
|
227
267
|
const security = facts.security
|
|
228
268
|
if (!Array.isArray(security) || 0 === security.length) return []
|
|
229
269
|
if (security.some((req: any) => null == req || 0 === Object.keys(req).length)) return []
|
|
230
270
|
|
|
271
|
+
const reqs = 'string' === typeof own && '' !== own ?
|
|
272
|
+
security.filter((req: any) => Object.keys(req).every((name) => name === own)) : security
|
|
231
273
|
const schemes = facts.securitySchemes || {}
|
|
232
274
|
const sets: Credential[][] = []
|
|
233
|
-
for (const req of
|
|
275
|
+
for (const req of reqs) {
|
|
234
276
|
const set = Object.keys(req).map((name) => credentialOf(schemes[name]))
|
|
235
277
|
if (set.every((c) => null != c)) sets.push(set as Credential[])
|
|
236
278
|
}
|