import {z} from 'zod' export type GetApiApiPropfirmsOffersQueryArgs = {offerId?: string | undefined, promoCode?: string | undefined, offerText?: string | undefined, isActive?: ('true' | 'false') | undefined, isFeatured?: ('true' | 'false') | undefined, discountIsPercent?: ('true' | 'false') | undefined, discountMin?: string | undefined, discountMax?: string | undefined, includeInactive?: ('true' | 'false') | undefined, includeExpired?: ('true' | 'false') | undefined, pageIndex?: string | undefined, pageQuantity?: string | undefined, direction?: ('asc' | 'desc') | undefined, text?: string | undefined, firmId?: string | undefined, propfirmId?: string | undefined, challengeId?: string | undefined, sort?: ('discountValue' | 'endsAt' | 'promoCode') | undefined}; export type GetApiApiPropfirmsOffersQueryOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const getApiApiPropfirmsOffersQueryResponse = z.object({data: z.object({offers: z.array(z.object({offerId: z.string(), firmId: z.string(), propfirmId: z.string(), propfirmName: z.string(), promoCode: z.string().nullable(), affiliateLink: z.string().nullable(), discountIsPercent: z.boolean(), discountValue: z.number().nullable(), shortDescription: z.string().nullable(), fullDescription: z.string().nullable(), isActive: z.boolean(), isFeatured: z.boolean(), hasEndDate: z.boolean(), endsAt: z.string().nullable(), scope: z.union([z.object({type: z.literal("all_challenges")}), z.object({type: z.literal("specific_challenges"), challengeIds: z.array(z.string())})])})), count: z.number()}), errors: z.unknown()}); 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 }; /** * Public: search promotional offers across visible firms. Defaults to live (active, unexpired) offers. Pass propfirmId for one firm's offers, or challengeId for offers that apply to a challenge (firm-wide offers included). * * GET /api/propfirms/offers/query */ export const getApiApiPropfirmsOffersQuery = async (args: GetApiApiPropfirmsOffersQueryArgs, options?: GetApiApiPropfirmsOffersQueryOptions) => { const {baseUrl = "https://app.luxalgo.com", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.offerId != null) query.append("offerId", String(args.offerId)) if (args.promoCode != null) query.append("promoCode", String(args.promoCode)) if (args.offerText != null) query.append("offerText", String(args.offerText)) if (args.isActive != null) query.append("isActive", String(args.isActive)) if (args.isFeatured != null) query.append("isFeatured", String(args.isFeatured)) if (args.discountIsPercent != null) query.append("discountIsPercent", String(args.discountIsPercent)) if (args.discountMin != null) query.append("discountMin", String(args.discountMin)) if (args.discountMax != null) query.append("discountMax", String(args.discountMax)) if (args.includeInactive != null) query.append("includeInactive", String(args.includeInactive)) if (args.includeExpired != null) query.append("includeExpired", String(args.includeExpired)) if (args.pageIndex != null) query.append("pageIndex", String(args.pageIndex)) if (args.pageQuantity != null) query.append("pageQuantity", String(args.pageQuantity)) if (args.direction != null) query.append("direction", String(args.direction)) if (args.text != null) query.append("text", String(args.text)) if (args.firmId != null) query.append("firmId", String(args.firmId)) if (args.propfirmId != null) query.append("propfirmId", String(args.propfirmId)) if (args.challengeId != null) query.append("challengeId", String(args.challengeId)) if (args.sort != null) query.append("sort", String(args.sort)) const url = `${baseUrl.replace(/\/+$/, '')}/api/propfirms/offers/query${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(getApiApiPropfirmsOffersQueryResponse, await res.json()) };