import {z} from 'zod' export type GetApiV1IndexesIndexChangesArgs = {index: string, limit?: number | undefined, offset?: number | undefined}; export type GetApiV1IndexesIndexChangesOptions = {baseUrl?: string | undefined, ApiKey?: string | undefined, fetch?: typeof fetch | undefined}; export const listingNotice = z.object({status: z.string().nullable().optional(), ticker: z.string().nullable().optional(), delistedOn: z.string().nullable().optional(), successorTicker: z.string().nullable().optional()}); export const indexChangeDto = z.object({direction: z.string().nullable().optional(), name: z.string().nullable().optional(), ticker: z.string().nullable().optional(), isLinked: z.boolean().optional(), observedAsOfDate: z.string().optional(), previousAsOfDate: z.string().optional(), weight: z.number().optional(), sourceCount: z.number().int().optional()}); export const pageMeta = z.object({limit: z.number().int().optional(), offset: z.number().int().optional(), count: z.number().int().optional(), hasMore: z.boolean().optional(), total: z.number().int().nullable().optional()}); export const indexChangeDtoPagedResponse = z.object({listingNotice: listingNotice.optional(), data: z.array(indexChangeDto).nullable().optional(), meta: pageMeta.optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Companies that joined or left an index, newest first. Derived by comparing consecutive lists from the funds that track it, so each change is dated to the window between two reports (previousAsOfDate to observedAsOfDate) rather than to an announcement. Records from several funds for the same company and direction over overlapping windows are collapsed into one event, keeping the narrowest window. * * GET /v1/indexes/{index}/changes */ export const getApiV1IndexesIndexChanges = async (args: GetApiV1IndexesIndexChangesArgs, options?: GetApiV1IndexesIndexChangesOptions) => { const {baseUrl = "https://api.equibles.com", fetch: fetchFn = fetch, ApiKey} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.limit != null) query.append("limit", String(args.limit)) if (args.offset != null) query.append("offset", String(args.offset)) if (ApiKey !== undefined) headers.set('authorization', `Bearer ${ApiKey}`) const url = `${baseUrl.replace(/\/+$/, '')}/v1/indexes/${encodeURIComponent(String(args.index))}/changes${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(indexChangeDtoPagedResponse, await res.json()) };