apps 0.0.1-beta.25 → 0.0.1-beta.27
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/README.md +6 -6
- package/framework-reference.json +1 -1
- package/js/{chunk-VWU6I23D.js → chunk-3TEX4ZND.js} +23 -17
- package/js/{chunk-K3MQX2KO.js → chunk-4OD7PHQL.js} +2 -2
- package/js/{chunk-AAAMPT6F.js → chunk-65SZ23BK.js} +2 -2
- package/js/{chunk-XBG3M64K.js → chunk-6JBTHTI5.js} +1 -1
- package/js/{chunk-J3RUZMLO.js → chunk-7AZNPMQH.js} +149 -15
- package/js/{chunk-VGEPL4BV.js → chunk-7R5JY5H7.js} +19 -5
- package/js/{chunk-VSLWGXPW.js → chunk-AHI26TO6.js} +24 -8
- package/js/{chunk-OBXHLFGQ.js → chunk-B5YJQU45.js} +1 -1
- package/js/{chunk-T7WRQJUF.js → chunk-BRGF7VFN.js} +2 -2
- package/js/{chunk-HQKIPKM5.js → chunk-BTJMXW4I.js} +1 -1
- package/js/{chunk-GG4IFBN3.js → chunk-HIJW4LWC.js} +64 -21
- package/js/{chunk-DAIW2WM3.js → chunk-KQCMHI3K.js} +3 -3
- package/js/{chunk-GH6PY5BQ.js → chunk-M2KEEOIQ.js} +1 -1
- package/js/{chunk-TACLXEAE.js → chunk-NSBRV4FJ.js} +1 -1
- package/js/{chunk-DM5U7G7V.js → chunk-NXTXZ635.js} +1842 -1840
- package/js/{chunk-3YN4UDPB.js → chunk-PTUZSCEV.js} +2 -2
- package/js/{chunk-KKGRSXUK.js → chunk-PWF2DRJ3.js} +1 -1
- package/js/{chunk-2TP7C25K.js → chunk-SDLIDQXG.js} +3 -3
- package/js/{chunk-NXO2GN2T.js → chunk-T2UFJKZR.js} +8 -8
- package/js/{chunk-PC5RHPUP.js → chunk-TSLG2WPA.js} +2 -2
- package/js/{chunk-WPKXOTKM.js → chunk-TX2XCAL6.js} +3 -3
- package/js/{chunk-KNJAOYV4.js → chunk-V2I3MMPM.js} +2 -2
- package/js/{chunk-ZVMZWXVF.js → chunk-VUVBMNKC.js} +2 -2
- package/js/{chunk-SUY33XAY.js → chunk-WQ5MVBTP.js} +1 -1
- package/js/{chunk-LPN4ONWW.js → chunk-XBQTJP76.js} +2 -2
- package/js/{chunk-IE6W5RNN.js → chunk-YML53Z7H.js} +2 -2
- package/js/{chunk-DUEZ2XCO.js → chunk-YXKXKGN6.js} +3 -3
- package/js/{chunk-XIRAIB3P.js → chunk-ZZOCEUTB.js} +4 -4
- package/js/client.js +10 -10
- package/js/contracts.js +7 -7
- package/js/effect.js +19 -19
- package/js/graphql.js +21 -21
- package/js/host.js +19 -19
- package/js/index.js +12 -12
- package/js/mcp/effect.js +23 -21
- package/js/mcp/stdio.js +21 -21
- package/js/mcp.js +29 -24
- package/js/openapi.js +595 -200
- package/js/react.js +3 -3
- package/js/skills/effect.js +3 -3
- package/js/skills.js +11 -11
- package/js/storage/facet.js +4 -4
- package/js/ui/auth/contracts.js +2 -2
- package/js/ui/auth.js +5 -5
- package/js/ui/contracts.js +4 -4
- package/js/ui/serving.js +8 -8
- package/package.json +1 -1
- package/runtime.json +1 -1
- package/types/apps/src/contracts/mcp.d.ts +49 -3
- package/types/apps/src/contracts/openapi-compile.d.ts +31 -3
- package/types/apps/src/contracts/openapi.d.ts +16 -6
- package/types/apps/src/contracts/provider.d.ts +6 -0
- package/types/apps/src/implementation/failure-detail.d.ts +3 -2
- package/types/apps/src/implementation/mcp-client.d.ts +1 -0
- package/types/apps/src/implementation/mcp.d.ts +11 -1
- package/types/apps/src/implementation/openapi-compile.d.ts +12 -2
- package/types/apps/src/implementation/openapi-document.d.ts +20 -6
- package/types/apps/src/implementation/openapi-names.d.ts +9 -4
- package/types/apps/src/implementation/openapi-source.d.ts +6 -0
- package/types/apps/src/mcp.d.ts +20 -1
package/js/openapi.js
CHANGED
|
@@ -8,72 +8,79 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
protocolOperations,
|
|
10
10
|
protocolRouter
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4OD7PHQL.js";
|
|
12
12
|
import {
|
|
13
|
+
OpenapiCompileError,
|
|
14
|
+
OpenapiCompileErrorCode,
|
|
13
15
|
OpenapiError,
|
|
14
16
|
OpenapiErrorResponse,
|
|
15
17
|
OpenapiOperation,
|
|
16
18
|
OpenapiParameter,
|
|
17
19
|
OpenapiRequestBody,
|
|
20
|
+
OpenapiSkippedOperation,
|
|
18
21
|
OpenapiToolsOptions,
|
|
19
22
|
defaultOpenapiResponseLimits,
|
|
20
23
|
isOpenapiFileSchema,
|
|
24
|
+
isOpenapiJsonSequence,
|
|
25
|
+
isOpenapiReadMethod,
|
|
21
26
|
isOpenapiTextMedia,
|
|
22
27
|
openapiBinaryResultSchema,
|
|
23
28
|
openapiMediaKind
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
29
|
+
} from "./chunk-7AZNPMQH.js";
|
|
30
|
+
import "./chunk-TSLG2WPA.js";
|
|
26
31
|
import {
|
|
27
32
|
fromPromise,
|
|
28
33
|
nativeOperation,
|
|
29
34
|
routerDeclaration,
|
|
30
35
|
toPromise
|
|
31
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-TX2XCAL6.js";
|
|
32
37
|
import {
|
|
33
38
|
accountProviderError,
|
|
34
39
|
httpProviderError
|
|
35
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-KQCMHI3K.js";
|
|
36
41
|
import {
|
|
37
42
|
ApiErrorRecovery,
|
|
38
43
|
ApiErrorResponse,
|
|
39
44
|
OpenapiResponseError,
|
|
40
45
|
RouterMeta,
|
|
41
46
|
defaultOpenapiErrorLimits
|
|
42
|
-
} from "./chunk-
|
|
43
|
-
import "./chunk-
|
|
47
|
+
} from "./chunk-7R5JY5H7.js";
|
|
48
|
+
import "./chunk-M2KEEOIQ.js";
|
|
44
49
|
import {
|
|
45
50
|
ProviderError,
|
|
46
51
|
cacheLimits
|
|
47
|
-
} from "./chunk-
|
|
48
|
-
import "./chunk-
|
|
52
|
+
} from "./chunk-BRGF7VFN.js";
|
|
53
|
+
import "./chunk-NSBRV4FJ.js";
|
|
49
54
|
import {
|
|
50
55
|
FetchHttpClient_exports
|
|
51
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-V2I3MMPM.js";
|
|
52
57
|
import {
|
|
53
58
|
HttpClientRequest_exports,
|
|
54
59
|
HttpClient_exports
|
|
55
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-B5YJQU45.js";
|
|
56
61
|
import {
|
|
57
62
|
jsonSchema,
|
|
58
63
|
lazyJsonSchemaDecoder,
|
|
59
64
|
once,
|
|
60
65
|
wrap
|
|
61
|
-
} from "./chunk-
|
|
62
|
-
import "./chunk-
|
|
66
|
+
} from "./chunk-YML53Z7H.js";
|
|
67
|
+
import "./chunk-BTJMXW4I.js";
|
|
63
68
|
import {
|
|
64
69
|
JsonObject
|
|
65
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-PWF2DRJ3.js";
|
|
66
71
|
import {
|
|
67
72
|
Deferred_exports,
|
|
68
73
|
Duration_exports,
|
|
69
74
|
Effect_exports,
|
|
70
75
|
Encoding_exports,
|
|
76
|
+
Exit_exports,
|
|
71
77
|
JsonPointer_exports,
|
|
72
78
|
JsonSchema_exports,
|
|
73
79
|
Option_exports,
|
|
80
|
+
SchemaIssue_exports,
|
|
74
81
|
Schema_exports,
|
|
75
82
|
Stream_exports
|
|
76
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-NXTXZ635.js";
|
|
77
84
|
import "./chunk-CZ7CSFO4.js";
|
|
78
85
|
|
|
79
86
|
// src/implementation/swagger-client.ts
|
|
@@ -189,6 +196,18 @@ function operationPath(op) {
|
|
|
189
196
|
return new RegExp("^" + pattern + "$");
|
|
190
197
|
}
|
|
191
198
|
var bytes = (value) => Uint8Array.from(atob(scalar(value)), (char) => char.charCodeAt(0));
|
|
199
|
+
function querystringValue(parameter, value) {
|
|
200
|
+
const [media] = Object.keys(parameter.content ?? {});
|
|
201
|
+
if (media === void 0) throw new Error("A querystring parameter declares no media type");
|
|
202
|
+
const kind = openapiMediaKind(media);
|
|
203
|
+
if (kind === "form") {
|
|
204
|
+
const form = new URLSearchParams();
|
|
205
|
+
for (const [name, field] of Object.entries(object(value)))
|
|
206
|
+
for (const item of Array.isArray(field) ? field : [field]) form.append(name, scalar(item));
|
|
207
|
+
return form.toString();
|
|
208
|
+
}
|
|
209
|
+
return encodeURIComponent(kind === "json" ? JSON.stringify(value) : scalar(value));
|
|
210
|
+
}
|
|
192
211
|
function createRequest(config) {
|
|
193
212
|
const { methods, oauth } = config;
|
|
194
213
|
function selectedCredentials(op, account) {
|
|
@@ -229,6 +248,7 @@ function createRequest(config) {
|
|
|
229
248
|
throw new Error("The selected account cannot call this tool");
|
|
230
249
|
const parameters = {};
|
|
231
250
|
let path = op.path;
|
|
251
|
+
const querystrings = [];
|
|
232
252
|
const swaggerParameters = op.request.parameters.filter((p) => {
|
|
233
253
|
const group = args[p.in === "header" ? "headers" : p.in];
|
|
234
254
|
const value = group === void 0 ? void 0 : object(group)[p.name];
|
|
@@ -237,6 +257,12 @@ function createRequest(config) {
|
|
|
237
257
|
path = path.replaceAll(`{${p.name}}`, reservedPathValue(value));
|
|
238
258
|
return false;
|
|
239
259
|
}
|
|
260
|
+
if (p.in === "querystring") {
|
|
261
|
+
if (value !== void 0) querystrings.push(querystringValue(p, value));
|
|
262
|
+
else if (p.required === true)
|
|
263
|
+
throw new Error("A required querystring parameter is missing");
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
240
266
|
if (group !== void 0) parameters[`${p.in}.${p.name}`] = value;
|
|
241
267
|
return true;
|
|
242
268
|
});
|
|
@@ -288,6 +314,8 @@ function createRequest(config) {
|
|
|
288
314
|
if (pathname.split("/").some((segment) => /^(?:\.|%2e){1,2}$/i.test(segment)))
|
|
289
315
|
throw new Error("This path value would change the request path");
|
|
290
316
|
const url = new URL(prepared2.url);
|
|
317
|
+
if (querystrings.length > 0)
|
|
318
|
+
url.search = [url.search.slice(1), ...querystrings].filter((part) => part !== "").join("&");
|
|
291
319
|
const origin = new URL(op.baseUrl).origin;
|
|
292
320
|
if (url.origin !== origin || !operationPath(op).test(url.pathname) || url.username || url.password)
|
|
293
321
|
throw new Error("The request escaped its API operation");
|
|
@@ -337,7 +365,7 @@ function createRequest(config) {
|
|
|
337
365
|
if (!isOpenapiTextMedia(contentType))
|
|
338
366
|
return { base64: Encoding_exports.encodeBase64(data), contentType };
|
|
339
367
|
const text = new TextDecoder().decode(data);
|
|
340
|
-
return contentType.includes("json") && !contentType
|
|
368
|
+
return contentType.includes("json") && !isOpenapiJsonSequence(contentType) ? yield* Schema_exports.decodeUnknownEffect(Schema_exports.fromJsonString(Schema_exports.Json))(text) : text;
|
|
341
369
|
})
|
|
342
370
|
).pipe(
|
|
343
371
|
Effect_exports.withSpan("provider.openapi.call", {
|
|
@@ -477,7 +505,7 @@ var openapiToolsEffect = (options, prepared) => Effect_exports.gen(function* ()
|
|
|
477
505
|
const { input, errors } = schemas;
|
|
478
506
|
const tool = {
|
|
479
507
|
description: op.description,
|
|
480
|
-
readOnly:
|
|
508
|
+
readOnly: isOpenapiReadMethod(op.method),
|
|
481
509
|
input,
|
|
482
510
|
run: (_context, value) => Schema_exports.decodeUnknownEffect(input)(
|
|
483
511
|
fillParameterDefaults(op, config.parameterDefaults, value)
|
|
@@ -505,43 +533,6 @@ var openapiToolsEffect = (options, prepared) => Effect_exports.gen(function* ()
|
|
|
505
533
|
return Object.fromEntries(entries);
|
|
506
534
|
});
|
|
507
535
|
|
|
508
|
-
// src/contracts/openapi-compile.ts
|
|
509
|
-
var OpenapiCompileErrorCode = Schema_exports.Literals([
|
|
510
|
-
"server_protocol",
|
|
511
|
-
"server_url",
|
|
512
|
-
"external_reference",
|
|
513
|
-
"circular_reference",
|
|
514
|
-
"schema_keyword",
|
|
515
|
-
"schema_reference",
|
|
516
|
-
"missing_component",
|
|
517
|
-
"openapi_version",
|
|
518
|
-
"auth_helper",
|
|
519
|
-
"auth_missing",
|
|
520
|
-
"operation_path",
|
|
521
|
-
"duplicate_operation",
|
|
522
|
-
"server_missing",
|
|
523
|
-
"multiple_hosts",
|
|
524
|
-
"parameter_encoding",
|
|
525
|
-
"parameter_style",
|
|
526
|
-
"request_body",
|
|
527
|
-
"combined_oauth",
|
|
528
|
-
"auth_method",
|
|
529
|
-
"input_schema",
|
|
530
|
-
"no_operations",
|
|
531
|
-
"no_supported_operations",
|
|
532
|
-
"invalid_document",
|
|
533
|
-
"source_generation",
|
|
534
|
-
"authoring_reference"
|
|
535
|
-
]);
|
|
536
|
-
var OpenapiCompileError = class extends Schema_exports.TaggedError()(
|
|
537
|
-
"OpenapiCompileError",
|
|
538
|
-
{
|
|
539
|
-
code: OpenapiCompileErrorCode,
|
|
540
|
-
reason: Schema_exports.String
|
|
541
|
-
}
|
|
542
|
-
) {
|
|
543
|
-
};
|
|
544
|
-
|
|
545
536
|
// ../../node_modules/.bun/js-yaml@5.4.2/node_modules/js-yaml/dist/js-yaml.mjs
|
|
546
537
|
var NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED");
|
|
547
538
|
function defineScalarTag(tagName, options) {
|
|
@@ -3908,7 +3899,8 @@ var yieldToRuntime = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
|
3908
3899
|
|
|
3909
3900
|
// src/implementation/openapi-document.ts
|
|
3910
3901
|
var DocumentObject = Schema_exports.declare(
|
|
3911
|
-
(value) => typeof value === "object" && value !== null && !Array.isArray(value)
|
|
3902
|
+
(value) => typeof value === "object" && value !== null && !Array.isArray(value),
|
|
3903
|
+
{ expected: "object" }
|
|
3912
3904
|
);
|
|
3913
3905
|
var documentObject = Schema_exports.decodeUnknownSync(DocumentObject);
|
|
3914
3906
|
var record = documentObject;
|
|
@@ -3916,6 +3908,79 @@ function fail(code, reason) {
|
|
|
3916
3908
|
throw new OpenapiCompileError({ code, reason });
|
|
3917
3909
|
}
|
|
3918
3910
|
var isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3911
|
+
var pointerToken = (key) => key.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
3912
|
+
var issueFormat = SchemaIssue_exports.makeFormatterStandardSchemaV1({
|
|
3913
|
+
leafHook: (issue) => SchemaIssue_exports.hasInput(issue) ? "Invalid value" : SchemaIssue_exports.defaultLeafHook(issue),
|
|
3914
|
+
checkHook: (issue) => SchemaIssue_exports.hasInput(issue) || SchemaIssue_exports.hasInput(issue.issue) ? SchemaIssue_exports.defaultCheckHook(issue) ?? "Invalid value" : SchemaIssue_exports.defaultCheckHook(issue)
|
|
3915
|
+
});
|
|
3916
|
+
var decodeDefinition = (schema2, value, at, what) => {
|
|
3917
|
+
try {
|
|
3918
|
+
return Schema_exports.decodeUnknownSync(schema2)(value);
|
|
3919
|
+
} catch (error) {
|
|
3920
|
+
if (!Schema_exports.isSchemaError(error)) throw error;
|
|
3921
|
+
const [issue] = issueFormat(error.issue).issues;
|
|
3922
|
+
const path = (issue?.path ?? []).map(
|
|
3923
|
+
(key) => pointerToken(String(typeof key === "object" ? key.key : key))
|
|
3924
|
+
);
|
|
3925
|
+
return fail(
|
|
3926
|
+
"invalid_document",
|
|
3927
|
+
`The ${what} at ${[at, ...path].join("/")} is invalid: ${issue?.message ?? "it does not match OpenAPI"}.`
|
|
3928
|
+
);
|
|
3929
|
+
}
|
|
3930
|
+
};
|
|
3931
|
+
var schemaKeywords = /* @__PURE__ */ new Set([
|
|
3932
|
+
"items",
|
|
3933
|
+
"additionalProperties",
|
|
3934
|
+
"not",
|
|
3935
|
+
"if",
|
|
3936
|
+
"then",
|
|
3937
|
+
"else",
|
|
3938
|
+
"contains",
|
|
3939
|
+
"propertyNames",
|
|
3940
|
+
"unevaluatedItems",
|
|
3941
|
+
"unevaluatedProperties",
|
|
3942
|
+
"contentSchema"
|
|
3943
|
+
]);
|
|
3944
|
+
var schemaArrayKeywords = /* @__PURE__ */ new Set(["allOf", "anyOf", "oneOf", "prefixItems"]);
|
|
3945
|
+
var schemaMapKeywords = /* @__PURE__ */ new Set(["properties", "patternProperties", "$defs", "dependentSchemas"]);
|
|
3946
|
+
var isSchemaValue = (value) => typeof value === "boolean" || isObject2(value);
|
|
3947
|
+
var jsonKind = (value) => Array.isArray(value) ? "an array" : value === null ? "null" : typeof value === "object" ? "an object" : `a ${typeof value}`;
|
|
3948
|
+
var holdsReference = (value) => Array.isArray(value) ? value.some(holdsReference) : isObject2(value) && (typeof value.$ref === "string" || Object.values(value).some(holdsReference));
|
|
3949
|
+
var checkSchemaKeywords = (schema2, at) => {
|
|
3950
|
+
const path = [];
|
|
3951
|
+
const child = (value, problem) => {
|
|
3952
|
+
if (isSchemaValue(value)) return visit(value);
|
|
3953
|
+
if (holdsReference(value))
|
|
3954
|
+
fail(
|
|
3955
|
+
"schema_keyword",
|
|
3956
|
+
`The schema at ${[at, ...path].join("/")} is invalid: ${problem()}, so the reference inside it cannot be resolved.`
|
|
3957
|
+
);
|
|
3958
|
+
};
|
|
3959
|
+
const visit = (node) => {
|
|
3960
|
+
if (!isObject2(node)) return;
|
|
3961
|
+
for (const [key, value] of Object.entries(node)) {
|
|
3962
|
+
path.push(pointerToken(key));
|
|
3963
|
+
if (schemaKeywords.has(key))
|
|
3964
|
+
child(value, () => `"${key}" must be a schema, not ${jsonKind(value)}`);
|
|
3965
|
+
else if (schemaArrayKeywords.has(key) || schemaMapKeywords.has(key)) {
|
|
3966
|
+
const entries = schemaArrayKeywords.has(key) ? Array.isArray(value) ? [...value.entries()] : void 0 : isObject2(value) ? Object.entries(value) : void 0;
|
|
3967
|
+
if (entries === void 0)
|
|
3968
|
+
child(
|
|
3969
|
+
value,
|
|
3970
|
+
() => schemaArrayKeywords.has(key) ? `"${key}" must be an array of schemas, not ${jsonKind(value)}` : `"${key}" must map names to schemas, not ${jsonKind(value)}`
|
|
3971
|
+
);
|
|
3972
|
+
else
|
|
3973
|
+
for (const [name, item] of entries) {
|
|
3974
|
+
path.push(pointerToken(String(name)));
|
|
3975
|
+
child(item, () => `each "${key}" entry must be a schema, not ${jsonKind(item)}`);
|
|
3976
|
+
path.pop();
|
|
3977
|
+
}
|
|
3978
|
+
}
|
|
3979
|
+
path.pop();
|
|
3980
|
+
}
|
|
3981
|
+
};
|
|
3982
|
+
visit(schema2);
|
|
3983
|
+
};
|
|
3919
3984
|
var pathItemMaps = /* @__PURE__ */ new Set(["paths", "webhooks", "pathItems"]);
|
|
3920
3985
|
var localPath = (ref) => {
|
|
3921
3986
|
if (!ref.startsWith("#")) return void 0;
|
|
@@ -3931,6 +3996,7 @@ var localPath = (ref) => {
|
|
|
3931
3996
|
};
|
|
3932
3997
|
function dereference(scope) {
|
|
3933
3998
|
const active = /* @__PURE__ */ new Set();
|
|
3999
|
+
const origins = /* @__PURE__ */ new WeakMap();
|
|
3934
4000
|
const target = (ref) => {
|
|
3935
4001
|
const path = localPath(ref);
|
|
3936
4002
|
let node = scope;
|
|
@@ -3964,14 +4030,15 @@ function dereference(scope) {
|
|
|
3964
4030
|
active.delete(ref);
|
|
3965
4031
|
if (!isObject2(resolved2)) return resolved2;
|
|
3966
4032
|
const { $ref: _, ...siblings } = value;
|
|
3967
|
-
|
|
3968
|
-
return {
|
|
4033
|
+
const result = pathItem ? { ...resolved2, ...fields(siblings) } : {
|
|
3969
4034
|
...resolved2,
|
|
3970
4035
|
...typeof siblings.summary === "string" ? { summary: siblings.summary } : {},
|
|
3971
4036
|
...typeof siblings.description === "string" ? { description: siblings.description } : {}
|
|
3972
4037
|
};
|
|
4038
|
+
origins.set(result, ref);
|
|
4039
|
+
return result;
|
|
3973
4040
|
};
|
|
3974
|
-
return record(visit(scope, false));
|
|
4041
|
+
return { document: record(visit(scope, false)), origins };
|
|
3975
4042
|
}
|
|
3976
4043
|
var DocumentSpecification = Schema_exports.Struct({
|
|
3977
4044
|
...Specification.fields,
|
|
@@ -3983,29 +4050,99 @@ var DocumentSpecification = Schema_exports.Struct({
|
|
|
3983
4050
|
})
|
|
3984
4051
|
)
|
|
3985
4052
|
});
|
|
4053
|
+
var MediaTypes = Schema_exports.Array(Schema_exports.String);
|
|
4054
|
+
var Swagger2Parameters = Schema_exports.Array(DocumentObject);
|
|
4055
|
+
var Swagger2Operation = Schema_exports.Struct({
|
|
4056
|
+
parameters: Schema_exports.optionalKey(Swagger2Parameters),
|
|
4057
|
+
consumes: Schema_exports.optionalKey(MediaTypes),
|
|
4058
|
+
produces: Schema_exports.optionalKey(MediaTypes),
|
|
4059
|
+
responses: Schema_exports.optionalKey(DocumentObject)
|
|
4060
|
+
});
|
|
4061
|
+
var Swagger2PathItem = Schema_exports.Struct({
|
|
4062
|
+
parameters: Schema_exports.optionalKey(Swagger2Parameters),
|
|
4063
|
+
get: Schema_exports.optionalKey(Swagger2Operation),
|
|
4064
|
+
put: Schema_exports.optionalKey(Swagger2Operation),
|
|
4065
|
+
post: Schema_exports.optionalKey(Swagger2Operation),
|
|
4066
|
+
delete: Schema_exports.optionalKey(Swagger2Operation),
|
|
4067
|
+
options: Schema_exports.optionalKey(Swagger2Operation),
|
|
4068
|
+
head: Schema_exports.optionalKey(Swagger2Operation),
|
|
4069
|
+
patch: Schema_exports.optionalKey(Swagger2Operation)
|
|
4070
|
+
});
|
|
4071
|
+
var Swagger2Definition = Schema_exports.Struct({
|
|
4072
|
+
paths: Schema_exports.optionalKey(DocumentObject),
|
|
4073
|
+
consumes: Schema_exports.optionalKey(MediaTypes),
|
|
4074
|
+
produces: Schema_exports.optionalKey(MediaTypes),
|
|
4075
|
+
securityDefinitions: Schema_exports.optionalKey(Schema_exports.Record(Schema_exports.String, DocumentObject))
|
|
4076
|
+
});
|
|
4077
|
+
var swagger2Methods = ["get", "put", "post", "delete", "options", "head", "patch"];
|
|
4078
|
+
function checkSwagger2(document) {
|
|
4079
|
+
const definition = decodeDefinition(Swagger2Definition, document, "#", "definition");
|
|
4080
|
+
for (const [path, value] of Object.entries(definition.paths ?? {})) {
|
|
4081
|
+
if (!path.startsWith("/")) continue;
|
|
4082
|
+
const itemAt = `#/paths/${pointerToken(path)}`;
|
|
4083
|
+
const item = decodeDefinition(Swagger2PathItem, value, itemAt, "path item");
|
|
4084
|
+
for (const method of swagger2Methods)
|
|
4085
|
+
for (const [status, response] of Object.entries(item[method]?.responses ?? {}))
|
|
4086
|
+
if (!status.startsWith("x-"))
|
|
4087
|
+
decodeDefinition(
|
|
4088
|
+
DocumentObject,
|
|
4089
|
+
response,
|
|
4090
|
+
`${itemAt}/${method}/responses/${pointerToken(status)}`,
|
|
4091
|
+
"response"
|
|
4092
|
+
);
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
3986
4095
|
function upgradeOwned(document) {
|
|
3987
|
-
|
|
4096
|
+
if (typeof document.swagger === "string" && document.swagger.startsWith("2.0"))
|
|
4097
|
+
checkSwagger2(document);
|
|
4098
|
+
let upgraded;
|
|
4099
|
+
try {
|
|
4100
|
+
upgraded = upgradeFromTwoToThree(document);
|
|
4101
|
+
} catch (error) {
|
|
4102
|
+
if (!(error instanceof TypeError)) throw error;
|
|
4103
|
+
return fail(
|
|
4104
|
+
"invalid_document",
|
|
4105
|
+
"The Swagger 2.0 definition could not be converted to OpenAPI 3.0: part of it does not have the structure Swagger 2.0 requires, such as a null entry in a path item or response map."
|
|
4106
|
+
);
|
|
4107
|
+
}
|
|
4108
|
+
return record(upgradeOpenApi30InPlace(record(upgraded)));
|
|
3988
4109
|
}
|
|
4110
|
+
var supportedVersion = /^3\.[12]\.\d+$/;
|
|
3989
4111
|
async function openApiDocument(input) {
|
|
3990
4112
|
const root = upgradeOwned(record(input));
|
|
3991
4113
|
await yieldToRuntime();
|
|
3992
|
-
const spec =
|
|
3993
|
-
if (!spec.openapi
|
|
3994
|
-
fail(
|
|
4114
|
+
const spec = decodeDefinition(DocumentSpecification, root, "#", "definition");
|
|
4115
|
+
if (!supportedVersion.test(spec.openapi))
|
|
4116
|
+
fail(
|
|
4117
|
+
"openapi_version",
|
|
4118
|
+
`This importer supports Swagger 2.0 and OpenAPI 3.0, 3.1 and 3.2, not openapi ${JSON.stringify(spec.openapi.slice(0, 32))}.`
|
|
4119
|
+
);
|
|
3995
4120
|
const components = spec.components?.schemas ?? {};
|
|
3996
4121
|
const convert = JsonSchema_exports.fromSchemaOpenApi3_1;
|
|
3997
4122
|
const componentsObject = root.components === void 0 ? {} : record(root.components);
|
|
3998
|
-
const
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
...restored,
|
|
4002
|
-
components: { ...record(restored.components), schemas: components }
|
|
4123
|
+
const { document: restored, origins } = dereference({
|
|
4124
|
+
...root,
|
|
4125
|
+
components: { ...componentsObject, schemas: {} }
|
|
4003
4126
|
});
|
|
4127
|
+
await yieldToRuntime();
|
|
4128
|
+
const parsed = decodeDefinition(
|
|
4129
|
+
DocumentSpecification,
|
|
4130
|
+
{ ...restored, components: { ...record(restored.components), schemas: components } },
|
|
4131
|
+
"#",
|
|
4132
|
+
"definition"
|
|
4133
|
+
);
|
|
4004
4134
|
const definitions = /* @__PURE__ */ new Map();
|
|
4005
4135
|
const references2 = /* @__PURE__ */ new Map();
|
|
4006
4136
|
return {
|
|
4007
4137
|
spec: parsed,
|
|
4008
4138
|
definitions,
|
|
4139
|
+
/**
|
|
4140
|
+
* The JSON Pointer of the object a local reference resolved to, so a diagnostic can locate
|
|
4141
|
+
* a resolved Response, Parameter, Request Body or Path Item where the definition declares it.
|
|
4142
|
+
*/
|
|
4143
|
+
origin(value) {
|
|
4144
|
+
return isObject2(value) ? origins.get(value) : void 0;
|
|
4145
|
+
},
|
|
4009
4146
|
/** Inspect a component schema without expanding its children. OpenAPI object refs must already be resolved by Swagger. */
|
|
4010
4147
|
resolve(value) {
|
|
4011
4148
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -4013,53 +4150,88 @@ async function openApiDocument(input) {
|
|
|
4013
4150
|
const ref = value.$ref;
|
|
4014
4151
|
const path = typeof ref === "string" ? JsonPointer_exports.parseUriFragment(ref) : void 0;
|
|
4015
4152
|
if (typeof ref !== "string" || path?.length !== 3 || path[0] !== "components" || path[1] !== "schemas" || path[2] === void 0)
|
|
4016
|
-
fail(
|
|
4153
|
+
fail(
|
|
4154
|
+
"external_reference",
|
|
4155
|
+
`The reference ${JSON.stringify(ref)} does not resolve within the definition. Only local references to objects the definition declares are supported.`
|
|
4156
|
+
);
|
|
4017
4157
|
if (visited.has(ref))
|
|
4018
|
-
fail("circular_reference",
|
|
4158
|
+
fail("circular_reference", `The schema ${ref} is a circular alias of itself.`);
|
|
4019
4159
|
visited.add(ref);
|
|
4020
|
-
|
|
4160
|
+
if (!Object.hasOwn(components, path[2]))
|
|
4161
|
+
fail(
|
|
4162
|
+
"missing_component",
|
|
4163
|
+
`The reference ${ref} names a schema the definition does not declare.`
|
|
4164
|
+
);
|
|
4165
|
+
value = record(components[path[2]]);
|
|
4021
4166
|
}
|
|
4022
4167
|
return value;
|
|
4023
4168
|
},
|
|
4024
4169
|
/** Compose a Draft 2020-12 schema around API Schema Objects. Only values passed to
|
|
4025
4170
|
* `api` use the document's OpenAPI dialect; Executor-authored wrappers are already
|
|
4026
|
-
* Draft 2020-12 and must not be reinterpreted.
|
|
4027
|
-
*
|
|
4171
|
+
* Draft 2020-12 and must not be reinterpreted. `api` takes the schema's JSON Pointer in the
|
|
4172
|
+
* definition, which failures name. Reached components are converted once into the shared
|
|
4173
|
+
* `definitions` and stay references here; nothing is inlined or copied per operation.
|
|
4028
4174
|
*/
|
|
4029
4175
|
schema(build) {
|
|
4030
4176
|
const added = [];
|
|
4031
4177
|
const direct = /* @__PURE__ */ new Set();
|
|
4032
4178
|
const local = {};
|
|
4033
|
-
const visit = (input2, direct2) => {
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4179
|
+
const visit = (input2, direct2, at) => {
|
|
4180
|
+
checkSchemaKeywords(input2, at);
|
|
4181
|
+
let document;
|
|
4182
|
+
try {
|
|
4183
|
+
document = convert(input2, {
|
|
4184
|
+
onReference(ref) {
|
|
4185
|
+
const path = JsonPointer_exports.parseUriFragment(ref);
|
|
4186
|
+
const name = path?.[2];
|
|
4187
|
+
if (path?.length !== 3 || path[0] !== "components" || path[1] !== "schemas" || name === void 0)
|
|
4188
|
+
fail(
|
|
4189
|
+
"schema_reference",
|
|
4190
|
+
`The schema at ${at} references ${JSON.stringify(ref)}. Only references to #/components/schemas/<name> are supported.`
|
|
4191
|
+
);
|
|
4192
|
+
const component = Object.hasOwn(components, name) ? components[name] : void 0;
|
|
4193
|
+
if (component === void 0)
|
|
4194
|
+
fail(
|
|
4195
|
+
"missing_component",
|
|
4196
|
+
`The schema at ${at} references ${ref}, which the definition does not declare.`
|
|
4197
|
+
);
|
|
4198
|
+
direct2.add(name);
|
|
4199
|
+
if (!definitions.has(name)) {
|
|
4200
|
+
added.push(name);
|
|
4201
|
+
definitions.set(name, {});
|
|
4202
|
+
const names = /* @__PURE__ */ new Set();
|
|
4203
|
+
definitions.set(
|
|
4204
|
+
name,
|
|
4205
|
+
visit(component, names, `#/components/schemas/${pointerToken(name)}`)
|
|
4206
|
+
);
|
|
4207
|
+
references2.set(name, names);
|
|
4208
|
+
}
|
|
4050
4209
|
}
|
|
4051
|
-
}
|
|
4052
|
-
})
|
|
4210
|
+
});
|
|
4211
|
+
} catch (error) {
|
|
4212
|
+
if (error instanceof OpenapiCompileError) throw error;
|
|
4213
|
+
return fail(
|
|
4214
|
+
"schema_keyword",
|
|
4215
|
+
`The schema at ${at} cannot be converted to JSON Schema 2020-12 without changing its constraints${error instanceof Error ? `: ${error.message}` : ""}.`
|
|
4216
|
+
);
|
|
4217
|
+
}
|
|
4053
4218
|
return record({
|
|
4054
4219
|
...document.schema,
|
|
4055
4220
|
...Object.keys(document.definitions).length ? { $defs: document.definitions } : {}
|
|
4056
4221
|
});
|
|
4057
4222
|
};
|
|
4058
|
-
const api = (input2) => {
|
|
4059
|
-
const {
|
|
4223
|
+
const api = (input2, at) => {
|
|
4224
|
+
const schema2 = input2 === true ? {} : input2 === false ? { not: {} } : isObject2(input2) ? input2 : fail(
|
|
4225
|
+
"schema_keyword",
|
|
4226
|
+
`The schema at ${at} must be a schema, not ${jsonKind(input2)}.`
|
|
4227
|
+
);
|
|
4228
|
+
const { $defs, ...converted } = visit(schema2, direct, at);
|
|
4060
4229
|
for (const [name, definition] of Object.entries($defs === void 0 ? {} : record($defs))) {
|
|
4061
4230
|
if (Object.hasOwn(local, name) && JSON.stringify(local[name]) !== JSON.stringify(definition))
|
|
4062
|
-
fail(
|
|
4231
|
+
fail(
|
|
4232
|
+
"schema_reference",
|
|
4233
|
+
`The schema at ${at} declares the local definition ${JSON.stringify(name)} differently from another schema of the same operation.`
|
|
4234
|
+
);
|
|
4063
4235
|
local[name] = definition;
|
|
4064
4236
|
}
|
|
4065
4237
|
return converted;
|
|
@@ -4074,10 +4246,11 @@ async function openApiDocument(input) {
|
|
|
4074
4246
|
reached.add(name);
|
|
4075
4247
|
pending.push(...references2.get(name) ?? []);
|
|
4076
4248
|
}
|
|
4077
|
-
|
|
4249
|
+
const shared = [...reached].find((name) => Object.hasOwn(local, name));
|
|
4250
|
+
if (shared !== void 0)
|
|
4078
4251
|
fail(
|
|
4079
4252
|
"schema_reference",
|
|
4080
|
-
|
|
4253
|
+
`A local definition named ${JSON.stringify(shared)} conflicts with the component schema of the same name.`
|
|
4081
4254
|
);
|
|
4082
4255
|
}
|
|
4083
4256
|
return {
|
|
@@ -4090,11 +4263,7 @@ async function openApiDocument(input) {
|
|
|
4090
4263
|
definitions.delete(name);
|
|
4091
4264
|
references2.delete(name);
|
|
4092
4265
|
}
|
|
4093
|
-
|
|
4094
|
-
return fail(
|
|
4095
|
-
"schema_keyword",
|
|
4096
|
-
"An API schema cannot be converted without changing its constraints."
|
|
4097
|
-
);
|
|
4266
|
+
throw error;
|
|
4098
4267
|
}
|
|
4099
4268
|
}
|
|
4100
4269
|
};
|
|
@@ -4130,6 +4299,15 @@ var leafOf = (input, group) => {
|
|
|
4130
4299
|
const leaf = camel(seed);
|
|
4131
4300
|
return leaf === "" || leaf === group ? fallbackLeaf(input, group) : leaf;
|
|
4132
4301
|
};
|
|
4302
|
+
var pathTokens = (path) => segments(path).flatMap((segment) => {
|
|
4303
|
+
if (version.test(segment) || segment.toLowerCase() === "api") return [];
|
|
4304
|
+
const parameter = segment.startsWith("{") && segment.endsWith("}");
|
|
4305
|
+
const word = camel(parameter ? segment.slice(1, -1) : segment);
|
|
4306
|
+
return word === "" ? [] : [{ key: `${parameter ? "{" : ""}${word}`, word, parameter }];
|
|
4307
|
+
});
|
|
4308
|
+
var describePath = (tokens) => tokens.map(
|
|
4309
|
+
(token, index) => token.parameter ? `${tokens[index - 1]?.parameter === true ? "And" : "By"}${pascal(token.word)}` : pascal(token.word)
|
|
4310
|
+
).join("");
|
|
4133
4311
|
var hash = (input) => {
|
|
4134
4312
|
const text = JSON.stringify([input.method.toUpperCase(), input.path, input.operationId ?? null]);
|
|
4135
4313
|
let value = 0;
|
|
@@ -4142,18 +4320,30 @@ var planOperationNames = (inputs) => {
|
|
|
4142
4320
|
const leaf = leafOf(input, group);
|
|
4143
4321
|
const versionSegment = segments(input.path).map((segment) => segment.toLowerCase()).find((segment) => version.test(segment));
|
|
4144
4322
|
const prefix = versionSegment === void 0 ? group : `${group}.${camel(versionSegment)}`;
|
|
4145
|
-
|
|
4323
|
+
const tokens = pathTokens(input.path);
|
|
4324
|
+
return { input, group, leaf, prefix, versionSegment, tokens, name: `${group}.${leaf}` };
|
|
4146
4325
|
});
|
|
4147
4326
|
const refine = (rename) => {
|
|
4148
4327
|
const buckets = /* @__PURE__ */ new Map();
|
|
4149
4328
|
for (const item of staged) buckets.set(item.name, [...buckets.get(item.name) ?? [], item]);
|
|
4150
4329
|
for (const bucket of buckets.values())
|
|
4151
|
-
if (bucket.length > 1)
|
|
4330
|
+
if (bucket.length > 1) {
|
|
4331
|
+
const names = bucket.map((item) => rename(item, bucket));
|
|
4332
|
+
for (const [index, item] of bucket.entries()) item.name = names[index] ?? item.name;
|
|
4333
|
+
}
|
|
4152
4334
|
};
|
|
4153
4335
|
refine((item) => item.versionSegment === void 0 ? item.name : `${item.prefix}.${item.leaf}`);
|
|
4336
|
+
refine((item, bucket) => {
|
|
4337
|
+
const shared = new Set(
|
|
4338
|
+
item.tokens.map((token) => token.key).filter((key) => bucket.every((other) => other.tokens.some((token) => token.key === key)))
|
|
4339
|
+
);
|
|
4340
|
+
const distinct = item.tokens.filter((token) => !shared.has(token.key));
|
|
4341
|
+
return distinct.length === 0 ? item.name : `${item.prefix}.${item.leaf}${describePath(distinct)}`;
|
|
4342
|
+
});
|
|
4343
|
+
refine((item) => `${item.prefix}.${item.leaf}${describePath(item.tokens)}`);
|
|
4154
4344
|
refine((item) => `${item.prefix}.${item.leaf}${pascal(item.input.method)}`);
|
|
4155
4345
|
refine((item) => `${item.prefix}.${item.leaf}${pascal(item.input.method)}${hash(item.input)}`);
|
|
4156
|
-
return staged.map((item) => item.name);
|
|
4346
|
+
return staged.map((item) => ({ ...item.input, name: item.name }));
|
|
4157
4347
|
};
|
|
4158
4348
|
|
|
4159
4349
|
// src/implementation/openapi-compile.ts
|
|
@@ -4166,12 +4356,25 @@ var OperationNaming = Schema_exports.Struct({
|
|
|
4166
4356
|
tags: Schema_exports.optionalKey(Schema_exports.Array(Schema_exports.String))
|
|
4167
4357
|
});
|
|
4168
4358
|
var identifier = (name) => name.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
4359
|
+
function parseUrl(value, base) {
|
|
4360
|
+
try {
|
|
4361
|
+
return new URL(value, base);
|
|
4362
|
+
} catch {
|
|
4363
|
+
return fail2(
|
|
4364
|
+
"server_url",
|
|
4365
|
+
base === void 0 && !/^[a-z][a-z0-9+.-]*:/i.test(value) ? "The server URL is relative, and an inline definition has no URL to resolve it against. Set baseUrl." : "The server URL is not a valid URL. Set baseUrl."
|
|
4366
|
+
);
|
|
4367
|
+
}
|
|
4368
|
+
}
|
|
4169
4369
|
function absolute(value) {
|
|
4170
|
-
const url =
|
|
4370
|
+
const url = parseUrl(value);
|
|
4171
4371
|
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
4172
|
-
fail2("server_protocol",
|
|
4372
|
+
fail2("server_protocol", `The server uses ${url.protocol}; only HTTP APIs can be imported.`);
|
|
4173
4373
|
if (url.username || url.password || url.hash || url.search || /[{}]/.test(value))
|
|
4174
|
-
fail2(
|
|
4374
|
+
fail2(
|
|
4375
|
+
"server_url",
|
|
4376
|
+
"The server URL has credentials, a query, a fragment or unresolved variables. Set baseUrl."
|
|
4377
|
+
);
|
|
4175
4378
|
return url.href.replace(/\/$/, "");
|
|
4176
4379
|
}
|
|
4177
4380
|
function serverAddress(server, connectUrl, documentServer) {
|
|
@@ -4196,16 +4399,19 @@ function serverAddress(server, connectUrl, documentServer) {
|
|
|
4196
4399
|
}
|
|
4197
4400
|
const relative = new URL(template, "https://relative.invalid");
|
|
4198
4401
|
const base = url?.protocol && url.host ? `${url.protocol.replace(/\W/g, "")}://${url.host}${url.pathname}` : url?.pathname ?? (template.startsWith("/") ? relative.pathname : relative.pathname.slice(1));
|
|
4199
|
-
return absolute(
|
|
4402
|
+
return absolute(parseUrl(`${base.endsWith("/") ? base.slice(0, -1) : base}/`, connectUrl).href);
|
|
4200
4403
|
}
|
|
4201
4404
|
var binaryInput = {
|
|
4202
4405
|
type: "string",
|
|
4203
4406
|
description: "File bytes encoded as base64.",
|
|
4204
4407
|
contentEncoding: "base64"
|
|
4205
4408
|
};
|
|
4206
|
-
|
|
4409
|
+
var declaredAt = (document, value, inline) => document.origin(value) ?? inline;
|
|
4410
|
+
var mediaSchemaAt = (document, at, type, media) => `${declaredAt(document, media, `${at}/content/${pointerToken(type)}`)}/schema`;
|
|
4411
|
+
var responsesOf = (operation) => operation.responses === void 0 ? {} : record2(operation.responses);
|
|
4412
|
+
function responseSchema(document, operation, at, method) {
|
|
4207
4413
|
if (method === "HEAD") return { type: "null" };
|
|
4208
|
-
const success = Object.entries(operation
|
|
4414
|
+
const success = Object.entries(responsesOf(operation)).filter(
|
|
4209
4415
|
([status]) => /^2(?:[0-9]{2}|XX)$/i.test(status)
|
|
4210
4416
|
);
|
|
4211
4417
|
if (success.length === 0) return void 0;
|
|
@@ -4215,12 +4421,13 @@ function responseSchema(document, operation, method) {
|
|
|
4215
4421
|
shapes.push(() => ({ type: "null" }));
|
|
4216
4422
|
continue;
|
|
4217
4423
|
}
|
|
4218
|
-
const
|
|
4424
|
+
const responseAt = declaredAt(document, response, `${at}/responses/${pointerToken(status)}`);
|
|
4425
|
+
const content = document.resolve(record2(response)).content;
|
|
4219
4426
|
if (content === void 0) return void 0;
|
|
4220
4427
|
const media = Object.entries(record2(content));
|
|
4221
4428
|
if (media.length === 0) return void 0;
|
|
4222
4429
|
for (const [type, body] of media) {
|
|
4223
|
-
if (!type.includes("json")) {
|
|
4430
|
+
if (!type.includes("json") || isOpenapiJsonSequence(type)) {
|
|
4224
4431
|
shapes.push(
|
|
4225
4432
|
() => isOpenapiTextMedia(type) ? { type: "string" } : openapiBinaryResultSchema
|
|
4226
4433
|
);
|
|
@@ -4228,7 +4435,8 @@ function responseSchema(document, operation, method) {
|
|
|
4228
4435
|
}
|
|
4229
4436
|
const schema2 = record2(body).schema;
|
|
4230
4437
|
if (schema2 === void 0) return void 0;
|
|
4231
|
-
|
|
4438
|
+
const schemaAt = mediaSchemaAt(document, responseAt, type, body);
|
|
4439
|
+
shapes.push((api) => api(schema2, schemaAt));
|
|
4232
4440
|
}
|
|
4233
4441
|
}
|
|
4234
4442
|
return document.schema((api) => ({
|
|
@@ -4251,14 +4459,14 @@ function errorContent(document, response) {
|
|
|
4251
4459
|
return void 0;
|
|
4252
4460
|
}
|
|
4253
4461
|
}
|
|
4254
|
-
function errorResponses(document, operation) {
|
|
4462
|
+
function errorResponses(document, operation, at) {
|
|
4255
4463
|
const errors = [];
|
|
4256
4464
|
const tagged = Schema_exports.Struct({
|
|
4257
4465
|
description: Schema_exports.optionalKey(Schema_exports.String),
|
|
4258
4466
|
required: Schema_exports.Array(Schema_exports.String),
|
|
4259
4467
|
properties: Schema_exports.Record(Schema_exports.String, JsonObject)
|
|
4260
4468
|
});
|
|
4261
|
-
const visit = (status, input, visited = /* @__PURE__ */ new Set(), parents = []) => {
|
|
4469
|
+
const visit = (status, input, schemaAt, visited = /* @__PURE__ */ new Set(), parents = []) => {
|
|
4262
4470
|
const object2 = Schema_exports.decodeUnknownOption(JsonObject)(input);
|
|
4263
4471
|
if (Option_exports.isNone(object2)) return;
|
|
4264
4472
|
const value = object2.value;
|
|
@@ -4266,9 +4474,14 @@ function errorResponses(document, operation) {
|
|
|
4266
4474
|
if (typeof value.$ref === "string" && visited.has(value.$ref)) return;
|
|
4267
4475
|
const next = typeof value.$ref === "string" ? /* @__PURE__ */ new Set([...visited, value.$ref]) : visited;
|
|
4268
4476
|
const shape = document.resolve(value);
|
|
4477
|
+
const shapeAt = typeof value.$ref === "string" && value.$ref.startsWith("#/") ? value.$ref : schemaAt;
|
|
4269
4478
|
const variants = shape.anyOf;
|
|
4270
4479
|
if (Array.isArray(variants)) {
|
|
4271
|
-
for (const variant of variants
|
|
4480
|
+
for (const [index, variant] of variants.entries())
|
|
4481
|
+
visit(status, variant, `${shapeAt}/anyOf/${index}`, next, [
|
|
4482
|
+
...parents,
|
|
4483
|
+
{ schema: value, at: schemaAt }
|
|
4484
|
+
]);
|
|
4272
4485
|
return;
|
|
4273
4486
|
}
|
|
4274
4487
|
const parsed = Schema_exports.decodeUnknownOption(tagged)(shape);
|
|
@@ -4283,26 +4496,49 @@ function errorResponses(document, operation) {
|
|
|
4283
4496
|
code,
|
|
4284
4497
|
status,
|
|
4285
4498
|
message: hasMessage ? { source: "body" } : { source: "schema", value: parsed.value.description },
|
|
4286
|
-
schema: document.schema((api) => ({
|
|
4499
|
+
schema: document.schema((api) => ({
|
|
4500
|
+
allOf: [...parents, { schema: value, at: schemaAt }].map(
|
|
4501
|
+
(part) => api(part.schema, part.at)
|
|
4502
|
+
)
|
|
4503
|
+
}))
|
|
4287
4504
|
});
|
|
4288
4505
|
if (Option_exports.isSome(declaration)) errors.push(declaration.value);
|
|
4289
4506
|
} catch (error) {
|
|
4290
4507
|
if (!(error instanceof OpenapiCompileError) && !Schema_exports.isSchemaError(error)) throw error;
|
|
4291
4508
|
}
|
|
4292
4509
|
};
|
|
4293
|
-
for (const [status, response] of Object.entries(operation
|
|
4510
|
+
for (const [status, response] of Object.entries(responsesOf(operation))) {
|
|
4294
4511
|
if (!/^[45][0-9]{2}$/.test(status)) continue;
|
|
4295
|
-
const content = errorContent(document, response);
|
|
4512
|
+
const content = errorContent(document, record2(response));
|
|
4296
4513
|
if (content === void 0) continue;
|
|
4514
|
+
const responseAt = declaredAt(document, response, `${at}/responses/${pointerToken(status)}`);
|
|
4297
4515
|
for (const [type, body] of Object.entries(record2(content))) {
|
|
4298
4516
|
if (!type.split(";")[0]?.trim().match(/^application\/(?:[\w.-]+\+)?json$/i))
|
|
4299
4517
|
continue;
|
|
4300
4518
|
const schema2 = record2(body).schema;
|
|
4301
|
-
if (schema2 !== void 0)
|
|
4519
|
+
if (schema2 !== void 0)
|
|
4520
|
+
visit(Number(status), schema2, mediaSchemaAt(document, responseAt, type, body));
|
|
4302
4521
|
}
|
|
4303
4522
|
}
|
|
4304
4523
|
return errors;
|
|
4305
4524
|
}
|
|
4525
|
+
var fixedMethods = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
4526
|
+
var fixedMethods32 = [...fixedMethods, "QUERY"];
|
|
4527
|
+
var isImportedMethod = Schema_exports.is(OpenapiOperation.fields.method);
|
|
4528
|
+
var pathPrefixPattern = /^(?:\/(?:[^/?#{}]|\{[A-Za-z_][\w.-]*\})+)+$/;
|
|
4529
|
+
function prefixParameters(prefix) {
|
|
4530
|
+
if (!pathPrefixPattern.test(prefix))
|
|
4531
|
+
fail2(
|
|
4532
|
+
"operation_path",
|
|
4533
|
+
"pathPrefix must start with /, have no empty segment, trailing /, ? or #, and write each parameter as {name}."
|
|
4534
|
+
);
|
|
4535
|
+
const names = [...prefix.matchAll(/\{([^{}]+)\}/g)].flatMap(
|
|
4536
|
+
(match) => match[1] === void 0 ? [] : [match[1]]
|
|
4537
|
+
);
|
|
4538
|
+
if (new Set(names).size !== names.length)
|
|
4539
|
+
fail2("operation_path", "pathPrefix names the same parameter twice.");
|
|
4540
|
+
return names;
|
|
4541
|
+
}
|
|
4306
4542
|
var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
4307
4543
|
let owned = inputDocument;
|
|
4308
4544
|
const take = () => {
|
|
@@ -4335,7 +4571,7 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4335
4571
|
{ scheme: name, field: "password", part: "password", prefix: "" }
|
|
4336
4572
|
]);
|
|
4337
4573
|
} else if (scheme.type === "oauth2") {
|
|
4338
|
-
const code = record2(scheme.flows).authorizationCode;
|
|
4574
|
+
const code = scheme.flows === void 0 ? void 0 : record2(scheme.flows).authorizationCode;
|
|
4339
4575
|
if (code !== void 0) {
|
|
4340
4576
|
const flow = record2(code);
|
|
4341
4577
|
if (typeof flow.authorizationUrl === "string" && typeof flow.tokenUrl === "string")
|
|
@@ -4343,9 +4579,9 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4343
4579
|
name,
|
|
4344
4580
|
config: entry.oauthDiscoveryUrl === void 0 ? {
|
|
4345
4581
|
authorizationUrl: absolute(
|
|
4346
|
-
|
|
4582
|
+
parseUrl(flow.authorizationUrl, entry.connectUrl).href
|
|
4347
4583
|
),
|
|
4348
|
-
tokenUrl: absolute(
|
|
4584
|
+
tokenUrl: absolute(parseUrl(flow.tokenUrl, entry.connectUrl).href),
|
|
4349
4585
|
scopes: [
|
|
4350
4586
|
...entry.scopes ?? Object.keys(record2(flow.scopes ?? {}))
|
|
4351
4587
|
].sort()
|
|
@@ -4378,11 +4614,10 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4378
4614
|
"This entry does not declare enough authentication details to generate an app."
|
|
4379
4615
|
);
|
|
4380
4616
|
const methods = /* @__PURE__ */ new Map();
|
|
4381
|
-
const
|
|
4382
|
-
const skipped = /* @__PURE__ */ new Set();
|
|
4383
|
-
const causes = /* @__PURE__ */ new Map();
|
|
4617
|
+
const skipped = [];
|
|
4384
4618
|
const built = [];
|
|
4385
4619
|
const documentServer = spec.servers?.[0];
|
|
4620
|
+
const prefix = options.pathPrefix === void 0 ? [] : prefixParameters(options.pathPrefix);
|
|
4386
4621
|
const addresses = /* @__PURE__ */ new Map();
|
|
4387
4622
|
const addressOf = (server) => {
|
|
4388
4623
|
const key = JSON.stringify([server, documentServer?.variables ?? null]);
|
|
@@ -4398,64 +4633,128 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4398
4633
|
if ("error" in known) throw known.error;
|
|
4399
4634
|
return known.address;
|
|
4400
4635
|
};
|
|
4636
|
+
const version32 = spec.openapi.startsWith("3.2.");
|
|
4401
4637
|
const candidates = Object.entries(spec.paths).flatMap(([path, source]) => {
|
|
4402
4638
|
const item = document.resolve(source);
|
|
4403
|
-
|
|
4639
|
+
const itemAt = declaredAt(document, source, `#/paths/${pointerToken(path)}`);
|
|
4640
|
+
const additional = version32 && item.additionalOperations !== void 0 ? Object.entries(record2(item.additionalOperations)).map(([method, value]) => ({
|
|
4641
|
+
method,
|
|
4642
|
+
value,
|
|
4643
|
+
at: `${itemAt}/additionalOperations/${pointerToken(method)}`
|
|
4644
|
+
})) : [];
|
|
4645
|
+
const fixed = (version32 ? fixedMethods32 : fixedMethods).filter((method) => item[method.toLowerCase()] !== void 0).map((method) => ({
|
|
4646
|
+
method,
|
|
4647
|
+
value: item[method.toLowerCase()],
|
|
4648
|
+
at: `${itemAt}/${method.toLowerCase()}`
|
|
4649
|
+
}));
|
|
4650
|
+
return [...fixed, ...additional].map((operation) => ({ ...operation, path, item, itemAt }));
|
|
4404
4651
|
});
|
|
4405
4652
|
if (!candidates.length) fail2("no_operations", "This API does not contain any operations.");
|
|
4406
|
-
const
|
|
4407
|
-
candidates.map((
|
|
4653
|
+
const named = planOperationNames(
|
|
4654
|
+
candidates.map((candidate) => {
|
|
4408
4655
|
const naming = Schema_exports.decodeUnknownOption(OperationNaming)(
|
|
4409
|
-
resolvedOrUndefined(document,
|
|
4656
|
+
resolvedOrUndefined(document, candidate.value)
|
|
4410
4657
|
).pipe(Option_exports.getOrUndefined);
|
|
4411
4658
|
return {
|
|
4659
|
+
...candidate,
|
|
4412
4660
|
operationId: naming?.operationId,
|
|
4413
|
-
tag: naming?.tags?.find((tag) => tag.trim() !== "")
|
|
4414
|
-
method,
|
|
4415
|
-
path
|
|
4661
|
+
tag: naming?.tags?.find((tag) => tag.trim() !== "")
|
|
4416
4662
|
};
|
|
4417
4663
|
})
|
|
4418
4664
|
);
|
|
4419
|
-
|
|
4665
|
+
const order = new Map(named.map(({ name }, index) => [name, index]));
|
|
4666
|
+
const inDefinitionOrder = (operations2) => [...operations2].sort((a, b) => (order.get(a.name) ?? 0) - (order.get(b.name) ?? 0));
|
|
4667
|
+
for (const [index, { name, path, item, itemAt, method, value, at }] of named.entries()) {
|
|
4420
4668
|
if (index % 100 === 99) await yieldToRuntime();
|
|
4421
4669
|
try {
|
|
4422
4670
|
if (!path.startsWith("/") || path.includes("?") || path.includes("#"))
|
|
4423
|
-
fail2("operation_path", "
|
|
4671
|
+
fail2("operation_path", "The path must start with / and contain no ? or #.");
|
|
4672
|
+
if (!isImportedMethod(method))
|
|
4673
|
+
fail2(
|
|
4674
|
+
"operation_method",
|
|
4675
|
+
`Executor does not send the HTTP method ${method}. It imports ${fixedMethods32.join(", ")} operations.`
|
|
4676
|
+
);
|
|
4424
4677
|
const operationMethods = [];
|
|
4425
|
-
const resolved2 = document.resolve(record2(
|
|
4426
|
-
const operation =
|
|
4678
|
+
const resolved2 = document.resolve(record2(value));
|
|
4679
|
+
const operation = decodeDefinition(Operation, resolved2, at, "operation");
|
|
4427
4680
|
const tags = Option_exports.getOrUndefined(
|
|
4428
4681
|
Schema_exports.decodeUnknownOption(Schema_exports.Array(Schema_exports.NonEmptyString))(resolved2.tags)
|
|
4429
4682
|
);
|
|
4430
|
-
const name = names[index] ?? fail2("operation_path", "An operation has no name.");
|
|
4431
4683
|
if (built.some((op) => op.operation.name === name))
|
|
4432
4684
|
fail2(
|
|
4433
4685
|
"duplicate_operation",
|
|
4434
|
-
|
|
4686
|
+
`Another operation has the same tool name, ${name}. Give one of them a distinct operationId.`
|
|
4435
4687
|
);
|
|
4436
|
-
const serverList = operation.servers ?? (Array.isArray(item.servers) ?
|
|
4688
|
+
const serverList = operation.servers ?? (Array.isArray(item.servers) ? decodeDefinition(
|
|
4689
|
+
Specification.fields.servers,
|
|
4690
|
+
item.servers,
|
|
4691
|
+
`${itemAt}/servers`,
|
|
4692
|
+
"servers"
|
|
4693
|
+
) : void 0) ?? spec.servers;
|
|
4437
4694
|
const server = serverList?.[0];
|
|
4438
4695
|
const serverUrl = options.baseUrl ?? server?.url;
|
|
4439
4696
|
if (serverUrl === void 0)
|
|
4440
|
-
fail2(
|
|
4697
|
+
fail2(
|
|
4698
|
+
"server_missing",
|
|
4699
|
+
"The definition declares no server for this operation. Set baseUrl."
|
|
4700
|
+
);
|
|
4441
4701
|
const baseUrl = addressOf(
|
|
4442
4702
|
options.baseUrl === void 0 && server !== void 0 ? server : { url: serverUrl }
|
|
4443
4703
|
);
|
|
4444
|
-
const
|
|
4445
|
-
...Array.isArray(item.parameters) ? item.parameters : []
|
|
4446
|
-
|
|
4704
|
+
const declared = [
|
|
4705
|
+
...(Array.isArray(item.parameters) ? item.parameters : []).map(
|
|
4706
|
+
(parameter, position) => ({
|
|
4707
|
+
parameter,
|
|
4708
|
+
at: declaredAt(document, parameter, `${itemAt}/parameters/${position}`)
|
|
4709
|
+
})
|
|
4710
|
+
),
|
|
4711
|
+
...(Array.isArray(resolved2.parameters) ? resolved2.parameters : []).map(
|
|
4712
|
+
(parameter, position) => ({
|
|
4713
|
+
parameter,
|
|
4714
|
+
at: declaredAt(document, parameter, `${at}/parameters/${position}`)
|
|
4715
|
+
})
|
|
4716
|
+
)
|
|
4447
4717
|
];
|
|
4448
4718
|
const parameters = /* @__PURE__ */ new Map();
|
|
4449
|
-
for (const parameter of
|
|
4450
|
-
const p =
|
|
4451
|
-
|
|
4719
|
+
for (const { parameter, at: parameterAt } of declared) {
|
|
4720
|
+
const p = decodeDefinition(
|
|
4721
|
+
OpenapiParameter,
|
|
4722
|
+
document.resolve(record2(parameter)),
|
|
4723
|
+
parameterAt,
|
|
4724
|
+
"parameter"
|
|
4725
|
+
);
|
|
4726
|
+
if (p.in === "querystring") {
|
|
4727
|
+
const [media, ...others] = Object.keys(p.content ?? {});
|
|
4728
|
+
const kind = media === void 0 || others.length > 0 ? void 0 : openapiMediaKind(media);
|
|
4729
|
+
if (kind !== "form" && kind !== "json" && kind !== "text")
|
|
4730
|
+
fail2(
|
|
4731
|
+
"parameter_encoding",
|
|
4732
|
+
`The querystring parameter at ${parameterAt} must declare one form, JSON or text media type in content.`
|
|
4733
|
+
);
|
|
4734
|
+
}
|
|
4735
|
+
parameters.set(`${p.in}:${p.name}`, { parameter: p, at: parameterAt });
|
|
4736
|
+
}
|
|
4737
|
+
for (const name2 of prefix) {
|
|
4738
|
+
const key = `path:${name2}`;
|
|
4739
|
+
if (path.includes(`{${name2}}`))
|
|
4740
|
+
fail2(
|
|
4741
|
+
"operation_path",
|
|
4742
|
+
`pathPrefix adds the path parameter {${name2}}, which this operation's path already uses.`
|
|
4743
|
+
);
|
|
4744
|
+
if (!parameters.has(key))
|
|
4745
|
+
parameters.set(key, {
|
|
4746
|
+
parameter: { name: name2, in: "path", required: true, schema: { type: "string" } },
|
|
4747
|
+
at: void 0
|
|
4748
|
+
});
|
|
4452
4749
|
}
|
|
4453
4750
|
const groups = /* @__PURE__ */ new Map();
|
|
4454
|
-
for (const p of parameters.values()) {
|
|
4751
|
+
for (const { parameter: p, at: parameterAt } of parameters.values()) {
|
|
4455
4752
|
const key = p.in === "header" ? "headers" : p.in;
|
|
4456
4753
|
const group = groups.get(key) ?? { properties: {}, required: [] };
|
|
4457
|
-
const content = p.content === void 0 ?
|
|
4458
|
-
|
|
4754
|
+
const [mediaType, content] = p.content === void 0 ? [] : Object.entries(p.content)[0] ?? [];
|
|
4755
|
+
const schema2 = p.schema ?? (content === void 0 ? {} : record2(content).schema ?? {});
|
|
4756
|
+
const schemaAt = p.schema !== void 0 || mediaType === void 0 ? `${parameterAt}/schema` : mediaSchemaAt(document, `${parameterAt}`, mediaType, content);
|
|
4757
|
+
group.properties[p.name] = parameterAt === void 0 ? () => schema2 : (api) => api(schema2, schemaAt);
|
|
4459
4758
|
if (p.required || p.in === "path") group.required.push(p.name);
|
|
4460
4759
|
groups.set(key, group);
|
|
4461
4760
|
}
|
|
@@ -4465,7 +4764,7 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4465
4764
|
properties[key] = (api) => ({
|
|
4466
4765
|
type: "object",
|
|
4467
4766
|
properties: Object.fromEntries(
|
|
4468
|
-
Object.entries(group.properties).map(([name2, schema2]) => [name2, api
|
|
4767
|
+
Object.entries(group.properties).map(([name2, schema2]) => [name2, schema2(api)])
|
|
4469
4768
|
),
|
|
4470
4769
|
required: group.required,
|
|
4471
4770
|
additionalProperties: false
|
|
@@ -4475,16 +4774,27 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4475
4774
|
const bodyVariants = [];
|
|
4476
4775
|
let retainedBody;
|
|
4477
4776
|
if (operation.requestBody) {
|
|
4478
|
-
const
|
|
4479
|
-
|
|
4777
|
+
const bodyAt = declaredAt(document, resolved2.requestBody, `${at}/requestBody`);
|
|
4778
|
+
const request = decodeDefinition(
|
|
4779
|
+
OpenapiRequestBody,
|
|
4780
|
+
document.resolve(operation.requestBody),
|
|
4781
|
+
bodyAt,
|
|
4782
|
+
"request body"
|
|
4480
4783
|
);
|
|
4784
|
+
const rawContent = record2(document.resolve(record2(resolved2.requestBody)).content);
|
|
4481
4785
|
const retainedContent = {};
|
|
4482
4786
|
for (const [contentType, content] of Object.entries(request.content)) {
|
|
4483
4787
|
const kind = openapiMediaKind(contentType);
|
|
4484
4788
|
const schema2 = document.resolve(content.schema ?? {});
|
|
4485
|
-
const
|
|
4789
|
+
const declared2 = content.schema ?? {};
|
|
4790
|
+
const schemaAt = mediaSchemaAt(
|
|
4791
|
+
document,
|
|
4792
|
+
bodyAt,
|
|
4793
|
+
contentType,
|
|
4794
|
+
rawContent[contentType]
|
|
4795
|
+
);
|
|
4486
4796
|
const retainedFiles = {};
|
|
4487
|
-
let inputSchema = kind === "binary" ? () => binaryInput : kind === "text" ? () => ({ type: "string" }) : (api) => api(
|
|
4797
|
+
let inputSchema = kind === "binary" ? () => binaryInput : kind === "text" ? () => ({ type: "string" }) : (api) => api(declared2, schemaAt);
|
|
4488
4798
|
if (kind === "multipart") {
|
|
4489
4799
|
const fields = { ...record2(schema2.properties ?? {}) };
|
|
4490
4800
|
const files = {};
|
|
@@ -4497,8 +4807,9 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4497
4807
|
}
|
|
4498
4808
|
}
|
|
4499
4809
|
const form = schema2;
|
|
4810
|
+
const formAt = typeof declared2.$ref === "string" ? declared2.$ref : schemaAt;
|
|
4500
4811
|
inputSchema = (api) => {
|
|
4501
|
-
const converted = api({ ...form, properties: fields });
|
|
4812
|
+
const converted = api({ ...form, properties: fields }, formAt);
|
|
4502
4813
|
return {
|
|
4503
4814
|
...converted,
|
|
4504
4815
|
properties: { ...record2(converted.properties ?? {}), ...files }
|
|
@@ -4517,7 +4828,7 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4517
4828
|
}
|
|
4518
4829
|
retainedBody = { ...request, content: retainedContent };
|
|
4519
4830
|
if (!bodyVariants.length)
|
|
4520
|
-
fail2("request_body",
|
|
4831
|
+
fail2("request_body", "The request body declares no media types.");
|
|
4521
4832
|
properties.body = () => ({});
|
|
4522
4833
|
properties.contentType = () => ({
|
|
4523
4834
|
type: "string",
|
|
@@ -4554,18 +4865,16 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4554
4865
|
try {
|
|
4555
4866
|
jsonSchema(input);
|
|
4556
4867
|
} catch {
|
|
4557
|
-
fail2(
|
|
4558
|
-
"input_schema",
|
|
4559
|
-
`Tool ${name} has an input schema this importer cannot preserve yet.`
|
|
4560
|
-
);
|
|
4868
|
+
fail2("input_schema", "Its input schema is not valid JSON.");
|
|
4561
4869
|
}
|
|
4562
|
-
const outputSchema = responseSchema(document,
|
|
4870
|
+
const outputSchema = responseSchema(document, resolved2, at, method);
|
|
4563
4871
|
const streaming = Object.values(operation.responses ?? {}).some((response) => {
|
|
4564
4872
|
const content = errorContent(document, response);
|
|
4565
4873
|
return content !== void 0 && Object.hasOwn(record2(content), "text/event-stream");
|
|
4566
4874
|
});
|
|
4567
4875
|
built.push({
|
|
4568
4876
|
methods: operationMethods,
|
|
4877
|
+
declared: { name, method, path },
|
|
4569
4878
|
operation: {
|
|
4570
4879
|
...streaming ? { streaming: true } : {},
|
|
4571
4880
|
...tags === void 0 || tags.length === 0 ? {} : { tags },
|
|
@@ -4573,17 +4882,20 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4573
4882
|
...operation.operationId === void 0 ? {} : { operationId: operation.operationId },
|
|
4574
4883
|
description: operation.summary ?? operation.description ?? name,
|
|
4575
4884
|
method,
|
|
4576
|
-
path
|
|
4885
|
+
path: `${options.pathPrefix ?? ""}${path}`,
|
|
4577
4886
|
baseUrl,
|
|
4578
4887
|
openapi: spec.openapi,
|
|
4579
4888
|
securitySchemes: Object.fromEntries(
|
|
4580
4889
|
[...new Set(security.flatMap(Object.keys))].map((key) => [
|
|
4581
4890
|
key,
|
|
4582
|
-
schemes[key] ?? fail2(
|
|
4891
|
+
schemes[key] ?? fail2(
|
|
4892
|
+
"auth_method",
|
|
4893
|
+
`A security requirement names ${JSON.stringify(key)}, which securitySchemes does not declare.`
|
|
4894
|
+
)
|
|
4583
4895
|
])
|
|
4584
4896
|
),
|
|
4585
4897
|
request: {
|
|
4586
|
-
parameters: [...parameters.values()],
|
|
4898
|
+
parameters: [...parameters.values()].map(({ parameter }) => parameter),
|
|
4587
4899
|
...retainedBody === void 0 ? {} : { requestBody: retainedBody },
|
|
4588
4900
|
security,
|
|
4589
4901
|
responses: Object.fromEntries(
|
|
@@ -4604,14 +4916,20 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4604
4916
|
},
|
|
4605
4917
|
input,
|
|
4606
4918
|
...outputSchema === void 0 ? {} : { outputSchema },
|
|
4607
|
-
errorResponses: errorResponses(document,
|
|
4919
|
+
errorResponses: errorResponses(document, resolved2, at)
|
|
4608
4920
|
}
|
|
4609
4921
|
});
|
|
4610
4922
|
} catch (error) {
|
|
4611
4923
|
if (!(error instanceof OpenapiCompileError) && !Schema_exports.isSchemaError(error)) throw error;
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4924
|
+
skipped.push({
|
|
4925
|
+
name,
|
|
4926
|
+
method,
|
|
4927
|
+
path,
|
|
4928
|
+
...error instanceof OpenapiCompileError ? { code: error.code, reason: error.reason } : {
|
|
4929
|
+
code: "invalid_document",
|
|
4930
|
+
reason: `The operation at ${at} does not match OpenAPI.`
|
|
4931
|
+
}
|
|
4932
|
+
});
|
|
4615
4933
|
}
|
|
4616
4934
|
}
|
|
4617
4935
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -4631,35 +4949,84 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4631
4949
|
const best = pinnedOrigin === void 0 ? 0 : counts.get(pinnedOrigin) ?? 0;
|
|
4632
4950
|
if (count > best || count === best && origin === documentOrigin) pinnedOrigin = origin;
|
|
4633
4951
|
}
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4952
|
+
const imported = [];
|
|
4953
|
+
for (const { operation, methods: operationMethods, declared } of built) {
|
|
4954
|
+
const origin = new URL(operation.baseUrl).origin;
|
|
4955
|
+
if (origin !== pinnedOrigin) {
|
|
4956
|
+
skipped.push({
|
|
4957
|
+
...declared,
|
|
4958
|
+
code: "multiple_hosts",
|
|
4959
|
+
reason: options.allowedOrigin === void 0 ? `Its server origin ${origin} differs from ${pinnedOrigin ?? "the origin"} most operations use.` : `Its server origin ${origin} is not allowedOrigin ${options.allowedOrigin}.`
|
|
4960
|
+
});
|
|
4637
4961
|
continue;
|
|
4638
4962
|
}
|
|
4639
|
-
|
|
4963
|
+
imported.push({ operation, declared });
|
|
4640
4964
|
for (const method of operationMethods) methods.set(method.name, method);
|
|
4641
4965
|
}
|
|
4966
|
+
const operations = imported.map(({ operation }) => operation);
|
|
4642
4967
|
if (!operations.length) {
|
|
4643
|
-
const
|
|
4644
|
-
if (
|
|
4645
|
-
throw
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4968
|
+
const left = inDefinitionOrder(skipped);
|
|
4969
|
+
if (options.allowedOrigin !== void 0 && built.length > 0)
|
|
4970
|
+
throw new OpenapiCompileError({
|
|
4971
|
+
code: "no_supported_operations",
|
|
4972
|
+
reason: `allowedOrigin ${options.allowedOrigin} is not the origin of any operation. They resolve to ${[...counts.keys()].join(", ")}. Set allowedOrigin to the origin that receives the account's credentials, or set baseUrl.`,
|
|
4973
|
+
skipped: left,
|
|
4974
|
+
origins: [...counts.keys()]
|
|
4975
|
+
});
|
|
4976
|
+
const [first] = left;
|
|
4977
|
+
if (first !== void 0 && left.every(({ code, reason }) => code === first.code && reason === first.reason))
|
|
4978
|
+
throw new OpenapiCompileError({ code: first.code, reason: first.reason, skipped: left });
|
|
4979
|
+
throw new OpenapiCompileError({
|
|
4980
|
+
code: "no_supported_operations",
|
|
4981
|
+
reason: "Executor cannot import any operation in this API definition.",
|
|
4982
|
+
skipped: left
|
|
4983
|
+
});
|
|
4650
4984
|
}
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4985
|
+
const supported = (requirement) => {
|
|
4986
|
+
const keys = Object.keys(requirement);
|
|
4987
|
+
return keys.every((key) => bindings.has(key)) || keys.length === 1 && oauth.some((method) => method.name === keys[0]);
|
|
4988
|
+
};
|
|
4989
|
+
const schemeLabel = (key) => {
|
|
4990
|
+
const scheme = document.resolve(record2(schemes[key]));
|
|
4991
|
+
const detail = scheme.type === "oauth2" ? Object.keys(record2(scheme.flows ?? {})).join("/") : scheme.type === "http" ? scheme.scheme : scheme.type === "apiKey" ? `in ${String(scheme.in)}` : void 0;
|
|
4992
|
+
return `${key} (${[scheme.type, detail].filter((part) => typeof part === "string" && part !== "").join(" ")})`;
|
|
4993
|
+
};
|
|
4994
|
+
const unsupportedBy = (requirement) => {
|
|
4995
|
+
const keys = Object.keys(requirement);
|
|
4996
|
+
const unknown = keys.filter(
|
|
4997
|
+
(key) => !bindings.has(key) && !oauth.some((method) => method.name === key)
|
|
4660
4998
|
);
|
|
4999
|
+
return unknown.length > 0 ? unknown.map(schemeLabel).join(" and ") : `${keys.map(schemeLabel).join(" with ")}, which combines OAuth sign-in with another scheme`;
|
|
5000
|
+
};
|
|
5001
|
+
const unusable = (operation) => {
|
|
5002
|
+
const { security } = operation.request;
|
|
5003
|
+
if (operation.streaming === true)
|
|
5004
|
+
return {
|
|
5005
|
+
code: "event_stream",
|
|
5006
|
+
reason: "It responds with text/event-stream, which a tool cannot return. Write a subscription for it."
|
|
5007
|
+
};
|
|
5008
|
+
if (security.length === 0 || security.some(supported)) return void 0;
|
|
5009
|
+
return {
|
|
5010
|
+
code: "auth_method",
|
|
5011
|
+
reason: `Executor cannot authenticate with any of its security requirements: ${security.map(unsupportedBy).join("; ")}.`
|
|
5012
|
+
};
|
|
5013
|
+
};
|
|
5014
|
+
if (imported.every(({ operation }) => unusable(operation) !== void 0))
|
|
5015
|
+
throw new OpenapiCompileError({
|
|
5016
|
+
code: "no_supported_operations",
|
|
5017
|
+
reason: "No operation can be called: each one is left out, streams its response, or needs authentication Executor does not support.",
|
|
5018
|
+
skipped: inDefinitionOrder([
|
|
5019
|
+
...skipped,
|
|
5020
|
+
...imported.flatMap(({ operation, declared }) => {
|
|
5021
|
+
const cause = unusable(operation);
|
|
5022
|
+
return cause === void 0 ? [] : [{ ...declared, ...cause }];
|
|
5023
|
+
})
|
|
5024
|
+
])
|
|
5025
|
+
});
|
|
4661
5026
|
return {
|
|
4662
5027
|
operations,
|
|
5028
|
+
/** Declared operations left out of `operations`, in definition order. */
|
|
5029
|
+
skipped: inDefinitionOrder(skipped),
|
|
4663
5030
|
definitions: Object.fromEntries(document.definitions),
|
|
4664
5031
|
methods: Object.fromEntries(
|
|
4665
5032
|
[...methods.values()].map((method) => [method.name, method.bindings])
|
|
@@ -4671,11 +5038,14 @@ var compileOpenApiDocument = (entry, inputDocument, options = {}) => {
|
|
|
4671
5038
|
fallback
|
|
4672
5039
|
};
|
|
4673
5040
|
},
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
5041
|
+
// Expected failures stay typed; anything else is a defect in the importer, not the definition.
|
|
5042
|
+
catch: (error) => error instanceof OpenapiCompileError ? Exit_exports.fail(error) : Schema_exports.isSchemaError(error) ? Exit_exports.fail(
|
|
5043
|
+
new OpenapiCompileError({
|
|
5044
|
+
code: "invalid_document",
|
|
5045
|
+
reason: "The definition's structure does not match OpenAPI."
|
|
5046
|
+
})
|
|
5047
|
+
) : Exit_exports.die(error)
|
|
5048
|
+
}).pipe(Effect_exports.catch((exit) => exit));
|
|
4679
5049
|
};
|
|
4680
5050
|
|
|
4681
5051
|
// src/implementation/openapi-source.ts
|
|
@@ -4684,6 +5054,7 @@ var Manifest = Schema_exports.Struct({
|
|
|
4684
5054
|
summaries: Schema_exports.Number,
|
|
4685
5055
|
operations: Schema_exports.Number,
|
|
4686
5056
|
definitions: Schema_exports.Number,
|
|
5057
|
+
skipped: Schema_exports.Number,
|
|
4687
5058
|
meta: Schema_exports.optionalKey(RouterMeta)
|
|
4688
5059
|
});
|
|
4689
5060
|
var OperationSummary = Schema_exports.Struct({
|
|
@@ -4815,7 +5186,7 @@ var decodeText = (decoder) => (text) => Effect_exports.try({ try: () => JSON.par
|
|
|
4815
5186
|
var schema = (decoder) => wrap(decoder, false);
|
|
4816
5187
|
var invoke = (work) => Effect_exports.tryPromise({ try: work, catch: (error) => error });
|
|
4817
5188
|
var invalid = () => new OpenapiError({ reason: "invalid_definition" });
|
|
4818
|
-
var format = "openapi-
|
|
5189
|
+
var format = "openapi-v4";
|
|
4819
5190
|
var writeEntries = cacheLimits.batchEntries;
|
|
4820
5191
|
var writeBytes = cacheLimits.batchBytes - 5e5;
|
|
4821
5192
|
var readParts = Math.floor(cacheLimits.batchBytes / bucketLimit);
|
|
@@ -4969,6 +5340,7 @@ var liveOpenapiRouter = (options) => {
|
|
|
4969
5340
|
source: options.source,
|
|
4970
5341
|
allowedOrigin: options.allowedOrigin,
|
|
4971
5342
|
baseUrl: options.baseUrl,
|
|
5343
|
+
pathPrefix: options.pathPrefix,
|
|
4972
5344
|
securitySchemes: options.securitySchemes,
|
|
4973
5345
|
patches: options.patches,
|
|
4974
5346
|
fallbackSecurity: options.fallbackSecurity
|
|
@@ -5016,7 +5388,8 @@ var liveOpenapiRouter = (options) => {
|
|
|
5016
5388
|
allowedOrigin: options.allowedOrigin,
|
|
5017
5389
|
securitySchemes: options.securitySchemes,
|
|
5018
5390
|
...options.fallbackSecurity === void 0 ? {} : { fallbackSecurity: options.fallbackSecurity },
|
|
5019
|
-
...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl }
|
|
5391
|
+
...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
|
|
5392
|
+
...options.pathPrefix === void 0 ? {} : { pathPrefix: options.pathPrefix }
|
|
5020
5393
|
}
|
|
5021
5394
|
);
|
|
5022
5395
|
return { revision, meta, compiled };
|
|
@@ -5029,10 +5402,12 @@ var liveOpenapiRouter = (options) => {
|
|
|
5029
5402
|
compiled.operations.map((operation) => [operation.name, operation])
|
|
5030
5403
|
);
|
|
5031
5404
|
const definitions = bucketize(Object.entries(compiled.definitions));
|
|
5405
|
+
const skipped = compiled.skipped.length === 0 ? [] : bucketize(compiled.skipped.map((operation) => [operation.name, operation]));
|
|
5032
5406
|
const parts = [
|
|
5033
5407
|
...summaries.map((value, name) => ({ kind: "summaries", name, value })),
|
|
5034
5408
|
...operations.map((value, name) => ({ kind: "operations", name, value })),
|
|
5035
|
-
...definitions.map((value, name) => ({ kind: "definitions", name, value }))
|
|
5409
|
+
...definitions.map((value, name) => ({ kind: "definitions", name, value })),
|
|
5410
|
+
...skipped.map((value, name) => ({ kind: "skipped", name, value }))
|
|
5036
5411
|
];
|
|
5037
5412
|
const batches = [];
|
|
5038
5413
|
let batch = [];
|
|
@@ -5061,6 +5436,7 @@ var liveOpenapiRouter = (options) => {
|
|
|
5061
5436
|
summaries: summaries.length,
|
|
5062
5437
|
operations: operations.length,
|
|
5063
5438
|
definitions: definitions.length,
|
|
5439
|
+
skipped: skipped.length,
|
|
5064
5440
|
...meta === void 0 ? {} : { meta }
|
|
5065
5441
|
},
|
|
5066
5442
|
batches,
|
|
@@ -5169,6 +5545,24 @@ var liveOpenapiRouter = (options) => {
|
|
|
5169
5545
|
value: value === void 0 ? void 0 : yield* Schema_exports.decodeUnknownEffect(OpenapiOperation)(value)
|
|
5170
5546
|
};
|
|
5171
5547
|
});
|
|
5548
|
+
const leftOutFor = (manifest, name) => Effect_exports.gen(function* () {
|
|
5549
|
+
if (manifest.skipped === 0) return { value: void 0 };
|
|
5550
|
+
const [bucket] = yield* read(
|
|
5551
|
+
manifest.revision,
|
|
5552
|
+
"skipped",
|
|
5553
|
+
[bucketOf(name, manifest.skipped)],
|
|
5554
|
+
Bucket
|
|
5555
|
+
);
|
|
5556
|
+
if (bucket === void 0) return void 0;
|
|
5557
|
+
const value = Object.hasOwn(bucket, name) ? bucket[name] : void 0;
|
|
5558
|
+
if (value === void 0) return { value: void 0 };
|
|
5559
|
+
const operation = yield* Schema_exports.decodeUnknownEffect(OpenapiSkippedOperation)(value);
|
|
5560
|
+
return yield* new OpenapiCompileError({
|
|
5561
|
+
code: operation.code,
|
|
5562
|
+
reason: operation.reason,
|
|
5563
|
+
skipped: [operation]
|
|
5564
|
+
});
|
|
5565
|
+
});
|
|
5172
5566
|
const operationsFor = (manifest) => Effect_exports.gen(function* () {
|
|
5173
5567
|
const summaries = yield* summariesFor(manifest);
|
|
5174
5568
|
if (summaries === void 0) return void 0;
|
|
@@ -5223,7 +5617,7 @@ var liveOpenapiRouter = (options) => {
|
|
|
5223
5617
|
const kindOf = (op) => {
|
|
5224
5618
|
const key = op.operationId ?? op.name;
|
|
5225
5619
|
const kinds = options.kinds ?? {};
|
|
5226
|
-
return Object.hasOwn(kinds, key) ? kinds[key] ?? "mutation" :
|
|
5620
|
+
return Object.hasOwn(kinds, key) ? kinds[key] ?? "mutation" : isOpenapiReadMethod(op.method) ? "query" : "mutation";
|
|
5227
5621
|
};
|
|
5228
5622
|
const readOnly = (op) => kindOf(op) === "query";
|
|
5229
5623
|
const summarize = (operation) => ({
|
|
@@ -5256,7 +5650,7 @@ var liveOpenapiRouter = (options) => {
|
|
|
5256
5650
|
if (operation === void 0) {
|
|
5257
5651
|
const found = yield* operationFor(manifest, name);
|
|
5258
5652
|
if (found === void 0) return void 0;
|
|
5259
|
-
if (found.value === void 0) return
|
|
5653
|
+
if (found.value === void 0) return yield* leftOutFor(manifest, name);
|
|
5260
5654
|
operation = found.value;
|
|
5261
5655
|
}
|
|
5262
5656
|
const definitions = memo?.definitions ?? (yield* definitionsFor(manifest, operation));
|
|
@@ -5301,7 +5695,7 @@ var liveOpenapiRouter = (options) => {
|
|
|
5301
5695
|
(manifest) => Effect_exports.gen(function* () {
|
|
5302
5696
|
const found = yield* operationFor(manifest, name);
|
|
5303
5697
|
if (found === void 0) return void 0;
|
|
5304
|
-
if (found.value === void 0) return
|
|
5698
|
+
if (found.value === void 0) return yield* leftOutFor(manifest, name);
|
|
5305
5699
|
const operation = found.value;
|
|
5306
5700
|
if (!createRequest(options).available(operation, options.account))
|
|
5307
5701
|
return { value: void 0 };
|
|
@@ -5325,6 +5719,7 @@ export {
|
|
|
5325
5719
|
OpenapiErrorResponse,
|
|
5326
5720
|
OpenapiParameter,
|
|
5327
5721
|
OpenapiRequestBody,
|
|
5722
|
+
OpenapiSkippedOperation,
|
|
5328
5723
|
isOpenapiTextMedia,
|
|
5329
5724
|
liveOpenapiRouter,
|
|
5330
5725
|
openapiBinaryResultSchema,
|