import {z} from 'zod' export type GetApiApiTransactionsArgs = {account_id?: (string | null) | undefined, account_ids?: (Array | null) | undefined, category_id?: (string | null) | undefined, category_ids?: (Array | null) | undefined, payee_id?: (string | null) | undefined, from?: (string | null) | undefined, to?: (string | null) | undefined, bill_id?: (string | null) | undefined, group_id?: (string | null) | undefined, unbilled_only?: boolean | undefined, statement_view?: boolean | undefined, q?: (string | null) | undefined, uncategorized?: boolean | undefined, type?: (string | null) | undefined, status?: (string | null) | undefined, page?: number | undefined, limit?: number | undefined, include_opening_balance?: boolean | undefined, include_running_balance?: boolean | undefined, exclude_transfers?: boolean | undefined, user_pnl_only?: boolean | undefined, exclude_ignored?: boolean | undefined, tags?: (Array | null) | undefined, min_amount?: (number | null) | undefined, max_amount?: (number | null) | undefined, sort_by?: (string | null) | undefined, sort_dir?: string | undefined, 'X-Workspace-Id'?: (string | null) | undefined}; export type GetApiApiTransactionsOptions = {baseUrl: string, OAuth2PasswordBearer?: string | undefined, fetch?: typeof fetch | undefined}; export const categoryRead = z.object({name: z.string(), icon: z.string().optional(), color: z.string().optional(), id: z.string(), user_id: z.string(), group_id: z.string().nullable().optional(), is_system: z.boolean(), is_hidden: z.boolean().optional(), treat_as_transfer: z.boolean().optional(), is_ignored: z.boolean().optional()}); export const transactionInvoiceLink = z.object({invoice_id: z.string(), number: z.number().int().nullable().optional(), series: z.string().nullable().optional(), external_number: z.string().nullable().optional(), amount: z.string()}); export const transactionTransferCounterpart = z.object({account_id: z.string(), account_name: z.string()}); export const transactionSplitRead = z.object({id: z.string(), transaction_id: z.string(), group_member_id: z.string(), share_amount: z.string(), share_type: z.string(), share_pct: z.string().nullable().optional(), notes: z.string().nullable().optional(), created_at: z.string()}); export const transactionRead = z.object({description: z.string(), amount: z.string(), date: z.string(), type: z.string(), external_id: z.string().nullable().optional(), currency: z.string().optional(), fx_rate: z.string().nullable().optional(), payee_raw: z.string().nullable().optional(), id: z.string(), user_id: z.string(), account_id: z.string().nullable().optional(), category_id: z.string().nullable().optional(), category: categoryRead.nullable().optional(), invoice_links: z.array(transactionInvoiceLink).optional(), source: z.string(), status: z.string().optional(), payee: z.string().nullable().optional(), original_description: z.string().nullable().optional(), payee_id: z.string().nullable().optional(), payee_name: z.string().nullable().optional(), notes: z.string().nullable().optional(), transfer_pair_id: z.string().nullable().optional(), transfer_counterpart: transactionTransferCounterpart.nullable().optional(), amount_primary: z.number().nullable().optional(), fx_rate_used: z.number().nullable().optional(), fx_fallback: z.boolean().optional(), attachment_count: z.number().int().optional(), installment_number: z.number().int().nullable().optional(), total_installments: z.number().int().nullable().optional(), installment_total_amount: z.number().nullable().optional(), installment_purchase_date: z.string().nullable().optional(), installment_series_id: z.string().nullable().optional(), bill_id: z.string().nullable().optional(), effective_bill_date: z.string().nullable().optional(), recurring_transaction_id: z.string().nullable().optional(), splits: z.array(transactionSplitRead).optional(), is_shared: z.boolean().optional(), viewer_share: z.string().nullable().optional(), group_id: z.string().nullable().optional(), parent_owner_name: z.string().nullable().optional(), is_ignored: z.boolean().optional(), exclude_from_pnl: z.boolean().optional(), running_balance: z.number().nullable().optional(), running_balance_primary: z.number().nullable().optional()}); export const transactionsSummary = z.object({income: z.number(), expense: z.number(), net: z.number(), excluded: z.number(), currency: z.string()}); export const paginatedTransactions = z.object({items: z.array(transactionRead), total: z.number().int(), page: z.number().int(), limit: z.number().int(), summary: transactionsSummary.nullable().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 }; /** * List Transactions * * GET /api/transactions */ export const getApiApiTransactions = async (args: GetApiApiTransactionsArgs, options: GetApiApiTransactionsOptions) => { const {baseUrl, fetch: fetchFn = fetch, OAuth2PasswordBearer} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.account_id != null) query.append("account_id", String(args.account_id)) for (const item of args.account_ids ?? []) query.append("account_ids", String(item)) if (args.category_id != null) query.append("category_id", String(args.category_id)) for (const item of args.category_ids ?? []) query.append("category_ids", String(item)) if (args.payee_id != null) query.append("payee_id", String(args.payee_id)) if (args.from != null) query.append("from", String(args.from)) if (args.to != null) query.append("to", String(args.to)) if (args.bill_id != null) query.append("bill_id", String(args.bill_id)) if (args.group_id != null) query.append("group_id", String(args.group_id)) if (args.unbilled_only != null) query.append("unbilled_only", String(args.unbilled_only)) if (args.statement_view != null) query.append("statement_view", String(args.statement_view)) if (args.q != null) query.append("q", String(args.q)) if (args.uncategorized != null) query.append("uncategorized", String(args.uncategorized)) if (args.type != null) query.append("type", String(args.type)) if (args.status != null) query.append("status", String(args.status)) if (args.page != null) query.append("page", String(args.page)) if (args.limit != null) query.append("limit", String(args.limit)) if (args.include_opening_balance != null) query.append("include_opening_balance", String(args.include_opening_balance)) if (args.include_running_balance != null) query.append("include_running_balance", String(args.include_running_balance)) if (args.exclude_transfers != null) query.append("exclude_transfers", String(args.exclude_transfers)) if (args.user_pnl_only != null) query.append("user_pnl_only", String(args.user_pnl_only)) if (args.exclude_ignored != null) query.append("exclude_ignored", String(args.exclude_ignored)) for (const item of args.tags ?? []) query.append("tags", String(item)) if (args.min_amount != null) query.append("min_amount", String(args.min_amount)) if (args.max_amount != null) query.append("max_amount", String(args.max_amount)) if (args.sort_by != null) query.append("sort_by", String(args.sort_by)) if (args.sort_dir != null) query.append("sort_dir", String(args.sort_dir)) if (args['X-Workspace-Id'] != null) headers.set("X-Workspace-Id", String(args['X-Workspace-Id'])) if (OAuth2PasswordBearer !== undefined) headers.set('authorization', `Bearer ${OAuth2PasswordBearer}`) const url = `${baseUrl.replace(/\/+$/, '')}/api/transactions${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(paginatedTransactions, await res.json()) };