import * as Schema from "effect/Schema"; import { createSourceAdapterRegistry } from "./registry"; import type { SourceAdapter, SourceAdapterInputSchema } from "./types"; type SchemaTypeOf = TSchema extends { readonly Type: infer T } ? T : never; type AdapterUnion = TAdapters[number]; type ConnectPayloadSchema = NonNullable["connectPayloadSchema"]>; type ExecutorAddInputSchema = NonNullable["executorAddInputSchema"]>; export type ConnectableSourceAdapter = TAdapter & { connectPayloadSchema: SourceAdapterInputSchema; }; export type ExecutorAddableSourceAdapter = TAdapter & { executorAddInputSchema: SourceAdapterInputSchema; }; export type LocalConfigurableSourceAdapter = TAdapter & { localConfigBindingSchema: SourceAdapterInputSchema; }; const isConnectableSourceAdapter = ( adapter: TAdapter, ): adapter is ConnectableSourceAdapter => adapter.connectPayloadSchema !== null; const isExecutorAddableSourceAdapter = ( adapter: TAdapter, ): adapter is ExecutorAddableSourceAdapter => adapter.executorAddInputSchema !== null; const isLocalConfigurableSourceAdapter = ( adapter: TAdapter, ): adapter is LocalConfigurableSourceAdapter => adapter.localConfigBindingSchema !== null; const asSchemaTuple = ( schemas: ReadonlyArray>, ): [ Schema.Schema, Schema.Schema, ...Array>, ] => schemas as [ Schema.Schema, Schema.Schema, ...Array>, ]; const createSchemaFromAdapters = ( schemas: ReadonlyArray, label: string, ): TSchema => (schemas.length === 0 ? (() => { throw new Error(`Cannot create ${label} without any schemas`); })() : schemas.length === 1 ? schemas[0]! : Schema.Union(...asSchemaTuple(schemas))) as TSchema; export const createSourceAdapterComposition = ( adapters: TAdapters, ) => { const connectableSourceAdapters = adapters.filter(isConnectableSourceAdapter); const executorAddableSourceAdapters = adapters.filter(isExecutorAddableSourceAdapter); const localConfigurableSourceAdapters = adapters.filter(isLocalConfigurableSourceAdapter); const registry = createSourceAdapterRegistry(adapters); return { connectableSourceAdapters, connectPayloadSchema: createSchemaFromAdapters( connectableSourceAdapters.map((adapter) => adapter.connectPayloadSchema), "connect payload schema", ) as Schema.Schema>, any, never>, executorAddableSourceAdapters, executorAddInputSchema: createSchemaFromAdapters( executorAddableSourceAdapters.map((adapter) => adapter.executorAddInputSchema), "executor add input schema", ) as Schema.Schema>, any, never>, localConfigurableSourceAdapters, ...registry, }; }; export type SourceAdapterComposition = ReturnType;