History

ralph

Rhys Sullivan committed 7 months ago

Commit 01ee9a61 parent 263c9a378 files · +13644 −179Browse files

Showing the changes to plugins/openapi (1 of 78 files). Show all

Unified · Split

plugins/openapi/sdk/index.ts+143−92
@@ -9,9 +9,12 @@ import { · 8 unmodified lines
99 import type { Source } from "@executor/platform-sdk/schema";
1010 import type {
1111 ExecutorSdkPlugin,
12+ ExecutorSdkPluginHost,
13+ ExecutorSourceConnector,
1214 SourcePluginRuntime,
1315 } from "@executor/platform-sdk/plugins";
1416 import {
17+ OpenApiConnectionAuthSchema,
1518 deriveOpenApiNamespace,
1619 previewOpenApiDocument,
1720 type OpenApiConnectInput,
@@ -90,6 +93,16 @@ export type OpenApiSdkPluginOptions = { · 72 unmodified lines
9093 secrets?: OpenApiSecrets;
9194 };
9295
96+const OpenApiExecutorAddInputSchema = Schema.Struct({
97+ kind: Schema.Literal("openapi"),
98+ name: Schema.String,
99+ specUrl: Schema.String,
100+ baseUrl: Schema.NullOr(Schema.String),
101+ auth: OpenApiConnectionAuthSchema,
102+});
103+
104+type OpenApiExecutorAddInput = typeof OpenApiExecutorAddInputSchema.Type;
105+
93106 const createStoredSourceData = (
94107 input: OpenApiConnectInput,
95108 ): OpenApiStoredSourceData => ({
@@ -249,6 +262,117 @@ const responseHeadersRecord = (response: Response): Record<string, string> => { · 153 unmodified lines
249262 return headers;
250263 };
251264
265+const createOpenApiSourceSdk = (
266+ options: OpenApiSdkPluginOptions,
267+ host: ExecutorSdkPluginHost,
268+) => ({
269+ getSourceConfig: (sourceId: Source["id"]) =>
270+ Effect.gen(function* () {
271+ const source = yield* host.sources.get(sourceId);
272+ if (source.kind !== "openapi") {
273+ return yield* Effect.fail(
274+ new Error(`Source ${sourceId} is not an OpenAPI source.`),
275+ );
276+ }
277+
278+ const stored = yield* options.storage.get({
279+ scopeId: source.scopeId,
280+ sourceId: source.id,
281+ });
282+ if (stored === null) {
283+ return yield* Effect.fail(
284+ new Error(`OpenAPI source storage missing for ${source.id}`),
285+ );
286+ }
287+
288+ return configFromStoredSourceData(source, stored);
289+ }),
290+ createSource: (input: OpenApiConnectInput) =>
291+ Effect.gen(function* () {
292+ const stored = createStoredSourceData(input);
293+ const createdSource = yield* host.sources.create({
294+ source: {
295+ name: input.name.trim(),
296+ kind: "openapi",
297+ status: "connected",
298+ enabled: true,
299+ namespace: deriveOpenApiNamespace({
300+ specUrl: input.specUrl,
301+ title: input.name,
302+ }),
303+ },
304+ });
305+
306+ yield* options.storage.put({
307+ scopeId: createdSource.scopeId,
308+ sourceId: createdSource.id,
309+ value: stored,
310+ });
311+
312+ return yield* host.sources.refreshCatalog(createdSource.id);
313+ }),
314+ updateSource: (input: OpenApiUpdateSourceInput) =>
315+ Effect.gen(function* () {
316+ const source = yield* host.sources.get(input.sourceId as Source["id"]);
317+ if (source.kind !== "openapi") {
318+ return yield* Effect.fail(
319+ new Error(`Source ${input.sourceId} is not an OpenAPI source.`),
320+ );
321+ }
322+
323+ const nextStored = createStoredSourceData(input.config);
324+ const savedSource = yield* host.sources.save({
325+ ...source,
326+ name: input.config.name.trim(),
327+ namespace: deriveOpenApiNamespace({
328+ specUrl: input.config.specUrl,
329+ title: input.config.name,
330+ }),
331+ });
332+
333+ yield* options.storage.put({
334+ scopeId: savedSource.scopeId,
335+ sourceId: savedSource.id,
336+ value: nextStored,
337+ });
338+
339+ return yield* host.sources.refreshCatalog(savedSource.id);
340+ }),
341+ removeSource: (sourceId: Source["id"]) =>
342+ Effect.gen(function* () {
343+ const source = yield* host.sources.get(sourceId);
344+ if (source.kind !== "openapi") {
345+ return yield* Effect.fail(
346+ new Error(`Source ${sourceId} is not an OpenAPI source.`),
347+ );
348+ }
349+
350+ if (options.storage.remove) {
351+ yield* options.storage.remove({
352+ scopeId: source.scopeId,
353+ sourceId: source.id,
354+ });
355+ }
356+
357+ return yield* host.sources.remove(source.id);
358+ }),
359+});
360+
361+const openApiSourceConnector = (
362+ options: OpenApiSdkPluginOptions,
363+): ExecutorSourceConnector<OpenApiExecutorAddInput> => ({
364+ kind: "openapi",
365+ displayName: "OpenAPI",
366+ inputSchema: OpenApiExecutorAddInputSchema,
367+ inputSignatureWidth: 280,
368+ helpText: [
369+ "Provide the OpenAPI document URL and optional base URL override.",
370+ "Use `auth.kind = \"bearer\"` with a stored secret ref when required.",
371+ ],
372+ createSource: ({ args, host }) =>
373+ createOpenApiSourceSdk(options, host).createSource(args),
374+});
375+
252376 const decodeResponseBody = async (response: Response): Promise<unknown> => {
253377 if (response.status === 204) {
254378 return null;
@@ -541,102 +665,29 @@ export const openApiSdkPlugin = ( · 286 unmodified lines
541665 ): ExecutorSdkPlugin<"openapi", OpenApiSdk> => ({
542666 key: "openapi",
543667 sources: [createOpenApiSourceRuntime(options)],
544− extendExecutor: ({ host }) => ({
668+ sourceConnectors: [openApiSourceConnector(options)],
669+ extendExecutor: ({ host, executor }) => {
670+ const sourceSdk = createOpenApiSourceSdk(options, host);
671+ const provideRuntime = <A>(
672+ effect: Effect.Effect<A, Error, any>,
673+ ): Effect.Effect<A, Error, never> =>
674+ effect.pipe(Effect.provide(executor.runtime.managedRuntime));
675+
676+ return {
545677 previewDocument: (input) =>
546678 Effect.tryPromise({
547679 try: () => previewOpenApiDocument(input),
548680 catch: (cause) =>
549681 cause instanceof Error ? cause : new Error(String(cause)),
550682 }),
551− getSourceConfig: (sourceId) =>
552− Effect.gen(function* () {
553− const source = yield* host.sources.get(sourceId);
554− if (source.kind !== "openapi") {
555− return yield* Effect.fail(
556− new Error(`Source ${sourceId} is not an OpenAPI source.`),
557− );
558− }
559−
560− const stored = yield* options.storage.get({
561− scopeId: source.scopeId,
562− sourceId: source.id,
563− });
564− if (stored === null) {
565− return yield* Effect.fail(
566− new Error(`OpenAPI source storage missing for ${source.id}`),
567− );
568− }
569−
570− return configFromStoredSourceData(source, stored);
571− }),
572− createSource: (input) =>
573− Effect.gen(function* () {
574− const stored = createStoredSourceData(input);
575− const createdSource = yield* host.sources.create({
576− source: {
577− name: input.name.trim(),
578− kind: "openapi",
579− status: "connected",
580− enabled: true,
581− namespace: deriveOpenApiNamespace({
582− specUrl: input.specUrl,
583− title: input.name,
584− }),
585− },
586− });
587−
588− yield* options.storage.put({
589− scopeId: createdSource.scopeId,
590− sourceId: createdSource.id,
591− value: stored,
592− });
593−
594− return yield* host.sources.refreshCatalog(createdSource.id);
595− }),
596− updateSource: (input) =>
597− Effect.gen(function* () {
598− const source = yield* host.sources.get(input.sourceId as Source["id"]);
599− if (source.kind !== "openapi") {
600− return yield* Effect.fail(
601− new Error(`Source ${input.sourceId} is not an OpenAPI source.`),
602− );
603− }
604−
605− const nextStored = createStoredSourceData(input.config);
606− const savedSource = yield* host.sources.save({
607− ...source,
608− name: input.config.name.trim(),
609− namespace: deriveOpenApiNamespace({
610− specUrl: input.config.specUrl,
611− title: input.config.name,
612− }),
613− });
614−
615− yield* options.storage.put({
616− scopeId: savedSource.scopeId,
617− sourceId: savedSource.id,
618− value: nextStored,
619− });
620−
621− return yield* host.sources.refreshCatalog(savedSource.id);
622− }),
623− removeSource: (sourceId) =>
624− Effect.gen(function* () {
625− const source = yield* host.sources.get(sourceId);
626− if (source.kind !== "openapi") {
627− return yield* Effect.fail(
628− new Error(`Source ${sourceId} is not an OpenAPI source.`),
629− );
630− }
631−
632− if (options.storage.remove) {
633− yield* options.storage.remove({
634− scopeId: source.scopeId,
635− sourceId: source.id,
636− });
637− }
638−
639− return yield* host.sources.remove(source.id);
640− }),
641− }),
683+ getSourceConfig: (sourceId) =>
684+ provideRuntime(sourceSdk.getSourceConfig(sourceId)),
685+ createSource: (input) =>
686+ provideRuntime(sourceSdk.createSource(input)),
687+ updateSource: (input) =>
688+ provideRuntime(sourceSdk.updateSource(input)),
689+ removeSource: (sourceId) =>
690+ provideRuntime(sourceSdk.removeSource(sourceId)),
691+ };
692+ },
642693 });

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t