From e827876ce2f5d7f7edf75059874235ef85a2ae58 Mon Sep 17 00:00:00 2001 From: Timofey-Makhankov Date: Thu, 15 May 2025 22:59:16 +0200 Subject: [PATCH] implemented User Schema & created seed Function for DB --- package.json | 4 ++- pnpm-lock.yaml | 9 +++++++ src/db/domain.ts | 16 ++++++++++++ src/db/schema.ts | 66 ++++++++++++++++++++++++++++++++++++++++++++++-- src/db/seed.ts | 57 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 src/db/domain.ts create mode 100644 src/db/seed.ts diff --git a/package.json b/package.json index 89803cc..fb7a103 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "dev": "tsx watch src/index.ts", "lint": "eslint .", "lint:fix": "pnpm run lint --fix", - "db:push": "npx drizzle-kit push" + "db:push": "npx drizzle-kit push", + "db:seed": "tsx ./src/db/seed.ts" }, "dependencies": { "@libsql/client": "^0.15.5", @@ -23,6 +24,7 @@ }, "devDependencies": { "@antfu/eslint-config": "^4.13.0", + "@faker-js/faker": "^9.8.0", "@types/express": "^5.0.1", "@types/node": "^22.15.17", "drizzle-kit": "^0.31.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc6bb62..6c65a6d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,6 +30,9 @@ importers: '@antfu/eslint-config': specifier: ^4.13.0 version: 4.13.0(@typescript-eslint/utils@8.32.1(eslint@9.26.0)(typescript@5.8.3))(@vue/compiler-sfc@3.5.13)(eslint-plugin-format@1.0.1(eslint@9.26.0))(eslint@9.26.0)(typescript@5.8.3) + '@faker-js/faker': + specifier: ^9.8.0 + version: 9.8.0 '@types/express': specifier: ^5.0.1 version: 5.0.1 @@ -506,6 +509,10 @@ packages: resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@faker-js/faker@9.8.0': + resolution: {integrity: sha512-U9wpuSrJC93jZBxx/Qq2wPjCuYISBueyVUGK7qqdmj7r/nxaxwW8AQDCLeRO7wZnjj94sh3p246cAYjUKuqgfg==} + engines: {node: '>=18.0.0', npm: '>=9.0.0'} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -2696,6 +2703,8 @@ snapshots: '@eslint/core': 0.13.0 levn: 0.4.1 + '@faker-js/faker@9.8.0': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': diff --git a/src/db/domain.ts b/src/db/domain.ts new file mode 100644 index 0000000..8571689 --- /dev/null +++ b/src/db/domain.ts @@ -0,0 +1,16 @@ +import { permissionsTable, rolesPermissionsTable, rolesTable, usersRolesTable, usersTable } from "./schema"; + +export type User = typeof usersTable.$inferSelect +export type InsertUser = typeof usersTable.$inferInsert + +export type Role = typeof rolesTable.$inferSelect +export type InsertRole = typeof rolesTable.$inferInsert + +export type Permission = typeof permissionsTable.$inferSelect +export type InsertPermission = typeof permissionsTable.$inferInsert + +export type RolePermission = typeof rolesPermissionsTable.$inferSelect +export type RolePermissionInsert = typeof rolesPermissionsTable.$inferInsert + +export type UserRole = typeof usersRolesTable.$inferSelect +export type UserRoleInsert = typeof usersRolesTable.$inferInsert \ No newline at end of file diff --git a/src/db/schema.ts b/src/db/schema.ts index 50f4114..7f2790f 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -1,2 +1,64 @@ -// @ts-ignore: Remove, when creating Schemas -import { int, sqliteTable, text } from "drizzle-orm/sqlite-core" \ No newline at end of file +import { relations } from "drizzle-orm" +import { int, sqliteTable, text, primaryKey } from "drizzle-orm/sqlite-core" + +export const usersTable = sqliteTable("users", { + id: int("id").primaryKey({ autoIncrement: true }), + name: text("name").notNull(), + password: text("hash_password").notNull(), + email: text("email").notNull().unique() +}) + +export const rolesTable = sqliteTable("roles", { + id: int("id").primaryKey({ autoIncrement: true }), + name: text("name").notNull() +}) + +export const permissionsTable = sqliteTable("permissions", { + id: int("id").primaryKey({ autoIncrement: true }), + name: text("name").notNull() +}) + +export const usersRolesTable = sqliteTable('users_roles', { + userId: int("user_id").notNull().references(() => usersTable.id), + roleId: int("role_id").notNull().references(() => rolesTable.id) +}, (t) => [ primaryKey({ columns: [ t.userId, t.roleId ] }) ]) + +export const rolesPermissionsTable = sqliteTable('roles_permissions', { + roleId: int("role_id").notNull().references(() => rolesTable.id), + permissionId: int("permission_id").notNull().references(() => permissionsTable.id) +}, (t) => [primaryKey({columns: [t.roleId, t.permissionId]})]) + +export const usersRelations = relations(usersTable, ({ many }) => ({ + usersToRoles: many(usersRolesTable), +})) + +export const rolesRelations = relations(rolesTable, ({ many }) => ({ + usersToRoles: many(usersRolesTable), + rolesToPermissions: many(rolesPermissionsTable) +})) + +export const permissionsRelations = relations(permissionsTable, ({ many }) => ({ + rolesToPermissions: many(rolesPermissionsTable) +})) + +export const usersToRolesRelations = relations(usersRolesTable, ({ one }) => ({ + user: one(usersTable, { + fields: [usersRolesTable.userId], + references: [usersTable.id] + }), + role: one(rolesTable, { + fields: [usersRolesTable.roleId], + references: [rolesTable.id] + }) +})) + +export const rolesToPermissionsRelations = relations(rolesPermissionsTable, ({one}) => ({ + role: one(rolesTable, { + fields: [rolesPermissionsTable.roleId], + references: [rolesTable.id] + }), + permission: one(permissionsTable, { + fields: [rolesPermissionsTable.permissionId], + references: [permissionsTable.id] + }) +})) diff --git a/src/db/seed.ts b/src/db/seed.ts new file mode 100644 index 0000000..7877a02 --- /dev/null +++ b/src/db/seed.ts @@ -0,0 +1,57 @@ +import { db } from "./config"; +import { InsertPermission, InsertRole, InsertUser, RolePermissionInsert, UserRoleInsert } from "./domain"; +import { permissionsTable, rolesPermissionsTable, rolesTable, usersRolesTable, usersTable } from "./schema"; +import { createHash } from "node:crypto" +import { faker } from '@faker-js/faker'; + +const permissions: InsertPermission[] = [ + {name: "READ"}, + {name: "WRITE"}, + {name: "UPDATE"}, + {name: "DELETE"} +] + +const roles: InsertRole[] = [ + {name: "Admin"}, + {name: "Client"}, + {name: "Employee"} +] + +const rolePermission: RolePermissionInsert[] = [ + {roleId: 1, permissionId: 1}, + {roleId: 1, permissionId: 2}, + {roleId: 1, permissionId: 3}, + {roleId: 1, permissionId: 4}, + {roleId: 2, permissionId: 1}, + {roleId: 3, permissionId: 1}, + {roleId: 3, permissionId: 2} +] + +const users: InsertUser[] = faker.helpers.multiple(() => ({ + name: faker.person.fullName(), + password: createHash('md5').update(faker.internet.password()).digest('hex'), + email: faker.internet.email() +}), {count: 10}) + +const userRole: UserRoleInsert[] = [ + {userId: 1, roleId: 1}, + {userId: 2, roleId: 1}, + {userId: 3, roleId: 2}, + {userId: 4, roleId: 2}, + {userId: 5, roleId: 2}, + {userId: 6, roleId: 2}, + {userId: 7, roleId: 2}, + {userId: 8, roleId: 3}, + {userId: 9, roleId: 3}, + {userId: 10, roleId: 3}, +] + +async function seedDB(){ + await db.insert(permissionsTable).values(permissions) + await db.insert(rolesTable).values(roles) + await db.insert(rolesPermissionsTable).values(rolePermission) + await db.insert(usersTable).values(users) + await db.insert(usersRolesTable).values(userRole) +} + +seedDB() \ No newline at end of file