feat: query plaid transactions
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
type ReadonlyJSONValue,
|
||||
type Transaction,
|
||||
withValidation,
|
||||
} from "@rocicorp/zero";
|
||||
import {
|
||||
@@ -11,13 +12,31 @@ import { PostgresJSConnection } from '@rocicorp/zero/pg';
|
||||
import postgres from 'postgres';
|
||||
import {
|
||||
createMutators as createMutatorsShared,
|
||||
isLoggedIn,
|
||||
queries,
|
||||
schema,
|
||||
type Mutators,
|
||||
type Schema,
|
||||
} from "@money/shared";
|
||||
import type { AuthData } from "@money/shared/auth";
|
||||
import { getHono } from "./hono";
|
||||
import { Configuration, CountryCode, PlaidApi, PlaidEnvironments, Products } from "plaid";
|
||||
import { randomUUID } from "crypto";
|
||||
import { db } from "./db";
|
||||
import { plaidAccessTokens, plaidLink, transaction } from "@money/shared/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
const configuration = new Configuration({
|
||||
basePath: PlaidEnvironments.production,
|
||||
baseOptions: {
|
||||
headers: {
|
||||
'PLAID-CLIENT-ID': process.env.PLAID_CLIENT_ID,
|
||||
'PLAID-SECRET': process.env.PLAID_SECRET,
|
||||
}
|
||||
}
|
||||
});
|
||||
const plaidClient = new PlaidApi(configuration);
|
||||
|
||||
|
||||
const processor = new PushProcessor(
|
||||
@@ -27,6 +46,8 @@ const processor = new PushProcessor(
|
||||
),
|
||||
);
|
||||
|
||||
type Tx = Transaction<Schema>;
|
||||
|
||||
const createMutators = (authData: AuthData | null) => {
|
||||
const mutators = createMutatorsShared(authData);
|
||||
return {
|
||||
@@ -34,7 +55,73 @@ const createMutators = (authData: AuthData | null) => {
|
||||
link: {
|
||||
...mutators.link,
|
||||
async create() {
|
||||
console.log("Here is my function running on the server!!!");
|
||||
isLoggedIn(authData);
|
||||
console.log("Creating Link token");
|
||||
const r = await plaidClient.linkTokenCreate({
|
||||
user: {
|
||||
client_user_id: authData.user.id,
|
||||
},
|
||||
client_name: "Koon Money",
|
||||
language: "en",
|
||||
products: [Products.Transactions],
|
||||
country_codes: [CountryCode.Us],
|
||||
hosted_link: {}
|
||||
});
|
||||
console.log("Result", r);
|
||||
const { link_token, hosted_link_url } = r.data;
|
||||
|
||||
if (!hosted_link_url) throw Error("No link in response");
|
||||
|
||||
await db.insert(plaidLink).values({
|
||||
id: randomUUID() as string,
|
||||
user_id: authData.user.id,
|
||||
link: hosted_link_url,
|
||||
token: link_token,
|
||||
});
|
||||
},
|
||||
async get(_, { link_token }) {
|
||||
isLoggedIn(authData);
|
||||
|
||||
const linkResp = await plaidClient.linkTokenGet({
|
||||
link_token,
|
||||
});
|
||||
if (!linkResp) throw Error("No link respo");
|
||||
console.log(JSON.stringify(linkResp.data, null, 4));
|
||||
const publicToken = linkResp.data.link_sessions?.at(0)?.results?.item_add_results.at(0)?.public_token;
|
||||
|
||||
if (!publicToken) throw Error("No public token");
|
||||
const { data } = await plaidClient.itemPublicTokenExchange({
|
||||
public_token: publicToken,
|
||||
})
|
||||
|
||||
await db.insert(plaidAccessTokens).values({
|
||||
id: randomUUID(),
|
||||
userId: authData.user.id,
|
||||
token: data.access_token,
|
||||
});
|
||||
},
|
||||
async updateTransactions() {
|
||||
isLoggedIn(authData);
|
||||
const accessToken = await db.query.plaidAccessTokens.findFirst({
|
||||
where: eq(plaidAccessTokens.userId, authData.user.id)
|
||||
});
|
||||
if (!accessToken) throw Error("No plaid account");
|
||||
|
||||
const { data } = await plaidClient.transactionsGet({
|
||||
access_token: accessToken.token,
|
||||
start_date: "2025-10-01",
|
||||
end_date: "2025-10-15",
|
||||
});
|
||||
|
||||
for (const t of data.transactions) {
|
||||
await db.insert(transaction).values({
|
||||
id: randomUUID(),
|
||||
user_id: authData.user.id,
|
||||
name: t.name,
|
||||
amount: t.amount,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} as const satisfies Mutators;
|
||||
|
||||
Reference in New Issue
Block a user