forked from tmiller/pokemon
[feat] update drizzle to v2 and add card-price relations
This commit is contained in:
1450
package-lock.json
generated
1450
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -14,14 +14,14 @@
|
|||||||
"bootstrap": "^5.3.8",
|
"bootstrap": "^5.3.8",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
"dotenv": "^17.2.4",
|
"dotenv": "^17.2.4",
|
||||||
"drizzle-orm": "^0.45.1",
|
"drizzle-orm": "^1.0.0-beta.15-859cf75",
|
||||||
"mysql2": "^3.16.3",
|
"mysql2": "^3.16.3",
|
||||||
"sass": "^1.97.3"
|
"sass": "^1.97.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bootstrap": "^5.2.10",
|
"@types/bootstrap": "^5.2.10",
|
||||||
"@types/node": "^25.2.1",
|
"@types/node": "^25.2.1",
|
||||||
"drizzle-kit": "^0.31.8",
|
"drizzle-kit": "^1.0.0-beta.15-859cf75",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,4 +48,4 @@
|
|||||||
// @import 'bootstrap/scss/helpers';
|
// @import 'bootstrap/scss/helpers';
|
||||||
|
|
||||||
// Optional utilities
|
// Optional utilities
|
||||||
// @import 'bootstrap/scss/utilities/api';
|
@import 'bootstrap/scss/utilities/api';
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
@import '_bootstrap';
|
@import '_bootstrap';
|
||||||
|
|
||||||
|
.copy-small {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// src/db/index.ts
|
// src/db/index.ts
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
|
import { relations } from './relations';
|
||||||
import { drizzle } from 'drizzle-orm/mysql2';
|
import { drizzle } from 'drizzle-orm/mysql2';
|
||||||
import mysql from 'mysql2/promise';
|
//import mysql from 'mysql2/promise';
|
||||||
import * as schema from './schema';
|
//import * as schema from './schema';
|
||||||
|
|
||||||
const poolConnection = mysql.createPool({
|
//const poolConnection = mysql.createPool(process.env.DATABASE_URL!);
|
||||||
uri: process.env.DATABASE_URL,
|
|
||||||
});
|
export const db = drizzle(process.env.DATABASE_URL!, { relations });
|
||||||
|
|
||||||
export const db = drizzle(poolConnection, { schema, mode: 'default' });
|
|
||||||
|
|||||||
16
src/db/relations.ts
Normal file
16
src/db/relations.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { defineRelations } from "drizzle-orm";
|
||||||
|
import * as schema from "./schema";
|
||||||
|
|
||||||
|
export const relations = defineRelations(schema, (r) => ({
|
||||||
|
skus: {
|
||||||
|
card: r.one.cards({
|
||||||
|
from: r.skus.productId,
|
||||||
|
to: r.cards.productId,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
cards: {
|
||||||
|
prices: r.many.skus(),
|
||||||
|
},
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
116
src/db/schema.ts
116
src/db/schema.ts
@@ -1,63 +1,63 @@
|
|||||||
// src/db/schema.ts
|
import { mysqlTable, int, varchar, boolean, decimal, datetime, index } from "drizzle-orm/mysql-core"
|
||||||
import { mysqlTable, varchar, int, boolean, decimal, datetime, index } from 'drizzle-orm/mysql-core';
|
|
||||||
|
|
||||||
export const cards = mysqlTable('cards', {
|
export const cards = mysqlTable("cards", {
|
||||||
productId: int().notNull().primaryKey(),
|
productId: int().primaryKey(),
|
||||||
productName: varchar({ length: 255 }).notNull(),
|
productName: varchar({ length: 255 }).notNull(),
|
||||||
productLineName: varchar({ length: 255 }).notNull().default(''),
|
productLineName: varchar({ length: 255 }).default("").notNull(),
|
||||||
productLineUrlName: varchar({ length: 255 }).notNull().default(''),
|
productLineUrlName: varchar({ length: 255 }).default("").notNull(),
|
||||||
productStatusId: int().notNull().default(0),
|
productStatusId: int().default(0).notNull(),
|
||||||
productTypeId: int().notNull().default(0),
|
productTypeId: int().default(0).notNull(),
|
||||||
productUrlName: varchar({ length: 255 }).notNull().default(''),
|
productUrlName: varchar({ length: 255 }).default("").notNull(),
|
||||||
rarityName: varchar({ length: 100 }).notNull().default(''),
|
rarityName: varchar({ length: 100 }).default("").notNull(),
|
||||||
score: decimal({ precision: 10, scale: 2 }).notNull().default('0'),
|
sealed: boolean().default(false).notNull(),
|
||||||
sealed: boolean().notNull().default(false),
|
sellerListable: boolean().default(false).notNull(),
|
||||||
sellerListable: boolean().notNull().default(false),
|
setId: int().default(0).notNull(),
|
||||||
setId: int().notNull().default(0),
|
shippingCategoryId: int().default(0).notNull(),
|
||||||
shippingCategoryId: int().notNull().default(0),
|
duplicate: boolean().default(false).notNull(),
|
||||||
duplicate: boolean().notNull().default(false),
|
foilOnly: boolean().default(false).notNull(),
|
||||||
foilOnly: boolean().notNull().default(false),
|
maxFulfillableQuantity: int().default(0).notNull(),
|
||||||
attack1: varchar({ length: 1024 }),
|
totalListings: int().default(0).notNull(),
|
||||||
attack2: varchar({ length: 1024 }),
|
score: decimal({ precision: 10, scale: 2, mode: 'number' }).default(0).notNull(),
|
||||||
attack3: varchar({ length: 1024 }),
|
lowestPrice: decimal({ precision: 10, scale: 2, mode: 'number' }).default(0).notNull(),
|
||||||
attack4: varchar({ length: 1024 }),
|
lowestPriceWithShipping: decimal({ precision: 10, scale: 2, mode: 'number' }).default(0).notNull(),
|
||||||
cardType: varchar({ length: 100 }),
|
marketPrice: decimal({ precision: 10, scale: 2, mode: 'number' }).default(0).notNull(),
|
||||||
cardTypeB: varchar({ length: 100 }),
|
medianPrice: decimal({ precision: 10, scale: 2, mode: 'number' }).default(0).notNull(),
|
||||||
energyType: varchar({ length: 100 }),
|
attack1: varchar({ length: 1024 }),
|
||||||
flavorText: varchar({ length: 1000 }),
|
attack2: varchar({ length: 1024 }),
|
||||||
hp: int().notNull().default(0),
|
attack3: varchar({ length: 1024 }),
|
||||||
number: varchar({ length: 50 }).notNull().default(''),
|
attack4: varchar({ length: 1024 }),
|
||||||
releaseDate: datetime(),
|
cardType: varchar({ length: 100 }),
|
||||||
resistance: varchar({ length: 100 }),
|
cardTypeB: varchar({ length: 100 }),
|
||||||
retreatCost: varchar({ length: 100 }),
|
energyType: varchar({ length: 100 }),
|
||||||
stage: varchar({ length: 100 }),
|
flavorText: varchar({ length: 1000 }),
|
||||||
weakness: varchar({ length: 100 }),
|
hp: int().default(0).notNull(),
|
||||||
lowestPrice: decimal({ precision: 10, scale: 2 }).notNull().default('0'),
|
number: varchar({ length: 50 }).default("").notNull(),
|
||||||
lowestPriceWithShipping: decimal({ precision: 10, scale: 2 }).notNull().default('0'),
|
releaseDate: datetime(),
|
||||||
marketPrice: decimal({ precision: 10, scale: 2 }).notNull().default('0'),
|
resistance: varchar({ length: 100 }),
|
||||||
maxFulfillableQuantity: int().notNull().default(0),
|
retreatCost: varchar({ length: 100 }),
|
||||||
medianPrice: decimal({ precision: 10, scale: 2 }).notNull().default('0'),
|
stage: varchar({ length: 100 }),
|
||||||
totalListings: int().notNull().default(0),
|
weakness: varchar({ length: 100 }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const sets = mysqlTable('sets', {
|
export const sets = mysqlTable("sets", {
|
||||||
setId: int().notNull().primaryKey(),
|
setId: int().primaryKey(),
|
||||||
setCode: varchar({ length: 100 }).notNull(),
|
setName: varchar({ length: 255 }).notNull(),
|
||||||
setName: varchar({ length: 255 }).notNull(),
|
setUrlName: varchar({ length: 255 }).notNull(),
|
||||||
setUrlName: varchar({ length: 255 }).notNull(),
|
setCode: varchar({ length: 100 }).notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const skus = mysqlTable('skus', {
|
export const skus = mysqlTable("skus", {
|
||||||
skuId: int().notNull().primaryKey(),
|
skuId: int().primaryKey(),
|
||||||
productId: int().notNull(),
|
productId: int().notNull(),
|
||||||
condition: varchar({ length: 255 }).notNull(),
|
condition: varchar({ length: 255 }).notNull(),
|
||||||
language: varchar({ length: 100 }).notNull(),
|
language: varchar({ length: 100 }).notNull(),
|
||||||
variant: varchar({ length: 100 }).notNull(),
|
variant: varchar({ length: 100 }).notNull(),
|
||||||
calculatedAt: datetime(),
|
calculatedAt: datetime(),
|
||||||
highestPrice: decimal({ precision: 10, scale: 2 }),
|
highestPrice: decimal({ precision: 10, scale: 2 }),
|
||||||
lowestPrice: decimal({ precision: 10, scale: 2 }),
|
lowestPrice: decimal({ precision: 10, scale: 2 }),
|
||||||
marketPrice: decimal({ precision: 10, scale: 2 }),
|
marketPrice: decimal({ precision: 10, scale: 2 }),
|
||||||
priceCount: int(),
|
priceCount: int(),
|
||||||
},(table) => ({
|
},
|
||||||
productIdIdx: index('productIdIdx').on(table.productId),
|
(table) => [
|
||||||
}));
|
index("productIdIdx").on(table.productId),
|
||||||
|
]);
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
---
|
---
|
||||||
import Layout from '../layouts/Main.astro';
|
import Layout from '../layouts/Main.astro';
|
||||||
|
|
||||||
import * as schema from '../db/schema.ts';
|
//import { eq } from 'drizzle-orm';
|
||||||
import { eq } from 'drizzle-orm';
|
|
||||||
import { db } from '../db';
|
import { db } from '../db';
|
||||||
|
//import * as schema from '../db/schema.ts';
|
||||||
|
|
||||||
|
|
||||||
// Get some sample Pokemon data from the database
|
// Get some sample Pokemon data from the database
|
||||||
const pokemon = await db.select().from(schema.cards).where(eq(schema.cards.productLineName, "pokemon")).limit(10);
|
//const pokemon = await db.select().from(schema.cards).where(eq(schema.cards.productLineName, "pokemon")).limit(16);
|
||||||
|
const pokemon = await db.query.cards.findMany({
|
||||||
|
where: { productLineName: "pokemon" },
|
||||||
|
limit: 16,
|
||||||
|
with: {
|
||||||
|
prices: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout>
|
<Layout>
|
||||||
@@ -16,11 +24,19 @@ const pokemon = await db.select().from(schema.cards).where(eq(schema.cards.produ
|
|||||||
<h1>Pokemon</h1>
|
<h1>Pokemon</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4">
|
<div class="row gy-4 row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4">
|
||||||
{pokemon.map((card) => (
|
{pokemon.map((card) => (
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<img src={`/public/cards/${card.productId}.jpg`} alt={card.productName} class="img-fluid" />
|
<img src={`/cards/${card.productId}.jpg`} alt={card.productName} class="img-fluid" />
|
||||||
{card.productName} - {card.number}
|
<div class="row justify-content-between">
|
||||||
|
<div class="col-auto"><strong>{card.productName}</strong></div>
|
||||||
|
<div class="col-auto">{card.number}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
{card.prices.map((price) => (
|
||||||
|
<div class="col-auto copy-small">{price.condition.split(' ').map((word) => word.charAt(0)).join('')}<br />{price.marketPrice}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user