@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.
Files changed (41) hide show
  1. package/dist/AddOpenApiSource-FLMNI742.js +19 -0
  2. package/dist/AddOpenApiSource-FLMNI742.js.map +1 -0
  3. package/dist/EditOpenApiSource-I4NIGIIJ.js +665 -0
  4. package/dist/EditOpenApiSource-I4NIGIIJ.js.map +1 -0
  5. package/dist/OpenApiSourceSummary-CM46DB4L.js +122 -0
  6. package/dist/OpenApiSourceSummary-CM46DB4L.js.map +1 -0
  7. package/dist/api/group.d.ts +224 -16
  8. package/dist/api/index.d.ts +634 -0
  9. package/dist/chunk-E7PZ2QGD.js +1303 -0
  10. package/dist/chunk-E7PZ2QGD.js.map +1 -0
  11. package/dist/chunk-GFQUEZUW.js +216 -0
  12. package/dist/chunk-GFQUEZUW.js.map +1 -0
  13. package/dist/chunk-OZ67JNID.js +1447 -0
  14. package/dist/chunk-OZ67JNID.js.map +1 -0
  15. package/dist/chunk-TGDT6QCH.js +1120 -0
  16. package/dist/chunk-TGDT6QCH.js.map +1 -0
  17. package/dist/client.js +165 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/core.js +8 -10
  20. package/dist/index.js +2 -1
  21. package/dist/react/AddOpenApiSource.d.ts +1 -1
  22. package/dist/react/OpenApiSourceDetailsFields.d.ts +18 -0
  23. package/dist/react/atoms.d.ts +320 -15
  24. package/dist/react/client.d.ts +226 -15
  25. package/dist/sdk/extract.d.ts +54 -3
  26. package/dist/sdk/index.d.ts +1 -1
  27. package/dist/sdk/invoke.d.ts +48 -4
  28. package/dist/sdk/openapi-utils.d.ts +4 -3
  29. package/dist/sdk/parse.d.ts +1 -1
  30. package/dist/sdk/parse.test.d.ts +1 -0
  31. package/dist/sdk/plugin.d.ts +247 -128
  32. package/dist/sdk/preview.d.ts +201 -49
  33. package/dist/sdk/store.d.ts +155 -45
  34. package/dist/sdk/types.d.ts +204 -137
  35. package/dist/sdk/usage-scope-isolation.test.d.ts +1 -0
  36. package/dist/testing/index.d.ts +34 -0
  37. package/dist/testing.js +56 -0
  38. package/dist/testing.js.map +1 -0
  39. package/package.json +16 -4
  40. package/dist/chunk-RBE3CVB4.js +0 -2837
  41. 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