@executor-js/plugin-openapi 0.1.0 → 1.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AddOpenApiSource-FLMNI742.js +19 -0
- package/dist/AddOpenApiSource-FLMNI742.js.map +1 -0
- package/dist/EditOpenApiSource-I4NIGIIJ.js +665 -0
- package/dist/EditOpenApiSource-I4NIGIIJ.js.map +1 -0
- package/dist/OpenApiSourceSummary-CM46DB4L.js +122 -0
- package/dist/OpenApiSourceSummary-CM46DB4L.js.map +1 -0
- package/dist/api/group.d.ts +224 -16
- package/dist/api/index.d.ts +634 -0
- package/dist/chunk-E7PZ2QGD.js +1303 -0
- package/dist/chunk-E7PZ2QGD.js.map +1 -0
- package/dist/chunk-GFQUEZUW.js +216 -0
- package/dist/chunk-GFQUEZUW.js.map +1 -0
- package/dist/chunk-OZ67JNID.js +1447 -0
- package/dist/chunk-OZ67JNID.js.map +1 -0
- package/dist/chunk-TGDT6QCH.js +1120 -0
- package/dist/chunk-TGDT6QCH.js.map +1 -0
- package/dist/client.js +165 -0
- package/dist/client.js.map +1 -0
- package/dist/core.js +8 -10
- package/dist/index.js +2 -1
- package/dist/react/AddOpenApiSource.d.ts +1 -1
- package/dist/react/OpenApiSourceDetailsFields.d.ts +18 -0
- package/dist/react/atoms.d.ts +320 -15
- package/dist/react/client.d.ts +226 -15
- package/dist/sdk/extract.d.ts +54 -3
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/invoke.d.ts +48 -4
- package/dist/sdk/openapi-utils.d.ts +4 -3
- package/dist/sdk/parse.d.ts +1 -1
- package/dist/sdk/parse.test.d.ts +1 -0
- package/dist/sdk/plugin.d.ts +247 -128
- package/dist/sdk/preview.d.ts +201 -49
- package/dist/sdk/store.d.ts +155 -45
- package/dist/sdk/types.d.ts +204 -137
- package/dist/sdk/usage-scope-isolation.test.d.ts +1 -0
- package/dist/testing/index.d.ts +34 -0
- package/dist/testing.js +56 -0
- package/dist/testing.js.map +1 -0
- package/package.json +16 -4
- package/dist/chunk-RBE3CVB4.js +0 -2837
- package/dist/chunk-RBE3CVB4.js.map +0 -1
|
@@ -0,0 +1,1303 @@
|
|
|
1
|
+
// src/sdk/errors.ts
|
|
2
|
+
import { Data, Schema } from "effect";
|
|
3
|
+
var OpenApiParseError = class extends Schema.TaggedErrorClass()(
|
|
4
|
+
"OpenApiParseError",
|
|
5
|
+
{
|
|
6
|
+
message: Schema.String
|
|
7
|
+
},
|
|
8
|
+
{ httpApiStatus: 400 }
|
|
9
|
+
) {
|
|
10
|
+
};
|
|
11
|
+
var OpenApiExtractionError = class extends Schema.TaggedErrorClass()(
|
|
12
|
+
"OpenApiExtractionError",
|
|
13
|
+
{
|
|
14
|
+
message: Schema.String
|
|
15
|
+
},
|
|
16
|
+
{ httpApiStatus: 400 }
|
|
17
|
+
) {
|
|
18
|
+
};
|
|
19
|
+
var OpenApiInvocationError = class extends Data.TaggedError("OpenApiInvocationError") {
|
|
20
|
+
};
|
|
21
|
+
var OpenApiOAuthError = class extends Schema.TaggedErrorClass()(
|
|
22
|
+
"OpenApiOAuthError",
|
|
23
|
+
{
|
|
24
|
+
message: Schema.String
|
|
25
|
+
},
|
|
26
|
+
{ httpApiStatus: 400 }
|
|
27
|
+
) {
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// src/sdk/parse.ts
|
|
31
|
+
import { Duration, Effect, Schema as Schema2 } from "effect";
|
|
32
|
+
import { HttpClient, HttpClientRequest } from "effect/unstable/http";
|
|
33
|
+
import YAML from "yaml";
|
|
34
|
+
var OpenApiExtractionErrorFromParse = class extends OpenApiExtractionError {
|
|
35
|
+
};
|
|
36
|
+
var fetchSpecText = Effect.fn("OpenApi.fetchSpecText")(function* (url, credentials) {
|
|
37
|
+
const client = yield* HttpClient.HttpClient;
|
|
38
|
+
const requestUrl = new URL(url);
|
|
39
|
+
for (const [name, value] of Object.entries(credentials?.queryParams ?? {})) {
|
|
40
|
+
requestUrl.searchParams.set(name, value);
|
|
41
|
+
}
|
|
42
|
+
let request = HttpClientRequest.get(requestUrl.toString()).pipe(
|
|
43
|
+
HttpClientRequest.setHeader("Accept", "application/json, application/yaml, text/yaml, */*")
|
|
44
|
+
);
|
|
45
|
+
for (const [name, value] of Object.entries(credentials?.headers ?? {})) {
|
|
46
|
+
request = HttpClientRequest.setHeader(request, name, value);
|
|
47
|
+
}
|
|
48
|
+
const response = yield* client.execute(request).pipe(
|
|
49
|
+
Effect.timeout(Duration.seconds(60)),
|
|
50
|
+
Effect.mapError(
|
|
51
|
+
(_cause) => new OpenApiParseError({
|
|
52
|
+
message: "Failed to fetch OpenAPI document"
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
if (response.status < 200 || response.status >= 300) {
|
|
57
|
+
return yield* new OpenApiParseError({
|
|
58
|
+
message: `Failed to fetch OpenAPI document: HTTP ${response.status}`
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return yield* response.text.pipe(
|
|
62
|
+
Effect.mapError(
|
|
63
|
+
(_cause) => new OpenApiParseError({
|
|
64
|
+
message: "Failed to read OpenAPI document body"
|
|
65
|
+
})
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
var resolveSpecText = (input, credentials) => input.startsWith("http://") || input.startsWith("https://") ? fetchSpecText(input, credentials) : Effect.succeed(input);
|
|
70
|
+
var parse = Effect.fn("OpenApi.parse")(function* (text) {
|
|
71
|
+
const api = yield* parseTextToObject(text);
|
|
72
|
+
if (!isOpenApi3(api)) {
|
|
73
|
+
return yield* new OpenApiExtractionErrorFromParse({
|
|
74
|
+
message: "Only OpenAPI 3.x documents are supported. Swagger 2.x documents should be converted first."
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return api;
|
|
78
|
+
});
|
|
79
|
+
var isOpenApi3 = (doc) => "openapi" in doc && typeof doc.openapi === "string" && doc.openapi.startsWith("3.");
|
|
80
|
+
var parseTextToObject = (text) => Effect.gen(function* () {
|
|
81
|
+
const trimmed = text.trim();
|
|
82
|
+
if (trimmed.length === 0) {
|
|
83
|
+
return yield* new OpenApiParseError({
|
|
84
|
+
message: "OpenAPI document is empty"
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const parsed = yield* parseJsonLike(trimmed).pipe(
|
|
88
|
+
Effect.mapError(
|
|
89
|
+
() => new OpenApiParseError({
|
|
90
|
+
message: "Failed to parse OpenAPI document"
|
|
91
|
+
})
|
|
92
|
+
)
|
|
93
|
+
);
|
|
94
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
95
|
+
return yield* new OpenApiParseError({
|
|
96
|
+
message: "OpenAPI document must parse to an object"
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return parsed;
|
|
100
|
+
});
|
|
101
|
+
var parseJsonText = Schema2.decodeUnknownEffect(Schema2.fromJsonString(Schema2.Unknown));
|
|
102
|
+
var parseJsonLike = (text) => {
|
|
103
|
+
const parseYaml = Effect.try({
|
|
104
|
+
try: () => YAML.parse(text),
|
|
105
|
+
catch: () => "YamlParseFailed"
|
|
106
|
+
});
|
|
107
|
+
if (!text.startsWith("{") && !text.startsWith("[")) return parseYaml;
|
|
108
|
+
return parseJsonText(text).pipe(Effect.catch(() => parseYaml));
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// src/sdk/openapi-utils.ts
|
|
112
|
+
import { Option } from "effect";
|
|
113
|
+
var DocResolver = class {
|
|
114
|
+
constructor(doc) {
|
|
115
|
+
this.doc = doc;
|
|
116
|
+
}
|
|
117
|
+
doc;
|
|
118
|
+
/** Resolve a value that might be a $ref, returning the resolved object */
|
|
119
|
+
resolve(value) {
|
|
120
|
+
if (isRef(value)) {
|
|
121
|
+
const resolved = this.resolvePointer(value.$ref);
|
|
122
|
+
return resolved;
|
|
123
|
+
}
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
resolvePointer(ref) {
|
|
127
|
+
if (!ref.startsWith("#/")) return null;
|
|
128
|
+
const segments = ref.slice(2).split("/");
|
|
129
|
+
let current = this.doc;
|
|
130
|
+
for (const segment of segments) {
|
|
131
|
+
if (typeof current !== "object" || current === null) return null;
|
|
132
|
+
current = current[segment];
|
|
133
|
+
}
|
|
134
|
+
return current;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
var isRef = (value) => typeof value === "object" && value !== null && "$ref" in value;
|
|
138
|
+
var substituteUrlVariables = (url, values) => {
|
|
139
|
+
let out = url;
|
|
140
|
+
for (const [name, value] of Object.entries(values)) {
|
|
141
|
+
out = out.replaceAll(`{${name}}`, value);
|
|
142
|
+
}
|
|
143
|
+
return out;
|
|
144
|
+
};
|
|
145
|
+
var OPENAPI_MAX_SERVER_VARIABLE_OPTIONS = 64;
|
|
146
|
+
var expandServerUrlOptions = (server, limit = OPENAPI_MAX_SERVER_VARIABLE_OPTIONS) => {
|
|
147
|
+
if (!Option.isSome(server.variables)) return [server.url];
|
|
148
|
+
let urls = [server.url];
|
|
149
|
+
for (const [name, variable] of Object.entries(server.variables.value)) {
|
|
150
|
+
const enumValues = typeof variable === "string" ? [] : Option.getOrElse(variable.enum, () => []);
|
|
151
|
+
const values = enumValues.length > 0 ? enumValues : [typeof variable === "string" ? variable : variable.default];
|
|
152
|
+
const next = [];
|
|
153
|
+
for (const url of urls) {
|
|
154
|
+
for (const value of values) {
|
|
155
|
+
next.push(url.replaceAll(`{${name}}`, value));
|
|
156
|
+
if (next.length >= limit) return next;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
urls = next;
|
|
160
|
+
}
|
|
161
|
+
return urls;
|
|
162
|
+
};
|
|
163
|
+
var resolveBaseUrl = (servers) => {
|
|
164
|
+
const server = servers[0];
|
|
165
|
+
if (!server) return "";
|
|
166
|
+
if (!Option.isSome(server.variables)) return server.url;
|
|
167
|
+
const values = {};
|
|
168
|
+
for (const [name, v] of Object.entries(server.variables.value)) {
|
|
169
|
+
values[name] = typeof v === "string" ? v : v.default;
|
|
170
|
+
}
|
|
171
|
+
return substituteUrlVariables(server.url, values);
|
|
172
|
+
};
|
|
173
|
+
var declaredContents = (content) => {
|
|
174
|
+
if (!content) return [];
|
|
175
|
+
return Object.entries(content).map(([mediaType, media]) => ({ mediaType, media }));
|
|
176
|
+
};
|
|
177
|
+
var preferredContent = (content) => {
|
|
178
|
+
const first = declaredContents(content)[0];
|
|
179
|
+
return first ? first : void 0;
|
|
180
|
+
};
|
|
181
|
+
var preferredResponseContent = (content) => {
|
|
182
|
+
if (!content) return void 0;
|
|
183
|
+
const entries = Object.entries(content);
|
|
184
|
+
const pick = entries.find(([mt]) => mt === "application/json") ?? entries.find(([mt]) => mt.toLowerCase().includes("+json")) ?? entries.find(([mt]) => mt.toLowerCase().includes("json")) ?? entries[0];
|
|
185
|
+
return pick ? { mediaType: pick[0], media: pick[1] } : void 0;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// src/sdk/types.ts
|
|
189
|
+
import { Schema as Schema3 } from "effect";
|
|
190
|
+
import {
|
|
191
|
+
ConnectionId,
|
|
192
|
+
ScopeId,
|
|
193
|
+
ScopedSecretCredentialInput,
|
|
194
|
+
SecretBackedValue,
|
|
195
|
+
SecretId
|
|
196
|
+
} from "@executor-js/sdk/core";
|
|
197
|
+
var OperationId = Schema3.String.pipe(Schema3.brand("OperationId"));
|
|
198
|
+
var HttpMethod = Schema3.Literals([
|
|
199
|
+
"get",
|
|
200
|
+
"put",
|
|
201
|
+
"post",
|
|
202
|
+
"delete",
|
|
203
|
+
"patch",
|
|
204
|
+
"head",
|
|
205
|
+
"options",
|
|
206
|
+
"trace"
|
|
207
|
+
]);
|
|
208
|
+
var ParameterLocation = Schema3.Literals(["path", "query", "header", "cookie"]);
|
|
209
|
+
var OperationParameter = Schema3.Struct({
|
|
210
|
+
name: Schema3.String,
|
|
211
|
+
location: ParameterLocation,
|
|
212
|
+
required: Schema3.Boolean,
|
|
213
|
+
schema: Schema3.OptionFromOptional(Schema3.Unknown),
|
|
214
|
+
style: Schema3.OptionFromOptional(Schema3.String),
|
|
215
|
+
explode: Schema3.OptionFromOptional(Schema3.Boolean),
|
|
216
|
+
allowReserved: Schema3.OptionFromOptional(Schema3.Boolean),
|
|
217
|
+
description: Schema3.OptionFromOptional(Schema3.String)
|
|
218
|
+
});
|
|
219
|
+
var EncodingObject = Schema3.Struct({
|
|
220
|
+
contentType: Schema3.OptionFromOptional(Schema3.String),
|
|
221
|
+
style: Schema3.OptionFromOptional(Schema3.String),
|
|
222
|
+
explode: Schema3.OptionFromOptional(Schema3.Boolean),
|
|
223
|
+
allowReserved: Schema3.OptionFromOptional(Schema3.Boolean)
|
|
224
|
+
});
|
|
225
|
+
var MediaBinding = Schema3.Struct({
|
|
226
|
+
contentType: Schema3.String,
|
|
227
|
+
schema: Schema3.OptionFromOptional(Schema3.Unknown),
|
|
228
|
+
encoding: Schema3.OptionFromOptional(Schema3.Record(Schema3.String, EncodingObject))
|
|
229
|
+
});
|
|
230
|
+
var OperationRequestBody = Schema3.Struct({
|
|
231
|
+
required: Schema3.Boolean,
|
|
232
|
+
/** Default media type — first declared in spec order (not JSON-first).
|
|
233
|
+
* Used when the caller does not override via the tool's `contentType` arg. */
|
|
234
|
+
contentType: Schema3.String,
|
|
235
|
+
/** Schema of the default media type. Kept for backward compat with stored
|
|
236
|
+
* bindings from before `contents` was added. */
|
|
237
|
+
schema: Schema3.OptionFromOptional(Schema3.Unknown),
|
|
238
|
+
/** All declared media types in spec order. Populated by `extract.ts`
|
|
239
|
+
* going forward; older persisted bindings may have this unset and will
|
|
240
|
+
* fall back to `{contentType, schema}`. */
|
|
241
|
+
contents: Schema3.OptionFromOptional(Schema3.Array(MediaBinding))
|
|
242
|
+
});
|
|
243
|
+
var ExtractedOperation = Schema3.Struct({
|
|
244
|
+
operationId: OperationId,
|
|
245
|
+
method: HttpMethod,
|
|
246
|
+
pathTemplate: Schema3.String,
|
|
247
|
+
summary: Schema3.OptionFromOptional(Schema3.String),
|
|
248
|
+
description: Schema3.OptionFromOptional(Schema3.String),
|
|
249
|
+
tags: Schema3.Array(Schema3.String),
|
|
250
|
+
parameters: Schema3.Array(OperationParameter),
|
|
251
|
+
requestBody: Schema3.OptionFromOptional(OperationRequestBody),
|
|
252
|
+
inputSchema: Schema3.OptionFromOptional(Schema3.Unknown),
|
|
253
|
+
outputSchema: Schema3.OptionFromOptional(Schema3.Unknown),
|
|
254
|
+
deprecated: Schema3.Boolean
|
|
255
|
+
});
|
|
256
|
+
var ServerVariable = Schema3.Struct({
|
|
257
|
+
default: Schema3.String,
|
|
258
|
+
enum: Schema3.OptionFromOptional(Schema3.Array(Schema3.String)),
|
|
259
|
+
description: Schema3.OptionFromOptional(Schema3.String)
|
|
260
|
+
});
|
|
261
|
+
var ServerInfo = Schema3.Struct({
|
|
262
|
+
url: Schema3.String,
|
|
263
|
+
description: Schema3.OptionFromOptional(Schema3.String),
|
|
264
|
+
variables: Schema3.OptionFromOptional(Schema3.Record(Schema3.String, ServerVariable))
|
|
265
|
+
});
|
|
266
|
+
var ExtractionResult = Schema3.Struct({
|
|
267
|
+
title: Schema3.OptionFromOptional(Schema3.String),
|
|
268
|
+
version: Schema3.OptionFromOptional(Schema3.String),
|
|
269
|
+
servers: Schema3.Array(ServerInfo),
|
|
270
|
+
operations: Schema3.Array(ExtractedOperation)
|
|
271
|
+
});
|
|
272
|
+
var OperationBinding = Schema3.Struct({
|
|
273
|
+
method: HttpMethod,
|
|
274
|
+
pathTemplate: Schema3.String,
|
|
275
|
+
parameters: Schema3.Array(OperationParameter),
|
|
276
|
+
requestBody: Schema3.OptionFromOptional(OperationRequestBody)
|
|
277
|
+
});
|
|
278
|
+
var HeaderValue = SecretBackedValue;
|
|
279
|
+
var ConfiguredHeaderBinding = Schema3.Struct({
|
|
280
|
+
kind: Schema3.Literal("binding"),
|
|
281
|
+
slot: Schema3.String,
|
|
282
|
+
prefix: Schema3.optional(Schema3.String)
|
|
283
|
+
}).annotate({ identifier: "OpenApiConfiguredHeaderBinding" });
|
|
284
|
+
var ConfiguredHeaderValue = Schema3.Union([Schema3.String, ConfiguredHeaderBinding]);
|
|
285
|
+
var OpenApiCredentialInput = Schema3.Union([
|
|
286
|
+
ScopedSecretCredentialInput,
|
|
287
|
+
HeaderValue,
|
|
288
|
+
ConfiguredHeaderValue
|
|
289
|
+
]);
|
|
290
|
+
var OpenApiSourceBindingValue = Schema3.Union([
|
|
291
|
+
Schema3.Struct({
|
|
292
|
+
kind: Schema3.Literal("secret"),
|
|
293
|
+
secretId: SecretId,
|
|
294
|
+
secretScopeId: Schema3.optional(ScopeId)
|
|
295
|
+
}),
|
|
296
|
+
Schema3.Struct({
|
|
297
|
+
kind: Schema3.Literal("connection"),
|
|
298
|
+
connectionId: ConnectionId
|
|
299
|
+
}),
|
|
300
|
+
Schema3.Struct({
|
|
301
|
+
kind: Schema3.Literal("text"),
|
|
302
|
+
text: Schema3.String
|
|
303
|
+
})
|
|
304
|
+
]);
|
|
305
|
+
var OpenApiSourceBindingInput = Schema3.Struct({
|
|
306
|
+
sourceId: Schema3.String,
|
|
307
|
+
sourceScope: ScopeId,
|
|
308
|
+
scope: ScopeId,
|
|
309
|
+
slot: Schema3.String,
|
|
310
|
+
value: OpenApiSourceBindingValue
|
|
311
|
+
});
|
|
312
|
+
var OpenApiSourceBindingRef = Schema3.Struct({
|
|
313
|
+
sourceId: Schema3.String,
|
|
314
|
+
sourceScopeId: ScopeId,
|
|
315
|
+
scopeId: ScopeId,
|
|
316
|
+
slot: Schema3.String,
|
|
317
|
+
value: OpenApiSourceBindingValue,
|
|
318
|
+
createdAt: Schema3.Date,
|
|
319
|
+
updatedAt: Schema3.Date
|
|
320
|
+
});
|
|
321
|
+
var OAuth2Flow = Schema3.Literals(["authorizationCode", "clientCredentials"]);
|
|
322
|
+
var OAuth2SourceConfig = Schema3.Struct({
|
|
323
|
+
kind: Schema3.Literal("oauth2"),
|
|
324
|
+
securitySchemeName: Schema3.String,
|
|
325
|
+
flow: OAuth2Flow,
|
|
326
|
+
tokenUrl: Schema3.String,
|
|
327
|
+
authorizationUrl: Schema3.NullOr(Schema3.String),
|
|
328
|
+
issuerUrl: Schema3.optional(Schema3.NullOr(Schema3.String)),
|
|
329
|
+
clientIdSlot: Schema3.String,
|
|
330
|
+
clientSecretSlot: Schema3.NullOr(Schema3.String),
|
|
331
|
+
connectionSlot: Schema3.String,
|
|
332
|
+
scopes: Schema3.Array(Schema3.String)
|
|
333
|
+
}).annotate({ identifier: "OpenApiOAuth2SourceConfig" });
|
|
334
|
+
var InvocationResult = Schema3.Struct({
|
|
335
|
+
status: Schema3.Number,
|
|
336
|
+
headers: Schema3.Record(Schema3.String, Schema3.String),
|
|
337
|
+
data: Schema3.NullOr(Schema3.Unknown),
|
|
338
|
+
error: Schema3.NullOr(Schema3.Unknown)
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// src/sdk/extract.ts
|
|
342
|
+
import { Effect as Effect2, Option as Option2 } from "effect";
|
|
343
|
+
var HTTP_METHODS = [
|
|
344
|
+
"get",
|
|
345
|
+
"put",
|
|
346
|
+
"post",
|
|
347
|
+
"delete",
|
|
348
|
+
"patch",
|
|
349
|
+
"head",
|
|
350
|
+
"options",
|
|
351
|
+
"trace"
|
|
352
|
+
];
|
|
353
|
+
var VALID_PARAM_LOCATIONS = /* @__PURE__ */ new Set(["path", "query", "header", "cookie"]);
|
|
354
|
+
var extractParameters = (pathItem, operation, r) => {
|
|
355
|
+
const merged = /* @__PURE__ */ new Map();
|
|
356
|
+
for (const raw of pathItem.parameters ?? []) {
|
|
357
|
+
const p = r.resolve(raw);
|
|
358
|
+
if (!p) continue;
|
|
359
|
+
merged.set(`${p.in}:${p.name}`, p);
|
|
360
|
+
}
|
|
361
|
+
for (const raw of operation.parameters ?? []) {
|
|
362
|
+
const p = r.resolve(raw);
|
|
363
|
+
if (!p) continue;
|
|
364
|
+
merged.set(`${p.in}:${p.name}`, p);
|
|
365
|
+
}
|
|
366
|
+
return [...merged.values()].filter((p) => VALID_PARAM_LOCATIONS.has(p.in)).map(
|
|
367
|
+
(p) => OperationParameter.make({
|
|
368
|
+
name: p.name,
|
|
369
|
+
location: p.in,
|
|
370
|
+
required: p.in === "path" ? true : p.required === true,
|
|
371
|
+
schema: Option2.fromNullishOr(p.schema),
|
|
372
|
+
style: Option2.fromNullishOr(p.style),
|
|
373
|
+
explode: Option2.fromNullishOr(p.explode),
|
|
374
|
+
allowReserved: Option2.fromNullishOr("allowReserved" in p ? p.allowReserved : void 0),
|
|
375
|
+
description: Option2.fromNullishOr(p.description)
|
|
376
|
+
})
|
|
377
|
+
);
|
|
378
|
+
};
|
|
379
|
+
var buildEncodingRecord = (encoding) => {
|
|
380
|
+
if (!encoding) return void 0;
|
|
381
|
+
const out = {};
|
|
382
|
+
for (const [prop, raw] of Object.entries(encoding)) {
|
|
383
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
384
|
+
const e = raw;
|
|
385
|
+
out[prop] = EncodingObject.make({
|
|
386
|
+
contentType: Option2.fromNullishOr(e.contentType),
|
|
387
|
+
style: Option2.fromNullishOr(e.style),
|
|
388
|
+
explode: Option2.fromNullishOr(e.explode),
|
|
389
|
+
allowReserved: Option2.fromNullishOr(e.allowReserved)
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
393
|
+
};
|
|
394
|
+
var extractRequestBody = (operation, r) => {
|
|
395
|
+
if (!operation.requestBody) return void 0;
|
|
396
|
+
const body = r.resolve(operation.requestBody);
|
|
397
|
+
if (!body) return void 0;
|
|
398
|
+
const contents = declaredContents(body.content).map(
|
|
399
|
+
({ mediaType, media }) => MediaBinding.make({
|
|
400
|
+
contentType: mediaType,
|
|
401
|
+
schema: Option2.fromNullishOr(media.schema),
|
|
402
|
+
encoding: Option2.fromNullishOr(
|
|
403
|
+
buildEncodingRecord(media.encoding)
|
|
404
|
+
)
|
|
405
|
+
})
|
|
406
|
+
);
|
|
407
|
+
if (contents.length === 0) return void 0;
|
|
408
|
+
const defaultContent = contents[0];
|
|
409
|
+
return OperationRequestBody.make({
|
|
410
|
+
required: body.required === true,
|
|
411
|
+
contentType: defaultContent.contentType,
|
|
412
|
+
schema: defaultContent.schema,
|
|
413
|
+
contents: Option2.some(contents)
|
|
414
|
+
});
|
|
415
|
+
};
|
|
416
|
+
var extractOutputSchema = (operation, r) => {
|
|
417
|
+
if (!operation.responses) return void 0;
|
|
418
|
+
const entries = Object.entries(operation.responses);
|
|
419
|
+
const preferred = [
|
|
420
|
+
...entries.filter(([s]) => /^2\d\d$/.test(s)).sort(([a], [b]) => a.localeCompare(b)),
|
|
421
|
+
...entries.filter(([s]) => s === "default")
|
|
422
|
+
];
|
|
423
|
+
for (const [, ref] of preferred) {
|
|
424
|
+
const resp = r.resolve(ref);
|
|
425
|
+
if (!resp) continue;
|
|
426
|
+
const content = preferredResponseContent(resp.content);
|
|
427
|
+
if (content?.media.schema) return content.media.schema;
|
|
428
|
+
}
|
|
429
|
+
return void 0;
|
|
430
|
+
};
|
|
431
|
+
var buildInputSchema = (parameters, requestBody) => {
|
|
432
|
+
const properties = {};
|
|
433
|
+
const required = [];
|
|
434
|
+
for (const param of parameters) {
|
|
435
|
+
properties[param.name] = Option2.getOrElse(param.schema, () => ({ type: "string" }));
|
|
436
|
+
if (param.required) required.push(param.name);
|
|
437
|
+
}
|
|
438
|
+
if (requestBody) {
|
|
439
|
+
properties.body = Option2.getOrElse(requestBody.schema, () => ({ type: "object" }));
|
|
440
|
+
if (requestBody.required) required.push("body");
|
|
441
|
+
const contents = Option2.getOrUndefined(requestBody.contents);
|
|
442
|
+
if (contents && contents.length > 1) {
|
|
443
|
+
properties.contentType = {
|
|
444
|
+
type: "string",
|
|
445
|
+
enum: contents.map((c) => c.contentType),
|
|
446
|
+
default: requestBody.contentType,
|
|
447
|
+
description: "Content-Type for the request body. Declared media types for this operation, in spec order."
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (Object.keys(properties).length === 0) return void 0;
|
|
452
|
+
return {
|
|
453
|
+
type: "object",
|
|
454
|
+
properties,
|
|
455
|
+
...required.length > 0 ? { required } : {},
|
|
456
|
+
additionalProperties: false
|
|
457
|
+
};
|
|
458
|
+
};
|
|
459
|
+
var deriveOperationId = (method, pathTemplate, operation) => operation.operationId ?? (`${method}_${pathTemplate.replace(/[^a-zA-Z0-9]+/g, "_")}`.replace(/^_+|_+$/g, "") || `${method}_operation`);
|
|
460
|
+
var extractServers = (doc) => (doc.servers ?? []).flatMap((server) => {
|
|
461
|
+
if (!server.url) return [];
|
|
462
|
+
const vars = server.variables ? Object.fromEntries(
|
|
463
|
+
Object.entries(server.variables).flatMap(([name, v]) => {
|
|
464
|
+
if (v.default === void 0 || v.default === null) return [];
|
|
465
|
+
const enumValues = Array.isArray(v.enum) ? v.enum.filter((x) => typeof x === "string") : void 0;
|
|
466
|
+
return [
|
|
467
|
+
[
|
|
468
|
+
name,
|
|
469
|
+
ServerVariable.make({
|
|
470
|
+
default: String(v.default),
|
|
471
|
+
enum: enumValues && enumValues.length > 0 ? Option2.some(enumValues) : Option2.none(),
|
|
472
|
+
description: Option2.fromNullishOr(v.description)
|
|
473
|
+
})
|
|
474
|
+
]
|
|
475
|
+
];
|
|
476
|
+
})
|
|
477
|
+
) : void 0;
|
|
478
|
+
return [
|
|
479
|
+
ServerInfo.make({
|
|
480
|
+
url: server.url,
|
|
481
|
+
description: Option2.fromNullishOr(server.description),
|
|
482
|
+
variables: vars && Object.keys(vars).length > 0 ? Option2.some(vars) : Option2.none()
|
|
483
|
+
})
|
|
484
|
+
];
|
|
485
|
+
});
|
|
486
|
+
var extract = Effect2.fn("OpenApi.extract")(function* (doc) {
|
|
487
|
+
const paths = doc.paths;
|
|
488
|
+
if (!paths) {
|
|
489
|
+
return yield* new OpenApiExtractionError({
|
|
490
|
+
message: "OpenAPI document has no paths defined"
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
const r = new DocResolver(doc);
|
|
494
|
+
const operations = [];
|
|
495
|
+
for (const [pathTemplate, pathItem] of Object.entries(paths).sort(
|
|
496
|
+
([a], [b]) => a.localeCompare(b)
|
|
497
|
+
)) {
|
|
498
|
+
if (!pathItem) continue;
|
|
499
|
+
for (const method of HTTP_METHODS) {
|
|
500
|
+
const operation = pathItem[method];
|
|
501
|
+
if (!operation) continue;
|
|
502
|
+
const parameters = extractParameters(pathItem, operation, r);
|
|
503
|
+
const requestBody = extractRequestBody(operation, r);
|
|
504
|
+
const inputSchema = buildInputSchema(parameters, requestBody);
|
|
505
|
+
const outputSchema = extractOutputSchema(operation, r);
|
|
506
|
+
const tags = (operation.tags ?? []).filter((t) => t.trim().length > 0);
|
|
507
|
+
operations.push(
|
|
508
|
+
ExtractedOperation.make({
|
|
509
|
+
operationId: OperationId.make(deriveOperationId(method, pathTemplate, operation)),
|
|
510
|
+
method,
|
|
511
|
+
pathTemplate,
|
|
512
|
+
summary: Option2.fromNullishOr(operation.summary),
|
|
513
|
+
description: Option2.fromNullishOr(operation.description),
|
|
514
|
+
tags,
|
|
515
|
+
parameters,
|
|
516
|
+
requestBody: Option2.fromNullishOr(requestBody),
|
|
517
|
+
inputSchema: Option2.fromNullishOr(inputSchema),
|
|
518
|
+
outputSchema: Option2.fromNullishOr(outputSchema),
|
|
519
|
+
deprecated: operation.deprecated === true
|
|
520
|
+
})
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return ExtractionResult.make({
|
|
525
|
+
title: Option2.fromNullishOr(doc.info?.title),
|
|
526
|
+
version: Option2.fromNullishOr(doc.info?.version),
|
|
527
|
+
servers: extractServers(doc),
|
|
528
|
+
operations
|
|
529
|
+
});
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// src/sdk/preview.ts
|
|
533
|
+
import { Effect as Effect3, Option as Option3 } from "effect";
|
|
534
|
+
import { Schema as Schema4 } from "effect";
|
|
535
|
+
var OAuth2Scopes = Schema4.Record(Schema4.String, Schema4.String);
|
|
536
|
+
var SecuritySchemeType = Schema4.Literals(["http", "apiKey", "oauth2", "openIdConnect"]);
|
|
537
|
+
var decodeSecuritySchemeType = Schema4.decodeUnknownOption(SecuritySchemeType);
|
|
538
|
+
var OAuth2AuthorizationCodeFlow = Schema4.Struct({
|
|
539
|
+
authorizationUrl: Schema4.String,
|
|
540
|
+
tokenUrl: Schema4.String,
|
|
541
|
+
refreshUrl: Schema4.OptionFromOptional(Schema4.String),
|
|
542
|
+
scopes: OAuth2Scopes
|
|
543
|
+
});
|
|
544
|
+
var OAuth2ClientCredentialsFlow = Schema4.Struct({
|
|
545
|
+
tokenUrl: Schema4.String,
|
|
546
|
+
refreshUrl: Schema4.OptionFromOptional(Schema4.String),
|
|
547
|
+
scopes: OAuth2Scopes
|
|
548
|
+
});
|
|
549
|
+
var OAuth2Flows = Schema4.Struct({
|
|
550
|
+
authorizationCode: Schema4.OptionFromOptional(OAuth2AuthorizationCodeFlow),
|
|
551
|
+
clientCredentials: Schema4.OptionFromOptional(OAuth2ClientCredentialsFlow)
|
|
552
|
+
});
|
|
553
|
+
var SecurityScheme = Schema4.Struct({
|
|
554
|
+
/** Key name in components.securitySchemes (e.g. "api_token") */
|
|
555
|
+
name: Schema4.String,
|
|
556
|
+
/** OpenAPI security scheme type */
|
|
557
|
+
type: SecuritySchemeType,
|
|
558
|
+
/** For type: "http" — e.g. "bearer", "basic" */
|
|
559
|
+
scheme: Schema4.OptionFromOptional(Schema4.String),
|
|
560
|
+
/** For type: "http" with scheme "bearer" — e.g. "JWT" */
|
|
561
|
+
bearerFormat: Schema4.OptionFromOptional(Schema4.String),
|
|
562
|
+
/** For type: "apiKey" — where the key goes */
|
|
563
|
+
in: Schema4.OptionFromOptional(Schema4.Literals(["header", "query", "cookie"])),
|
|
564
|
+
/** For type: "apiKey" — the header/query/cookie name */
|
|
565
|
+
headerName: Schema4.OptionFromOptional(Schema4.String),
|
|
566
|
+
description: Schema4.OptionFromOptional(Schema4.String),
|
|
567
|
+
/** For type: "oauth2" — declared flows (authorizationCode / clientCredentials only; implicit and password are deprecated). */
|
|
568
|
+
flows: Schema4.OptionFromOptional(OAuth2Flows),
|
|
569
|
+
/** For type: "openIdConnect" — the discovery URL. */
|
|
570
|
+
openIdConnectUrl: Schema4.OptionFromOptional(Schema4.String)
|
|
571
|
+
});
|
|
572
|
+
var AuthStrategy = Schema4.Struct({
|
|
573
|
+
/** The security schemes required together for this strategy */
|
|
574
|
+
schemes: Schema4.Array(Schema4.String)
|
|
575
|
+
});
|
|
576
|
+
var HeaderPreset = Schema4.Struct({
|
|
577
|
+
/** Human-readable label for the UI (e.g. "Bearer Token", "API Key + Email") */
|
|
578
|
+
label: Schema4.String,
|
|
579
|
+
/** Headers this strategy needs. Value is null when the user must provide it. */
|
|
580
|
+
headers: Schema4.Record(Schema4.String, Schema4.NullOr(Schema4.String)),
|
|
581
|
+
/** Which headers should be stored as secrets */
|
|
582
|
+
secretHeaders: Schema4.Array(Schema4.String)
|
|
583
|
+
});
|
|
584
|
+
var OAuth2Preset = Schema4.Struct({
|
|
585
|
+
/** Human-readable label for the UI (e.g. "OAuth2 (Authorization Code) — oauth_app") */
|
|
586
|
+
label: Schema4.String,
|
|
587
|
+
/** The source security scheme this preset came from (components.securitySchemes key). */
|
|
588
|
+
securitySchemeName: Schema4.String,
|
|
589
|
+
/** Which OAuth2 flow this preset uses. */
|
|
590
|
+
flow: Schema4.Literals(["authorizationCode", "clientCredentials"]),
|
|
591
|
+
/** For authorizationCode: user-agent redirect URL (from the spec). */
|
|
592
|
+
authorizationUrl: Schema4.OptionFromOptional(Schema4.String),
|
|
593
|
+
/** Token endpoint to exchange the code / refresh. */
|
|
594
|
+
tokenUrl: Schema4.String,
|
|
595
|
+
/** Optional refresh endpoint if the spec declares one separately. */
|
|
596
|
+
refreshUrl: Schema4.OptionFromOptional(Schema4.String),
|
|
597
|
+
/** Declared scopes for this flow: `{ scope: description }`. */
|
|
598
|
+
scopes: Schema4.Record(Schema4.String, Schema4.String)
|
|
599
|
+
});
|
|
600
|
+
var PreviewOperation = Schema4.Struct({
|
|
601
|
+
operationId: Schema4.String,
|
|
602
|
+
method: HttpMethod,
|
|
603
|
+
path: Schema4.String,
|
|
604
|
+
summary: Schema4.OptionFromOptional(Schema4.String),
|
|
605
|
+
tags: Schema4.Array(Schema4.String),
|
|
606
|
+
deprecated: Schema4.Boolean
|
|
607
|
+
});
|
|
608
|
+
var SpecPreview = Schema4.Struct({
|
|
609
|
+
title: Schema4.OptionFromOptional(Schema4.String),
|
|
610
|
+
version: Schema4.OptionFromOptional(Schema4.String),
|
|
611
|
+
/** Reuses ServerInfo from extraction */
|
|
612
|
+
servers: Schema4.Array(ServerInfo),
|
|
613
|
+
operationCount: Schema4.Number,
|
|
614
|
+
/** Lightweight operation list for the add-source UI */
|
|
615
|
+
operations: Schema4.Array(PreviewOperation),
|
|
616
|
+
tags: Schema4.Array(Schema4.String),
|
|
617
|
+
securitySchemes: Schema4.Array(SecurityScheme),
|
|
618
|
+
/** Valid auth strategies (each is a set of schemes used together) */
|
|
619
|
+
authStrategies: Schema4.Array(AuthStrategy),
|
|
620
|
+
/** Pre-built header presets derived from auth strategies */
|
|
621
|
+
headerPresets: Schema4.Array(HeaderPreset),
|
|
622
|
+
/** OAuth2 presets — one per (oauth2 scheme × supported flow) combination */
|
|
623
|
+
oauth2Presets: Schema4.Array(OAuth2Preset)
|
|
624
|
+
});
|
|
625
|
+
var stringRecord = (value) => {
|
|
626
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
627
|
+
const out = {};
|
|
628
|
+
for (const [k, v] of Object.entries(value)) {
|
|
629
|
+
if (typeof v === "string") out[k] = v;
|
|
630
|
+
}
|
|
631
|
+
return out;
|
|
632
|
+
};
|
|
633
|
+
var extractFlows = (rawFlows) => {
|
|
634
|
+
if (!rawFlows || typeof rawFlows !== "object") return Option3.none();
|
|
635
|
+
const flows = rawFlows;
|
|
636
|
+
const parseFlow = (key) => flows[key];
|
|
637
|
+
let authorizationCode = Option3.none();
|
|
638
|
+
const authCodeRaw = parseFlow("authorizationCode");
|
|
639
|
+
if (authCodeRaw && typeof authCodeRaw === "object") {
|
|
640
|
+
const f = authCodeRaw;
|
|
641
|
+
const authUrl = typeof f.authorizationUrl === "string" ? f.authorizationUrl : null;
|
|
642
|
+
const tokenUrl = typeof f.tokenUrl === "string" ? f.tokenUrl : null;
|
|
643
|
+
if (authUrl && tokenUrl) {
|
|
644
|
+
authorizationCode = Option3.some(
|
|
645
|
+
OAuth2AuthorizationCodeFlow.make({
|
|
646
|
+
authorizationUrl: authUrl,
|
|
647
|
+
tokenUrl,
|
|
648
|
+
refreshUrl: Option3.fromNullishOr(
|
|
649
|
+
typeof f.refreshUrl === "string" ? f.refreshUrl : void 0
|
|
650
|
+
),
|
|
651
|
+
scopes: stringRecord(f.scopes)
|
|
652
|
+
})
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
let clientCredentials = Option3.none();
|
|
657
|
+
const ccRaw = parseFlow("clientCredentials");
|
|
658
|
+
if (ccRaw && typeof ccRaw === "object") {
|
|
659
|
+
const f = ccRaw;
|
|
660
|
+
const tokenUrl = typeof f.tokenUrl === "string" ? f.tokenUrl : null;
|
|
661
|
+
if (tokenUrl) {
|
|
662
|
+
clientCredentials = Option3.some(
|
|
663
|
+
OAuth2ClientCredentialsFlow.make({
|
|
664
|
+
tokenUrl,
|
|
665
|
+
refreshUrl: Option3.fromNullishOr(
|
|
666
|
+
typeof f.refreshUrl === "string" ? f.refreshUrl : void 0
|
|
667
|
+
),
|
|
668
|
+
scopes: stringRecord(f.scopes)
|
|
669
|
+
})
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if (Option3.isNone(authorizationCode) && Option3.isNone(clientCredentials)) {
|
|
674
|
+
return Option3.none();
|
|
675
|
+
}
|
|
676
|
+
return Option3.some(OAuth2Flows.make({ authorizationCode, clientCredentials }));
|
|
677
|
+
};
|
|
678
|
+
var extractSecuritySchemes = (rawSchemes, resolver) => Object.entries(rawSchemes).flatMap(([name, schemeOrRef]) => {
|
|
679
|
+
if (!schemeOrRef || typeof schemeOrRef !== "object") return [];
|
|
680
|
+
const resolved = resolver.resolve(
|
|
681
|
+
schemeOrRef
|
|
682
|
+
);
|
|
683
|
+
if (!resolved || typeof resolved !== "object") return [];
|
|
684
|
+
const scheme = resolved;
|
|
685
|
+
const type = decodeSecuritySchemeType(scheme.type);
|
|
686
|
+
if (Option3.isNone(type)) return [];
|
|
687
|
+
const schemeType = type.value;
|
|
688
|
+
return [
|
|
689
|
+
SecurityScheme.make({
|
|
690
|
+
name,
|
|
691
|
+
type: schemeType,
|
|
692
|
+
scheme: Option3.fromNullishOr(scheme.scheme),
|
|
693
|
+
bearerFormat: Option3.fromNullishOr(scheme.bearerFormat),
|
|
694
|
+
in: Option3.fromNullishOr(scheme.in),
|
|
695
|
+
headerName: Option3.fromNullishOr(scheme.name),
|
|
696
|
+
description: Option3.fromNullishOr(scheme.description),
|
|
697
|
+
flows: schemeType === "oauth2" ? extractFlows(scheme.flows) : Option3.none(),
|
|
698
|
+
openIdConnectUrl: Option3.fromNullishOr(scheme.openIdConnectUrl)
|
|
699
|
+
})
|
|
700
|
+
];
|
|
701
|
+
});
|
|
702
|
+
var buildHeaderPresets = (schemes, strategies) => {
|
|
703
|
+
const schemeMap = new Map(schemes.map((s) => [s.name, s]));
|
|
704
|
+
return strategies.flatMap((strategy) => {
|
|
705
|
+
const resolved = strategy.schemes.map((name) => schemeMap.get(name)).filter((s) => s !== void 0);
|
|
706
|
+
if (resolved.length === 0) return [];
|
|
707
|
+
const headers = {};
|
|
708
|
+
const secretHeaders = [];
|
|
709
|
+
const labelParts = [];
|
|
710
|
+
for (const scheme of resolved) {
|
|
711
|
+
if (scheme.type === "http" && Option3.getOrElse(scheme.scheme, () => "") === "bearer") {
|
|
712
|
+
headers["Authorization"] = null;
|
|
713
|
+
secretHeaders.push("Authorization");
|
|
714
|
+
labelParts.push("Bearer Token");
|
|
715
|
+
} else if (scheme.type === "http" && Option3.getOrElse(scheme.scheme, () => "") === "basic") {
|
|
716
|
+
headers["Authorization"] = null;
|
|
717
|
+
secretHeaders.push("Authorization");
|
|
718
|
+
labelParts.push("Basic Auth");
|
|
719
|
+
} else if (scheme.type === "apiKey" && Option3.getOrElse(scheme.in, () => "") === "header") {
|
|
720
|
+
const headerName = Option3.getOrElse(scheme.headerName, () => scheme.name);
|
|
721
|
+
headers[headerName] = null;
|
|
722
|
+
secretHeaders.push(headerName);
|
|
723
|
+
labelParts.push(scheme.name);
|
|
724
|
+
} else if (scheme.type === "apiKey") {
|
|
725
|
+
labelParts.push(`${scheme.name} (${Option3.getOrElse(scheme.in, () => "unknown")})`);
|
|
726
|
+
} else if (scheme.type === "oauth2" || scheme.type === "openIdConnect") {
|
|
727
|
+
return [];
|
|
728
|
+
} else {
|
|
729
|
+
labelParts.push(scheme.name);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
if (Object.keys(headers).length === 0 && resolved.length > 0) {
|
|
733
|
+
return [
|
|
734
|
+
HeaderPreset.make({
|
|
735
|
+
label: labelParts.join(" + "),
|
|
736
|
+
headers: {},
|
|
737
|
+
secretHeaders: []
|
|
738
|
+
})
|
|
739
|
+
];
|
|
740
|
+
}
|
|
741
|
+
return [
|
|
742
|
+
HeaderPreset.make({
|
|
743
|
+
label: labelParts.join(" + "),
|
|
744
|
+
headers,
|
|
745
|
+
secretHeaders
|
|
746
|
+
})
|
|
747
|
+
];
|
|
748
|
+
});
|
|
749
|
+
};
|
|
750
|
+
var buildOAuth2Presets = (schemes) => {
|
|
751
|
+
const presets = [];
|
|
752
|
+
for (const scheme of schemes) {
|
|
753
|
+
if (scheme.type !== "oauth2") continue;
|
|
754
|
+
if (Option3.isNone(scheme.flows)) continue;
|
|
755
|
+
const flows = scheme.flows.value;
|
|
756
|
+
if (Option3.isSome(flows.authorizationCode)) {
|
|
757
|
+
const flow = flows.authorizationCode.value;
|
|
758
|
+
presets.push(
|
|
759
|
+
OAuth2Preset.make({
|
|
760
|
+
label: `OAuth2 Authorization Code \xB7 ${scheme.name}`,
|
|
761
|
+
securitySchemeName: scheme.name,
|
|
762
|
+
flow: "authorizationCode",
|
|
763
|
+
authorizationUrl: Option3.some(flow.authorizationUrl),
|
|
764
|
+
tokenUrl: flow.tokenUrl,
|
|
765
|
+
refreshUrl: flow.refreshUrl,
|
|
766
|
+
scopes: flow.scopes
|
|
767
|
+
})
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
if (Option3.isSome(flows.clientCredentials)) {
|
|
771
|
+
const flow = flows.clientCredentials.value;
|
|
772
|
+
presets.push(
|
|
773
|
+
OAuth2Preset.make({
|
|
774
|
+
label: `OAuth2 Client Credentials \xB7 ${scheme.name}`,
|
|
775
|
+
securitySchemeName: scheme.name,
|
|
776
|
+
flow: "clientCredentials",
|
|
777
|
+
authorizationUrl: Option3.none(),
|
|
778
|
+
tokenUrl: flow.tokenUrl,
|
|
779
|
+
refreshUrl: flow.refreshUrl,
|
|
780
|
+
scopes: flow.scopes
|
|
781
|
+
})
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
return presets;
|
|
786
|
+
};
|
|
787
|
+
var collectTags = (result) => {
|
|
788
|
+
const tagSet = /* @__PURE__ */ new Set();
|
|
789
|
+
for (const op of result.operations) {
|
|
790
|
+
for (const tag of op.tags) tagSet.add(tag);
|
|
791
|
+
}
|
|
792
|
+
return [...tagSet].sort();
|
|
793
|
+
};
|
|
794
|
+
var previewSpec = Effect3.fn("OpenApi.previewSpec")(function* (input) {
|
|
795
|
+
const specText = yield* resolveSpecText(input);
|
|
796
|
+
const doc = yield* parse(specText);
|
|
797
|
+
const result = yield* extract(doc);
|
|
798
|
+
const resolver = new DocResolver(doc);
|
|
799
|
+
const securitySchemes = extractSecuritySchemes(doc.components?.securitySchemes ?? {}, resolver);
|
|
800
|
+
const rawSecurity = doc.security ?? [];
|
|
801
|
+
const declaredStrategies = rawSecurity.map(
|
|
802
|
+
(entry) => AuthStrategy.make({ schemes: Object.keys(entry) })
|
|
803
|
+
);
|
|
804
|
+
const authStrategies = declaredStrategies.length > 0 ? declaredStrategies : securitySchemes.map((scheme) => AuthStrategy.make({ schemes: [scheme.name] }));
|
|
805
|
+
return SpecPreview.make({
|
|
806
|
+
title: result.title,
|
|
807
|
+
version: result.version,
|
|
808
|
+
servers: result.servers,
|
|
809
|
+
operationCount: result.operations.length,
|
|
810
|
+
operations: result.operations.map(
|
|
811
|
+
(op) => PreviewOperation.make({
|
|
812
|
+
operationId: op.operationId,
|
|
813
|
+
method: op.method,
|
|
814
|
+
path: op.pathTemplate,
|
|
815
|
+
summary: op.summary,
|
|
816
|
+
tags: op.tags,
|
|
817
|
+
deprecated: op.deprecated
|
|
818
|
+
})
|
|
819
|
+
),
|
|
820
|
+
tags: collectTags(result),
|
|
821
|
+
securitySchemes,
|
|
822
|
+
authStrategies,
|
|
823
|
+
headerPresets: buildHeaderPresets(securitySchemes, authStrategies),
|
|
824
|
+
oauth2Presets: buildOAuth2Presets(securitySchemes)
|
|
825
|
+
});
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
// src/sdk/store.ts
|
|
829
|
+
import { Effect as Effect4, Option as Option4, Schema as Schema5 } from "effect";
|
|
830
|
+
import { defineSchema } from "@executor-js/sdk/core";
|
|
831
|
+
var openapiSchema = defineSchema({
|
|
832
|
+
openapi_source: {
|
|
833
|
+
fields: {
|
|
834
|
+
id: { type: "string", required: true },
|
|
835
|
+
scope_id: { type: "string", required: true, index: true },
|
|
836
|
+
name: { type: "string", required: true },
|
|
837
|
+
spec: { type: "string", required: true },
|
|
838
|
+
// Origin URL the spec was fetched from. Set when `addSpec` was
|
|
839
|
+
// invoked with an http(s) URL; null when the caller passed raw
|
|
840
|
+
// spec text. Drives `canRefresh` on the core source row and
|
|
841
|
+
// is the address re-fetched on `refreshSource`.
|
|
842
|
+
source_url: { type: "string", required: false },
|
|
843
|
+
base_url: { type: "string", required: false },
|
|
844
|
+
// OAuth2 stays JSON because it is one typed source-owned config object
|
|
845
|
+
// carrying slot names, not concrete secret/connection ids.
|
|
846
|
+
oauth2: { type: "json", required: false }
|
|
847
|
+
}
|
|
848
|
+
},
|
|
849
|
+
openapi_operation: {
|
|
850
|
+
fields: {
|
|
851
|
+
id: { type: "string", required: true },
|
|
852
|
+
scope_id: { type: "string", required: true, index: true },
|
|
853
|
+
source_id: { type: "string", required: true, index: true },
|
|
854
|
+
binding: { type: "json", required: true }
|
|
855
|
+
}
|
|
856
|
+
},
|
|
857
|
+
openapi_source_header: {
|
|
858
|
+
fields: {
|
|
859
|
+
id: { type: "string", required: true },
|
|
860
|
+
scope_id: { type: "string", required: true, index: true },
|
|
861
|
+
source_id: { type: "string", required: true, index: true },
|
|
862
|
+
name: { type: "string", required: true },
|
|
863
|
+
kind: { type: ["text", "binding"], required: true },
|
|
864
|
+
text_value: { type: "string", required: false },
|
|
865
|
+
slot_key: { type: "string", required: false },
|
|
866
|
+
prefix: { type: "string", required: false }
|
|
867
|
+
}
|
|
868
|
+
},
|
|
869
|
+
openapi_source_query_param: {
|
|
870
|
+
fields: {
|
|
871
|
+
id: { type: "string", required: true },
|
|
872
|
+
scope_id: { type: "string", required: true, index: true },
|
|
873
|
+
source_id: { type: "string", required: true, index: true },
|
|
874
|
+
name: { type: "string", required: true },
|
|
875
|
+
kind: { type: ["text", "binding"], required: true },
|
|
876
|
+
text_value: { type: "string", required: false },
|
|
877
|
+
slot_key: { type: "string", required: false },
|
|
878
|
+
prefix: { type: "string", required: false }
|
|
879
|
+
}
|
|
880
|
+
},
|
|
881
|
+
openapi_source_spec_fetch_header: {
|
|
882
|
+
fields: {
|
|
883
|
+
id: { type: "string", required: true },
|
|
884
|
+
scope_id: { type: "string", required: true, index: true },
|
|
885
|
+
source_id: { type: "string", required: true, index: true },
|
|
886
|
+
name: { type: "string", required: true },
|
|
887
|
+
kind: { type: ["text", "binding"], required: true },
|
|
888
|
+
text_value: { type: "string", required: false },
|
|
889
|
+
slot_key: { type: "string", required: false },
|
|
890
|
+
prefix: { type: "string", required: false }
|
|
891
|
+
}
|
|
892
|
+
},
|
|
893
|
+
openapi_source_spec_fetch_query_param: {
|
|
894
|
+
fields: {
|
|
895
|
+
id: { type: "string", required: true },
|
|
896
|
+
scope_id: { type: "string", required: true, index: true },
|
|
897
|
+
source_id: { type: "string", required: true, index: true },
|
|
898
|
+
name: { type: "string", required: true },
|
|
899
|
+
kind: { type: ["text", "binding"], required: true },
|
|
900
|
+
text_value: { type: "string", required: false },
|
|
901
|
+
slot_key: { type: "string", required: false },
|
|
902
|
+
prefix: { type: "string", required: false }
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
var StoredSourceSchema = Schema5.Struct({
|
|
907
|
+
namespace: Schema5.String,
|
|
908
|
+
scope: Schema5.String,
|
|
909
|
+
name: Schema5.String,
|
|
910
|
+
config: Schema5.Struct({
|
|
911
|
+
spec: Schema5.String,
|
|
912
|
+
sourceUrl: Schema5.optional(Schema5.String),
|
|
913
|
+
baseUrl: Schema5.optional(Schema5.String),
|
|
914
|
+
namespace: Schema5.optional(Schema5.String),
|
|
915
|
+
headers: Schema5.optional(Schema5.Record(Schema5.String, ConfiguredHeaderValue)),
|
|
916
|
+
queryParams: Schema5.optional(Schema5.Record(Schema5.String, ConfiguredHeaderValue)),
|
|
917
|
+
specFetchCredentials: Schema5.optional(
|
|
918
|
+
Schema5.Struct({
|
|
919
|
+
headers: Schema5.optional(Schema5.Record(Schema5.String, ConfiguredHeaderValue)),
|
|
920
|
+
queryParams: Schema5.optional(Schema5.Record(Schema5.String, ConfiguredHeaderValue))
|
|
921
|
+
})
|
|
922
|
+
),
|
|
923
|
+
// Canonical source-owned OAuth config. Concrete client credentials
|
|
924
|
+
// and connection ids live in OpenAPI-owned scoped binding rows.
|
|
925
|
+
oauth2: Schema5.optional(OAuth2SourceConfig)
|
|
926
|
+
})
|
|
927
|
+
}).annotate({ identifier: "OpenApiStoredSource" });
|
|
928
|
+
var encodeBinding = Schema5.encodeSync(OperationBinding);
|
|
929
|
+
var decodeBinding = Schema5.decodeUnknownSync(OperationBinding);
|
|
930
|
+
var decodeBindingJson = Schema5.decodeUnknownSync(Schema5.fromJsonString(OperationBinding));
|
|
931
|
+
var decodeOAuth2SourceConfigOption = Schema5.decodeUnknownOption(OAuth2SourceConfig);
|
|
932
|
+
var decodeOAuth2SourceConfigJsonOption = Schema5.decodeUnknownOption(
|
|
933
|
+
Schema5.fromJsonString(OAuth2SourceConfig)
|
|
934
|
+
);
|
|
935
|
+
var encodeOAuth2SourceConfig = Schema5.encodeSync(OAuth2SourceConfig);
|
|
936
|
+
var NullableString = Schema5.NullOr(Schema5.String);
|
|
937
|
+
var OptionalNullableString = Schema5.optional(NullableString);
|
|
938
|
+
var ChildStorageRow = Schema5.Struct({
|
|
939
|
+
name: Schema5.String,
|
|
940
|
+
kind: Schema5.Literals(["text", "binding"]),
|
|
941
|
+
text_value: OptionalNullableString,
|
|
942
|
+
slot_key: OptionalNullableString,
|
|
943
|
+
prefix: OptionalNullableString
|
|
944
|
+
});
|
|
945
|
+
var decodeChildStorageRowOption = Schema5.decodeUnknownOption(ChildStorageRow);
|
|
946
|
+
var SourceStorageRow = Schema5.Struct({
|
|
947
|
+
id: Schema5.String,
|
|
948
|
+
scope_id: Schema5.String,
|
|
949
|
+
name: Schema5.String,
|
|
950
|
+
spec: Schema5.String,
|
|
951
|
+
source_url: OptionalNullableString,
|
|
952
|
+
base_url: OptionalNullableString,
|
|
953
|
+
oauth2: Schema5.optional(Schema5.Unknown)
|
|
954
|
+
});
|
|
955
|
+
var decodeSourceStorageRow = Schema5.decodeUnknownSync(SourceStorageRow);
|
|
956
|
+
var OperationStorageRow = Schema5.Struct({
|
|
957
|
+
id: Schema5.String,
|
|
958
|
+
source_id: Schema5.String,
|
|
959
|
+
binding: Schema5.Unknown
|
|
960
|
+
});
|
|
961
|
+
var decodeOperationStorageRow = Schema5.decodeUnknownSync(OperationStorageRow);
|
|
962
|
+
var valueMapToChildRows = (sourceId, scope, values) => {
|
|
963
|
+
if (!values) return [];
|
|
964
|
+
return Object.entries(values).map(([name, value]) => {
|
|
965
|
+
const id = JSON.stringify([sourceId, name]);
|
|
966
|
+
if (typeof value === "string") {
|
|
967
|
+
return {
|
|
968
|
+
id,
|
|
969
|
+
scope_id: scope,
|
|
970
|
+
source_id: sourceId,
|
|
971
|
+
name,
|
|
972
|
+
kind: "text",
|
|
973
|
+
text_value: value
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
return {
|
|
977
|
+
id,
|
|
978
|
+
scope_id: scope,
|
|
979
|
+
source_id: sourceId,
|
|
980
|
+
name,
|
|
981
|
+
kind: "binding",
|
|
982
|
+
slot_key: value.slot,
|
|
983
|
+
prefix: value.prefix
|
|
984
|
+
};
|
|
985
|
+
});
|
|
986
|
+
};
|
|
987
|
+
var childRowsToValueMap = (rows) => {
|
|
988
|
+
const out = {};
|
|
989
|
+
for (const row of rows) {
|
|
990
|
+
const decoded = decodeChildStorageRowOption(row);
|
|
991
|
+
if (Option4.isSome(decoded)) {
|
|
992
|
+
const child = decoded.value;
|
|
993
|
+
if (child.kind === "binding" && child.slot_key != null) {
|
|
994
|
+
out[child.name] = child.prefix != null ? ConfiguredHeaderBinding.make({
|
|
995
|
+
kind: "binding",
|
|
996
|
+
slot: child.slot_key,
|
|
997
|
+
prefix: child.prefix
|
|
998
|
+
}) : ConfiguredHeaderBinding.make({
|
|
999
|
+
kind: "binding",
|
|
1000
|
+
slot: child.slot_key
|
|
1001
|
+
});
|
|
1002
|
+
} else if (child.kind === "text" && child.text_value != null) {
|
|
1003
|
+
out[child.name] = child.text_value;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return out;
|
|
1008
|
+
};
|
|
1009
|
+
var toJsonRecord = (value) => value;
|
|
1010
|
+
var slugifySlotPart = (value) => value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "default";
|
|
1011
|
+
var headerBindingSlot = (headerName) => `header:${slugifySlotPart(headerName)}`;
|
|
1012
|
+
var queryParamBindingSlot = (name) => `query_param:${slugifySlotPart(name)}`;
|
|
1013
|
+
var oauth2ClientIdSlot = (securitySchemeName) => `oauth2:${slugifySlotPart(securitySchemeName)}:client-id`;
|
|
1014
|
+
var oauth2ClientSecretSlot = (securitySchemeName) => `oauth2:${slugifySlotPart(securitySchemeName)}:client-secret`;
|
|
1015
|
+
var oauth2ConnectionSlot = (securitySchemeName) => `oauth2:${slugifySlotPart(securitySchemeName)}:connection`;
|
|
1016
|
+
var normalizeStoredOAuth2 = (value) => {
|
|
1017
|
+
if (value == null) return void 0;
|
|
1018
|
+
const sourceConfig = typeof value === "string" ? decodeOAuth2SourceConfigJsonOption(value) : decodeOAuth2SourceConfigOption(value);
|
|
1019
|
+
if (Option4.isSome(sourceConfig)) {
|
|
1020
|
+
return sourceConfig.value;
|
|
1021
|
+
}
|
|
1022
|
+
return void 0;
|
|
1023
|
+
};
|
|
1024
|
+
var makeDefaultOpenapiStore = ({ adapter }) => {
|
|
1025
|
+
const loadChildValueMap = (model, sourceId, scope) => adapter.findMany({
|
|
1026
|
+
model,
|
|
1027
|
+
where: [
|
|
1028
|
+
{ field: "source_id", value: sourceId },
|
|
1029
|
+
{ field: "scope_id", value: scope }
|
|
1030
|
+
]
|
|
1031
|
+
}).pipe(Effect4.map(childRowsToValueMap));
|
|
1032
|
+
const rowToSource = (row) => Effect4.gen(function* () {
|
|
1033
|
+
const sourceRow = decodeSourceStorageRow(row);
|
|
1034
|
+
const sourceId = sourceRow.id;
|
|
1035
|
+
const scope = sourceRow.scope_id;
|
|
1036
|
+
const oauth2 = normalizeStoredOAuth2(sourceRow.oauth2);
|
|
1037
|
+
const headers = yield* loadChildValueMap("openapi_source_header", sourceId, scope);
|
|
1038
|
+
const queryParams = yield* loadChildValueMap("openapi_source_query_param", sourceId, scope);
|
|
1039
|
+
const specFetchHeaders = yield* loadChildValueMap(
|
|
1040
|
+
"openapi_source_spec_fetch_header",
|
|
1041
|
+
sourceId,
|
|
1042
|
+
scope
|
|
1043
|
+
);
|
|
1044
|
+
const specFetchQueryParams = yield* loadChildValueMap(
|
|
1045
|
+
"openapi_source_spec_fetch_query_param",
|
|
1046
|
+
sourceId,
|
|
1047
|
+
scope
|
|
1048
|
+
);
|
|
1049
|
+
const specFetchCredentials = Object.keys(specFetchHeaders).length === 0 && Object.keys(specFetchQueryParams).length === 0 ? void 0 : {
|
|
1050
|
+
...Object.keys(specFetchHeaders).length > 0 ? { headers: specFetchHeaders } : {},
|
|
1051
|
+
...Object.keys(specFetchQueryParams).length > 0 ? { queryParams: specFetchQueryParams } : {}
|
|
1052
|
+
};
|
|
1053
|
+
return {
|
|
1054
|
+
namespace: sourceId,
|
|
1055
|
+
scope,
|
|
1056
|
+
name: sourceRow.name,
|
|
1057
|
+
config: {
|
|
1058
|
+
spec: sourceRow.spec,
|
|
1059
|
+
sourceUrl: sourceRow.source_url ?? void 0,
|
|
1060
|
+
baseUrl: sourceRow.base_url ?? void 0,
|
|
1061
|
+
headers,
|
|
1062
|
+
queryParams,
|
|
1063
|
+
specFetchCredentials,
|
|
1064
|
+
oauth2
|
|
1065
|
+
}
|
|
1066
|
+
};
|
|
1067
|
+
});
|
|
1068
|
+
const rowToOperation = (row) => {
|
|
1069
|
+
const operationRow = decodeOperationStorageRow(row);
|
|
1070
|
+
return {
|
|
1071
|
+
toolId: operationRow.id,
|
|
1072
|
+
sourceId: operationRow.source_id,
|
|
1073
|
+
binding: decodeBinding(
|
|
1074
|
+
typeof operationRow.binding === "string" ? decodeBindingJson(operationRow.binding) : operationRow.binding
|
|
1075
|
+
)
|
|
1076
|
+
};
|
|
1077
|
+
};
|
|
1078
|
+
const replaceChildRows = (model, sourceId, scope, values) => Effect4.gen(function* () {
|
|
1079
|
+
yield* adapter.deleteMany({
|
|
1080
|
+
model,
|
|
1081
|
+
where: [
|
|
1082
|
+
{ field: "source_id", value: sourceId },
|
|
1083
|
+
{ field: "scope_id", value: scope }
|
|
1084
|
+
]
|
|
1085
|
+
});
|
|
1086
|
+
const rows = valueMapToChildRows(sourceId, scope, values);
|
|
1087
|
+
if (rows.length === 0) return;
|
|
1088
|
+
yield* adapter.createMany({
|
|
1089
|
+
model,
|
|
1090
|
+
data: rows,
|
|
1091
|
+
forceAllowId: true
|
|
1092
|
+
});
|
|
1093
|
+
});
|
|
1094
|
+
const deleteSource = (namespace, scope) => Effect4.gen(function* () {
|
|
1095
|
+
yield* adapter.deleteMany({
|
|
1096
|
+
model: "openapi_operation",
|
|
1097
|
+
where: [
|
|
1098
|
+
{ field: "source_id", value: namespace },
|
|
1099
|
+
{ field: "scope_id", value: scope }
|
|
1100
|
+
]
|
|
1101
|
+
});
|
|
1102
|
+
for (const model of [
|
|
1103
|
+
"openapi_source_header",
|
|
1104
|
+
"openapi_source_query_param",
|
|
1105
|
+
"openapi_source_spec_fetch_header",
|
|
1106
|
+
"openapi_source_spec_fetch_query_param"
|
|
1107
|
+
]) {
|
|
1108
|
+
yield* adapter.deleteMany({
|
|
1109
|
+
model,
|
|
1110
|
+
where: [
|
|
1111
|
+
{ field: "source_id", value: namespace },
|
|
1112
|
+
{ field: "scope_id", value: scope }
|
|
1113
|
+
]
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
yield* adapter.delete({
|
|
1117
|
+
model: "openapi_source",
|
|
1118
|
+
where: [
|
|
1119
|
+
{ field: "id", value: namespace },
|
|
1120
|
+
{ field: "scope_id", value: scope }
|
|
1121
|
+
]
|
|
1122
|
+
});
|
|
1123
|
+
});
|
|
1124
|
+
return {
|
|
1125
|
+
upsertSource: (input, operations) => Effect4.gen(function* () {
|
|
1126
|
+
yield* deleteSource(input.namespace, input.scope);
|
|
1127
|
+
yield* adapter.create({
|
|
1128
|
+
model: "openapi_source",
|
|
1129
|
+
data: {
|
|
1130
|
+
id: input.namespace,
|
|
1131
|
+
scope_id: input.scope,
|
|
1132
|
+
name: input.name,
|
|
1133
|
+
spec: input.config.spec,
|
|
1134
|
+
source_url: input.config.sourceUrl ?? void 0,
|
|
1135
|
+
base_url: input.config.baseUrl ?? void 0,
|
|
1136
|
+
oauth2: input.config.oauth2 ? toJsonRecord(encodeOAuth2SourceConfig(input.config.oauth2)) : void 0
|
|
1137
|
+
},
|
|
1138
|
+
forceAllowId: true
|
|
1139
|
+
});
|
|
1140
|
+
yield* replaceChildRows(
|
|
1141
|
+
"openapi_source_header",
|
|
1142
|
+
input.namespace,
|
|
1143
|
+
input.scope,
|
|
1144
|
+
input.config.headers
|
|
1145
|
+
);
|
|
1146
|
+
yield* replaceChildRows(
|
|
1147
|
+
"openapi_source_query_param",
|
|
1148
|
+
input.namespace,
|
|
1149
|
+
input.scope,
|
|
1150
|
+
input.config.queryParams
|
|
1151
|
+
);
|
|
1152
|
+
yield* replaceChildRows(
|
|
1153
|
+
"openapi_source_spec_fetch_header",
|
|
1154
|
+
input.namespace,
|
|
1155
|
+
input.scope,
|
|
1156
|
+
input.config.specFetchCredentials?.headers
|
|
1157
|
+
);
|
|
1158
|
+
yield* replaceChildRows(
|
|
1159
|
+
"openapi_source_spec_fetch_query_param",
|
|
1160
|
+
input.namespace,
|
|
1161
|
+
input.scope,
|
|
1162
|
+
input.config.specFetchCredentials?.queryParams
|
|
1163
|
+
);
|
|
1164
|
+
if (operations.length > 0) {
|
|
1165
|
+
yield* adapter.createMany({
|
|
1166
|
+
model: "openapi_operation",
|
|
1167
|
+
data: operations.map((op) => ({
|
|
1168
|
+
id: op.toolId,
|
|
1169
|
+
scope_id: input.scope,
|
|
1170
|
+
source_id: op.sourceId,
|
|
1171
|
+
binding: toJsonRecord(encodeBinding(op.binding))
|
|
1172
|
+
})),
|
|
1173
|
+
forceAllowId: true
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
}),
|
|
1177
|
+
updateSourceMeta: (namespace, scope, patch) => Effect4.gen(function* () {
|
|
1178
|
+
const existingRow = yield* adapter.findOne({
|
|
1179
|
+
model: "openapi_source",
|
|
1180
|
+
where: [
|
|
1181
|
+
{ field: "id", value: namespace },
|
|
1182
|
+
{ field: "scope_id", value: scope }
|
|
1183
|
+
]
|
|
1184
|
+
});
|
|
1185
|
+
if (!existingRow) return;
|
|
1186
|
+
const existing = yield* rowToSource(existingRow);
|
|
1187
|
+
const nextName = patch.name?.trim() || existing.name;
|
|
1188
|
+
const nextBaseUrl = patch.baseUrl !== void 0 ? patch.baseUrl : existing.config.baseUrl;
|
|
1189
|
+
const nextOAuth2 = patch.oauth2 !== void 0 ? patch.oauth2 : existing.config.oauth2;
|
|
1190
|
+
yield* adapter.update({
|
|
1191
|
+
model: "openapi_source",
|
|
1192
|
+
where: [
|
|
1193
|
+
{ field: "id", value: namespace },
|
|
1194
|
+
{ field: "scope_id", value: scope }
|
|
1195
|
+
],
|
|
1196
|
+
update: {
|
|
1197
|
+
name: nextName,
|
|
1198
|
+
base_url: nextBaseUrl ?? void 0,
|
|
1199
|
+
oauth2: nextOAuth2 ? toJsonRecord(encodeOAuth2SourceConfig(nextOAuth2)) : void 0
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
if (patch.headers !== void 0) {
|
|
1203
|
+
yield* replaceChildRows("openapi_source_header", namespace, scope, patch.headers);
|
|
1204
|
+
}
|
|
1205
|
+
if (patch.queryParams !== void 0) {
|
|
1206
|
+
yield* replaceChildRows(
|
|
1207
|
+
"openapi_source_query_param",
|
|
1208
|
+
namespace,
|
|
1209
|
+
scope,
|
|
1210
|
+
patch.queryParams
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
}),
|
|
1214
|
+
getSource: (namespace, scope) => Effect4.gen(function* () {
|
|
1215
|
+
const row = yield* adapter.findOne({
|
|
1216
|
+
model: "openapi_source",
|
|
1217
|
+
where: [
|
|
1218
|
+
{ field: "id", value: namespace },
|
|
1219
|
+
{ field: "scope_id", value: scope }
|
|
1220
|
+
]
|
|
1221
|
+
});
|
|
1222
|
+
if (!row) return null;
|
|
1223
|
+
return yield* rowToSource(row);
|
|
1224
|
+
}),
|
|
1225
|
+
listSources: () => Effect4.gen(function* () {
|
|
1226
|
+
const rows = yield* adapter.findMany({ model: "openapi_source" });
|
|
1227
|
+
return yield* Effect4.forEach(rows, rowToSource, {
|
|
1228
|
+
concurrency: "unbounded"
|
|
1229
|
+
});
|
|
1230
|
+
}),
|
|
1231
|
+
getOperationByToolId: (toolId, scope) => adapter.findOne({
|
|
1232
|
+
model: "openapi_operation",
|
|
1233
|
+
where: [
|
|
1234
|
+
{ field: "id", value: toolId },
|
|
1235
|
+
{ field: "scope_id", value: scope }
|
|
1236
|
+
]
|
|
1237
|
+
}).pipe(Effect4.map((row) => row ? rowToOperation(row) : null)),
|
|
1238
|
+
listOperationsBySource: (sourceId, scope) => adapter.findMany({
|
|
1239
|
+
model: "openapi_operation",
|
|
1240
|
+
where: [
|
|
1241
|
+
{ field: "source_id", value: sourceId },
|
|
1242
|
+
{ field: "scope_id", value: scope }
|
|
1243
|
+
]
|
|
1244
|
+
}).pipe(Effect4.map((rows) => rows.map(rowToOperation))),
|
|
1245
|
+
removeSource: (namespace, scope) => deleteSource(namespace, scope)
|
|
1246
|
+
};
|
|
1247
|
+
};
|
|
1248
|
+
|
|
1249
|
+
export {
|
|
1250
|
+
OpenApiParseError,
|
|
1251
|
+
OpenApiExtractionError,
|
|
1252
|
+
OpenApiInvocationError,
|
|
1253
|
+
OpenApiOAuthError,
|
|
1254
|
+
fetchSpecText,
|
|
1255
|
+
resolveSpecText,
|
|
1256
|
+
parse,
|
|
1257
|
+
DocResolver,
|
|
1258
|
+
substituteUrlVariables,
|
|
1259
|
+
expandServerUrlOptions,
|
|
1260
|
+
resolveBaseUrl,
|
|
1261
|
+
preferredContent,
|
|
1262
|
+
OperationId,
|
|
1263
|
+
HttpMethod,
|
|
1264
|
+
ParameterLocation,
|
|
1265
|
+
OperationParameter,
|
|
1266
|
+
EncodingObject,
|
|
1267
|
+
MediaBinding,
|
|
1268
|
+
OperationRequestBody,
|
|
1269
|
+
ExtractedOperation,
|
|
1270
|
+
ServerVariable,
|
|
1271
|
+
ServerInfo,
|
|
1272
|
+
ExtractionResult,
|
|
1273
|
+
OperationBinding,
|
|
1274
|
+
HeaderValue,
|
|
1275
|
+
ConfiguredHeaderBinding,
|
|
1276
|
+
ConfiguredHeaderValue,
|
|
1277
|
+
OpenApiCredentialInput,
|
|
1278
|
+
OpenApiSourceBindingValue,
|
|
1279
|
+
OpenApiSourceBindingInput,
|
|
1280
|
+
OpenApiSourceBindingRef,
|
|
1281
|
+
OAuth2SourceConfig,
|
|
1282
|
+
InvocationResult,
|
|
1283
|
+
extract,
|
|
1284
|
+
OAuth2AuthorizationCodeFlow,
|
|
1285
|
+
OAuth2ClientCredentialsFlow,
|
|
1286
|
+
OAuth2Flows,
|
|
1287
|
+
SecurityScheme,
|
|
1288
|
+
AuthStrategy,
|
|
1289
|
+
HeaderPreset,
|
|
1290
|
+
OAuth2Preset,
|
|
1291
|
+
PreviewOperation,
|
|
1292
|
+
SpecPreview,
|
|
1293
|
+
previewSpec,
|
|
1294
|
+
openapiSchema,
|
|
1295
|
+
StoredSourceSchema,
|
|
1296
|
+
headerBindingSlot,
|
|
1297
|
+
queryParamBindingSlot,
|
|
1298
|
+
oauth2ClientIdSlot,
|
|
1299
|
+
oauth2ClientSecretSlot,
|
|
1300
|
+
oauth2ConnectionSlot,
|
|
1301
|
+
makeDefaultOpenapiStore
|
|
1302
|
+
};
|
|
1303
|
+
//# sourceMappingURL=chunk-E7PZ2QGD.js.map
|