History

feat(plugins): consolidate icon URL handling

- Remove configInput parameter from toConfigSource and toConfig - Centralize iconUrl handling in scopeConfigSourceBaseFromSource - Remove configuredIconUrlFromConfigInput utility (moved to source-core) - Simplify iconUrl handling with optional chaining trim pattern - Re-export getFaviconUrlForRemoteUrl from source-core in plugin shared modules

Saatvik Arya committed 7 months ago

Commit 9dcd6461 parent 27ebe8610 files · +32 −66Browse files

Unified · Split

10 files
  1. packages/platform/sdk/src/plugins.ts +6 −11
  2. packages/platform/sdk/src/runtime/sources/source-definitions.ts +2 −6
  3. packages/platform/sdk/src/runtime/sources/source-icon.ts +2 −11
  4. packages/platform/sdk/src/runtime/sources/source-store/config.ts +5 −2
  5. packages/platform/sdk/src/runtime/sources/source-store/plugin-scope-config.ts +0 −9
  6. plugins/graphql/sdk/index.ts +5 −7
  7. plugins/graphql/shared/index.ts +1 −0
  8. plugins/mcp/sdk/index.ts +5 −13
  9. plugins/mcp/shared/index.ts +1 −0
  10. plugins/openapi/sdk/index.ts +5 −7
