Files
pokemon/scripts/pokemon-helper.ts

241 lines
11 KiB
TypeScript
Raw Normal View History

2026-03-12 08:18:40 -04:00
import chalk from 'chalk';
import { client } from '../src/db/typesense.ts';
import type { DBInstance } from '../src/db/index.ts';
import fs from "node:fs/promises";
import { sql } from 'drizzle-orm'
2026-04-07 22:34:31 -04:00
import * as util from 'util';
2026-03-12 08:18:40 -04:00
const DollarToInt = (dollar: any) => {
if (dollar === null) return null;
return Math.round(dollar * 100);
}
export const Sleep = (ms: number) => {
return new Promise(resolve => setTimeout(resolve, ms));
}
export const FileExists = async (path: string): Promise<boolean> => {
try {
await fs.access(path);
return true;
} catch {
return false;
}
}
export const GetNumberOrNull = (value: any): number | null => {
const number = Number(value); // Attempt to convert the value to a number
if (Number.isNaN(number)) {
return null; // Return null if the result is NaN
}
return number; // Otherwise, return the number
}
2026-03-12 08:18:40 -04:00
// Delete and recreate the 'cards' index
export const createCardCollection = async () => {
try {
await client.collections('cards').delete();
} catch (error) {
// Ignore error, just means collection doesn't exist
}
await client.collections().create({
name: 'cards',
fields: [
{ name: 'id', type: 'string' },
{ name: 'cardId', type: 'int32' },
{ name: 'productId', type: 'int32' },
{ name: 'variant', type: 'string', facet: true },
{ name: 'productName', type: 'string' },
{ name: 'productLineName', type: 'string', facet: true },
{ name: 'rarityName', type: 'string', facet: true },
{ name: 'setName', type: 'string', facet: true },
{ name: 'cardType', type: 'string', facet: true },
{ name: 'energyType', type: 'string', facet: true },
{ name: 'number', type: 'string', sort: true },
{ name: 'Artist', type: 'string' },
{ name: 'sealed', type: 'bool' },
{ name: 'releaseDate', type: 'int32' },
{ name: 'marketPrice', type: 'int32', optional: true, sort: true },
2026-03-12 08:18:40 -04:00
{ name: 'content', type: 'string', token_separators: ['/'] },
// { name: 'sku_id', type: 'string[]', optional: true, reference: 'skus.id', async_reference: true }
2026-03-12 08:18:40 -04:00
],
});
console.log(chalk.green('Collection "cards" created successfully.'));
}
// Delete and recreate the 'skus' index
export const createSkuCollection = async () => {
try {
await client.collections('skus').delete();
} catch (error) {
// Ignore error, just means collection doesn't exist
}
await client.collections().create({
name: 'skus',
fields: [
{ name: 'id', type: 'string' },
{ name: 'condition', type: 'string' },
{ name: 'highestPrice', type: 'int32', optional: true },
{ name: 'lowestPrice', type: 'int32', optional: true },
{ name: 'marketPrice', type: 'int32', optional: true },
2026-04-07 22:34:31 -04:00
{ name: 'card_id', type: 'string', reference: 'cards.id', async_reference: true },
2026-03-12 08:18:40 -04:00
]
});
console.log(chalk.green('Collection "skus" created successfully.'));
}
// Delete and recreate the 'inventory' index
export const createInventoryCollection = async () => {
try {
await client.collections('inventories').delete();
} catch (error) {
// Ignore error, just means collection doesn't exist
}
await client.collections().create({
name: 'inventories',
fields: [
{ name: 'id', type: 'string' },
{ name: 'userId', type: 'string' },
{ name: 'catalogName', type: 'string' },
2026-04-07 22:34:31 -04:00
{ name: 'card_id', type: 'string', reference: 'cards.id', async_reference: true },
{ name: 'sku_id', type: 'string', reference: 'skus.id', async_reference: true },
{ name: 'purchasePrice', type: 'int32', optional: true },
2026-04-07 22:34:31 -04:00
// content,setName,productLineName,rarityName,energyType,cardType from cards for searching
{ name: 'content', type: 'string', token_separators: ['/'] },
{ name: 'setName', type: 'string' },
{ name: 'productLineName', type: 'string' },
{ name: 'rarityName', type: 'string' },
{ name: 'energyType', type: 'string' },
{ name: 'cardType', type: 'string' },
]
});
console.log(chalk.green('Collection "inventories" created successfully.'));
}
2026-03-12 08:18:40 -04:00
export const upsertCardCollection = async (db:DBInstance) => {
const pokemon = await db.query.cards.findMany({
with: { set: true, tcgdata: true, prices: true },
});
await client.collections('cards').documents().import(pokemon.map(card => {
const marketPrice = card.tcgdata?.marketPrice ? DollarToInt(card.tcgdata.marketPrice) : null;
return {
id: card.cardId.toString(),
cardId: card.cardId,
productId: card.productId,
variant: card.variant,
productName: card.productName,
productLineName: card.productLineName,
rarityName: card.rarityName,
setName: card.set?.setName || "",
cardType: card.cardType || "",
energyType: card.energyType || "",
number: card.number,
Artist: card.artist || "",
sealed: card.sealed,
content: [card.productName, card.productLineName, card.set?.setName || "", card.number, card.rarityName, card.artist || ""].join(' '),
releaseDate: card.tcgdata?.releaseDate ? Math.floor(new Date(card.tcgdata.releaseDate).getTime() / 1000) : 0,
...(marketPrice !== null && { marketPrice }),
// sku_id: card.prices.map(price => price.skuId.toString())
};
}), { action: 'upsert' });
2026-03-12 08:18:40 -04:00
console.log(chalk.green('Collection "cards" indexed successfully.'));
}
export const upsertSkuCollection = async (db:DBInstance) => {
const skus = await db.query.skus.findMany();
await client.collections('skus').documents().import(skus.map(sku => ({
id: sku.skuId.toString(),
condition: sku.condition,
highestPrice: DollarToInt(sku.highestPrice),
lowestPrice: DollarToInt(sku.lowestPrice),
marketPrice: DollarToInt(sku.marketPrice),
card_id: sku.cardId.toString(),
2026-04-07 22:34:31 -04:00
})), { action: 'upsert' });
2026-03-12 08:18:40 -04:00
console.log(chalk.green('Collection "skus" indexed successfully.'));
}
export const upsertInventoryCollection = async (db:DBInstance) => {
2026-04-07 22:34:31 -04:00
const inv = await db.query.inventory.findMany({
with: { sku: { with: { card: { with: { set: true } } } } }
});
await client.collections('inventories').documents().import(inv.map(i => ({
id: i.inventoryId,
userId: i.userId,
catalogName: i.catalogName,
2026-04-07 22:34:31 -04:00
card_id: i.sku?.cardId.toString(),
sku_id: i.skuId.toString(),
purchasePrice: DollarToInt(i.purchasePrice),
2026-04-07 22:34:31 -04:00
productLineName: i.sku?.card?.productLineName,
rarityName: i.sku?.card?.rarityName,
setName: i.sku?.card?.set?.setName || "",
cardType: i.sku?.card?.cardType || "",
energyType: i.sku?.card?.energyType || "",
content: [
i.sku?.card?.productName,
i.sku?.card?.productLineName,
i.sku?.card?.set?.setName || "",
i.sku?.card?.number,
i.sku?.card?.rarityName,
i.sku?.card?.artist || ""
].join(' '),
})), { action: 'upsert' });
console.log(chalk.green('Collection "inventories" indexed successfully.'));
}
export const UpdateVariants = async (db:DBInstance) => {
const updates = await db.execute(sql`update cards as c
set
product_name = a.product_name, product_line_name = a.product_line_name, product_url_name = a.product_url_name, rarity_name = a.rarity_name,
sealed = a.sealed, set_id = a.set_id, card_type = a.card_type, energy_type = a.energy_type, number = a.number, artist = a.artist
from (
select t.product_id, b.variant,
coalesce(o.product_name, regexp_replace(regexp_replace(coalesce(nullif(t.product_name, ''), t.product_url_name),' \\\\(.*\\\\)',''),' - .*$','')) as product_name,
coalesce(o.product_line_name, t.product_line_name) as product_line_name, coalesce(o.product_url_name, t.product_url_name) as product_url_name,
coalesce(o.rarity_name, t.rarity_name) as rarity_name, coalesce(o.sealed, t.sealed) as sealed, coalesce(o.set_id, t.set_id) as set_id,
coalesce(o.card_type, t.card_type) as card_type, coalesce(o.energy_type, t.energy_type) as energy_type,
coalesce(o.number, t.number) as number, coalesce(o.artist, t.artist) as artist
from tcg_cards t
join (select distinct product_id, variant from skus) b on t.product_id = b.product_id
left join tcg_overrides o on t.product_id = o.product_id
) a
where c.product_id = a.product_id and c.variant = a.variant and
(
c.product_name is distinct from a.product_name or c.product_line_name is distinct from a.product_line_name or
c.product_url_name is distinct from a.product_url_name or c.rarity_name is distinct from a.rarity_name or
c.sealed is distinct from a.sealed or c.set_id is distinct from a.set_id or c.card_type is distinct from a.card_type or
c.energy_type is distinct from a.energy_type or c."number" is distinct from a."number" or c.artist is distinct from a.artist
)
`);
console.log(`Updated ${updates.rowCount} rows in cards table`);
const inserts = await db.execute(sql`insert into cards (product_id, variant, product_name, product_line_name, product_url_name, rarity_name, sealed, set_id, card_type, energy_type, "number", artist)
select t.product_id, b.variant,
coalesce(o.product_name, regexp_replace(regexp_replace(coalesce(nullif(t.product_name, ''), t.product_url_name),' \\\\(.*\\\\)',''),' - .*$','')) as product_name,
coalesce(o.product_line_name, t.product_line_name) as product_line_name, coalesce(o.product_url_name, t.product_url_name) as product_url_name, coalesce(o.rarity_name, t.rarity_name) as rarity_name,
coalesce(o.sealed, t.sealed) as sealed, coalesce(o.set_id, t.set_id) as set_id, coalesce(o.card_type, t.card_type) as card_type,
coalesce(o.energy_type, t.energy_type) as energy_type, coalesce(o.number, t.number) as number, coalesce(o.artist, t.artist) as artist
from tcg_cards t
join (select distinct product_id, variant from skus) b on t.product_id = b.product_id
left join tcg_overrides o on t.product_id = o.product_id
where not exists (select 1 from cards where product_id=t.product_id and variant=b.variant)
`);
console.log(`Inserted ${inserts.rowCount} rows into cards table`);
2026-04-08 15:38:56 -04:00
const skuUpdates = await db.execute(sql`update skus s set card_id = c.card_id from cards c where s.product_id = c.product_id and s.variant = c.variant and s.card_id is distinct from c.card_id`);
console.log(`Updated ${skuUpdates.rowCount} rows in skus table`);
}