Fixing env.ts to look for env variables, fix seeding data, adding dependencies needed for this.

This commit is contained in:
Bradley Shellnut 2024-06-13 17:32:09 -07:00
parent e4ff068fe1
commit 43877868a4
13 changed files with 185 additions and 148 deletions

View file

@ -35,7 +35,6 @@
"@typescript-eslint/eslint-plugin": "^7.12.0",
"@typescript-eslint/parser": "^7.12.0",
"autoprefixer": "^10.4.19",
"dotenv": "^16.4.5",
"drizzle-kit": "^0.22.7",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
@ -90,6 +89,8 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cookie": "^0.6.0",
"dotenv": "^16.4.5",
"dotenv-expand": "^11.0.6",
"drizzle-orm": "^0.31.2",
"feather-icons": "^4.29.2",
"formsnap": "^1.0.0",

View file

@ -53,6 +53,12 @@ importers:
cookie:
specifier: ^0.6.0
version: 0.6.0
dotenv:
specifier: ^16.4.5
version: 16.4.5
dotenv-expand:
specifier: ^11.0.6
version: 11.0.6
drizzle-orm:
specifier: ^0.31.2
version: 0.31.2(@neondatabase/serverless@0.9.3)(@types/pg@8.11.6)(pg@8.12.0)(postgres@3.4.4)
@ -162,9 +168,6 @@ importers:
autoprefixer:
specifier: ^10.4.19
version: 10.4.19(postcss@8.4.38)
dotenv:
specifier: ^16.4.5
version: 16.4.5
drizzle-kit:
specifier: ^0.22.7
version: 0.22.7
@ -2371,6 +2374,10 @@ packages:
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
engines: {node: '>=6.0.0'}
dotenv-expand@11.0.6:
resolution: {integrity: sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==}
engines: {node: '>=12'}
dotenv@16.4.5:
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
engines: {node: '>=12'}
@ -6058,6 +6065,10 @@ snapshots:
dependencies:
esutils: 2.0.3
dotenv-expand@11.0.6:
dependencies:
dotenv: 16.4.5
dotenv@16.4.5: {}
drizzle-kit@0.22.7:

View file

