Create timer function to initialise card database from filesystem (#14)
- Create a new datasource for an in-memory sqlite database - Create a setup function to initialise the card database #13 Reviewed-on: https://gitea.vylpes.xyz/External/card-drop/pulls/14 Co-authored-by: Ethan Lane <ethan@vylpes.com> Co-committed-by: Ethan Lane <ethan@vylpes.com>
This commit is contained in:
parent
c2c2998fe8
commit
51d97bacd5
17 changed files with 813 additions and 28 deletions
src
Functions
constants
contracts
database
dataSources
entities
migrations
111
src/Functions/CardSetupFunctions.ts
Normal file
111
src/Functions/CardSetupFunctions.ts
Normal file
|
@ -0,0 +1,111 @@
|
|||
import { existsSync, readdirSync } from "fs";
|
||||
import CardDataSource from "../database/dataSources/cardDataSource";
|
||||
import Card from "../database/entities/card/Card";
|
||||
import Series from "../database/entities/card/Series";
|
||||
import path from "path";
|
||||
import { CardRarity } from "../constants/CardRarity";
|
||||
|
||||
export default class CardSetupFunctions {
|
||||
public async Execute() {
|
||||
await this.ClearDatabase();
|
||||
await this.ReadSeries();
|
||||
await this.ReadCards();
|
||||
}
|
||||
|
||||
private async ClearDatabase() {
|
||||
const cardRepository = CardDataSource.getRepository(Card);
|
||||
await cardRepository.clear();
|
||||
|
||||
const seriesRepository = CardDataSource.getRepository(Series);
|
||||
await seriesRepository.clear();
|
||||
}
|
||||
|
||||
private async ReadSeries() {
|
||||
const seriesDir = readdirSync(path.join(process.cwd(), 'cards'));
|
||||
|
||||
const seriesRepository = CardDataSource.getRepository(Series);
|
||||
|
||||
const seriesToSave: Series[] = [];
|
||||
|
||||
for (let dir of seriesDir) {
|
||||
const dirPart = dir.split(' ');
|
||||
|
||||
const seriesId = dirPart.shift();
|
||||
const seriesName = dirPart.join(' ');
|
||||
|
||||
const series = new Series(seriesId!, seriesName, dir);
|
||||
|
||||
seriesToSave.push(series);
|
||||
}
|
||||
|
||||
await seriesRepository.save(seriesToSave);
|
||||
}
|
||||
|
||||
private async ReadCards() {
|
||||
const loadedSeries = await Series.FetchAll(Series);
|
||||
|
||||
const cardRepository = CardDataSource.getRepository(Card);
|
||||
|
||||
const cardsToSave: Card[] = [];
|
||||
|
||||
for (let series of loadedSeries) {
|
||||
const bronzeExists = existsSync(path.join(process.cwd(), 'cards', series.Path, 'BRONZE'));
|
||||
const goldExists = existsSync(path.join(process.cwd(), 'cards', series.Path, 'GOLD'));
|
||||
const legendaryExists = existsSync(path.join(process.cwd(), 'cards', series.Path, 'LEGENDARY'));
|
||||
const silverExists = existsSync(path.join(process.cwd(), 'cards', series.Path, 'SILVER'));
|
||||
|
||||
const cardDirBronze = bronzeExists ? readdirSync(path.join(process.cwd(), 'cards', series.Path, 'BRONZE')) : [];
|
||||
const cardDirGold = goldExists ? readdirSync(path.join(process.cwd(), 'cards', series.Path, 'GOLD')) : [];
|
||||
const cardDirLegendary = legendaryExists ? readdirSync(path.join(process.cwd(), 'cards', series.Path, 'LEGENDARY')) : [];
|
||||
const cardDirSilver = silverExists ? readdirSync(path.join(process.cwd(), 'cards', series.Path, 'SILVER')) : [];
|
||||
|
||||
for (let file of cardDirBronze) {
|
||||
const filePart = file.split('.');
|
||||
|
||||
const cardId = filePart[0];
|
||||
const cardName = filePart[0];
|
||||
|
||||
const card = new Card(cardId, cardName, CardRarity.Bronze);
|
||||
|
||||
cardsToSave.push(card);
|
||||
}
|
||||
|
||||
for (let file of cardDirGold) {
|
||||
const filePart = file.split('.');
|
||||
|
||||
const cardId = filePart[0];
|
||||
const cardName = filePart[0];
|
||||
|
||||
const card = new Card(cardId, cardName, CardRarity.Gold);
|
||||
|
||||
cardsToSave.push(card);
|
||||
}
|
||||
|
||||
for (let file of cardDirLegendary) {
|
||||
const filePart = file.split('.');
|
||||
|
||||
const cardId = filePart[0];
|
||||
const cardName = filePart[0];
|
||||
|
||||
const card = new Card(cardId, cardName, CardRarity.Legendary);
|
||||
|
||||
cardsToSave.push(card);
|
||||
}
|
||||
|
||||
for (let file of cardDirSilver) {
|
||||
const filePart = file.split('.');
|
||||
|
||||
const cardId = filePart[0];
|
||||
const cardName = filePart[0];
|
||||
|
||||
const card = new Card(cardId, cardName, CardRarity.Silver);
|
||||
|
||||
cardsToSave.push(card);
|
||||
}
|
||||
}
|
||||
|
||||
await cardRepository.save(cardsToSave);
|
||||
|
||||
console.log(`Loaded ${cardsToSave.length} cards to database`);
|
||||
}
|
||||
}
|
6
src/constants/CardRarity.ts
Normal file
6
src/constants/CardRarity.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export enum CardRarity {
|
||||
Bronze,
|
||||
Silver,
|
||||
Gold,
|
||||
Legendary,
|
||||
}
|
|
@ -2,7 +2,7 @@ import { Column, DeepPartial, EntityTarget, PrimaryColumn, ObjectLiteral, FindOp
|
|||
import { v4 } from "uuid";
|
||||
import AppDataSource from "../database/dataSources/appDataSource";
|
||||
|
||||
export default class BaseEntity {
|
||||
export default class AppBaseEntity {
|
||||
constructor() {
|
||||
this.Id = v4();
|
||||
|
||||
|
@ -19,7 +19,7 @@ export default class BaseEntity {
|
|||
@Column()
|
||||
WhenUpdated: Date;
|
||||
|
||||
public async Save<T extends BaseEntity>(target: EntityTarget<T>, entity: DeepPartial<T>): Promise<void> {
|
||||
public async Save<T extends AppBaseEntity>(target: EntityTarget<T>, entity: DeepPartial<T>): Promise<void> {
|
||||
this.WhenUpdated = new Date();
|
||||
|
||||
const repository = AppDataSource.getRepository<T>(target);
|
||||
|
@ -27,13 +27,13 @@ export default class BaseEntity {
|
|||
await repository.save(entity);
|
||||
}
|
||||
|
||||
public static async Remove<T extends BaseEntity>(target: EntityTarget<T>, entity: T): Promise<void> {
|
||||
public static async Remove<T extends AppBaseEntity>(target: EntityTarget<T>, entity: T): Promise<void> {
|
||||
const repository = AppDataSource.getRepository<T>(target);
|
||||
|
||||
await repository.remove(entity);
|
||||
}
|
||||
|
||||
public static async FetchAll<T extends BaseEntity>(target: EntityTarget<T>, relations?: string[]): Promise<T[]> {
|
||||
public static async FetchAll<T extends AppBaseEntity>(target: EntityTarget<T>, relations?: string[]): Promise<T[]> {
|
||||
const repository = AppDataSource.getRepository<T>(target);
|
||||
|
||||
const all = await repository.find({ relations: relations || [] });
|
||||
|
@ -41,7 +41,7 @@ export default class BaseEntity {
|
|||
return all;
|
||||
}
|
||||
|
||||
public static async FetchOneById<T extends BaseEntity>(target: EntityTarget<T>, id: string, relations?: string[]): Promise<T | null> {
|
||||
public static async FetchOneById<T extends AppBaseEntity>(target: EntityTarget<T>, id: string, relations?: string[]): Promise<T | null> {
|
||||
const repository = AppDataSource.getRepository<T>(target);
|
||||
|
||||
const single = await repository.findOne({ where: ({ Id: id } as FindOptionsWhere<T>), relations: relations || {} });
|
60
src/contracts/CardBaseEntity.ts
Normal file
60
src/contracts/CardBaseEntity.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { Column, DeepPartial, EntityTarget, PrimaryColumn, ObjectLiteral, FindOptionsWhere } from "typeorm";
|
||||
import { v4 } from "uuid";
|
||||
import AppDataSource from "../database/dataSources/appDataSource";
|
||||
import CardDataSource from "../database/dataSources/cardDataSource";
|
||||
|
||||
export default class CardBaseEntity {
|
||||
constructor() {
|
||||
this.Id = v4();
|
||||
|
||||
this.WhenCreated = new Date();
|
||||
this.WhenUpdated = new Date();
|
||||
}
|
||||
|
||||
@PrimaryColumn()
|
||||
Id: string;
|
||||
|
||||
@Column()
|
||||
WhenCreated: Date;
|
||||
|
||||
@Column()
|
||||
WhenUpdated: Date;
|
||||
|
||||
public async Save<T extends CardBaseEntity>(target: EntityTarget<T>, entity: DeepPartial<T>): Promise<void> {
|
||||
this.WhenUpdated = new Date();
|
||||
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
await repository.save(entity);
|
||||
}
|
||||
|
||||
public static async Remove<T extends CardBaseEntity>(target: EntityTarget<T>, entity: T): Promise<void> {
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
await repository.remove(entity);
|
||||
}
|
||||
|
||||
public static async FetchAll<T extends CardBaseEntity>(target: EntityTarget<T>, relations?: string[]): Promise<T[]> {
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
const all = await repository.find({ relations: relations || [] });
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
public static async FetchOneById<T extends CardBaseEntity>(target: EntityTarget<T>, id: string, relations?: string[]): Promise<T | null> {
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
const single = await repository.findOne({ where: ({ Id: id } as FindOptionsWhere<T>), relations: relations || {} });
|
||||
|
||||
return single;
|
||||
}
|
||||
|
||||
public static async Any<T extends ObjectLiteral>(target: EntityTarget<T>): Promise<boolean> {
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
const any = await repository.find();
|
||||
|
||||
return any.length > 0;
|
||||
}
|
||||
}
|
|
@ -13,13 +13,13 @@ const AppDataSource = new DataSource({
|
|||
synchronize: process.env.DB_SYNC == "true",
|
||||
logging: process.env.DB_LOGGING == "true",
|
||||
entities: [
|
||||
"dist/database/entities/**/*.js",
|
||||
"dist/database/entities/app/**/*.js",
|
||||
],
|
||||
migrations: [
|
||||
"dist/database/migrations/**/*.js",
|
||||
"dist/database/migrations/app/**/*.js",
|
||||
],
|
||||
subscribers: [
|
||||
"dist/database/subscribers/**/*.js",
|
||||
"dist/database/subscribers/app/**/*.js",
|
||||
],
|
||||
});
|
||||
|
||||
|
|
22
src/database/dataSources/cardDataSource.ts
Normal file
22
src/database/dataSources/cardDataSource.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { DataSource } from "typeorm";
|
||||
import * as dotenv from "dotenv";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const CardDataSource = new DataSource({
|
||||
type: "sqlite",
|
||||
database: process.env.DB_CARD_FILE!,
|
||||
synchronize: process.env.DB_SYNC == "true",
|
||||
logging: process.env.DB_LOGGING == "true",
|
||||
entities: [
|
||||
"dist/database/entities/card/**/*.js",
|
||||
],
|
||||
migrations: [
|
||||
"dist/database/migrations/card/**/*.js",
|
||||
],
|
||||
subscribers: [
|
||||
"dist/database/subscribers/card/**/*.js",
|
||||
],
|
||||
});
|
||||
|
||||
export default CardDataSource;
|
36
src/database/entities/card/Card.ts
Normal file
36
src/database/entities/card/Card.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { Column, Entity, OneToMany } from "typeorm";
|
||||
import CardBaseEntity from "../../../contracts/CardBaseEntity";
|
||||
import { CardRarity } from "../../../constants/CardRarity";
|
||||
import Series from "./Series";
|
||||
import CardDataSource from "../../dataSources/cardDataSource";
|
||||
|
||||
@Entity()
|
||||
export default class Card extends CardBaseEntity {
|
||||
constructor(cardNumber: string, name: string, rarity: CardRarity) {
|
||||
super();
|
||||
|
||||
this.CardNumber = cardNumber;
|
||||
this.Name = name;
|
||||
this.Rarity = rarity;
|
||||
}
|
||||
|
||||
@Column()
|
||||
CardNumber: string
|
||||
|
||||
@Column()
|
||||
Name: string;
|
||||
|
||||
@Column()
|
||||
Rarity: CardRarity;
|
||||
|
||||
@OneToMany(() => Series, x => x.Cards)
|
||||
Series: Series;
|
||||
|
||||
public static async FetchAllByRarity(rarity: CardRarity): Promise<Card[]> {
|
||||
const repository = CardDataSource.getRepository(Card);
|
||||
|
||||
const all = await repository.find({ where: { Rarity: rarity }});
|
||||
|
||||
return all;
|
||||
}
|
||||
}
|
29
src/database/entities/card/Series.ts
Normal file
29
src/database/entities/card/Series.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { Column, Entity, ManyToOne } from "typeorm";
|
||||
import CardBaseEntity from "../../../contracts/CardBaseEntity";
|
||||
import Card from "./Card";
|
||||
|
||||
@Entity()
|
||||
export default class Series extends CardBaseEntity {
|
||||
constructor(id: string, name: string, path: string) {
|
||||
super();
|
||||
|
||||
this.Id = id;
|
||||
this.Name = name;
|
||||
this.Path = path;
|
||||
}
|
||||
|
||||
@Column()
|
||||
Name: string;
|
||||
|
||||
@Column()
|
||||
Path: string;
|
||||
|
||||
@ManyToOne(() => Card, x => x.Series)
|
||||
Cards: Card[];
|
||||
|
||||
public async AddCard(card: Card) {
|
||||
if (!this.Cards) return;
|
||||
|
||||
this.Cards.push(card);
|
||||
}
|
||||
}
|
0
src/database/migrations/card/.gitkeep
Normal file
0
src/database/migrations/card/.gitkeep
Normal file
Loading…
Add table
Add a link
Reference in a new issue