Skip to content

Commit 280262b

Browse files
[feat 🖤] user modue | extension modules | categories module for all create 🐱‍🏍
1 parent be84775 commit 280262b

22 files changed

Lines changed: 240 additions & 80 deletions

server/src/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { DirzzleModule } from "./drizzle/drizzle.module";
33
import { ConfigModule } from "@nestjs/config";
44
import { UserModule } from "./modules/users/users.module";
55
import { ExtensionModule } from "./modules/extensions/extensions.module";
6+
import { CategoriesModule } from "./modules/categories/categories.module";
67

78
@Module({
89
imports: [
@@ -12,6 +13,7 @@ import { ExtensionModule } from "./modules/extensions/extensions.module";
1213
DirzzleModule,
1314
UserModule,
1415
ExtensionModule,
16+
CategoriesModule,
1517
],
1618
controllers: [],
1719
providers: [],
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Body, Controller, Get, Post, UsePipes } from "@nestjs/common";
2+
import { ZodValidationPipe } from "@/pipes";
3+
import {
4+
CategoriesSchema,
5+
categoriesSchema,
6+
} from "./data-transfer-object/categories.dto";
7+
import { CategoriesService } from "./categories.service";
8+
9+
@Controller({ path: "categories", version: "v1" })
10+
export class CategoriesController {
11+
constructor(private readonly service: CategoriesService) {}
12+
13+
@Post("/")
14+
@UsePipes(new ZodValidationPipe(categoriesSchema))
15+
async store(@Body() body: CategoriesSchema) {
16+
try {
17+
return await this.service.store(body);
18+
} catch (err) {
19+
return err;
20+
}
21+
}
22+
23+
@Get("/")
24+
async index() {
25+
return await this.service.index();
26+
}
27+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Module } from "@nestjs/common";
2+
import { CategoriesController } from "./categories.controller";
3+
import { CategoriesRepository } from "./categories.repository";
4+
import { CategoriesService } from "./categories.service";
5+
6+
@Module({
7+
controllers: [CategoriesController],
8+
providers: [CategoriesRepository, CategoriesService],
9+
exports: [CategoriesRepository],
10+
})
11+
export class CategoriesModule {}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Injectable } from "@nestjs/common";
2+
import { eq, SQL } from "drizzle-orm";
3+
import { db } from "@/drizzle";
4+
import { CategoriesSchema } from "./data-transfer-object/categories.dto";
5+
import categories from "./categories.schema";
6+
7+
@Injectable()
8+
export class CategoriesRepository {
9+
async create(input: CategoriesSchema) {
10+
const [data] = await db
11+
.insert(categories)
12+
.values({ ...input, slug: String(input.slug) })
13+
.returning();
14+
return data;
15+
}
16+
async fetch() {
17+
const filter: SQL[] = [];
18+
19+
return await db.query.categories.findMany();
20+
}
21+
async findBySlug(slug: string) {
22+
return await db.query.categories.findFirst({
23+
where: eq(categories.slug, slug),
24+
});
25+
}
26+
}

server/src/modules/categories/categories.schema.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ const categories = pgTable(
1414
icon: text("icon"),
1515
sortOrder: integer("sort_order").default(0),
1616
},
17-
(table) => ({
18-
slugIdx: index("categories_slug_idx").on(table.slug),
19-
}),
17+
(table) => [index("categories_slug_idx").on(table.slug)],
2018
);
2119

2220
export const categoriesRelations = relations(categories, ({ many }) => ({
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { ConflictException, Injectable } from "@nestjs/common";
2+
import { slugify } from "@/lib/utils";
3+
import { CategoriesRepository } from "./categories.repository";
4+
import { CategoriesSchema } from "./data-transfer-object/categories.dto";
5+
6+
@Injectable()
7+
export class CategoriesService {
8+
constructor(private readonly repository: CategoriesRepository) {}
9+
10+
async store(input: CategoriesSchema) {
11+
// generate slug from the category name
12+
const slug = slugify(input.name, "-");
13+
// search category into db using slug
14+
const category = await this.repository.findBySlug(slug);
15+
if (category)
16+
throw new ConflictException(
17+
"This name of category already has on this store",
18+
);
19+
20+
// now create category
21+
return await this.repository.create({ ...input, slug });
22+
}
23+
async index() {
24+
return await this.repository.fetch();
25+
}
26+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { z } from "zod";
2+
3+
export const categoriesSchema = z.object({
4+
name: z.string().min(1),
5+
slug: z.string().optional(),
6+
7+
description: z.string().min(1),
8+
icon: z.url().optional(),
9+
sortOrder: z.number().default(0),
10+
});
11+
12+
export type CategoriesSchema = z.infer<typeof categoriesSchema>;

server/src/modules/downloads/downloads.schema.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ const downloads = pgTable(
1717
.references(() => extensions.id, { onDelete: "cascade" }),
1818
ipAddress: text("ip_address"),
1919
},
20-
(table) => ({
21-
extensionIdIdx: index("downloads_extension_id_idx").on(table.extensionId),
22-
userIdIdx: index("downloads_user_id_idx").on(table.userId),
23-
createdAtIdx: index("downloads_created_at_idx").on(table.createdAt),
24-
}),
20+
(table) => [
21+
index("downloads_extension_id_idx").on(table.extensionId),
22+
index("downloads_user_id_idx").on(table.userId),
23+
index("downloads_created_at_idx").on(table.createdAt),
24+
],
2525
);
2626
export const downloadsRelations = relations(downloads, ({ one }) => ({
2727
user: one(users, {

server/src/modules/earnings/earnings.schema.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ const earnings = pgTable(
3333
status: typedTextEnum("status", earningStatus).default("pending"),
3434
paidAt: createdAt("paid_at"),
3535
},
36-
(table) => ({
37-
sellerIdIdx: index("earnings_seller_id_idx").on(table.sellerId),
38-
purchaseIdIdx: uniqueIndex("earnings_purchase_id_idx").on(table.purchaseId),
39-
statusIdx: index("earnings_status_idx").on(table.status),
40-
}),
36+
(table) => [
37+
index("earnings_seller_id_idx").on(table.sellerId),
38+
uniqueIndex("earnings_purchase_id_idx").on(table.purchaseId),
39+
index("earnings_status_idx").on(table.status),
40+
],
4141
);
4242

4343
export const earningsRelations = relations(earnings, ({ one }) => ({

server/src/modules/extension-files/extension-file.schema.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { baseSchema } from "@/utils/db-utility";
33
import extensions from "../extensions/extensions.schema";
44
import { relations } from "drizzle-orm";
55

6-
// Extension files table (for version management)
76
const extensionFiles = pgTable(
87
"extension_files",
98
{
@@ -18,15 +17,10 @@ const extensionFiles = pgTable(
1817
fileHash: text("file_hash").notNull(),
1918
fileSize: integer("file_size").notNull(),
2019
},
21-
(table) => ({
22-
extensionIdIdx: index("extension_files_extension_id_idx").on(
23-
table.extensionId,
24-
),
25-
versionIdx: index("extension_files_version_idx").on(
26-
table.extensionId,
27-
table.version,
28-
),
29-
}),
20+
(table) => [
21+
index("extension_files_extension_id_idx").on(table.extensionId),
22+
index("extension_files_version_idx").on(table.extensionId, table.version),
23+
],
3024
);
3125

3226
export const extensionFilesRelations = relations(extensionFiles, ({ one }) => ({

0 commit comments

Comments
 (0)