diff --git a/api/package-lock.json b/api/package-lock.json index 0c653c6..b96faf6 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -23,7 +23,6 @@ "@types/node": "^22.9.0", "@types/nodemailer": "^6.4.16", "@types/supertest": "^6.0.2", - "@types/uuid": "^10.0.0", "@types/validator": "^13.12.2", "axios": "^1.7.7", "babel-jest": "^29.7.0", @@ -44,13 +43,13 @@ "jose": "^5.9.6", "mongoose": "^8.8.0", "multer": "^1.4.4", + "nanoid": "^5.0.8", "nocache": "^4.0.0", "nodemailer": "^6.9.16", "rimraf": "^6.0.1", "stripe": "^17.3.1", "supertest": "^7.0.0", "typescript": "^5.4.5", - "uuid": "^11.0.2", "validator": "^13.12.0", "winston": "^3.16.0" }, @@ -3407,12 +3406,6 @@ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", "license": "MIT" }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "license": "MIT" - }, "node_modules/@types/validator": { "version": "13.12.2", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.2.tgz", @@ -8673,6 +8666,24 @@ "node": ">= 0.10.0" } }, + "node_modules/nanoid": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", + "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -11047,19 +11058,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.2.tgz", - "integrity": "sha512-14FfcOJmqdjbBPdDjFQyk/SdT4NySW4eM0zcG+HqbHP5jzuH56xO3J1DGhgs/cEMCfwYi3HQI1gnTO62iaG+tQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", diff --git a/api/package.json b/api/package.json index d9c14c7..eee6189 100644 --- a/api/package.json +++ b/api/package.json @@ -28,7 +28,6 @@ "@types/node": "^22.9.0", "@types/nodemailer": "^6.4.16", "@types/supertest": "^6.0.2", - "@types/uuid": "^10.0.0", "@types/validator": "^13.12.2", "axios": "^1.7.7", "babel-jest": "^29.7.0", @@ -49,13 +48,13 @@ "jose": "^5.9.6", "mongoose": "^8.8.0", "multer": "^1.4.4", + "nanoid": "^5.0.8", "nocache": "^4.0.0", "nodemailer": "^6.9.16", "rimraf": "^6.0.1", "stripe": "^17.3.1", "supertest": "^7.0.0", "typescript": "^5.4.5", - "uuid": "^11.0.2", "validator": "^13.12.0", "winston": "^3.16.0" }, diff --git a/api/src/common/helper.ts b/api/src/common/helper.ts index 0944e11..086a159 100644 --- a/api/src/common/helper.ts +++ b/api/src/common/helper.ts @@ -3,7 +3,7 @@ import path from 'node:path' import mongoose from 'mongoose' import validator from 'validator' import Stripe from 'stripe' -import { v1 as uuid } from 'uuid' +import { nanoid } from 'nanoid' import axios from 'axios' import * as wexcommerceTypes from ':wexcommerce-types' @@ -155,7 +155,7 @@ export const isValidEmail = (email?: string) => !!email && validator.isEmail(ema * * @returns {string} */ -export const generateToken = () => `${uuid()}-${Date.now()}` +export const generateToken = () => `${nanoid()}-${Date.now()}` /** * The IETF language tag of the locale Checkout is displayed in. diff --git a/api/src/controllers/categoryController.ts b/api/src/controllers/categoryController.ts index badd0e6..d81fe71 100644 --- a/api/src/controllers/categoryController.ts +++ b/api/src/controllers/categoryController.ts @@ -1,7 +1,7 @@ import mongoose from 'mongoose' import path from 'node:path' import fs from 'node:fs/promises' -import { v1 as uuid } from 'uuid' +import { nanoid } from 'nanoid' import escapeStringRegexp from 'escape-string-regexp' import { Request, Response } from 'express' import * as wexcommerceTypes from ':wexcommerce-types' @@ -529,7 +529,7 @@ export const createImage = async (req: Request, res: Response) => { throw new Error('[category.createImage] req.file not found') } - const filename = `${helper.getFilenameWithoutExtension(req.file.originalname)}_${uuid()}_${Date.now()}${path.extname(req.file.originalname)}` + const filename = `${helper.getFilenameWithoutExtension(req.file.originalname)}_${nanoid()}_${Date.now()}${path.extname(req.file.originalname)}` const filepath = path.join(env.CDN_TEMP_CATEGORIES, filename) await fs.writeFile(filepath, req.file.buffer) diff --git a/api/src/controllers/productController.ts b/api/src/controllers/productController.ts index 629d664..23cccee 100644 --- a/api/src/controllers/productController.ts +++ b/api/src/controllers/productController.ts @@ -1,7 +1,7 @@ import mongoose, { Expression } from 'mongoose' import fs from 'fs/promises' import path from 'path' -import { v1 as uuid } from 'uuid' +import { nanoid } from 'nanoid' import { Request, Response } from 'express' import escapeStringRegexp from 'escape-string-regexp' import * as wexcommerceTypes from ':wexcommerce-types' @@ -31,7 +31,7 @@ export const uploadImage = async (req: Request, res: Response) => { throw new Error('[product.uploadImage] req.file not found') } - const filename = `${uuid()}_${Date.now()}${path.extname(req.file.originalname)}` + const filename = `${nanoid()}_${Date.now()}${path.extname(req.file.originalname)}` const filepath = path.join(env.CDN_TEMP_PRODUCTS, filename) await fs.writeFile(filepath, req.file.buffer) @@ -156,7 +156,7 @@ export const create = async (req: Request, res: Response) => { const __image = path.join(env.CDN_TEMP_PRODUCTS, image) if (await helper.exists(__image)) { - const filename = `${product._id}_${uuid()}_${Date.now()}_${i}${path.extname(image)}` + const filename = `${product._id}_${nanoid()}_${Date.now()}_${i}${path.extname(image)}` const newPath = path.join(env.CDN_PRODUCTS, filename) await fs.rename(__image, newPath) @@ -263,7 +263,7 @@ export const update = async (req: Request, res: Response) => { const _image = path.join(env.CDN_TEMP_PRODUCTS, imageFile) if (await helper.exists(_image)) { - const filename = `${product._id}_${uuid()}_${Date.now()}_${i}${path.extname(imageFile)}` + const filename = `${product._id}_${nanoid()}_${Date.now()}_${i}${path.extname(imageFile)}` const newPath = path.join(env.CDN_PRODUCTS, filename) await fs.rename(_image, newPath) diff --git a/api/src/controllers/userController.ts b/api/src/controllers/userController.ts index a0350ac..ff35a3a 100644 --- a/api/src/controllers/userController.ts +++ b/api/src/controllers/userController.ts @@ -6,7 +6,7 @@ import path from 'node:path' import fs from 'node:fs/promises' import escapeStringRegexp from 'escape-string-regexp' import axios from 'axios' -import { v1 as uuid } from 'uuid' +import { nanoid } from 'nanoid' import * as wexcommerceTypes from ':wexcommerce-types' import * as logger from '../common/logger' import i18n from '../lang/i18n' @@ -1141,7 +1141,7 @@ export const createAvatar = async (req: Request, res: Response) => { throw new Error('[user.createAvatar] req.file not found') } - const filename = `${helper.getFilenameWithoutExtension(req.file.originalname)}_${uuid()}_${Date.now()}${path.extname(req.file.originalname)}` + const filename = `${helper.getFilenameWithoutExtension(req.file.originalname)}_${nanoid()}_${Date.now()}${path.extname(req.file.originalname)}` const filepath = path.join(env.CDN_TEMP_USERS, filename) await fs.writeFile(filepath, req.file.buffer) diff --git a/api/tests/testHelper.ts b/api/tests/testHelper.ts index b0d05b2..d7e01ef 100644 --- a/api/tests/testHelper.ts +++ b/api/tests/testHelper.ts @@ -1,7 +1,7 @@ import request from 'supertest' import cookieParser from 'cookie-parser' import bcrypt from 'bcrypt' -import { v1 as uuid } from 'uuid' +import { nanoid } from 'nanoid' import mongoose from 'mongoose' import * as wexcommerceTypes from ':wexcommerce-types' import app from '../src/app' @@ -16,7 +16,7 @@ import * as settingController from '../src/controllers/settingController' export const getName = (prefix: string) => { expect(prefix.length).toBeGreaterThan(1) - return `${prefix}.${uuid()}` + return `${prefix}.${nanoid()}`.toLowerCase() } export const getRandomString = () => getName(Date.now().toString()) @@ -109,7 +109,7 @@ export const signinAsAdmin = () => signin(wexcommerceTypes.AppType.Backend, ADMI export const signinAsUser = () => signin(wexcommerceTypes.AppType.Frontend, USER_EMAIL) -export const GetRandomEmail = () => `random.${uuid()}.${Date.now()}@test.wexcommerce.ma` +export const GetRandomEmail = () => `random.${nanoid()}.${Date.now()}@test.wexcommerce.ma` export const GetRandromObjectId = () => new mongoose.Types.ObjectId() diff --git a/api/tests/user.test.ts b/api/tests/user.test.ts index 48f9041..784e13d 100644 --- a/api/tests/user.test.ts +++ b/api/tests/user.test.ts @@ -3,7 +3,7 @@ import request from 'supertest' import url from 'url' import path from 'path' import fs from 'node:fs/promises' -import { v1 as uuid } from 'uuid' +import { nanoid } from 'nanoid' import mongoose from 'mongoose' import * as wexcommerceTypes from ':wexcommerce-types' import app from '../src/app' @@ -50,7 +50,7 @@ afterAll(async () => { if (mongoose.connection.readyState) { await testHelper.close() - await Token.deleteMany({ user: { $in: [ADMIN_ID] } }) + await Token.deleteMany({ user: { $in: [ADMIN_ID, USER1_ID] } }) await databaseHelper.close() } @@ -95,7 +95,7 @@ describe('POST /api/sign-up', () => { const email = testHelper.GetRandomEmail() payload.email = email - payload.avatar = `${uuid()}.jpg` + payload.avatar = `${nanoid()}.jpg` res = await request(app) .post('/api/sign-up') .send(payload) @@ -170,7 +170,7 @@ describe('GET /api/check-token/:type/:userId/:email/:token', () => { expect(res.statusCode).toBe(204) res = await request(app) - .get(`/api/check-token/${wexcommerceTypes.AppType.Frontend}/${USER1_ID}/${USER1_EMAIL}/${uuid()}`) + .get(`/api/check-token/${wexcommerceTypes.AppType.Frontend}/${USER1_ID}/${USER1_EMAIL}/${nanoid()}`) expect(res.statusCode).toBe(204) res = await request(app) @@ -238,11 +238,11 @@ describe('GET /api/confirm-email/:email/:token', () => { expect(res.statusCode).toBe(204) res = await request(app) - .get(`/api/confirm-email/${USER1_EMAIL}/${uuid()}`) + .get(`/api/confirm-email/${USER1_EMAIL}/${nanoid()}`) expect(res.statusCode).toBe(400) res = await request(app) - .get(`/api/confirm-email/unknown/${uuid()}`) + .get(`/api/confirm-email/unknown/${nanoid()}`) expect(res.statusCode).toBe(400) }) }) @@ -499,7 +499,7 @@ describe('POST /api/validate-access-token', () => { res = await request(app) .post('/api/validate-access-token') - .set(env.X_ACCESS_TOKEN, uuid()) + .set(env.X_ACCESS_TOKEN, nanoid()) expect(res.statusCode).toBe(401) @@ -646,7 +646,7 @@ describe('POST /api/update-avatar/:userId', () => { expect(user?.avatar).toBeDefined() expect(user?.avatar).not.toBeNull() - user!.avatar = `${uuid()}.jpg` + user!.avatar = `${nanoid()}.jpg` await user?.save() res = await request(app) .post(`/api/update-avatar/${USER1_ID}`) @@ -706,7 +706,7 @@ describe('POST /api/delete-avatar/:userId', () => { expect(user).not.toBeNull() expect(user?.avatar).toBeUndefined() - user!.avatar = `${uuid()}.jpg` + user!.avatar = `${nanoid()}.jpg` await user?.save() res = await request(app) .post(`/api/delete-avatar/${USER1_ID}`)