packages/platform/sdk/src/plugins.ts+6−11
@@ -294,7 +294,6 @@ export type ExecutorSourcePluginDefinition< · 293 unmodified lines
294294 toConfig: (input: {
295295 source: ExecutorSource;
296296 stored: TStored;
297− configSource: ExecutorScopeConfigSource | null;
298297 }) => TSourceConfig;
299298 remove?: (input: {
300299 source: ExecutorSource;
@@ -305,7 +304,6 @@ export type ExecutorSourcePluginDefinition< · 4 unmodified lines
305304 toConfigSource: (input: {
306305 source: ExecutorSource;
307306 stored: TStored;
308− configInput: TConnectInput | TSourceConfig | null;
309307 }) => ExecutorScopeConfigSource;
310308 recoverStored: (input: {
311309 source: ExecutorSource;
@@ -610,7 +608,6 @@ const persistSourceScopeConfig = < · 298 unmodified lines
610608 input: {
611609 source: ExecutorSource;
612610 stored: TStored;
613− configInput: TConnectInput | TSourceConfig | null;
614611 },
615612 ): Effect.Effect<void, Error, ScopeConfigStore> =>
616613 definition.scopeConfig
@@ -619,12 +616,12 @@ const persistSourceScopeConfig = < · 2 unmodified lines
619616 const scopeConfigStore = yield* ScopeConfigStore;
620617 const loadedConfig = yield* scopeConfigStore.load();
621618 const projectConfig = cloneJson(loadedConfig.projectConfig ?? {});
619+
622620 const sources = {
623621 ...projectConfig.sources,
624622 [input.source.id]: scopeConfig.toConfigSource({
625623 source: input.source,
626624 stored: input.stored,
627− configInput: input.configInput,
628625 }),
629626 };
630627
@@ -737,12 +734,12 @@ const createExecutorSourcePluginApi = < · 106 unmodified lines
737734
738735 const scopeConfigStore = yield* ScopeConfigStore;
739736 const loadedConfig = yield* scopeConfigStore.load();
737+ const iconUrl = loadedConfig.config?.sources?.[source.id]?.iconUrl;
740738
741− return definition.source.toConfig({
742− source,
743− stored,
744− configSource: loadedConfig.config?.sources?.[source.id] ?? null,
745− });
739+ return {
740+ ...definition.source.toConfig({ source, stored }),
741+ ...(iconUrl ? { iconUrl } : {}),
742+ };
746743 }),
747744 createSource: (input) =>
748745 Effect.gen(function* () {
@@ -759,7 +756,6 @@ const createExecutorSourcePluginApi = < · 10 unmodified lines
759756 yield* persistSourceScopeConfig(definition, {
760757 source,
761758 stored: created.stored,
762− configInput: input,
763759 });
764760
765761 return yield* host.sources.refreshCatalog(source.id);
@@ -784,7 +780,6 @@ const createExecutorSourcePluginApi = < · 18 unmodified lines
784780 yield* persistSourceScopeConfig(definition, {
785781 source: saved,
786782 stored: updated.stored,
787− configInput: input.config,
788783 });
789784
790785 return yield* host.sources.refreshCatalog(saved.id);
packages/platform/sdk/src/runtime/sources/source-definitions.ts+2−6
@@ -126,9 +126,7 @@ export const normalizeSourceForCreate = (input: { · 125 unmodified lines
126126 status: input.source.status,
127127 enabled: input.source.enabled,
128128 namespace: trimOrNull(input.source.namespace),
129− ...(trimOrNull(input.source.iconUrl)
130− ? { iconUrl: trimOrNull(input.source.iconUrl) ?? undefined }
131− : {}),
129+ ...(input.source.iconUrl?.trim() ? { iconUrl: input.source.iconUrl.trim() } : {}),
132130 createdAt: input.now,
133131 updatedAt: input.now,
134132 });
@@ -141,9 +139,7 @@ export const normalizeSourceForSave = (input: { · 6 unmodified lines
141139 ...input.source,
142140 name: input.source.name.trim(),
143141 namespace: trimOrNull(input.source.namespace),
144− ...(trimOrNull(input.source.iconUrl)
145− ? { iconUrl: trimOrNull(input.source.iconUrl) ?? undefined }
146− : {}),
142+ ...(input.source.iconUrl?.trim() ? { iconUrl: input.source.iconUrl.trim() } : {}),
147143 updatedAt: input.now,
148144 });
149145
packages/platform/sdk/src/runtime/sources/source-icon.ts+2−11
@@ -1,18 +1,9 @@
11 import {
22 getFaviconUrlForRemoteUrl,
3+ isRecord,
34 } from "@executor/source-core";
45
5−const trimOrNull = (value: string | null | undefined): string | null => {
6− if (value == null) {
7− return null;
8− }
9−
10− const trimmed = value.trim();
11− return trimmed.length > 0 ? trimmed : null;
12−};
13−
14−const isRecord = (value: unknown): value is Record<string, unknown> =>
15− typeof value === "object" && value !== null && !Array.isArray(value);
6+import { trimOrNull } from "./source-store/config";
167
178 export const resolveSourceIconUrl = (input: {
189 configuredIconUrl?: string | null;
packages/platform/sdk/src/runtime/sources/source-store/config.ts+5−2
@@ -47,6 +47,9 @@ export const scopeConfigSourceBaseFromSource = (input: { · 46 unmodified lines
4747 ...(trimOrNull(input.source.namespace) !== trimOrNull(input.source.id)
4848 ? { namespace: input.source.namespace ?? undefined }
4949 : {}),
50+ ...(input.source.iconUrl?.trim()
51+ ? { iconUrl: input.source.iconUrl.trim() }
52+ : {}),
5053 ...(input.source.enabled === false ? { enabled: false } : {}),
5154 });
5255
@@ -58,8 +61,8 @@ export const scopeConfigSourceFromSource = (input: { · 5 unmodified lines
5861 ...scopeConfigSourceBaseFromSource({
5962 source: input.source,
6063 }),
61− ...(trimOrNull(input.existingConfig?.iconUrl)
62− ? { iconUrl: trimOrNull(input.existingConfig?.iconUrl) ?? undefined }
64+ ...(input.existingConfig?.iconUrl?.trim()
65+ ? { iconUrl: input.existingConfig.iconUrl.trim() }
6366 : {}),
6467 kind: input.source.kind as ExecutorScopeConfigSource["kind"],
6568 ...(input.existingConfig?.config !== undefined
packages/platform/sdk/src/runtime/sources/source-store/plugin-scope-config.ts+0−9
@@ -29,19 +29,10 @@ export const createPluginScopeConfigEntrySchema = < · 28 unmodified lines
2929 export const pluginScopeConfigSourceFromConfig = <TConfig>(input: {
3030 source: Source;
3131 config: TConfig;
32− iconUrl?: string | null;
3332 }): ExecutorScopeConfigSource => ({
3433 ...scopeConfigSourceBaseFromSource({
3534 source: input.source,
3635 }),
37− ...(input.iconUrl ? { iconUrl: input.iconUrl } : {}),
3836 kind: input.source.kind as ExecutorScopeConfigSource["kind"],
3937 config: cloneJson(input.config),
4038 });
41−
42−export const configuredIconUrlFromConfigInput = (input: unknown): string | null =>
43− input && typeof input === "object" && "iconUrl" in input
44− ? (typeof input.iconUrl === "string"
45− ? input.iconUrl.trim() || null
46− : null)
47− : null;
plugins/graphql/sdk/index.ts+5−7
@@ -23,7 +23,6 @@ import { · 22 unmodified lines
2323 } from "@executor/platform-sdk/plugins";
2424 import {
2525 SecretMaterialResolverService,
26− configuredIconUrlFromConfigInput,
2726 createPluginScopeConfigEntrySchema,
2827 pluginScopeConfigSourceFromConfig,
2928 provideExecutorRuntime,
@@ -320,10 +319,8 @@ const storedSourceDataFromInput = ( · 290 unmodified lines
320319 const sourceConfigFromStored = (
321320 source: Source,
322321 stored: GraphqlStoredSourceData,
323− configSource: { iconUrl?: string } | null,
324322 ): GraphqlSourceConfigPayload => ({
325323 name: source.name,
326− ...(configSource?.iconUrl ? { iconUrl: configSource.iconUrl } : {}),
327324 endpoint: stored.endpoint,
328325 defaultHeaders: stored.defaultHeaders,
329326 auth: stored.auth,
@@ -385,6 +382,7 @@ export const graphqlSdkPlugin = (options: { · 55 unmodified lines
385382 endpoint: input.endpoint,
386383 title: input.name,
387384 }),
385+ ...(input.iconUrl?.trim() ? { iconUrl: input.iconUrl.trim() } : {}),
388386 },
389387 stored: storedSourceDataFromInput(input),
390388 }),
@@ -396,18 +394,18 @@ export const graphqlSdkPlugin = (options: { · 5 unmodified lines
396394 endpoint: config.endpoint,
397395 title: config.name,
398396 }),
397+ ...(config.iconUrl?.trim() ? { iconUrl: config.iconUrl.trim() } : {}),
399398 },
400399 stored: storedSourceDataFromInput(config),
401400 }),
402− toConfig: ({ source, stored, configSource }) =>
403− sourceConfigFromStored(source, normalizeStoredSourceData(stored), configSource),
401+ toConfig: ({ source, stored }) =>
402+ sourceConfigFromStored(source, normalizeStoredSourceData(stored)),
404403 },
405404 scopeConfig: {
406− toConfigSource: ({ source, stored, configInput }) =>
405+ toConfigSource: ({ source, stored }) =>
407406 pluginScopeConfigSourceFromConfig({
408407 source,
409408 config: normalizeStoredSourceData(stored),
410− iconUrl: configuredIconUrlFromConfigInput(configInput),
411409 }),
412410 recoverStored: ({ config, loadedConfig }) =>
413411 graphqlStoredSourceDataFromLocalConfig({
plugins/graphql/shared/index.ts+1−0
@@ -11,6 +11,7 @@ import { · 10 unmodified lines
1111
1212 export { getFaviconUrlForRemoteUrl } from "@executor/source-core";
1313
14+
1415 export const GraphqlConnectionAuthSchema = Schema.Union(
1516 Schema.Struct({
1617 kind: Schema.Literal("none"),
plugins/mcp/sdk/index.ts+5−13
@@ -31,7 +31,6 @@ import { · 30 unmodified lines
3131 defineExecutorSourcePlugin,
3232 } from "@executor/platform-sdk/plugins";
3333 import {
34− configuredIconUrlFromConfigInput,
3534 createPluginScopeConfigEntrySchema,
3635 pluginScopeConfigSourceFromConfig,
3736 SecretMaterialDeleterService,
@@ -339,10 +338,8 @@ const normalizeStoredSourceData = ( · 301 unmodified lines
339338 const sourceConfigFromStored = (
340339 source: Source,
341340 stored: McpStoredSourceData,
342− configSource: { iconUrl?: string } | null,
343341 ): McpSourceConfigPayload => ({
344342 name: source.name,
345− ...(configSource?.iconUrl ? { iconUrl: configSource.iconUrl } : {}),
346343 endpoint: stored.endpoint,
347344 transport: stored.transport,
348345 queryParams: stored.queryParams,
@@ -692,9 +689,7 @@ export const mcpSdkPlugin = ( · 343 unmodified lines
692689 endpoint: input.endpoint,
693690 command: input.command,
694691 }),
695− ...(input.iconUrl && input.iconUrl.trim().length > 0
696− ? { iconUrl: input.iconUrl.trim() }
697− : {}),
692+ ...(input.iconUrl?.trim() ? { iconUrl: input.iconUrl.trim() } : {}),
698693 },
699694 stored: Effect.runSync(normalizeStoredSourceData(input)),
700695 }),
@@ -710,15 +705,13 @@ export const mcpSdkPlugin = ( · 9 unmodified lines
710705 endpoint: stored.endpoint,
711706 command: stored.command,
712707 }),
713− ...(config.iconUrl && config.iconUrl.trim().length > 0
714− ? { iconUrl: config.iconUrl.trim() }
715− : { iconUrl: undefined }),
708+ ...(config.iconUrl?.trim() ? { iconUrl: config.iconUrl.trim() } : {}),
716709 },
717710 stored,
718711 };
719712 },
720− toConfig: ({ source, stored, configSource }) =>
721− sourceConfigFromStored(source, stored, configSource),
713+ toConfig: ({ source, stored }) =>
714+ sourceConfigFromStored(source, stored),
722715 remove: ({ stored }) =>
723716 Effect.gen(function* () {
724717 if (stored?.auth.kind === "oauth2") {
@@ -731,11 +724,10 @@ export const mcpSdkPlugin = ( · 6 unmodified lines
731724 }),
732725 },
733726 scopeConfig: {
734− toConfigSource: ({ source, stored, configInput }) =>
727+ toConfigSource: ({ source, stored }) =>
735728 pluginScopeConfigSourceFromConfig({
736729 source,
737730 config: stored,
738− iconUrl: configuredIconUrlFromConfigInput(configInput),
739731 }),
740732 recoverStored: ({ config }) =>
741733 mcpStoredSourceDataFromLocalConfig(config),
plugins/mcp/shared/index.ts+1−0
@@ -16,6 +16,7 @@ import { · 15 unmodified lines
1616
1717 export { getFaviconUrlForRemoteUrl } from "@executor/source-core";
1818
19+
1920 export const McpConnectionAuthSchema = Schema.Union(
2021 Schema.Struct({
2122 kind: Schema.Literal("none"),
plugins/openapi/sdk/index.ts+5−7
@@ -18,7 +18,6 @@ import { · 17 unmodified lines
1818 defineExecutorSourcePlugin,
1919 } from "@executor/platform-sdk/plugins";
2020 import {
21− configuredIconUrlFromConfigInput,
2221 createPluginScopeConfigEntrySchema,
2322 pluginScopeConfigSourceFromConfig,
2423 SecretMaterialResolverService,
@@ -186,10 +185,8 @@ const createStoredSourceData = ( · 161 unmodified lines
186185 const configFromStoredSourceData = (
187186 source: Source,
188187 stored: OpenApiStoredSourceData,
189− configSource: { iconUrl?: string } | null,
190188 ): OpenApiSourceConfigPayload => ({
191189 name: source.name,
192− ...(configSource?.iconUrl ? { iconUrl: configSource.iconUrl } : {}),
193190 specUrl: stored.specUrl,
194191 baseUrl: stored.baseUrl,
195192 auth: stored.auth,
@@ -527,6 +524,7 @@ export const openApiSdkPlugin = ( · 331 unmodified lines
527524 specUrl: input.specUrl,
528525 title: input.name,
529526 }),
527+ ...(input.iconUrl?.trim() ? { iconUrl: input.iconUrl.trim() } : {}),
530528 },
531529 stored: createStoredSourceData(input),
532530 }),
@@ -538,14 +536,15 @@ export const openApiSdkPlugin = ( · 5 unmodified lines
538536 specUrl: config.specUrl,
539537 title: config.name,
540538 }),
539+ ...(config.iconUrl?.trim() ? { iconUrl: config.iconUrl.trim() } : {}),
541540 },
542541 stored: createStoredSourceData(config),
543542 }),
544− toConfig: ({ source, stored, configSource }) =>
545− configFromStoredSourceData(source, normalizeStoredSourceData(stored), configSource),
543+ toConfig: ({ source, stored }) =>
544+ configFromStoredSourceData(source, normalizeStoredSourceData(stored)),
546545 },
547546 scopeConfig: {
548− toConfigSource: ({ source, stored, configInput }) =>
547+ toConfigSource: ({ source, stored }) =>
549548 pluginScopeConfigSourceFromConfig({
550549 source,
551550 config: {
@@ -554,7 +553,6 @@ export const openApiSdkPlugin = ( · 2 unmodified lines
554553 auth: stored.auth,
555554 defaultHeaders: stored.defaultHeaders,
556555 },
557− iconUrl: configuredIconUrlFromConfigInput(configInput),
558556 }),
559557 recoverStored: ({ config, loadedConfig }) =>
560558 openApiStoredSourceDataFromLocalConfig({