Skip to content

Commit

Permalink
feat: initial database library
Browse files Browse the repository at this point in the history
  • Loading branch information
Aericio committed May 28, 2024
0 parents commit f239b57
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
.idea/
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# hive-tools-database

Built with Postgres and DrizzleORM, with zod for type-safety.
3 changes: 3 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";

export default [eslintPluginPrettierRecommended];
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "hive-tools-database",
"version": "1.0.0",
"module": "src/index.ts",
"type": "module",
"author": "paroxity",
"dependencies": {
"drizzle-kit": "^0.21.4",
"drizzle-orm": "^0.30.10",
"drizzle-zod": "^0.5.1",
"postgres": "^3.4.4",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/node": "^20.12.12",
"eslint": "^9.3.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"prettier": "^3.2.5",
"typescript": "^5.4.5"
}
}
16 changes: 16 additions & 0 deletions prettier.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Config } from "prettier";

const config: Config = {
printWidth: 80,
useTabs: true,
semi: true,
singleQuote: false,
quoteProps: "as-needed",
jsxSingleQuote: false,
trailingComma: "none",
bracketSpacing: true,
arrowParens: "avoid",
endOfLine: "lf",
};

export default config;
20 changes: 20 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import postgres from "postgres";
import { drizzle } from "drizzle-orm/postgres-js";
import { cosmetics, players } from "./schema.ts";

/**
* @param connectionString See {@link https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS Postgres Connection URIs}
*/
export default function initializeDatabase({
connectionUri,
}: {
connectionUri: string;
}) {
const client = postgres(connectionUri, { prepare: false });
const db = drizzle(client, { schema: { cosmetics, players } });

return { client, db };
}

export * from "./types.ts";
export { CosmeticSchema, PlayerSchema } from "./schema.ts";
78 changes: 78 additions & 0 deletions src/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {
integer,
json,
pgTable,
real,
text,
timestamp,
} from "drizzle-orm/pg-core";
import {
CosmeticImage,
CosmeticImageLocalizedString,
CosmeticRating,
PlayerAvatar,
} from "./types.ts";
import { sql } from "drizzle-orm";
import { z } from "zod";

/**
* Players Schema
*/

export const players = pgTable("players", {
id: text("uuid").primaryKey().notNull(),
username: text("username").notNull(),
rank: text("rank").notNull(),
equipped_avatar: json("equipped_avatar"),
});

export const PlayerSchema = z.object({
id: z.string(),
username: z.string(),
rank: z.string(),
equipped_avatar: PlayerAvatar,
});
export type PlayerSchema = z.infer<typeof PlayerSchema>;

/**
* Cosmetics Schema
*/

export const cosmetics = pgTable("cosmetics", {
id: text("id").primaryKey().notNull(),
title: json("title").notNull(),
description: json("description").notNull(),
creation_date: timestamp("creation_date").notNull(),
last_modified: timestamp("last_modified").notNull(),
start_date: timestamp("start_date"),
end_date: timestamp("end_date"),
thumbnail: text("thumbnail").notNull(),
images: json("images").notNull(),
avg_rating: real("avg_rating").notNull(),
ratings: json("ratings").notNull(),
price: integer("price").notNull(),
manual_tags: text("manual_tags")
.array()
.default(sql`ARRAY[]::text[]`),
row_created: timestamp("row_created").defaultNow(),
row_updated: timestamp("row_updated").defaultNow(),
});

export const CosmeticSchema = z.object({
id: z.string(),
title: CosmeticImageLocalizedString,
description: CosmeticImageLocalizedString,
creation_date: z.date(),
last_modified: z.date(),
start_date: z.date().nullable(),
end_date: z.date().nullable(),
thumbnail: z.string(),
images: z.array(CosmeticImage),
avg_rating: z.number(),
ratings: CosmeticRating,
price: z.number(),
manual_tags: z.array(z.string()),
row_created: z.date().optional(),
row_updated: z.date().optional(),
});
export type CosmeticSchema = z.infer<typeof CosmeticSchema>;
45 changes: 45 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { z } from "zod";

/**
* Player Types
*/

export const PlayerAvatar = z.object({
url: z.string(),
name: z.string(),
});
export type PlayerAvatar = z.infer<typeof PlayerAvatar>;

/**
* Cosmetic Types
*/

export const CosmeticImageLocalizedString = z
.object({
neutral: z.string(),
})
.catchall(z.string());
export type CosmeticImageLocalizedString = z.infer<
typeof CosmeticImageLocalizedString
>;

export const CosmeticImage = z.object({
Id: z.string(),
Tag: z.string(),
Type: z.string(),
Url: z.string(),
});
export type CosmeticImage = z.infer<typeof CosmeticImage>;

const CosmeticRatingDefaultNumber = z.number().default(0);

export const CosmeticRating = z.object({
Average: CosmeticRatingDefaultNumber,
TotalCount: CosmeticRatingDefaultNumber,
Count5Star: CosmeticRatingDefaultNumber,
Count4Star: CosmeticRatingDefaultNumber,
Count3Star: CosmeticRatingDefaultNumber,
Count2Star: CosmeticRatingDefaultNumber,
Count1Star: CosmeticRatingDefaultNumber,
});
export type CosmeticRating = z.infer<typeof CosmeticRating>;
28 changes: 28 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"allowJs": true,

// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,

"sourceMap": true,

// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,

// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}

0 comments on commit f239b57

Please sign in to comment.