@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
TypeScript
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 };