@executor-js/plugin-openapi 0.0.1-beta.5 → 0.0.1-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/api/group.d.ts +16 -1
- package/dist/{chunk-C57CSNPZ.js → chunk-V3D5A6HA.js} +225 -194
- package/dist/chunk-V3D5A6HA.js.map +1 -0
- package/dist/core.js +44 -2
- package/dist/core.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/promise.d.ts +1 -1
- package/dist/react/AddOpenApiSource.d.ts +1 -0
- package/dist/react/index.d.ts +1 -1
- package/dist/sdk/config-file-store.d.ts +10 -0
- package/dist/sdk/index.d.ts +5 -4
- package/dist/sdk/invoke.d.ts +1 -1
- package/dist/sdk/kv-operation-store.d.ts +1 -1
- package/dist/sdk/operation-store.d.ts +3 -1
- package/dist/sdk/plugin.d.ts +11 -2
- package/dist/sdk/stored-source.d.ts +46 -0
- package/package.json +33 -31
- package/dist/chunk-C57CSNPZ.js.map +0 -1
|
@@ -14,9 +14,7 @@ var OpenApiExtractionError = class extends Schema.TaggedError()(
|
|
|
14
14
|
}
|
|
15
15
|
) {
|
|
16
16
|
};
|
|
17
|
-
var OpenApiInvocationError = class extends Data.TaggedError(
|
|
18
|
-
"OpenApiInvocationError"
|
|
19
|
-
) {
|
|
17
|
+
var OpenApiInvocationError = class extends Data.TaggedError("OpenApiInvocationError") {
|
|
20
18
|
};
|
|
21
19
|
|
|
22
20
|
// src/sdk/parse.ts
|
|
@@ -25,11 +23,15 @@ import { Effect } from "effect";
|
|
|
25
23
|
import YAML from "yaml";
|
|
26
24
|
var parse = Effect.fn("OpenApi.parse")(function* (input) {
|
|
27
25
|
const api = yield* Effect.tryPromise({
|
|
28
|
-
try: () => {
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
try: async () => {
|
|
27
|
+
const source = input.startsWith("http://") || input.startsWith("https://") ? input : parseTextToObject(input);
|
|
28
|
+
try {
|
|
29
|
+
return await SwaggerParser.bundle(source);
|
|
30
|
+
} catch {
|
|
31
|
+
const parsed = await SwaggerParser.parse(source);
|
|
32
|
+
resolveRefsInPlace(parsed);
|
|
33
|
+
return parsed;
|
|
31
34
|
}
|
|
32
|
-
return SwaggerParser.bundle(parseTextToObject(input));
|
|
33
35
|
},
|
|
34
36
|
catch: (error) => new OpenApiParseError({
|
|
35
37
|
message: `Failed to parse OpenAPI document: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -59,6 +61,67 @@ var parseTextToObject = (text) => {
|
|
|
59
61
|
}
|
|
60
62
|
return parsed;
|
|
61
63
|
};
|
|
64
|
+
var resolveRefsInPlace = (doc) => {
|
|
65
|
+
const lookup = (pointer) => {
|
|
66
|
+
if (!pointer.startsWith("#/")) return void 0;
|
|
67
|
+
const parts = pointer.slice(2).split("/");
|
|
68
|
+
let current = doc;
|
|
69
|
+
for (const part of parts) {
|
|
70
|
+
if (typeof current !== "object" || current === null) return void 0;
|
|
71
|
+
current = current[part];
|
|
72
|
+
}
|
|
73
|
+
return current;
|
|
74
|
+
};
|
|
75
|
+
const resolving = /* @__PURE__ */ new Set();
|
|
76
|
+
const resolveRef = (pointer) => {
|
|
77
|
+
if (resolving.has(pointer)) return void 0;
|
|
78
|
+
const target = lookup(pointer);
|
|
79
|
+
if (!target) return void 0;
|
|
80
|
+
resolving.add(pointer);
|
|
81
|
+
const cloned = deepClone(target);
|
|
82
|
+
walk(cloned);
|
|
83
|
+
resolving.delete(pointer);
|
|
84
|
+
return cloned;
|
|
85
|
+
};
|
|
86
|
+
const deepClone = (obj) => {
|
|
87
|
+
if (!obj || typeof obj !== "object") return obj;
|
|
88
|
+
if (Array.isArray(obj)) return obj.map(deepClone);
|
|
89
|
+
const result = {};
|
|
90
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
91
|
+
result[k] = deepClone(v);
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
};
|
|
95
|
+
const walk = (obj) => {
|
|
96
|
+
if (!obj || typeof obj !== "object") return;
|
|
97
|
+
if (Array.isArray(obj)) {
|
|
98
|
+
for (let i = 0; i < obj.length; i++) {
|
|
99
|
+
const item = obj[i];
|
|
100
|
+
if (isRef(item)) {
|
|
101
|
+
const resolved = resolveRef(item.$ref);
|
|
102
|
+
if (resolved) obj[i] = resolved;
|
|
103
|
+
else obj[i] = { description: `Unresolved: ${item.$ref}` };
|
|
104
|
+
} else {
|
|
105
|
+
walk(item);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const record = obj;
|
|
111
|
+
for (const [k, v] of Object.entries(record)) {
|
|
112
|
+
if (k === "$ref") continue;
|
|
113
|
+
if (isRef(v)) {
|
|
114
|
+
const resolved = resolveRef(v.$ref);
|
|
115
|
+
if (resolved) record[k] = resolved;
|
|
116
|
+
else record[k] = { description: `Unresolved: ${v.$ref}` };
|
|
117
|
+
} else {
|
|
118
|
+
walk(v);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
walk(doc);
|
|
123
|
+
};
|
|
124
|
+
var isRef = (v) => typeof v === "object" && v !== null && "$ref" in v && typeof v.$ref === "string";
|
|
62
125
|
|
|
63
126
|
// src/sdk/openapi-utils.ts
|
|
64
127
|
import { Option } from "effect";
|
|
@@ -69,7 +132,7 @@ var DocResolver = class {
|
|
|
69
132
|
doc;
|
|
70
133
|
/** Resolve a value that might be a $ref, returning the resolved object */
|
|
71
134
|
resolve(value) {
|
|
72
|
-
if (
|
|
135
|
+
if (isRef2(value)) {
|
|
73
136
|
const resolved = this.resolvePointer(value.$ref);
|
|
74
137
|
return resolved;
|
|
75
138
|
}
|
|
@@ -86,7 +149,7 @@ var DocResolver = class {
|
|
|
86
149
|
return current;
|
|
87
150
|
}
|
|
88
151
|
};
|
|
89
|
-
var
|
|
152
|
+
var isRef2 = (value) => typeof value === "object" && value !== null && "$ref" in value;
|
|
90
153
|
var resolveBaseUrl = (servers) => {
|
|
91
154
|
const server = servers[0];
|
|
92
155
|
if (!server) return "";
|
|
@@ -119,9 +182,7 @@ var HttpMethod = Schema2.Literal(
|
|
|
119
182
|
"trace"
|
|
120
183
|
);
|
|
121
184
|
var ParameterLocation = Schema2.Literal("path", "query", "header", "cookie");
|
|
122
|
-
var OperationParameter = class extends Schema2.Class(
|
|
123
|
-
"OperationParameter"
|
|
124
|
-
)({
|
|
185
|
+
var OperationParameter = class extends Schema2.Class("OperationParameter")({
|
|
125
186
|
name: Schema2.String,
|
|
126
187
|
location: ParameterLocation,
|
|
127
188
|
required: Schema2.Boolean,
|
|
@@ -140,9 +201,7 @@ var OperationRequestBody = class extends Schema2.Class(
|
|
|
140
201
|
schema: Schema2.optionalWith(Schema2.Unknown, { as: "Option" })
|
|
141
202
|
}) {
|
|
142
203
|
};
|
|
143
|
-
var ExtractedOperation = class extends Schema2.Class(
|
|
144
|
-
"ExtractedOperation"
|
|
145
|
-
)({
|
|
204
|
+
var ExtractedOperation = class extends Schema2.Class("ExtractedOperation")({
|
|
146
205
|
operationId: OperationId,
|
|
147
206
|
method: HttpMethod,
|
|
148
207
|
pathTemplate: Schema2.String,
|
|
@@ -158,24 +217,19 @@ var ExtractedOperation = class extends Schema2.Class(
|
|
|
158
217
|
};
|
|
159
218
|
var ServerInfo = class extends Schema2.Class("ServerInfo")({
|
|
160
219
|
url: Schema2.String,
|
|
161
|
-
variables: Schema2.optionalWith(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
)
|
|
220
|
+
variables: Schema2.optionalWith(Schema2.Record({ key: Schema2.String, value: Schema2.String }), {
|
|
221
|
+
as: "Option"
|
|
222
|
+
})
|
|
165
223
|
}) {
|
|
166
224
|
};
|
|
167
|
-
var ExtractionResult = class extends Schema2.Class(
|
|
168
|
-
"ExtractionResult"
|
|
169
|
-
)({
|
|
225
|
+
var ExtractionResult = class extends Schema2.Class("ExtractionResult")({
|
|
170
226
|
title: Schema2.optionalWith(Schema2.String, { as: "Option" }),
|
|
171
227
|
version: Schema2.optionalWith(Schema2.String, { as: "Option" }),
|
|
172
228
|
servers: Schema2.Array(ServerInfo),
|
|
173
229
|
operations: Schema2.Array(ExtractedOperation)
|
|
174
230
|
}) {
|
|
175
231
|
};
|
|
176
|
-
var OperationBinding = class extends Schema2.Class(
|
|
177
|
-
"OperationBinding"
|
|
178
|
-
)({
|
|
232
|
+
var OperationBinding = class extends Schema2.Class("OperationBinding")({
|
|
179
233
|
method: HttpMethod,
|
|
180
234
|
pathTemplate: Schema2.String,
|
|
181
235
|
parameters: Schema2.Array(OperationParameter),
|
|
@@ -189,20 +243,15 @@ var HeaderValue = Schema2.Union(
|
|
|
189
243
|
prefix: Schema2.optional(Schema2.String)
|
|
190
244
|
})
|
|
191
245
|
);
|
|
192
|
-
var InvocationConfig = class extends Schema2.Class(
|
|
193
|
-
"InvocationConfig"
|
|
194
|
-
)({
|
|
246
|
+
var InvocationConfig = class extends Schema2.Class("InvocationConfig")({
|
|
195
247
|
baseUrl: Schema2.String,
|
|
196
248
|
/** Headers applied to every request. Values can reference secrets. */
|
|
197
|
-
headers: Schema2.optionalWith(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
)
|
|
249
|
+
headers: Schema2.optionalWith(Schema2.Record({ key: Schema2.String, value: HeaderValue }), {
|
|
250
|
+
default: () => ({})
|
|
251
|
+
})
|
|
201
252
|
}) {
|
|
202
253
|
};
|
|
203
|
-
var InvocationResult = class extends Schema2.Class(
|
|
204
|
-
"InvocationResult"
|
|
205
|
-
)({
|
|
254
|
+
var InvocationResult = class extends Schema2.Class("InvocationResult")({
|
|
206
255
|
status: Schema2.Number,
|
|
207
256
|
headers: Schema2.Record({ key: Schema2.String, value: Schema2.String }),
|
|
208
257
|
data: Schema2.NullOr(Schema2.Unknown),
|
|
@@ -243,9 +292,7 @@ var extractParameters = (pathItem, operation, r) => {
|
|
|
243
292
|
schema: Option2.fromNullable(p.schema),
|
|
244
293
|
style: Option2.fromNullable(p.style),
|
|
245
294
|
explode: Option2.fromNullable(p.explode),
|
|
246
|
-
allowReserved: Option2.fromNullable(
|
|
247
|
-
"allowReserved" in p ? p.allowReserved : void 0
|
|
248
|
-
),
|
|
295
|
+
allowReserved: Option2.fromNullable("allowReserved" in p ? p.allowReserved : void 0),
|
|
249
296
|
description: Option2.fromNullable(p.description)
|
|
250
297
|
})
|
|
251
298
|
);
|
|
@@ -296,10 +343,7 @@ var buildInputSchema = (parameters, requestBody) => {
|
|
|
296
343
|
additionalProperties: false
|
|
297
344
|
};
|
|
298
345
|
};
|
|
299
|
-
var deriveOperationId = (method, pathTemplate, operation) => operation.operationId ?? (`${method}_${pathTemplate.replace(/[^a-zA-Z0-9]+/g, "_")}`.replace(
|
|
300
|
-
/^_+|_+$/g,
|
|
301
|
-
""
|
|
302
|
-
) || `${method}_operation`);
|
|
346
|
+
var deriveOperationId = (method, pathTemplate, operation) => operation.operationId ?? (`${method}_${pathTemplate.replace(/[^a-zA-Z0-9]+/g, "_")}`.replace(/^_+|_+$/g, "") || `${method}_operation`);
|
|
303
347
|
var extractServers = (doc) => (doc.servers ?? []).flatMap((server) => {
|
|
304
348
|
if (!server.url) return [];
|
|
305
349
|
const vars = server.variables ? Object.fromEntries(
|
|
@@ -337,9 +381,7 @@ var extract = Effect2.fn("OpenApi.extract")(function* (doc) {
|
|
|
337
381
|
const tags = (operation.tags ?? []).filter((t) => t.trim().length > 0);
|
|
338
382
|
operations.push(
|
|
339
383
|
new ExtractedOperation({
|
|
340
|
-
operationId: OperationId.make(
|
|
341
|
-
deriveOperationId(method, pathTemplate, operation)
|
|
342
|
-
),
|
|
384
|
+
operationId: OperationId.make(deriveOperationId(method, pathTemplate, operation)),
|
|
343
385
|
method,
|
|
344
386
|
pathTemplate,
|
|
345
387
|
summary: Option2.fromNullable(operation.summary),
|
|
@@ -364,14 +406,11 @@ var extract = Effect2.fn("OpenApi.extract")(function* (doc) {
|
|
|
364
406
|
|
|
365
407
|
// src/sdk/invoke.ts
|
|
366
408
|
import { Effect as Effect3, Layer, Option as Option3 } from "effect";
|
|
367
|
-
import {
|
|
368
|
-
HttpClient,
|
|
369
|
-
HttpClientRequest
|
|
370
|
-
} from "@effect/platform";
|
|
409
|
+
import { HttpClient, HttpClientRequest } from "@effect/platform";
|
|
371
410
|
import {
|
|
372
411
|
ToolInvocationResult,
|
|
373
412
|
ToolInvocationError
|
|
374
|
-
} from "@executor-js/sdk
|
|
413
|
+
} from "@executor-js/sdk";
|
|
375
414
|
var CONTAINER_KEYS = {
|
|
376
415
|
path: ["path", "pathParams", "params"],
|
|
377
416
|
query: ["query", "queryParams", "params"],
|
|
@@ -404,19 +443,13 @@ var resolvePath = Effect3.fn("OpenApi.resolvePath")(function* (pathTemplate, arg
|
|
|
404
443
|
}
|
|
405
444
|
continue;
|
|
406
445
|
}
|
|
407
|
-
resolved = resolved.replaceAll(
|
|
408
|
-
`{${param.name}}`,
|
|
409
|
-
encodeURIComponent(String(value))
|
|
410
|
-
);
|
|
446
|
+
resolved = resolved.replaceAll(`{${param.name}}`, encodeURIComponent(String(value)));
|
|
411
447
|
}
|
|
412
448
|
const remaining = [...resolved.matchAll(/\{([^{}]+)\}/g)].map((m) => m[1]).filter((v) => typeof v === "string");
|
|
413
449
|
for (const name of remaining) {
|
|
414
450
|
const value = args[name];
|
|
415
451
|
if (value !== void 0 && value !== null) {
|
|
416
|
-
resolved = resolved.replaceAll(
|
|
417
|
-
`{${name}}`,
|
|
418
|
-
encodeURIComponent(String(value))
|
|
419
|
-
);
|
|
452
|
+
resolved = resolved.replaceAll(`{${name}}`, encodeURIComponent(String(value)));
|
|
420
453
|
}
|
|
421
454
|
}
|
|
422
455
|
const unresolved = [...resolved.matchAll(/\{([^{}]+)\}/g)].map((m) => m[1]).filter((v) => typeof v === "string");
|
|
@@ -462,32 +495,20 @@ var isJsonContentType = (ct) => {
|
|
|
462
495
|
};
|
|
463
496
|
var invoke = Effect3.fn("OpenApi.invoke")(function* (operation, args, config, resolvedHeaders) {
|
|
464
497
|
const client = yield* HttpClient.HttpClient;
|
|
465
|
-
const resolvedPath = yield* resolvePath(
|
|
466
|
-
operation.pathTemplate,
|
|
467
|
-
args,
|
|
468
|
-
operation.parameters
|
|
469
|
-
);
|
|
498
|
+
const resolvedPath = yield* resolvePath(operation.pathTemplate, args, operation.parameters);
|
|
470
499
|
const path = resolvedPath.startsWith("/") ? resolvedPath : `/${resolvedPath}`;
|
|
471
500
|
let request = HttpClientRequest.make(operation.method.toUpperCase())(path);
|
|
472
501
|
for (const param of operation.parameters) {
|
|
473
502
|
if (param.location !== "query") continue;
|
|
474
503
|
const value = readParamValue(args, param);
|
|
475
504
|
if (value === void 0 || value === null) continue;
|
|
476
|
-
request = HttpClientRequest.setUrlParam(
|
|
477
|
-
request,
|
|
478
|
-
param.name,
|
|
479
|
-
String(value)
|
|
480
|
-
);
|
|
505
|
+
request = HttpClientRequest.setUrlParam(request, param.name, String(value));
|
|
481
506
|
}
|
|
482
507
|
for (const param of operation.parameters) {
|
|
483
508
|
if (param.location !== "header") continue;
|
|
484
509
|
const value = readParamValue(args, param);
|
|
485
510
|
if (value === void 0 || value === null) continue;
|
|
486
|
-
request = HttpClientRequest.setHeader(
|
|
487
|
-
request,
|
|
488
|
-
param.name,
|
|
489
|
-
String(value)
|
|
490
|
-
);
|
|
511
|
+
request = HttpClientRequest.setHeader(request, param.name, String(value));
|
|
491
512
|
}
|
|
492
513
|
if (Option3.isSome(operation.requestBody)) {
|
|
493
514
|
const rb = operation.requestBody.value;
|
|
@@ -513,9 +534,7 @@ var invoke = Effect3.fn("OpenApi.invoke")(function* (operation, args, config, re
|
|
|
513
534
|
const status = response.status;
|
|
514
535
|
const responseHeaders = { ...response.headers };
|
|
515
536
|
const contentType = response.headers["content-type"] ?? null;
|
|
516
|
-
const responseBody = status === 204 ? null : isJsonContentType(contentType) ? yield* response.json.pipe(
|
|
517
|
-
Effect3.catchAll(() => response.text)
|
|
518
|
-
) : yield* response.text;
|
|
537
|
+
const responseBody = status === 204 ? null : isJsonContentType(contentType) ? yield* response.json.pipe(Effect3.catchAll(() => response.text)) : yield* response.text;
|
|
519
538
|
const ok = status >= 200 && status < 300;
|
|
520
539
|
return new InvocationResult({
|
|
521
540
|
status,
|
|
@@ -549,18 +568,12 @@ var makeOpenApiInvoker = (opts) => ({
|
|
|
549
568
|
}
|
|
550
569
|
const { binding, config } = entry;
|
|
551
570
|
const baseUrl = config.baseUrl;
|
|
552
|
-
const resolvedHeaders = yield* resolveHeaders(
|
|
553
|
-
config.headers,
|
|
554
|
-
opts.secrets,
|
|
555
|
-
opts.scopeId
|
|
556
|
-
);
|
|
571
|
+
const resolvedHeaders = yield* resolveHeaders(config.headers, opts.secrets, opts.scopeId);
|
|
557
572
|
const clientWithBaseUrl = baseUrl ? Layer.effect(
|
|
558
573
|
HttpClient.HttpClient,
|
|
559
574
|
Effect3.map(
|
|
560
575
|
HttpClient.HttpClient,
|
|
561
|
-
HttpClient.mapRequest(
|
|
562
|
-
HttpClientRequest.prependUrl(baseUrl)
|
|
563
|
-
)
|
|
576
|
+
HttpClient.mapRequest(HttpClientRequest.prependUrl(baseUrl))
|
|
564
577
|
)
|
|
565
578
|
).pipe(Layer.provide(opts.httpClientLayer)) : opts.httpClientLayer;
|
|
566
579
|
const result = yield* invoke(
|
|
@@ -591,30 +604,34 @@ var makeOpenApiInvoker = (opts) => ({
|
|
|
591
604
|
});
|
|
592
605
|
|
|
593
606
|
// src/sdk/kv-operation-store.ts
|
|
594
|
-
import { Effect as Effect4, Schema as
|
|
595
|
-
import { scopeKv, makeInMemoryScopedKv } from "@executor-js/sdk
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}) {
|
|
601
|
-
};
|
|
602
|
-
var encodeEntry = Schema3.encodeSync(Schema3.parseJson(StoredEntry));
|
|
603
|
-
var decodeEntry = Schema3.decodeUnknownSync(Schema3.parseJson(StoredEntry));
|
|
604
|
-
var StoredSourceSchema = Schema3.Struct({
|
|
607
|
+
import { Effect as Effect4, Schema as Schema4 } from "effect";
|
|
608
|
+
import { scopeKv, makeInMemoryScopedKv } from "@executor-js/sdk";
|
|
609
|
+
|
|
610
|
+
// src/sdk/stored-source.ts
|
|
611
|
+
import { Schema as Schema3 } from "effect";
|
|
612
|
+
var StoredSourceSchema = class extends Schema3.Class("OpenApiStoredSource")({
|
|
605
613
|
namespace: Schema3.String,
|
|
606
614
|
name: Schema3.String,
|
|
607
615
|
config: Schema3.Struct({
|
|
608
616
|
spec: Schema3.String,
|
|
609
617
|
baseUrl: Schema3.optional(Schema3.String),
|
|
610
618
|
namespace: Schema3.optional(Schema3.String),
|
|
611
|
-
headers: Schema3.optional(
|
|
612
|
-
Schema3.Record({ key: Schema3.String, value: HeaderValue })
|
|
613
|
-
)
|
|
619
|
+
headers: Schema3.optional(Schema3.Record({ key: Schema3.String, value: HeaderValue }))
|
|
614
620
|
})
|
|
615
|
-
})
|
|
616
|
-
|
|
617
|
-
|
|
621
|
+
}) {
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
// src/sdk/kv-operation-store.ts
|
|
625
|
+
var StoredEntry = class extends Schema4.Class("StoredEntry")({
|
|
626
|
+
namespace: Schema4.String,
|
|
627
|
+
binding: OperationBinding,
|
|
628
|
+
config: InvocationConfig
|
|
629
|
+
}) {
|
|
630
|
+
};
|
|
631
|
+
var encodeEntry = Schema4.encodeSync(Schema4.parseJson(StoredEntry));
|
|
632
|
+
var decodeEntry = Schema4.decodeUnknownSync(Schema4.parseJson(StoredEntry));
|
|
633
|
+
var encodeSource = Schema4.encodeSync(Schema4.parseJson(StoredSourceSchema));
|
|
634
|
+
var decodeSource = Schema4.decodeUnknownSync(Schema4.parseJson(StoredSourceSchema));
|
|
618
635
|
var makeStore = (bindings, sources) => {
|
|
619
636
|
const withKvTransaction = (kv, effect) => kv.withTransaction?.(effect) ?? effect;
|
|
620
637
|
return {
|
|
@@ -626,16 +643,14 @@ var makeStore = (bindings, sources) => {
|
|
|
626
643
|
}),
|
|
627
644
|
put: (entries) => withKvTransaction(
|
|
628
645
|
bindings,
|
|
629
|
-
|
|
630
|
-
entries,
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
),
|
|
635
|
-
{ discard: true }
|
|
646
|
+
bindings.set(
|
|
647
|
+
entries.map(({ toolId, namespace, binding, config }) => ({
|
|
648
|
+
key: toolId,
|
|
649
|
+
value: encodeEntry(new StoredEntry({ namespace, binding, config }))
|
|
650
|
+
}))
|
|
636
651
|
)
|
|
637
652
|
),
|
|
638
|
-
remove: (toolId) => bindings.delete(toolId).pipe(Effect4.asVoid),
|
|
653
|
+
remove: (toolId) => bindings.delete([toolId]).pipe(Effect4.asVoid),
|
|
639
654
|
listByNamespace: (namespace) => Effect4.gen(function* () {
|
|
640
655
|
const entries = yield* bindings.list();
|
|
641
656
|
const ids = [];
|
|
@@ -650,73 +665,76 @@ var makeStore = (bindings, sources) => {
|
|
|
650
665
|
const ids = [];
|
|
651
666
|
for (const e of entries) {
|
|
652
667
|
const entry = decodeEntry(e.value);
|
|
653
|
-
if (entry.namespace === namespace)
|
|
654
|
-
ids.push(e.key);
|
|
655
|
-
yield* bindings.delete(e.key);
|
|
656
|
-
}
|
|
668
|
+
if (entry.namespace === namespace) ids.push(e.key);
|
|
657
669
|
}
|
|
670
|
+
if (ids.length > 0) yield* bindings.delete(ids);
|
|
658
671
|
return ids;
|
|
659
672
|
}),
|
|
660
|
-
putSource: (source) => sources.set(source.namespace, encodeSource(source)),
|
|
661
|
-
removeSource: (namespace) => sources.delete(namespace).pipe(Effect4.asVoid),
|
|
673
|
+
putSource: (source) => sources.set([{ key: source.namespace, value: encodeSource(source) }]),
|
|
674
|
+
removeSource: (namespace) => sources.delete([namespace]).pipe(Effect4.asVoid),
|
|
662
675
|
listSources: () => Effect4.gen(function* () {
|
|
663
676
|
const entries = yield* sources.list();
|
|
664
677
|
return entries.map((e) => decodeSource(e.value));
|
|
678
|
+
}),
|
|
679
|
+
getSource: (namespace) => Effect4.gen(function* () {
|
|
680
|
+
const raw = yield* sources.get(namespace);
|
|
681
|
+
if (!raw) return null;
|
|
682
|
+
return decodeSource(raw);
|
|
683
|
+
}),
|
|
684
|
+
getSourceConfig: (namespace) => Effect4.gen(function* () {
|
|
685
|
+
const raw = yield* sources.get(namespace);
|
|
686
|
+
if (!raw) return null;
|
|
687
|
+
const source = decodeSource(raw);
|
|
688
|
+
return source.config;
|
|
665
689
|
})
|
|
666
690
|
};
|
|
667
691
|
};
|
|
668
|
-
var makeKvOperationStore = (kv, namespace) => makeStore(
|
|
669
|
-
|
|
670
|
-
scopeKv(kv, `${namespace}.sources`)
|
|
671
|
-
);
|
|
672
|
-
var makeInMemoryOperationStore = () => makeStore(
|
|
673
|
-
makeInMemoryScopedKv(),
|
|
674
|
-
makeInMemoryScopedKv()
|
|
675
|
-
);
|
|
692
|
+
var makeKvOperationStore = (kv, namespace) => makeStore(scopeKv(kv, `${namespace}.bindings`), scopeKv(kv, `${namespace}.sources`));
|
|
693
|
+
var makeInMemoryOperationStore = () => makeStore(makeInMemoryScopedKv(), makeInMemoryScopedKv());
|
|
676
694
|
|
|
677
695
|
// src/sdk/preview.ts
|
|
678
696
|
import { Effect as Effect5, Option as Option4 } from "effect";
|
|
679
|
-
import { Schema as
|
|
680
|
-
var SecurityScheme = class extends
|
|
697
|
+
import { Schema as Schema5 } from "effect";
|
|
698
|
+
var SecurityScheme = class extends Schema5.Class("SecurityScheme")({
|
|
681
699
|
/** Key name in components.securitySchemes (e.g. "api_token") */
|
|
682
|
-
name:
|
|
700
|
+
name: Schema5.String,
|
|
683
701
|
/** OpenAPI security scheme type */
|
|
684
|
-
type:
|
|
702
|
+
type: Schema5.Literal("http", "apiKey", "oauth2", "openIdConnect"),
|
|
685
703
|
/** For type: "http" — e.g. "bearer", "basic" */
|
|
686
|
-
scheme:
|
|
704
|
+
scheme: Schema5.optionalWith(Schema5.String, { as: "Option" }),
|
|
687
705
|
/** For type: "apiKey" — where the key goes */
|
|
688
|
-
in:
|
|
706
|
+
in: Schema5.optionalWith(Schema5.Literal("header", "query", "cookie"), { as: "Option" }),
|
|
689
707
|
/** For type: "apiKey" — the header/query/cookie name */
|
|
690
|
-
headerName:
|
|
691
|
-
description:
|
|
708
|
+
headerName: Schema5.optionalWith(Schema5.String, { as: "Option" }),
|
|
709
|
+
description: Schema5.optionalWith(Schema5.String, { as: "Option" })
|
|
692
710
|
}) {
|
|
693
711
|
};
|
|
694
|
-
var AuthStrategy = class extends
|
|
712
|
+
var AuthStrategy = class extends Schema5.Class("AuthStrategy")({
|
|
695
713
|
/** The security schemes required together for this strategy */
|
|
696
|
-
schemes:
|
|
714
|
+
schemes: Schema5.Array(Schema5.String)
|
|
697
715
|
}) {
|
|
698
716
|
};
|
|
699
|
-
var HeaderPreset = class extends
|
|
717
|
+
var HeaderPreset = class extends Schema5.Class("HeaderPreset")({
|
|
700
718
|
/** Human-readable label for the UI (e.g. "Bearer Token", "API Key + Email") */
|
|
701
|
-
label:
|
|
719
|
+
label: Schema5.String,
|
|
702
720
|
/** Headers this strategy needs. Value is null when the user must provide it. */
|
|
703
|
-
headers:
|
|
721
|
+
headers: Schema5.Record({ key: Schema5.String, value: Schema5.NullOr(Schema5.String) }),
|
|
704
722
|
/** Which headers should be stored as secrets */
|
|
705
|
-
secretHeaders:
|
|
723
|
+
secretHeaders: Schema5.Array(Schema5.String)
|
|
706
724
|
}) {
|
|
707
725
|
};
|
|
708
|
-
var SpecPreview = class extends
|
|
709
|
-
title:
|
|
710
|
-
version:
|
|
726
|
+
var SpecPreview = class extends Schema5.Class("SpecPreview")({
|
|
727
|
+
title: Schema5.optionalWith(Schema5.String, { as: "Option" }),
|
|
728
|
+
version: Schema5.optionalWith(Schema5.String, { as: "Option" }),
|
|
711
729
|
/** Reuses ServerInfo from extraction */
|
|
712
|
-
servers:
|
|
713
|
-
operationCount:
|
|
714
|
-
tags:
|
|
715
|
-
securitySchemes:
|
|
730
|
+
servers: Schema5.Array(Schema5.Unknown),
|
|
731
|
+
operationCount: Schema5.Number,
|
|
732
|
+
tags: Schema5.Array(Schema5.String),
|
|
733
|
+
securitySchemes: Schema5.Array(SecurityScheme),
|
|
716
734
|
/** Valid auth strategies (each is a set of schemes used together) */
|
|
717
|
-
authStrategies:
|
|
735
|
+
authStrategies: Schema5.Array(AuthStrategy),
|
|
718
736
|
/** Pre-built header presets derived from auth strategies */
|
|
719
|
-
headerPresets:
|
|
737
|
+
headerPresets: Schema5.Array(HeaderPreset)
|
|
720
738
|
}) {
|
|
721
739
|
};
|
|
722
740
|
var extractSecuritySchemes = (rawSchemes) => Object.entries(rawSchemes).flatMap(([name, schemeOrRef]) => {
|
|
@@ -730,9 +748,7 @@ var extractSecuritySchemes = (rawSchemes) => Object.entries(rawSchemes).flatMap(
|
|
|
730
748
|
name,
|
|
731
749
|
type,
|
|
732
750
|
scheme: Option4.fromNullable(scheme.scheme),
|
|
733
|
-
in: Option4.fromNullable(
|
|
734
|
-
scheme.in
|
|
735
|
-
),
|
|
751
|
+
in: Option4.fromNullable(scheme.in),
|
|
736
752
|
headerName: Option4.fromNullable(scheme.name),
|
|
737
753
|
description: Option4.fromNullable(scheme.description)
|
|
738
754
|
})
|
|
@@ -767,13 +783,9 @@ var buildHeaderPresets = (schemes, strategies) => {
|
|
|
767
783
|
}
|
|
768
784
|
}
|
|
769
785
|
if (Object.keys(headers).length === 0 && resolved.length > 0) {
|
|
770
|
-
return [
|
|
771
|
-
new HeaderPreset({ label: labelParts.join(" + "), headers: {}, secretHeaders: [] })
|
|
772
|
-
];
|
|
786
|
+
return [new HeaderPreset({ label: labelParts.join(" + "), headers: {}, secretHeaders: [] })];
|
|
773
787
|
}
|
|
774
|
-
return [
|
|
775
|
-
new HeaderPreset({ label: labelParts.join(" + "), headers, secretHeaders })
|
|
776
|
-
];
|
|
788
|
+
return [new HeaderPreset({ label: labelParts.join(" + "), headers, secretHeaders })];
|
|
777
789
|
});
|
|
778
790
|
};
|
|
779
791
|
var collectTags = (result) => {
|
|
@@ -786,9 +798,7 @@ var collectTags = (result) => {
|
|
|
786
798
|
var previewSpec = Effect5.fn("OpenApi.previewSpec")(function* (specText) {
|
|
787
799
|
const doc = yield* parse(specText);
|
|
788
800
|
const result = yield* extract(doc);
|
|
789
|
-
const securitySchemes = extractSecuritySchemes(
|
|
790
|
-
doc.components?.securitySchemes ?? {}
|
|
791
|
-
);
|
|
801
|
+
const securitySchemes = extractSecuritySchemes(doc.components?.securitySchemes ?? {});
|
|
792
802
|
const rawSecurity = doc.security ?? [];
|
|
793
803
|
const authStrategies = rawSecurity.map(
|
|
794
804
|
(entry) => new AuthStrategy({ schemes: Object.keys(entry) })
|
|
@@ -806,7 +816,7 @@ var previewSpec = Effect5.fn("OpenApi.previewSpec")(function* (specText) {
|
|
|
806
816
|
});
|
|
807
817
|
|
|
808
818
|
// src/sdk/plugin.ts
|
|
809
|
-
import { Effect as Effect6, Option as Option5, Schema as
|
|
819
|
+
import { Effect as Effect6, Option as Option5, Schema as Schema6 } from "effect";
|
|
810
820
|
import { FetchHttpClient } from "@effect/platform";
|
|
811
821
|
import {
|
|
812
822
|
Source,
|
|
@@ -815,7 +825,7 @@ import {
|
|
|
815
825
|
registerRuntimeTools,
|
|
816
826
|
runtimeTool,
|
|
817
827
|
ToolId
|
|
818
|
-
} from "@executor-js/sdk
|
|
828
|
+
} from "@executor-js/sdk";
|
|
819
829
|
|
|
820
830
|
// src/sdk/definitions.ts
|
|
821
831
|
var splitWords = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z0-9]+)/g, "$1 $2").replace(/[^a-zA-Z0-9]+/g, " ").trim().split(/\s+/).filter((part) => part.length > 0);
|
|
@@ -937,26 +947,22 @@ var compileToolDefinitions = (operations) => {
|
|
|
937
947
|
operation: op
|
|
938
948
|
};
|
|
939
949
|
});
|
|
940
|
-
return resolveCollisions(raw).sort(
|
|
941
|
-
(a, b) => a.toolPath.localeCompare(b.toolPath)
|
|
942
|
-
);
|
|
950
|
+
return resolveCollisions(raw).sort((a, b) => a.toolPath.localeCompare(b.toolPath));
|
|
943
951
|
};
|
|
944
952
|
|
|
945
953
|
// src/sdk/plugin.ts
|
|
946
|
-
var PreviewSpecInputSchema =
|
|
947
|
-
spec:
|
|
954
|
+
var PreviewSpecInputSchema = Schema6.Struct({
|
|
955
|
+
spec: Schema6.String
|
|
948
956
|
});
|
|
949
|
-
var AddSourceInputSchema =
|
|
950
|
-
spec:
|
|
951
|
-
baseUrl:
|
|
952
|
-
namespace:
|
|
953
|
-
headers:
|
|
954
|
-
Schema5.Record({ key: Schema5.String, value: HeaderValue })
|
|
955
|
-
)
|
|
957
|
+
var AddSourceInputSchema = Schema6.Struct({
|
|
958
|
+
spec: Schema6.String,
|
|
959
|
+
baseUrl: Schema6.optional(Schema6.String),
|
|
960
|
+
namespace: Schema6.optional(Schema6.String),
|
|
961
|
+
headers: Schema6.optional(Schema6.Record({ key: Schema6.String, value: HeaderValue }))
|
|
956
962
|
});
|
|
957
|
-
var AddSourceOutputSchema =
|
|
958
|
-
sourceId:
|
|
959
|
-
toolCount:
|
|
963
|
+
var AddSourceOutputSchema = Schema6.Struct({
|
|
964
|
+
sourceId: Schema6.String,
|
|
965
|
+
toolCount: Schema6.Number
|
|
960
966
|
});
|
|
961
967
|
var normalizeOpenApiRefs = (node) => {
|
|
962
968
|
if (node == null || typeof node !== "object") return node;
|
|
@@ -988,10 +994,7 @@ var toRegistration = (def, namespace) => {
|
|
|
988
994
|
const op = def.operation;
|
|
989
995
|
const description = Option5.getOrElse(
|
|
990
996
|
op.description,
|
|
991
|
-
() => Option5.getOrElse(
|
|
992
|
-
op.summary,
|
|
993
|
-
() => `${op.method.toUpperCase()} ${op.pathTemplate}`
|
|
994
|
-
)
|
|
997
|
+
() => Option5.getOrElse(op.summary, () => `${op.method.toUpperCase()} ${op.pathTemplate}`)
|
|
995
998
|
);
|
|
996
999
|
return {
|
|
997
1000
|
id: ToolId.make(`${namespace}.${def.toolPath}`),
|
|
@@ -1035,7 +1038,8 @@ var openApiPlugin = (options) => {
|
|
|
1035
1038
|
kind: "openapi",
|
|
1036
1039
|
runtime: false,
|
|
1037
1040
|
canRemove: true,
|
|
1038
|
-
canRefresh: false
|
|
1041
|
+
canRefresh: false,
|
|
1042
|
+
canEdit: true
|
|
1039
1043
|
})
|
|
1040
1044
|
)
|
|
1041
1045
|
)
|
|
@@ -1050,13 +1054,9 @@ var openApiPlugin = (options) => {
|
|
|
1050
1054
|
if (!trimmed) return null;
|
|
1051
1055
|
const parsed = yield* Effect6.try(() => new URL(trimmed)).pipe(Effect6.option);
|
|
1052
1056
|
if (parsed._tag === "None") return null;
|
|
1053
|
-
const doc = yield* parse(trimmed).pipe(
|
|
1054
|
-
Effect6.catchAll(() => Effect6.succeed(null))
|
|
1055
|
-
);
|
|
1057
|
+
const doc = yield* parse(trimmed).pipe(Effect6.catchAll(() => Effect6.succeed(null)));
|
|
1056
1058
|
if (!doc) return null;
|
|
1057
|
-
const result = yield* extract(doc).pipe(
|
|
1058
|
-
Effect6.catchAll(() => Effect6.succeed(null))
|
|
1059
|
-
);
|
|
1059
|
+
const result = yield* extract(doc).pipe(Effect6.catchAll(() => Effect6.succeed(null)));
|
|
1060
1060
|
if (!result) return null;
|
|
1061
1061
|
const namespace = Option5.getOrElse(result.title, () => "api").toLowerCase().replace(/[^a-z0-9]+/g, "_");
|
|
1062
1062
|
const name = Option5.getOrElse(result.title, () => namespace);
|
|
@@ -1086,9 +1086,7 @@ var openApiPlugin = (options) => {
|
|
|
1086
1086
|
headers: config.headers ?? {}
|
|
1087
1087
|
});
|
|
1088
1088
|
const definitions = compileToolDefinitions(result.operations);
|
|
1089
|
-
const registrations = definitions.map(
|
|
1090
|
-
(def) => toRegistration(def, namespace)
|
|
1091
|
-
);
|
|
1089
|
+
const registrations = definitions.map((def) => toRegistration(def, namespace));
|
|
1092
1090
|
yield* operationStore.put(
|
|
1093
1091
|
definitions.map((def) => ({
|
|
1094
1092
|
toolId: ToolId.make(`${namespace}.${def.toolPath}`),
|
|
@@ -1098,7 +1096,7 @@ var openApiPlugin = (options) => {
|
|
|
1098
1096
|
}))
|
|
1099
1097
|
);
|
|
1100
1098
|
yield* ctx.tools.register(registrations);
|
|
1101
|
-
const sourceName = Option5.getOrElse(result.title, () => namespace);
|
|
1099
|
+
const sourceName = config.name ?? Option5.getOrElse(result.title, () => namespace);
|
|
1102
1100
|
yield* operationStore.putSource({
|
|
1103
1101
|
namespace,
|
|
1104
1102
|
name: sourceName,
|
|
@@ -1142,15 +1140,48 @@ var openApiPlugin = (options) => {
|
|
|
1142
1140
|
return {
|
|
1143
1141
|
extension: {
|
|
1144
1142
|
previewSpec: (specText) => previewSpec(specText),
|
|
1145
|
-
addSpec: (config) => addSpecInternal(config).pipe(
|
|
1146
|
-
Effect6.map(({ toolCount }) => ({ toolCount }))
|
|
1147
|
-
),
|
|
1143
|
+
addSpec: (config) => addSpecInternal(config).pipe(Effect6.map(({ toolCount }) => ({ toolCount }))),
|
|
1148
1144
|
removeSpec: (namespace) => Effect6.gen(function* () {
|
|
1149
1145
|
const toolIds = yield* operationStore.removeByNamespace(namespace);
|
|
1150
1146
|
if (toolIds.length > 0) {
|
|
1151
1147
|
yield* ctx.tools.unregister(toolIds);
|
|
1152
1148
|
}
|
|
1153
1149
|
yield* operationStore.removeSource(namespace);
|
|
1150
|
+
}),
|
|
1151
|
+
getSource: (namespace) => operationStore.getSource(namespace),
|
|
1152
|
+
updateSource: (namespace, input) => Effect6.gen(function* () {
|
|
1153
|
+
const existingSource = yield* operationStore.getSourceConfig(namespace);
|
|
1154
|
+
if (!existingSource) return;
|
|
1155
|
+
const updatedConfig = {
|
|
1156
|
+
...existingSource,
|
|
1157
|
+
...input.baseUrl !== void 0 ? { baseUrl: input.baseUrl } : {},
|
|
1158
|
+
...input.headers !== void 0 ? { headers: input.headers } : {}
|
|
1159
|
+
};
|
|
1160
|
+
const newInvocationConfig = new InvocationConfig({
|
|
1161
|
+
baseUrl: updatedConfig.baseUrl ?? resolveBaseUrl([]),
|
|
1162
|
+
headers: updatedConfig.headers ?? {}
|
|
1163
|
+
});
|
|
1164
|
+
const toolIds = yield* operationStore.listByNamespace(namespace);
|
|
1165
|
+
for (const toolId of toolIds) {
|
|
1166
|
+
const entry = yield* operationStore.get(toolId);
|
|
1167
|
+
if (entry) {
|
|
1168
|
+
yield* operationStore.put([
|
|
1169
|
+
{
|
|
1170
|
+
toolId,
|
|
1171
|
+
namespace,
|
|
1172
|
+
binding: entry.binding,
|
|
1173
|
+
config: newInvocationConfig
|
|
1174
|
+
}
|
|
1175
|
+
]);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
const sources = yield* operationStore.listSources();
|
|
1179
|
+
const existingMeta = sources.find((s) => s.namespace === namespace);
|
|
1180
|
+
yield* operationStore.putSource({
|
|
1181
|
+
namespace,
|
|
1182
|
+
name: existingMeta?.name ?? namespace,
|
|
1183
|
+
config: updatedConfig
|
|
1184
|
+
});
|
|
1154
1185
|
})
|
|
1155
1186
|
},
|
|
1156
1187
|
close: () => runtimeTools.close()
|
|
@@ -1190,4 +1221,4 @@ export {
|
|
|
1190
1221
|
previewSpec,
|
|
1191
1222
|
openApiPlugin
|
|
1192
1223
|
};
|
|
1193
|
-
//# sourceMappingURL=chunk-
|
|
1224
|
+
//# sourceMappingURL=chunk-V3D5A6HA.js.map
|