From 3e4e9e1f77c09bcf2e261144aad92ad13f91f5de Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Mon, 18 May 2026 13:51:34 +0330 Subject: [PATCH] add alug --- database/migrations/.snapshot-dpage.json | 657 ++++++++++++++++++ ...igration20260518092926_addCatalogueSlug.ts | 11 + src/modules/catalogue/catalogue.controller.ts | 5 + src/modules/catalogue/catalogue.service.ts | 8 + 4 files changed, 681 insertions(+) create mode 100644 database/migrations/.snapshot-dpage.json create mode 100644 database/migrations/Migration20260518092926_addCatalogueSlug.ts diff --git a/database/migrations/.snapshot-dpage.json b/database/migrations/.snapshot-dpage.json new file mode 100644 index 0000000..d0ed02c --- /dev/null +++ b/database/migrations/.snapshot-dpage.json @@ -0,0 +1,657 @@ +{ + "namespaces": [ + "public" + ], + "name": "public", + "tables": [ + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "danak_subscription_id": { + "name": "danak_subscription_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "uuid" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "domain": { + "name": "domain", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 255, + "mappedType": "string" + }, + "is_domain_verified": { + "name": "is_domain_verified", + "type": "boolean", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "false", + "mappedType": "boolean" + }, + "domain_verification_token": { + "name": "domain_verification_token", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 255, + "mappedType": "string" + }, + "domain_verified_at": { + "name": "domain_verified_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "logo_url": { + "name": "logo_url", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 255, + "mappedType": "string" + }, + "max_catalogues_count": { + "name": "max_catalogues_count", + "type": "numeric(10,0)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "precision": 10, + "scale": 0, + "default": "0", + "mappedType": "decimal" + } + }, + "name": "business", + "schema": "public", + "indexes": [ + { + "columnNames": [ + "danak_subscription_id" + ], + "composite": false, + "keyName": "business_danak_subscription_id_unique", + "constraint": true, + "primary": false, + "unique": true + }, + { + "keyName": "business_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "business_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "business_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": {}, + "nativeEnums": {} + }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "first_name": { + "name": "first_name", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 255, + "mappedType": "string" + }, + "last_name": { + "name": "last_name", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 255, + "mappedType": "string" + }, + "phone": { + "name": "phone", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "business_id": { + "name": "business_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + } + }, + "name": "admins", + "schema": "public", + "indexes": [ + { + "columnNames": [ + "business_id" + ], + "composite": false, + "keyName": "admins_business_id_unique", + "constraint": true, + "primary": false, + "unique": true + }, + { + "keyName": "admins_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "admins_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "admins_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "admins_business_id_foreign": { + "constraintName": "admins_business_id_foreign", + "columnNames": [ + "business_id" + ], + "localTableName": "public.admins", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.business", + "updateRule": "cascade" + } + }, + "nativeEnums": {} + }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "content": { + "name": "content", + "type": "jsonb", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "json" + }, + "status": { + "name": "status", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "enumItems": [ + "APPROVED", + "PENDING", + "REJECTED" + ], + "mappedType": "enum" + }, + "size": { + "name": "size", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "enumItems": [ + "a4", + "a3", + "a5" + ], + "mappedType": "enum" + }, + "business_id": { + "name": "business_id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + } + }, + "name": "catalogue", + "schema": "public", + "indexes": [ + { + "keyName": "catalogue_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "catalogue_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "catalogue_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "catalogue_business_id_foreign": { + "constraintName": "catalogue_business_id_foreign", + "columnNames": [ + "business_id" + ], + "localTableName": "public.catalogue", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.business", + "deleteRule": "restrict", + "updateRule": "cascade" + } + }, + "nativeEnums": {} + }, + { + "columns": { + "id": { + "name": "id", + "type": "char(26)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 26, + "mappedType": "character" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "hashed_token": { + "name": "hashed_token", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "admin_id": { + "name": "admin_id", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "business_id": { + "name": "business_id", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 255, + "mappedType": "string" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "mappedType": "datetime" + } + }, + "name": "refreshtokens", + "schema": "public", + "indexes": [ + { + "keyName": "refreshtokens_created_at_index", + "columnNames": [ + "created_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "refreshtokens_deleted_at_index", + "columnNames": [ + "deleted_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "refreshtokens_expires_at_index", + "columnNames": [ + "expires_at" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "refreshtokens_hashed_token_index", + "columnNames": [ + "hashed_token" + ], + "composite": false, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "refreshtokens_admin_id_business_id_index", + "columnNames": [ + "admin_id", + "business_id" + ], + "composite": true, + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "refreshtokens_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": {}, + "nativeEnums": {} + } + ], + "nativeEnums": {} +} diff --git a/database/migrations/Migration20260518092926_addCatalogueSlug.ts b/database/migrations/Migration20260518092926_addCatalogueSlug.ts new file mode 100644 index 0000000..935b859 --- /dev/null +++ b/database/migrations/Migration20260518092926_addCatalogueSlug.ts @@ -0,0 +1,11 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20260518092926_addCatalogueSlug extends Migration { + + override async up(): Promise { + this.addSql(`alter table "catalogue" add column "slug" varchar(255);`); + this.addSql(`update "catalogue" set "slug" = lower("id"::text) where "slug" is null;`); + this.addSql(`alter table "catalogue" alter column "slug" set not null;`); + } + +} diff --git a/src/modules/catalogue/catalogue.controller.ts b/src/modules/catalogue/catalogue.controller.ts index 3eced65..9485449 100644 --- a/src/modules/catalogue/catalogue.controller.ts +++ b/src/modules/catalogue/catalogue.controller.ts @@ -27,6 +27,11 @@ export class CatalogueController { return this.catalogueService.findOne(id); } + @Get('public/catalogue/slug/:slug') + findOneBySlugAsPublic(@Param('slug') slug: string) { + return this.catalogueService.findOneOrFailBySlug(slug); + } + // ============= Admin Routes ============== @Post('admin/catalogue') diff --git a/src/modules/catalogue/catalogue.service.ts b/src/modules/catalogue/catalogue.service.ts index 6d9070d..b899777 100644 --- a/src/modules/catalogue/catalogue.service.ts +++ b/src/modules/catalogue/catalogue.service.ts @@ -67,6 +67,14 @@ export class CatalogueService { return catalogue } + async findOneOrFailBySlug(slug: string) { + const catalogue = await this.catalogueRepository.findOne({ slug }) + if (!catalogue) { + throw new NotFoundException("catalogue by slug not found") + } + return catalogue + } + async update(id: string, dto: UpdateCatalogueDto) { const catalogue = await this.findOneOrFail(id) this.em.assign(catalogue, dto)