@ -1,30 +1,22 @@
import { drizzle } from 'drizzle-orm/node-postgres';
import pg from 'pg';
import {
DATABASE_USER,
DATABASE_PASSWORD,
DATABASE_HOST,
DATABASE_DB,
DATABASE_PORT,
DB_MIGRATING,
DB_SEEDING,
} from '$env/static/private';
import env from '../env';
import * as schema from './schema';
// create the connection
const pool = new pg.Pool({
user: DATABASE_USER,
password: DATABASE_PASSWORD,
host: DATABASE_HOST,
port: Number(DATABASE_PORT).valueOf(),
database: DATABASE_DB,
ssl: DATABASE_HOST !== 'localhost',
max: DB_MIGRATING || DB_SEEDING ? 1 : undefined,
export const pool = new pg.Pool({
user: env.DATABASE_USER,
password: env.DATABASE_PASSWORD,
host: env.DATABASE_HOST,
port: Number(env.DATABASE_PORT).valueOf(),
database: env.DATABASE_DB,
ssl: env.DATABASE_HOST !== 'localhost',
max: env.DB_MIGRATING || env.DB_SEEDING ? 1 : undefined,
});
const db = drizzle(pool, {
export const db = drizzle(pool, {
schema,
logger: process.env.NODE_ENV === 'development',
logger: env.NODE_ENV === 'development',
});
export type db = typeof db;

View file

@ -1,16 +1,17 @@
import 'dotenv/config';
import postgres from 'postgres';
import config from '../../drizzle.config';
import { drizzle } from 'drizzle-orm/postgres-js';
import { migrate } from 'drizzle-orm/postgres-js/migrator';
import env from '../env';
import config from '../../drizzle.config';
const connection = postgres({
host: process.env.DATABASE_HOST || 'localhost',
port: process.env.DATABASE_PORT,
user: process.env.DATABASE_USER || 'root',
password: process.env.DATABASE_PASSWORD || '',
database: process.env.DATABASE_DB || 'boredgame',
ssl: process.env.NODE_ENV === 'development' ? false : 'require',
host: env.DATABASE_HOST || 'localhost',
port: env.DATABASE_PORT,
user: env.DATABASE_USER || 'root',
password: env.DATABASE_PASSWORD || '',
database: env.DATABASE_DB || 'boredgame',
ssl: env.NODE_ENV === 'development' ? false : 'require',
max: 1,
});
const db = drizzle(connection);

View file

@ -30,3 +30,5 @@ export const expansion_relations = relations(expansions, ({ one }) => ({
references: [games.id],
}),
}));
export default expansions;

View file

@ -23,7 +23,7 @@ export {
export { default as externalIds, type ExternalIds, type ExternalIdType } from './externalIds';
export { default as games, gameRelations, type Games } from './games';
export { default as gamesToExternalIds } from './gamesToExternalIds';
export { default as expansions, expansions_relations, type Expansions } from './expansions';
export { default as expansions, expansion_relations, type Expansions } from './expansions';
export { default as publishers, publishers_relations, type Publishers } from './publishers';
export { default as publishers_to_games, publishers_to_games_relations } from './publishersToGames';
export { default as publishersToExternalIds } from './publishersToExternalIds';

View file

@ -1,11 +1,10 @@
import { Table, getTableName, sql } from 'drizzle-orm';
import { Argon2id } from 'oslo/password';
import { ADMIN_USERNAME, DB_SEEDING } from '$env/static/private';
import { db } from '../db';
import env from '../env';
import { db, pool } from '$db';
import * as schema from './schema';
import * as seeds from './seeds';
if (!DB_SEEDING) {
if (!env.DB_SEEDING) {
throw new Error('You must set DB_SEEDING to "true" when running seeds');
}
@ -43,66 +42,7 @@ for (const table of [
}
await seeds.roles(db);
await connection.end();
console.log('Creating roles ...');
const adminRole = await db
.insert(schema.roles)
.values([{ name: 'admin' }])
.onConflictDoNothing()
.returning();
const userRole = await db
.insert(schema.roles)
.values([{ name: 'user' }])
.onConflictDoNothing()
.returning();
await db
.insert(schema.roles)
.values([{ name: 'editor' }])
.onConflictDoNothing();
await db
.insert(schema.roles)
.values([{ name: 'moderator' }])
.onConflictDoNothing();
console.log('Roles created.');
console.log('Admin Role: ', adminRole);
const adminUser = await db
.insert(schema.users)
.values({
username: `${ADMIN_USERNAME}`,
email: '',
hashed_password: await new Argon2id().hash(`${process.env.ADMIN_PASSWORD}`),
first_name: 'Brad',
last_name: 'S',
verified: true,
})
.returning()
.onConflictDoNothing();
console.log('Admin user created.', adminUser);
await db
.insert(schema.user_roles)
.values({
user_id: adminUser[0].id,
role_id: adminRole[0].id,
})
.onConflictDoNothing();
console.log('Admin user given admin role.');
await db
.insert(schema.user_roles)
.values({
user_id: adminUser[0].id,
role_id: userRole[0].id,
})
.onConflictDoNothing();
console.log('Admin user given user role.');
await seeds.users(db);
await pool.end();
process.exit();

View file

@ -0,0 +1,14 @@
[
{
"name": "admin"
},
{
"name": "user"
},
{
"name": "editor"
},
{
"name": "moderator"
}
]

View file

@ -4,20 +4,59 @@
"last_name": "Smith",
"username": "john.smith",
"email": "john.smith@example.com",
"password": "password"
"password": "password",
"roles": [
{
"name": "user",
"primary": true
}
]
},
{
"first_name": "Jane",
"last_name": "Doe",
"username": "jane.doe",
"email": "jane.doe@example.com",
"password": "password"
"password": "password",
"roles": [
{
"name": "user",
"primary": true
}
]
},
{
"first_name": "Michael",
"last_name": "Jones",
"username": "michael.jones",
"email": "michael.jones@example.com",
"password": "password"
"last_name": "Editor",
"username": "michael.editor",
"email": "michael.editor@example.com",
"password": "password",
"roles": [
{
"name": "editor",
"primary": true
},
{
"name": "user",
"primary": false
}
]
},
{
"first_name": "Jane",
"last_name": "Moderator",
"username": "jane.moderator",
"email": "jane.moderator@example.com",
"password": "password",
"roles": [
{
"name": "moderator",
"primary": true
},
{
"name": "user",
"primary": false
}
]
}
]

2
src/db/seeds/index.ts Normal file
View file

@ -0,0 +1,2 @@
export { default as users } from './users';
export { default as roles } from './roles';

View file

@ -1,30 +1,12 @@
import { eq } from 'drizzle-orm';
import type db from '@/db';
import * as schema from '@/db/schema';
import { type db } from '$db';
import * as schema from '$db/schema';
import roles from './data/roles.json';
// console.log('Creating roles ...');
// const adminRole = await db
// .insert(schema.roles)
// .values([{ name: 'admin' }])
// .onConflictDoNothing()
// .returning();
// const userRole = await db
// .insert(schema.roles)
// .values([{ name: 'user' }])
// .onConflictDoNothing()
// .returning();
// await db
// .insert(schema.roles)
// .values([{ name: 'editor' }])
// .onConflictDoNothing();
// await db
// .insert(schema.roles)
// .values([{ name: 'moderator' }])
// .onConflictDoNothing();
// console.log('Roles created.');
export default async function seed(db: db) {
await db.insert(schema.roles).values({ name: 'user' });
await db.insert(schema.roles).values({ name: 'admin' });
console.log('Creating roles ...');
for (const role of roles) {
await db.insert(schema.roles).values(role).onConflictDoNothing();
}
console.log('Roles created.');
}

View file

@ -1,38 +1,85 @@
import { eq } from 'drizzle-orm';
import * as argon2 from 'argon2';
import type db from '@/db';
import * as schema from '@/db/schema';
import { Argon2id } from 'oslo/password';
import { type db } from '$db';
import * as schema from '$db/schema';
import users from './data/users.json';
import env from '../../env';
async function getCityId(db: db, cityName: string) {
const city = await db.query.city.findFirst({
where: eq(schema.city.name, cityName),
});
if (!city) {
throw new Error('Unknown city name: ' + cityName);
}
return city.id;
}
type JsonUser = {
id: string;
username: string;
email: string;
password: string;
roles: {
name: string;
primary: boolean;
}[];
};
type JsonRole = {
name: string;
primary: boolean;
};
export default async function seed(db: db) {
const adminRole = await db.select().from(schema.roles).where(eq(schema.roles.name, 'admin'));
const userRole = await db.select().from(schema.roles).where(eq(schema.roles.name, 'user'));
console.log('Admin Role: ', adminRole);
const adminUser = await db
.insert(schema.users)
.values({
username: `${env.ADMIN_USERNAME}`,
email: '',
hashed_password: await new Argon2id().hash(`${env.ADMIN_PASSWORD}`),
first_name: 'Brad',
last_name: 'S',
verified: true,
})
.returning()
.onConflictDoNothing();
console.log('Admin user created.', adminUser);
await db
.insert(schema.userRoles)
.values({
user_id: adminUser[0].id,
role_id: adminRole[0].id,
})
.onConflictDoNothing();
console.log('Admin user given admin role.');
await db
.insert(schema.userRoles)
.values({
user_id: adminUser[0].id,
role_id: userRole[0].id,
})
.onConflictDoNothing();
console.log('Admin user given user role.');
await Promise.all(
users.map(async (user) => {
const [insertedUser] = await db
.insert(schema.user)
.insert(schema.users)
.values({
...user,
emailVerified: true,
phoneVerified: true,
password: await argon2.hash(user.password),
hashed_password: await new Argon2id().hash(user.password),
})
.returning();
await db.insert(schema.collections).values({ user_id: insertedUser?.id });
await db.insert(schema.wishlists).values({ user_id: insertedUser?.id });
await Promise.all(
user.addresses.map(async (address) => {
await db.insert(schema.address).values({
...address,
streetAddress1: address.street_address,
userId: insertedUser.id,
cityId: await getCityId(db, address.city),
user.roles.map(async (role: JsonRole) => {
const foundRole = await db.query.roles.findFirst({
where: eq(schema.roles.name, role.name),
});
await db.insert(schema.userRoles).values({
user_id: insertedUser?.id,
role_id: foundRole?.id,
primary: role?.primary,
});
}),
);

View file

@ -1,3 +1,5 @@
import { config } from 'dotenv';
import { expand } from 'dotenv-expand';
import { ZodError, z } from 'zod';
const stringBoolean = z.coerce
@ -21,10 +23,14 @@ const EnvSchema = z.object({
PUBLIC_UMAMI_URL: z.string(),
DB_MIGRATING: stringBoolean,
DB_SEEDING: stringBoolean,
ADMIN_USERNAME: z.string(),
ADMIN_PASSWORD: z.string(),
});
export type EnvSchema = z.infer<typeof EnvSchema>;
expand(config());
try {
EnvSchema.parse(process.env);
} catch (error) {