UNPKG

@loqate/compose

Version:

Loqate Compose SDK — high-level flows that compose base API clients into easy-to-use sessions.

513 lines (505 loc) 18.3 kB
import { RequestOptions } from '@loqate/core/lib/sdks.js'; import { CleansingInternationalBatchServiceResponseItemMatch, CaptureInteractiveFindResponseItem, CleansingInternationalBatchServiceRequestAddress, CaptureInteractiveRetrieveResponseItem, CleansingInternationalBatchServiceResponseItem, EmailValidationInteractiveValidateResponseItem, EmailValidationBatchValidateResponseItem, PhoneNumberValidationInteractiveValidateResponseItem, LocationServicesDistanceFinderNearbyExternalResponseDestinationLocation, LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem, LocationServicesDistanceFinderNearbyPointData } from '@loqate/core/models'; export { CaptureInteractiveFindResponseItem, CaptureInteractiveRetrieveResponseItem, CleansingInternationalBatchServiceRequestAddress, CleansingInternationalBatchServiceResponseItem, CleansingInternationalBatchServiceResponseItemMatch, EmailValidationBatchValidateResponseItem, EmailValidationInteractiveValidateResponseItem, LocationServicesDistanceFinderNearbyExternalResponseDestinationLocation, LocationServicesDistanceFinderNearbyPointData, LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem, PhoneNumberValidationInteractiveValidateResponseItem } from '@loqate/core/models'; import { CaptureInteractiveFindRequest, CaptureInteractiveRetrieveRequest, VerifyServiceRequest, EmailValidationInteractiveValidateRequest, EmailValidationBatchValidateRequest, PhoneNumberValidationInteractiveValidateRequest, NearByRequest, TypeAheadGeocodingRequest, ExternalResponse } from '@loqate/core/models/operations'; export { CaptureInteractiveFindRequest, CaptureInteractiveRetrieveRequest, EmailValidationBatchValidateRequest, EmailValidationInteractiveValidateRequest, ExternalResponse, NearByRequest, PhoneNumberValidationInteractiveValidateRequest, TypeAheadGeocodingRequest, VerifyServiceRequest } from '@loqate/core/models/operations'; import { P as ParsedAVC, M as MatchRule } from './evaluator.d-B24x91Nd.js'; import { Emitter, Handler, WildcardHandler } from 'mitt'; type Unsubscribe = () => void; type Selector< T, S > = (state: T) => S; type EqualityFn<T> = (a: T, b: T) => boolean; type DeepPartial<T> = T extends Function ? T : T extends Array<infer U> ? Array<DeepPartial<U>> : T extends object ? { [K in keyof T]? : DeepPartial<T[K]> } : T; type DeepStore<T extends object> = { get(): T set(next: T): void patch(delta: DeepPartial<T>): void setAt(path: (string | number)[], value: any): void reset(): void markClean(): void isDirty(): boolean subscribe(fn: () => void): Unsubscribe subscribeSel<S>(sel: Selector<T, S>, eq?: EqualityFn<S>): Unsubscribe }; interface BaseLogger { debug: (...args: unknown[]) => void; info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; error: (...args: unknown[]) => void; } /** * Generic, typed event-emitter base with optional store + state snapshot * provided to *WithStore helpers. * * E: event map (key -> payload type) * S: state shape (your snapshot) * TStore: store interface you want to expose (can be read-only) */ declare abstract class Eventful< E extends Record<string, any>, S, TStore, TLogger extends BaseLogger = BaseLogger > { protected readonly emitter: Emitter<E>; protected readonly logger: TLogger; protected constructor(logger?: TLogger); /** Subclasses must provide a current snapshot for WithStore helpers. */ protected abstract getState(): S; /** Subclasses must provide a store reference (or a facade) for WithStore helpers. */ protected abstract getStore(): TStore; on<K extends keyof E>(type: K, handler: Handler<E[K]>): () => void; off<K extends keyof E>(type: K, handler: Handler<E[K]>): void; once<K extends keyof E>(type: K, handler: Handler<E[K]>): () => void; onAny(handler: WildcardHandler<E>): () => void; offAny(handler: WildcardHandler<E>): void; onceAny(handler: WildcardHandler<E>): () => void; onWithStore<K extends keyof E>(type: K, handler: (payload: E[K], ctx: { store: TStore state: S }) => void): () => void; onceWithStore<K extends keyof E>(type: K, handler: (payload: E[K], ctx: { store: TStore state: S }) => void): () => void; onAnyWithStore(handler: (type: keyof E, payload: E[keyof E], ctx: { store: TStore state: S }) => void): () => void; onceAnyWithStore(handler: (type: keyof E, payload: E[keyof E], ctx: { store: TStore state: S }) => void): () => void; /** Protected emit for subclasses. Keeps external API clean. */ protected emit<K extends keyof E>(type: K, payload: E[K]): void; } type VerifyComposedMatch = { match: CleansingInternationalBatchServiceResponseItemMatch | null parsedAVC: ParsedAVC | null evaluation: "pass" | "review" | "fail" }; type AddressSessionInit = { apiKey: string logger?: BaseLogger biasing?: { country?: string location?: { latitude?: number longitude?: number } } capture?: { mappings?: CaptureAddressMapping[] find?: { debounceMs?: number request?: Partial<CaptureInteractiveFindRequest> } retrieve?: { request?: Partial<CaptureInteractiveRetrieveRequest> } } verify?: { request?: Partial<VerifyServiceRequest> outputMappings?: VerifyOutputAddressMapping[] inputMappings?: VerifyInputAddressMapping[] evalution?: { pass?: MatchRule review?: MatchRule } } }; type OutputMap = Record<string, string | undefined>; type AddressSessionState = { findCount: number apiKey: string retrieveCount: number verifyCount: number isCleanCapture: boolean biasing?: { country?: string location?: { latitude?: number longitude?: number } } outMap?: { captureClean?: boolean verifyClean?: boolean map?: OutputMap } verify: { request?: Omit<VerifyServiceRequest, "addresses"> response?: VerifyComposedMatch[] requestHistory: { request: VerifyServiceRequest options?: RequestOptions }[] outputMappings: VerifyOutputAddressMapping[] inputMappings: VerifyInputAddressMapping[] evaluation: { pass: MatchRule review: MatchRule } } capture: { retrieve: { request?: Omit<CaptureInteractiveRetrieveRequest, "id"> mappings: CaptureAddressMapping[] items?: CaptureInteractiveRetrieveResponseItem[] debounceMs?: number requestHistory: { request: CaptureInteractiveRetrieveRequest options?: RequestOptions }[] } find: { request?: Omit<CaptureInteractiveFindRequest, "text" | "container"> currentContainer?: string searchText: string requestHistory: { request: CaptureInteractiveFindRequest options?: RequestOptions }[] items?: CaptureInteractiveFindResponseItem[] debounceMs?: number } } }; type CaptureAddressMapping = { id: string field?: string | keyof CaptureInteractiveFindResponseItem }; type VerifyOutputAddressMapping = { id: string field?: string | keyof CleansingInternationalBatchServiceResponseItemMatch }; type VerifyInputAddressMapping = { id: string field?: keyof CleansingInternationalBatchServiceRequestAddress }; type AddressSessionStateStore = DeepStore<AddressSessionState>; type AddressSessionEvents = { "bias:changed": AddressSessionState["biasing"] "find:request": { request: CaptureInteractiveFindRequest } "find:response": { request: CaptureInteractiveFindRequest items: CaptureInteractiveFindResponseItem[] } "find:expandContainer": string "retrieve:request": { request: CaptureInteractiveRetrieveRequest } "retrieve:response": { request: CaptureInteractiveRetrieveRequest items: CaptureInteractiveRetrieveResponseItem[] map: OutputMap | undefined } "verify:request": { request: VerifyServiceRequest } "verify:response": { request: VerifyServiceRequest raw: CleansingInternationalBatchServiceResponseItem[] composed: VerifyComposedMatch[] } "map:updated": OutputMap "state:changed": AddressSessionState error: unknown }; declare class AddressSession extends Eventful<AddressSessionEvents, AddressSessionState, AddressSessionStateStore> { private _loqate; private _store; constructor(init: AddressSessionInit); protected getState(): AddressSessionState; protected getStore(): AddressSessionStateStore; /** Patch store and emit a single 'state:changed'. */ private _patch; private _biasChanged; biasToIP(ip?: string): Promise<void>; biasToCountry(country: string): void; biasToLocation(lat: number, lon: number): void; subscribe<S>(sel: (s: AddressSessionState) => S, onChange: (slice: S, store: DeepStore<AddressSessionState>) => void, eq?: (a: S, b: S) => boolean): () => void; private _generateOutMap; private _generateCaptureMappingMap; private _generateVerifyMappingMap; select(item: CaptureInteractiveFindResponseItem | number): Promise<void>; expandContainer(container: string | CaptureInteractiveFindResponseItem | number): Promise<CaptureInteractiveFindResponseItem[]>; updateMapFields(updates: { id: string value: string }[]): OutputMap; updateMapField(id: string, value: string): OutputMap; private _generateVerifyInputAddress; acceptVerifyResponse(): OutputMap; verify(options?: { force?: boolean country?: string }): Promise<{ raw: CleansingInternationalBatchServiceResponseItem[] map?: OutputMap composed: VerifyComposedMatch[] }>; retrieve(request: CaptureInteractiveRetrieveRequest | CaptureInteractiveFindResponseItem | string | number, options?: RequestOptions): Promise<{ raw: CaptureInteractiveRetrieveResponseItem[] map?: OutputMap }>; private _generateBiasParams; private _findTimer; private _findPendingResolves; private _findPendingRejects; /** * Single public find method: * - If debounceMs <= 0: runs immediately. * - If debounceMs > 0: debounces and coalesces callers. */ find(request: CaptureInteractiveFindRequest | string, options?: RequestOptions): Promise<CaptureInteractiveFindResponseItem[]>; /** * Internal, immediate execution used by find(). */ private _doFind; } type EmailSessionInit = { apiKey: string logger?: BaseLogger validate?: { request?: Partial<EmailValidationInteractiveValidateRequest> } batch?: { request?: Partial<EmailValidationBatchValidateRequest> } }; type EmailSessionState = { validateCount: number batchCount: number apiKey: string validate: { email?: string request?: Omit<EmailValidationInteractiveValidateRequest, "email"> response?: EmailValidationInteractiveValidateResponseItem[] requestHistory: { request: EmailValidationInteractiveValidateRequest options?: RequestOptions }[] } batch: { emails?: string[] request?: Omit<EmailValidationBatchValidateRequest, "emails"> response?: EmailValidationBatchValidateResponseItem[] requestHistory: { request: EmailValidationBatchValidateRequest options?: RequestOptions }[] } }; type EmailSessionStateStore = DeepStore<EmailSessionState>; type EmailSessionEvents = { "validate:request": { request: EmailValidationInteractiveValidateRequest } "validate:response": { request: EmailValidationInteractiveValidateRequest response: EmailValidationInteractiveValidateResponseItem[] } "batch:request": { request: EmailValidationBatchValidateRequest } "batch:response": { request: EmailValidationBatchValidateRequest response: EmailValidationBatchValidateResponseItem[] } "state:changed": EmailSessionState error: unknown }; declare class EmailSession extends Eventful<EmailSessionEvents, EmailSessionState, EmailSessionStateStore> { private _loqate; private _store; constructor(init: EmailSessionInit); protected getState(): EmailSessionState; protected getStore(): EmailSessionStateStore; /** Patch store and emit a single 'state:changed'. */ private _patch; subscribe<S>(sel: (s: EmailSessionState) => S, onChange: (slice: S, store: DeepStore<EmailSessionState>) => void, eq?: (a: S, b: S) => boolean): () => void; validate(request: EmailValidationInteractiveValidateRequest | string, options?: RequestOptions): Promise<EmailValidationInteractiveValidateResponseItem[]>; batch(request: EmailValidationBatchValidateRequest | string[] | string, options?: RequestOptions): Promise<EmailValidationBatchValidateResponseItem[]>; } type PhoneSessionInit = { apiKey: string logger?: BaseLogger validate?: { request?: Partial<PhoneNumberValidationInteractiveValidateRequest> } }; type PhoneSessionState = { validateCount: number apiKey: string validate: { phoneNumber?: string request?: Omit<PhoneNumberValidationInteractiveValidateRequest, "phone"> response?: PhoneNumberValidationInteractiveValidateResponseItem[] requestHistory: { request: PhoneNumberValidationInteractiveValidateRequest options?: RequestOptions }[] } }; type PhoneSessionStateStore = DeepStore<PhoneSessionState>; type PhoneSessionEvents = { "validate:request": { request: PhoneNumberValidationInteractiveValidateRequest } "validate:response": { request: PhoneNumberValidationInteractiveValidateRequest response: PhoneNumberValidationInteractiveValidateResponseItem[] } "state:changed": PhoneSessionState error: unknown }; declare class PhoneSession extends Eventful<PhoneSessionEvents, PhoneSessionState, PhoneSessionStateStore> { private _loqate; private _store; constructor(init: PhoneSessionInit); protected getState(): PhoneSessionState; protected getStore(): PhoneSessionStateStore; /** Patch store and emit a single 'state:changed'. */ private _patch; subscribe<S>(sel: (s: PhoneSessionState) => S, onChange: (slice: S, store: DeepStore<PhoneSessionState>) => void, eq?: (a: S, b: S) => boolean): () => void; validate(request: PhoneNumberValidationInteractiveValidateRequest | string, options?: RequestOptions): Promise<PhoneNumberValidationInteractiveValidateResponseItem[]>; } type StoreFinderSessionInit = { apiKey: string logger?: BaseLogger selectedLocation?: { latitude: number longitude: number } biasing?: { country?: string location?: { latitude?: number longitude?: number } } nearby?: { request?: Partial<NearByRequest> } typeahead?: { find?: { request?: Partial<TypeAheadGeocodingRequest> } retrieve?: { request?: Partial<TypeAheadGeocodingRequest> } } }; type StoreFinderSessionState = { apiKey: string biasing?: { country?: string location?: { latitude?: number longitude?: number } } destinationStores?: LocationServicesDistanceFinderNearbyExternalResponseDestinationLocation[] selectedLocation?: { latitude: number longitude: number } nearby?: { count: number request?: Partial<NearByRequest> response?: any requestHistory: { request: NearByRequest options?: RequestOptions }[] } typeahead?: { count: number find?: { count: number searchText?: string request?: Partial<TypeAheadGeocodingRequest> response?: LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem[] requestHistory: { request: TypeAheadGeocodingRequest options?: RequestOptions }[] } retrieve?: { count: number addressID?: string request?: Partial<TypeAheadGeocodingRequest> response?: LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem requestHistory: { request: TypeAheadGeocodingRequest options?: RequestOptions }[] } } }; type StoreFinderSessionStateStore = DeepStore<StoreFinderSessionState>; type StoreFinderSessionEvents = { "bias:changed": StoreFinderSessionState["biasing"] "location:changed": StoreFinderSessionState["selectedLocation"] "locationList:changed": { locationListId?: string locations?: LocationServicesDistanceFinderNearbyPointData[] } "destinationStores:changed": LocationServicesDistanceFinderNearbyExternalResponseDestinationLocation[] "typeahead:find:request": { request: TypeAheadGeocodingRequest } "typeahead:find:response": { request: TypeAheadGeocodingRequest response: LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem[] } "typeahead:retrieve:request": { request: TypeAheadGeocodingRequest } "typeahead:retrieve:response": { request: TypeAheadGeocodingRequest response: LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem[] item: LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem | undefined } "nearby:request": { request: NearByRequest } "nearby:response": { request: NearByRequest response: ExternalResponse } "state:changed": StoreFinderSessionState error: unknown }; declare class StoreFinderSession extends Eventful<StoreFinderSessionEvents, StoreFinderSessionState, StoreFinderSessionStateStore> { private _loqate; private _store; constructor(init: StoreFinderSessionInit); protected getState(): StoreFinderSessionState; protected getStore(): StoreFinderSessionStateStore; /** Patch store and emit a single 'state:changed'. */ private _patch; private _biasChanged; private _locationChanged; private _locationListChanged; biasToIP(ip?: string): Promise<void>; biasToCountry(country: string): void; biasToLocation(lat: number, lon: number): void; subscribe<S>(sel: (s: StoreFinderSessionState) => S, onChange: (slice: S, store: DeepStore<StoreFinderSessionState>) => void, eq?: (a: S, b: S) => boolean): () => void; private _generateBiasParams; updateLocation(latitude: number, longitude: number): void; updateLocationList(args: { locationListId?: string locations?: LocationServicesDistanceFinderNearbyPointData[] }): void; nearby(): Promise<ExternalResponse>; retrieve(request: TypeAheadGeocodingRequest | LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem | string | number, options?: RequestOptions): Promise<LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem>; find(request: TypeAheadGeocodingRequest | string, options?: RequestOptions): Promise<LocationServicesGeocodingGlobalTypeAheadExternalTypeaheadResponseItem[]>; } export { AddressSession, EmailSession, PhoneSession, StoreFinderSession }; export type { AddressSessionEvents, AddressSessionInit, AddressSessionState, AddressSessionStateStore, CaptureAddressMapping, EmailSessionEvents, EmailSessionInit, EmailSessionState, EmailSessionStateStore, OutputMap, PhoneSessionEvents, PhoneSessionInit, PhoneSessionState, PhoneSessionStateStore, StoreFinderSessionEvents, StoreFinderSessionInit, StoreFinderSessionState, StoreFinderSessionStateStore, VerifyComposedMatch, VerifyInputAddressMapping, VerifyOutputAddressMapping };