@sudowealth/schwab-api
Version:
TypeScript client for Charles Schwab API with OAuth support, market data, trading functionality, and complete type safety
78 lines (77 loc) • 4.29 kB
JavaScript
import { z } from 'zod';
import { dateStringSchema } from '../../utils/date-utils';
import { mergeShapes } from '../../utils/schema-utils';
import { InstrumentAssetTypeEnum } from '../shared';
// Enum for the 'markets' query parameter
export const MarketHoursMarketQueryEnum = z.enum([
'equity',
'option',
'bond',
'future',
'forex',
]);
// Schema for ISO 8601 datetime string (YYYY-MM-DDTHH:mm:ss±HH:mm)
const timeStringSchema = z
.string()
// Accept ISO 8601 datetime format from the API
.regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:Z|[+-]\d{2}:\d{2})$/, 'Time must be in ISO 8601 format');
// Schema for session interval (start and end times)
const SessionIntervalSchema = z.object({
start: timeStringSchema.describe('Session start time in ISO 8601 format (YYYY-MM-DDTHH:mm:ss±HH:mm)'),
end: timeStringSchema.describe('Session end time in ISO 8601 format (YYYY-MM-DDTHH:mm:ss±HH:mm)'),
});
// Schema for sessionHours (e.g., { regularMarket: [{start, end}] })
const MarketSessionHoursSchema = z.record(z.string(), // Session name (e.g., "preMarket", "regularMarket", "postMarket")
z.array(SessionIntervalSchema));
// Schema for the data of a single market in the response
export const MarketHoursDataSchema = z.object({
date: dateStringSchema
.optional()
.describe('Date for the market hours (Date object)'), // Optional as per example where it might be part of equity.date
marketType: InstrumentAssetTypeEnum.describe('Type of market'),
exchange: z.string().optional().describe('Exchange name'),
category: z.string().optional().describe('Category of the market'),
product: z.string().optional().describe('Product name'),
productName: z.string().optional().describe('Display name for the product'),
isOpen: z.boolean().describe('Indicates if the market is currently open'),
sessionHours: MarketSessionHoursSchema.optional().describe('Market session hours'),
});
// --- GET /markets endpoint schemas ---
// Path Parameters Schema for GET /markets (no path params)
export const GetMarketHoursPathParams = z.object({});
// Query Parameters Schema for GET /markets
export const GetMarketHoursQueryParams = z.object({
markets: z
.union([MarketHoursMarketQueryEnum, z.array(MarketHoursMarketQueryEnum)])
.transform((val) => (Array.isArray(val) ? val : [val]))
.describe(`List of markets. Available values: ${MarketHoursMarketQueryEnum.options.join(', ')}`),
date: dateStringSchema
.optional()
.describe('Date for market hours. Defaults to current day.'),
});
// Request Params Schema for GET /markets (merged path + query params)
export const GetMarketHoursParams = z.object(mergeShapes(GetMarketHoursQueryParams.shape, GetMarketHoursPathParams.shape));
// Schema for Response Body of GET /markets
// The response is a nested structure with market type as the top level key,
// then product code as second level, containing the market hours data
export const GetMarketHoursResponse = z.record(MarketHoursMarketQueryEnum, // Top level key (e.g., "equity")
z.record(z.string(), // Second level key (e.g., "EQ") - product code
MarketHoursDataSchema));
// Path Parameters Schema for GET /markets/{market_id}
export const GetMarketHoursByMarketIdPathParams = z.object({
market_id: MarketHoursMarketQueryEnum.describe('Market ID (equity, option, etc.)'),
});
// Query Parameters Schema for GET /markets/{market_id}
export const GetMarketHoursByMarketIdQueryParams = z.object({
date: dateStringSchema
.optional()
.describe('Date for market hours. Defaults to current day.'),
});
// Response Body Schema for GET /markets/{market_id}
// This endpoint returns a nested structure with market type as the top level key,
// then product code as second level, containing the market hours data
export const GetMarketHoursByMarketIdResponse = z.record(MarketHoursMarketQueryEnum, // Top level key (e.g., "equity")
z.record(z.string(), // Second level key (e.g., "EQ") - product code
MarketHoursDataSchema));
// Request Params Schema for GET /markets/{market_id} (merged path + query params)
export const GetMarketHoursByMarketIdParams = z.object(mergeShapes(GetMarketHoursByMarketIdQueryParams.shape, GetMarketHoursByMarketIdPathParams.shape));