57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
import { defineAction } from "@agent-native/core/action";
|
|||
|
|
import { and, desc, eq, or, sql } from "@agent-native/core/db/schema";
|
||
|
|
import { z } from "zod";
|
||
|
|
|
||
|
|
import { getDb } from "../server/db/index.js";
|
||
|
|
import { stocks } from "../server/db/schema.js";
|
||
|
|
|
||
|
|
function booleanParam(value: string | undefined): boolean | undefined {
|
||
|
|
if (value === undefined) return undefined;
|
||
|
|
return value === "true" || value === "1";
|
||
|
|
}
|
||
|
|
|
||
|
|
export default defineAction({
|
||
|
|
description:
|
||
|
|
"List stock listings, optionally filtered by search text (symbol or company name), exchange, or watchlisted status.",
|
||
|
|
schema: z.object({
|
||
|
|
search: z
|
||
|
|
.string()
|
||
|
|
.optional()
|
||
|
|
.describe("Filter by symbol or company name (case-insensitive substring match)"),
|
||
|
|
exchange: z.string().optional().describe("Filter by exchange (e.g. NASDAQ, NYSE)"),
|
||
|
|
watchlistedOnly: z
|
||
|
|
.string()
|
||
|
|
.optional()
|
||
|
|
.describe("Set to \"true\" to only return watchlisted stocks"),
|
||
|
|
}),
|
||
|
|
http: { method: "GET" },
|
||
|
|
readOnly: true,
|
||
|
|
run: async (args, ctx) => {
|
||
|
|
if (!ctx?.userEmail) throw new Error("Authentication required.");
|
||
|
|
const db = getDb();
|
||
|
|
|
||
|
|
const conditions = [eq(stocks.ownerEmail, ctx.userEmail)];
|
||
|
|
if (args.search) {
|
||
|
|
const term = `%${args.search.toLowerCase()}%`;
|
||
|
|
conditions.push(
|
||
|
|
or(
|
||
|
|
sql`lower(${stocks.symbol}) like ${term}`,
|
||
|
|
sql`lower(${stocks.companyName}) like ${term}`,
|
||
|
|
)!,
|
||
|
|
);
|
||
|
|
}
|
||
|
|
if (args.exchange) conditions.push(eq(stocks.exchange, args.exchange));
|
||
|
|
if (booleanParam(args.watchlistedOnly)) {
|
||
|
|
conditions.push(eq(stocks.watchlisted, true));
|
||
|
|
}
|
||
|
|
|
||
|
|
const rows = await db
|
||
|
|
.select()
|
||
|
|
.from(stocks)
|
||
|
|
.where(and(...conditions))
|
||
|
|
.orderBy(desc(stocks.watchlisted), stocks.symbol);
|
||
|
|
|
||
|
|
return { stocks: rows };
|
||
|
|
},
|
||
|
|
});
|