import { StandardSchemaV1 } from "@standard-schema/spec";

//#region src/types/extract.d.ts
type ExtractObjectShape<T> = NonNullable<T> extends readonly unknown[] ? never : NonNullable<T> extends object ? NonNullable<T> : never;
interface ExtractNode {
  attr(name: string): string | undefined;
  html(): string | undefined;
  text(): string;
}
type ExtractValueCallback<T = unknown> = (node: ExtractNode, key: string, object: Record<string, unknown>) => T | undefined;
interface ExtractDescriptor<T = unknown> {
  selector: string;
  value?: string | ExtractValueCallback<T> | ExtractConfig<ExtractObjectShape<T>>;
}
type ExtractField<T = unknown> = string | ExtractDescriptor<T> | (T extends readonly (infer Item)[] ? [string | ExtractDescriptor<NonNullable<Item>>] : never);
type ExtractShape<T> = [T] extends [never] ? Record<string, unknown> : NonNullable<T> extends object ? NonNullable<T> : Record<string, unknown>;
type ExtractConfig<T = Record<string, unknown>> = { [K in keyof ExtractShape<T>]: ExtractField<ExtractShape<T>[K]> };
//#endregion
//#region src/types/main.d.ts
interface ScraperConfig<S extends StandardSchemaV1, R extends StandardSchemaV1.InferOutput<S> = StandardSchemaV1.InferOutput<S>> {
  extract: ExtractConfig<StandardSchemaV1.InferOutput<S>>;
  schema: S;
  transform?: (data: StandardSchemaV1.InferOutput<S>) => Promise<R> | R;
}
type ScraperResult<T> = {
  data: T;
  error?: undefined;
} | {
  data?: undefined;
  error: unknown;
};
//#endregion
//#region src/index.d.ts
declare function defineScraper<S extends StandardSchemaV1, R extends StandardSchemaV1.InferOutput<S> = StandardSchemaV1.InferOutput<S>>(config: ScraperConfig<S, R>): (html: string) => Promise<ScraperResult<R>>;
//#endregion
export { type ExtractConfig, type ExtractDescriptor, type ExtractField, type ExtractNode, type ExtractValueCallback, type ScraperConfig, type ScraperResult, defineScraper };