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' ;
2026-03-19 22:18:06 -04:00
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 ) ;
}
2026-03-19 22:18:06 -04:00
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' } ,
2026-03-16 14:39:55 -04:00
{ 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 : [ '/' ] } ,
2026-04-07 09:52:17 -04:00
// { 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.' ) ) ;
}
2026-04-02 19:24:51 -04:00
// 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 } ,
2026-04-08 08:13:52 -04:00
{ 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' } ,
2026-04-02 19:24:51 -04:00
]
} ) ;
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 } ,
} ) ;
2026-03-16 14:39:55 -04:00
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 } ) ,
2026-04-07 09:52:17 -04:00
// sku_id: card.prices.map(price => price.skuId.toString())
2026-03-16 14:39:55 -04:00
} ;
} ) , { 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 ) ,
2026-04-07 09:52:17 -04:00
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.' ) ) ;
2026-03-19 22:18:06 -04:00
}
2026-04-02 19:24:51 -04:00
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 } } } } }
} ) ;
2026-04-02 19:24:51 -04:00
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 ( ) ,
2026-04-07 09:52:17 -04:00
sku_id : i.skuId.toString ( ) ,
2026-04-08 08:13:52 -04:00
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 ( ' ' ) ,
2026-04-02 19:24:51 -04:00
} ) ) , { action : 'upsert' } ) ;
console . log ( chalk . green ( 'Collection "inventories" indexed successfully.' ) ) ;
}
2026-03-19 22:18:06 -04:00
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 ` ) ;
2026-03-19 22:18:06 -04:00
}