From bf410063cd997e759eb315a06f017670f2994768 Mon Sep 17 00:00:00 2001 From: devavi-labs Date: Sun, 27 Jun 2021 23:53:00 +0530 Subject: [PATCH] refactor: migrated to harperdbjs --- .eslintrc | 3 +- lib/adapters/haerperDB.ts | 69 ++++++---- lib/harperDB/index.ts | 129 +----------------- lib/middlewares/authenticate.ts | 12 +- lib/models/appUser.ts | 4 +- lib/models/payment.ts | 16 +-- lib/models/store.ts | 12 +- package.json | 1 + pages/api/auth/[...nextauth].ts | 6 +- pages/api/auth/currentUser.ts | 11 +- pages/api/payment/all.ts | 7 +- pages/api/payment/razorpay/create-order.ts | 2 +- pages/api/payment/razorpay/success.ts | 44 +++--- pages/api/store/[storeId]/deactivate.ts | 23 ++-- pages/api/store/[storeId]/index.ts | 84 ++++++------ .../product/[productId]/deactivate.ts | 25 ++-- .../product/[productId]/field/create.ts | 43 +++--- .../product/[productId]/field/edit/[key].ts | 30 ++-- .../product/[productId]/field/remove/[key].ts | 39 +++--- .../[storeId]/product/[productId]/index.ts | 75 +++++----- .../[productId]/regenerateProductKey.ts | 25 ++-- .../product/[productId]/settings/edit.ts | 26 ++-- pages/api/store/[storeId]/product/all.ts | 20 ++- pages/api/store/[storeId]/product/create.ts | 61 ++++----- .../api/store/[storeId]/regenerateStoreKey.ts | 22 +-- pages/api/store/all.ts | 13 +- pages/api/store/create.ts | 33 +++-- pages/api/v1/[productId]/index.ts | 24 ++-- yarn.lock | 53 ++++++- 29 files changed, 441 insertions(+), 471 deletions(-) diff --git a/.eslintrc b/.eslintrc index b799db8..13ddd02 100644 --- a/.eslintrc +++ b/.eslintrc @@ -36,7 +36,8 @@ "no-empty-function": "off", "@typescript-eslint/no-empty-function": ["error"], "global-require": "off", - "import/no-dynamic-require": "off" + "import/no-dynamic-require": "off", + "camelcase": "off" }, "settings": { "import/resolver": { diff --git a/lib/adapters/haerperDB.ts b/lib/adapters/haerperDB.ts index fa06eef..1c2e6ec 100644 --- a/lib/adapters/haerperDB.ts +++ b/lib/adapters/haerperDB.ts @@ -1,8 +1,8 @@ import add from "date-fns/add" +import { HarperDB } from "harperdbjs" import { Account, Profile } from "next-auth" import { Adapter } from "next-auth/adapters" import pricing from "../../pricing.json" -import { HarperDB } from "../harperDB" import { AppUser, AppUserJSON, IAppUser, PaymentStatus, Plans } from "../models" // @ts-expect-error @@ -26,40 +26,52 @@ export const HarperDBAdapter: Adapter = (db) }, } - const [userId] = await db.insert>({ + const { inserted_hashes } = await db.insert>(user, { + schema: "dev", table: "users", - records: [user], }) + if (!inserted_hashes?.[0]) { + return null + } + + const [userId] = inserted_hashes + return AppUser.fromJSON({ id: userId, ...user }) }, async getUser(id) { - const [user] = await db.findByIds([id], { table: "users" }) + const { + records: [user], + } = await db.searchByHash([id], { schema: "dev", table: "users" }) if (!user) return null - return AppUser.fromJSON(user) + return AppUser.fromJSON(user as AppUserJSON) }, async getUserByEmail(email) { if (!email) return null - const [user] = await db.findByValue("email", email, { table: "users" }) + const { + records: [user], + } = await db.searchByValue("email", email, { schema: "dev", table: "users" }) if (!user) return null - return AppUser.fromJSON(user) + return AppUser.fromJSON(user as AppUserJSON) }, async getUserByProviderAccountId(providerId, providerAccountId) { - const [accountSnapshot] = await db.findByConditions( - "and", + const { + records: [accountSnapshot], + } = await db.searchByConditions( [ - { attribute: "providerId", type: "equals", value: providerId }, - { attribute: "providerAccountId", type: "equals", value: providerAccountId }, + { searchAttribute: "providerId", searchType: "equals", searchValue: providerId }, + { searchAttribute: "providerAccountId", searchType: "equals", searchValue: providerAccountId }, ], { + schema: "dev", table: "accounts", limit: 1, } @@ -67,28 +79,31 @@ export const HarperDBAdapter: Adapter = (db) if (!accountSnapshot) return null - const userId = accountSnapshot?.userId as string + const userId = (accountSnapshot as Account)?.userId as string if (!userId) return null - const [user] = await db.findByIds([userId], { table: "users" }) + const { + records: [user], + } = await db.searchByHash([userId], { schema: "dev", table: "users" }) if (!user) return null - return AppUser.fromJSON(user) + return AppUser.fromJSON(user as AppUserJSON) }, async updateUser(user) { - await db.update({ + await db.updateOne(new AppUser(user).toJSON(), { + schema: "dev", table: "users", - records: [new AppUser(user).toJSON()], }) return user }, async deleteUser(userId) { - await db.delete([userId], { + await db.deleteOne(userId, { + schema: "dev", table: "users", }) }, @@ -104,23 +119,25 @@ export const HarperDBAdapter: Adapter = (db) accessTokenExpires, } - await db.insert({ + await db.insert(account, { + schema: "dev", table: "accounts", - records: [account], }) return account }, async unlinkAccount(userId, providerId, providerAccountId) { - const [account] = await db.findByConditions( - "and", + const { + records: [account], + } = await db.searchByConditions( [ - { attribute: "userId", type: "equals", value: userId }, - { attribute: "providerId", type: "equals", value: providerId }, - { attribute: "providerAccountId", type: "equals", value: providerAccountId }, + { searchAttribute: "userId", searchType: "equals", searchValue: userId }, + { searchAttribute: "providerId", searchType: "equals", searchValue: providerId }, + { searchAttribute: "providerAccountId", searchType: "equals", searchValue: providerAccountId }, ], { + schema: "dev", table: "accounts", limit: 1, } @@ -128,9 +145,9 @@ export const HarperDBAdapter: Adapter = (db) if (!account) return null - const accountId = account.id + const accountId = (account as Account).id - return db.delete([accountId], { table: "accounts" }) + return db.deleteOne(accountId, { schema: "dev", table: "accounts" }) }, // next-auth throws error if these functions aren't defined diff --git a/lib/harperDB/index.ts b/lib/harperDB/index.ts index 5a3b6c9..9e29457 100644 --- a/lib/harperDB/index.ts +++ b/lib/harperDB/index.ts @@ -1,125 +1,6 @@ -import axios, { AxiosResponse } from "axios" -import omitBy from "lodash/omitBy" -import isNil from "lodash/isNil" +import { HarperDB } from "harperdbjs" -/* eslint-disable camelcase */ -export class HarperDB { - private readonly baseURL = process.env.NEXT_PUBLIC_DB_ENDPOINT - - private readonly authToken = process.env.NEXT_PUBLIC_DB_AUTH_TOKEN - - constructor(public readonly schema: string) {} - - private readonly client = axios.create({ - baseURL: this.baseURL, - headers: { - Authorization: `Basic ${this.authToken}`, - "Content-Type": "application/json", - }, - method: "POST", - }) - - async insert(options: { table: string; records: T[] }) { - const data = JSON.stringify({ - operation: "insert", - schema: this.schema, - table: options.table, - records: options.records.map((record) => omitBy(record, isNil)), - }) - - const { - data: { inserted_hashes }, - } = await this.client({ data }) - return (inserted_hashes ?? []) as string[] - } - - async findByIds(ids: string[], options: { table: string; attributes?: string[] }) { - const data = JSON.stringify({ - operation: "search_by_hash", - schema: this.schema, - table: options.table, - hash_values: ids, - get_attributes: options.attributes ?? ["*"], - }) - - return ((await this.client({ data })) as AxiosResponse).data - } - - async findByValue(attribute: string, value: string, options: { table: string; attributes?: string[] }) { - const data = JSON.stringify({ - operation: "search_by_value", - schema: this.schema, - table: options.table, - search_attribute: attribute, - search_value: value, - get_attributes: options.attributes ?? ["*"], - }) - - return ((await this.client({ data })) as AxiosResponse).data - } - - async findByConditions( - operator: "and" | "or", - conditions: { - attribute: string - type: "equals" | "contains" | "starts_with" | "ends_with" | "greater_than" | "greater_than_equal" | "less_than" | "less_than_equal" | "between" - value: string - }[], - options: { table: string; attributes?: string[]; limit?: number; offset?: number } - ) { - const data = JSON.stringify({ - operation: "search_by_conditions", - schema: this.schema, - table: options.table, - operator, - offset: options.offset ?? 0, - limit: options.offset ?? 20, - get_attributes: options.attributes ?? ["*"], - conditions: conditions.map(({ attribute, type, value }) => ({ search_attribute: attribute, search_type: type, search_value: value })), - }) - - return ((await this.client({ data })) as AxiosResponse).data - } - - async update(options: { table: string; records: ({ id: string } & Partial)[] }) { - const data = JSON.stringify({ - operation: "update", - schema: this.schema, - table: options.table, - records: options.records.map((record) => omitBy(record, isNil)), - }) - - const { - data: { update_hashes }, - } = await this.client({ data }) - return (update_hashes ?? []) as string[] - } - - async upsert(options: { table: string; records: T[] }) { - const data = JSON.stringify({ - operation: "upsert", - schema: this.schema, - table: options.table, - records: omitBy(options.records, isNil), - }) - - const { - data: { upserted_hashes }, - } = await this.client({ data }) - return (upserted_hashes ?? []) as string[] - } - - async delete(ids: string[], options: { table: string }) { - const data = JSON.stringify({ - operation: "delete", - schema: this.schema, - table: options.table, - hash_values: ids, - }) - - const { - data: { deleted_hashes }, - } = await this.client({ data }) - return (deleted_hashes ?? []) as string[] - } -} +export const harperdb = new HarperDB({ + url: process.env.DB_URL ?? "", + token: process.env.DB_TOKEN, +}) diff --git a/lib/middlewares/authenticate.ts b/lib/middlewares/authenticate.ts index 79bba55..1c4cf09 100644 --- a/lib/middlewares/authenticate.ts +++ b/lib/middlewares/authenticate.ts @@ -2,8 +2,8 @@ import { NextApiRequest, NextApiResponse } from "next" import { NextMiddleware, use } from "next-api-middleware" import { Session } from "next-auth" import { getSession } from "next-auth/client" -import { HarperDB } from "../harperDB" -import { AppUser, IAppUser } from "../models" +import { harperdb } from "../harperDB" +import { AppUser, AppUserJSON } from "../models" export type NextApiRequestWithAuth = NextApiRequest & { session: Session @@ -17,16 +17,16 @@ const authenticate = async (req: NextApiRequestWithAuth, res: NextApiResponse, n return res.status(403).json({ message: "You are not allowed to perform this action." }) } - const db = new HarperDB("dev") - - const [user] = await db.findByIds([session.id], { table: "users" }) + const { + records: [user], + } = (await harperdb.searchByHash([session.id], { schema: "dev", table: "users" })) as unknown as { records: AppUserJSON[] } if (!user) { return res.status(403).json({ message: "You are not allowed to perform this action." }) } req.session = session - req.user = new AppUser(user) + req.user = AppUser.fromJSON(user) return next() } diff --git a/lib/models/appUser.ts b/lib/models/appUser.ts index 1e000a4..fc49d44 100644 --- a/lib/models/appUser.ts +++ b/lib/models/appUser.ts @@ -4,7 +4,7 @@ import { IUsage, Usage } from "./usage" import pricing from "../../pricing.json" export interface IAppUser { - id: string + id: string | number name?: string email?: string isEmailVerified?: boolean @@ -16,7 +16,7 @@ export interface IAppUser { export type AppUserJSON = Omit & { subscription: SubscriptionJSON } export class AppUser implements IAppUser { - id: string + id: string | number name?: string | undefined diff --git a/lib/models/payment.ts b/lib/models/payment.ts index bb093f7..41ce075 100644 --- a/lib/models/payment.ts +++ b/lib/models/payment.ts @@ -2,15 +2,15 @@ import format from "date-fns/format" import { Plans } from "./subscription" export interface IPayment { - id: string - userId: string + id: string | number + userId: string | number plan: Plans amount: number currency: string couponUsed?: string discount?: number - razorpayOrderId: string - razorpayPaymentId: string + razorpayOrderId: string | number + razorpayPaymentId: string | number createdAt?: string updatedAt?: string } @@ -18,9 +18,9 @@ export interface IPayment { export type PaymentJSON = Omit & { __createdtime__: string; __updatedtime__: string } export class Payment implements IPayment { - id: string + id: string | number - userId: string + userId: string | number plan: Plans @@ -32,9 +32,9 @@ export class Payment implements IPayment { discount?: number | undefined - razorpayOrderId: string + razorpayOrderId: string | number - razorpayPaymentId: string + razorpayPaymentId: string | number createdAt?: string | undefined diff --git a/lib/models/store.ts b/lib/models/store.ts index 7867128..2bc9da1 100644 --- a/lib/models/store.ts +++ b/lib/models/store.ts @@ -1,9 +1,9 @@ import formatDistanceToNow from "date-fns/formatDistanceToNow" export interface IStore { - id?: string - ownerId: string - storeId: string + id?: string | number + ownerId: string | number + storeId: string | number url?: string products?: number isActive?: boolean @@ -15,11 +15,11 @@ export interface IStore { export type StoreJSON = Omit & { __createdtime__: string; __updatedtime__: string } export class Store implements IStore { - id?: string | undefined + id?: string | number | undefined - ownerId: string + ownerId: string | number - storeId: string + storeId: string | number url?: string | undefined diff --git a/package.json b/package.json index d2fce01..34257de 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "date-fns": "^2.22.1", "formik": "^2.2.9", "framer-motion": "4", + "harperdbjs": "^0.1.0", "lodash": "^4.17.21", "lottie-react": "^2.1.0", "next": "10.2.3", diff --git a/pages/api/auth/[...nextauth].ts b/pages/api/auth/[...nextauth].ts index 9510b78..d690a24 100644 --- a/pages/api/auth/[...nextauth].ts +++ b/pages/api/auth/[...nextauth].ts @@ -1,7 +1,7 @@ +import { HarperDBAdapter } from "@lib/adapters/haerperDB" +import { harperdb } from "@lib/harperDB" import NextAuth from "next-auth" import Providers from "next-auth/providers" -import { HarperDBAdapter } from "../../../lib/adapters/haerperDB" -import { HarperDB } from "../../../lib/harperDB" export default NextAuth({ providers: [ @@ -25,7 +25,7 @@ export default NextAuth({ maxAge: 30 * 24 * 60 * 60, // 30 days updateAge: 24 * 60 * 60, // 24 hours }, - adapter: HarperDBAdapter(new HarperDB("dev")), + adapter: HarperDBAdapter(harperdb), pages: { signIn: "/auth/signin", signOut: "/auth/signout", diff --git a/pages/api/auth/currentUser.ts b/pages/api/auth/currentUser.ts index 39e981a..73432ee 100644 --- a/pages/api/auth/currentUser.ts +++ b/pages/api/auth/currentUser.ts @@ -1,7 +1,6 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../lib/middlewares" -import { IAppUser } from "../../../lib/models" const getCurrentUser = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const { @@ -10,9 +9,9 @@ const getCurrentUser = async (req: NextApiRequestWithAuth, res: NextApiResponse) if (req.method === "GET") { try { - const db = new HarperDB("dev") - - const [user] = await db.findByIds([id as string], { table: "users" }) + const { + records: [user], + } = await harperdb.searchByHash([id as string], { schema: "dev", table: "users" }) if (!user) { return res.status(404).json({ code: 404, message: "User doesn't exist" }) diff --git a/pages/api/payment/all.ts b/pages/api/payment/all.ts index b142afb..b5a6519 100644 --- a/pages/api/payment/all.ts +++ b/pages/api/payment/all.ts @@ -1,6 +1,5 @@ -import { HarperDB } from "@lib/harperDB" +import { harperdb } from "@lib/harperDB" import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" -import { PaymentJSON } from "@lib/models/payment" import orderBy from "lodash/orderBy" import { NextApiHandler, NextApiResponse } from "next" @@ -8,9 +7,7 @@ const getAllPayments = async (req: NextApiRequestWithAuth, res: NextApiResponse) const { method, user } = req if (method === "GET") { - const db = new HarperDB("dev") - - const payments = await db.findByValue("userId", user.id, { table: "payments" }) + const { records: payments } = await harperdb.searchByValue("userId", user.id, { schema: "dev", table: "payments" }) if (!payments) { return res.status(404).json({ message: "No payment history found." }) diff --git a/pages/api/payment/razorpay/create-order.ts b/pages/api/payment/razorpay/create-order.ts index c507275..c5c2272 100644 --- a/pages/api/payment/razorpay/create-order.ts +++ b/pages/api/payment/razorpay/create-order.ts @@ -28,7 +28,7 @@ const createOrder = async (req: NextApiRequestWithAuth, res: NextApiResponse) => const notes = { plan, description: `Payment for ${plan.toUpperCase()} plan`, - user: user.id, + user: String(user.id), } if (coupon) { diff --git a/pages/api/payment/razorpay/success.ts b/pages/api/payment/razorpay/success.ts index 49d5f78..2d2c4aa 100644 --- a/pages/api/payment/razorpay/success.ts +++ b/pages/api/payment/razorpay/success.ts @@ -1,5 +1,5 @@ /* eslint-disable camelcase */ -import { HarperDB } from "@lib/harperDB" +import { harperdb } from "@lib/harperDB" import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" import { AppUserJSON, PaymentStatus, Plans } from "@lib/models" import { PaymentJSON } from "@lib/models/payment" @@ -41,9 +41,18 @@ const handleSuccess = async (req: NextApiRequestWithAuth, res: NextApiResponse) razorpayPaymentId: razorpayPaymentId as string, } - const db = new HarperDB("dev") + const { inserted_hashes } = await harperdb.insert>(payment, { + schema: "dev", + table: "payments", + }) - const [paymentId] = await db.insert>({ table: "payments", records: [payment] }) + if (!inserted_hashes?.[0]) { + await razorpay.payments.payment(razorpayPaymentId as string).refund({ + reverse_all: 1, + }) + } + + const paymentId = inserted_hashes?.[0] if (!paymentId) { await razorpay.payments.payment(razorpayPaymentId as string).refund({ @@ -64,21 +73,22 @@ const handleSuccess = async (req: NextApiRequestWithAuth, res: NextApiResponse) razorpayCustomerId = id } - await db.update({ - table: "users", - records: [ - { - id: user.id, - subscription: { - ...user.subscription, - razorpayCustomerId, - plan: plan as Plans, - expiry: add(new Date(), { days: pricingPlan.days ?? 30 }).getTime(), - status: PaymentStatus.Paid, - }, + await harperdb.updateOne( + { + id: user.id, + subscription: { + ...user.subscription, + razorpayCustomerId, + plan: plan as Plans, + expiry: add(new Date(), { days: pricingPlan.days ?? 30 }).getTime(), + status: PaymentStatus.Paid, }, - ], - }) + }, + { + schema: "dev", + table: "users", + } + ) return res.status(200).json({ message: `Thanks for subscribing for ${plan} plan` }) } diff --git a/pages/api/store/[storeId]/deactivate.ts b/pages/api/store/[storeId]/deactivate.ts index ec43bba..9fd9bbf 100644 --- a/pages/api/store/[storeId]/deactivate.ts +++ b/pages/api/store/[storeId]/deactivate.ts @@ -1,7 +1,7 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { StoreJSON } from "@models" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../lib/middlewares" -import { StoreJSON } from "../../../../lib/models" const deactivateStore = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { if (req.method === "PUT") { @@ -15,24 +15,23 @@ const deactivateStore = async (req: NextApiRequestWithAuth, res: NextApiResponse const setStatus = (isActive: boolean) => async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const { storeId } = req.query - const db = new HarperDB("dev") try { - const [store] = await db.findByConditions( - "and", + const { + records: [store], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, ], - - { table: "stores" } - ) + { schema: "dev", table: "stores" } + )) as unknown as { records: StoreJSON[] } if (!store) { return res.status(404).json({ message: "No store exists with the provided store id." }) } - await db.update({ table: "stores", records: [{ id: store.id as string, isActive }] }) + await harperdb.updateOne({ id: store.id as string, isActive }, { schema: "dev", table: "stores" }) return res.status(200).json({ message: `Store ${storeId} ${isActive ? "re-activated" : "deactivated"} successfully.` }) } catch (err) { return res.status(500).json({ message: "Some unexpected error occurred." }) diff --git a/pages/api/store/[storeId]/index.ts b/pages/api/store/[storeId]/index.ts index 227ea1b..32fb6bb 100644 --- a/pages/api/store/[storeId]/index.ts +++ b/pages/api/store/[storeId]/index.ts @@ -1,25 +1,24 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { ProductJSON, Store, StoreJSON } from "@models" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../lib/middlewares" -import { IAppUser, ProductJSON, Store, StoreJSON } from "../../../../lib/models" const getStore = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const { storeId } = req.query - const db = new HarperDB("dev") const { user, method } = req if (method === "GET") { try { - const [store] = await db.findByConditions( - "and", + const { + records: [store], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: user.id }, - { attribute: "storeId", type: "equals", value: storeId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: user.id }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, ], - - { table: "stores" } - ) + { schema: "dev", table: "stores" } + )) as unknown as { records: StoreJSON[] } if (!store) { return res.status(404).json({ message: "No store exists with the provided store id." }) @@ -32,21 +31,27 @@ const getStore = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { } else if (method === "DELETE") { try { // finding the store with the storeId if its owned by the current user - const [store] = await db.findByConditions( - "and", + const { + records: [store], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: user.id }, - { attribute: "storeId", type: "equals", value: storeId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: user.id }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, ], - - { table: "stores" } - ) + { schema: "dev", table: "stores" } + )) as unknown as { records: StoreJSON[] } if (!store) { return res.status(404).json({ message: "No store exists with the provided store id." }) } - const [deletedStoreId] = await db.delete([store.id as string], { table: "stores" }) + const { deleted_hashes } = await harperdb.deleteOne(store.id as string, { schema: "dev", table: "stores" }) + + if (!deleted_hashes || !deleted_hashes?.[0]) { + return res.status(500).json({ message: "Some unexpected error occurred." }) + } + + const deletedStoreId = deleted_hashes[0] if (!deletedStoreId) { return res.status(500).json({ message: "Some unexpected error occurred." }) @@ -57,39 +62,42 @@ const getStore = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { // if store has products inside it, we will delete them as well if (store.products) { - const products = await db.findByValue("storeId", store.storeId, { table: "products" }) + const { records: products } = (await harperdb.searchByValue("storeId", store.storeId, { schema: "dev", table: "products" })) as unknown as { + records: ProductJSON[] + } if (products.length) { - const deletedProductsIds = await db.delete( + const { deleted_hashes: del_hashes } = await harperdb.deleteMany( products.map(({ id }) => id!), - { table: "products" } + { schema: "dev", table: "products" } ) - if (deletedProductsIds.length) { + if (del_hashes?.length) { deletedFieldsCount = products - .filter(({ id }) => deletedProductsIds.includes(id!)) + .filter(({ id }) => del_hashes.includes(id!)) .map(({ fields }) => fields?.length ?? 0) .reduce((prev, curr) => prev + curr) - deletedProductsCount = deletedProductsIds.length + deletedProductsCount = del_hashes.length } } } - await db.update({ - table: "users", - records: [ - { - id: user.id, - usage: { - ...(user.usage ?? {}), - stores: (user.usage?.stores ?? 1) - 1, - products: (user.usage?.products ?? deletedProductsCount) - deletedProductsCount, - fields: (user.usage?.fields ?? deletedFieldsCount) - deletedFieldsCount, - }, + await harperdb.updateOne( + { + id: user.id, + usage: { + ...(user.usage ?? {}), + stores: (user.usage?.stores ?? 1) - 1, + products: (user.usage?.products ?? deletedProductsCount) - deletedProductsCount, + fields: (user.usage?.fields ?? deletedFieldsCount) - deletedFieldsCount, }, - ], - }) + }, + { + schema: "dev", + table: "users", + } + ) return res.status(200).json({ message: `Store ${storeId} destroyed.` }) } catch (err) { diff --git a/pages/api/store/[storeId]/product/[productId]/deactivate.ts b/pages/api/store/[storeId]/product/[productId]/deactivate.ts index eb85c4c..eaa503b 100644 --- a/pages/api/store/[storeId]/product/[productId]/deactivate.ts +++ b/pages/api/store/[storeId]/product/[productId]/deactivate.ts @@ -1,7 +1,7 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { ProductJSON } from "@models" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../../lib/middlewares" -import { ProductJSON } from "../../../../../../lib/models" const deactivateProduct = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { if (req.method === "PUT") { @@ -15,25 +15,24 @@ const deactivateProduct = async (req: NextApiRequestWithAuth, res: NextApiRespon const setStatus = (isActive: boolean) => async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const { storeId, productId } = req.query - const db = new HarperDB("dev") try { - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product) { return res.status(404).json({ message: "No product exists with the provided product id." }) } - await db.update({ table: "products", records: [{ id: product.id as string, isActive }] }) + await harperdb.updateOne({ id: product.id as string, isActive }, { schema: "dev", table: "products" }) return res.status(200).json({ message: `Product ${productId} ${isActive ? "re-activated" : "deactivated"} successfully.` }) } catch (err) { return res.status(500).json({ message: "Some unexpected error occurred." }) diff --git a/pages/api/store/[storeId]/product/[productId]/field/create.ts b/pages/api/store/[storeId]/product/[productId]/field/create.ts index 76f07c0..c09de74 100644 --- a/pages/api/store/[storeId]/product/[productId]/field/create.ts +++ b/pages/api/store/[storeId]/product/[productId]/field/create.ts @@ -1,9 +1,9 @@ +import { Encrypt } from "@lib/encrypt" +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { Field, IField, ProductJSON } from "@models" +import { FieldError } from "@types" import { NextApiHandler, NextApiResponse } from "next" -import { Encrypt } from "../../../../../../../lib/encrypt" -import { HarperDB } from "../../../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../../../lib/middlewares" -import { Field, IAppUser, IField, ProductJSON } from "../../../../../../../lib/models" -import { FieldError } from "../../../../../../../lib/types" const createField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const { user, method } = req @@ -37,18 +37,16 @@ const createField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => fieldErrors.push({ field: "value", error: "Field value is required" }) } - const db = new HarperDB("dev") - - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: user.id }, - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: user.id }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product) { return res.status(400).json({ message: "No product exists with the provided store id." }) @@ -89,16 +87,19 @@ const createField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => const { id, fields } = product try { - const [newFieldId] = await db.update({ table: "products", records: [{ id: id as string, fields }] }) + const { update_hashes } = await harperdb.updateOne({ id: id as string, fields }, { schema: "dev", table: "products" }) - if (!newFieldId) { + if (!update_hashes || !update_hashes[0]) { return res.status(500).json({ message: "Some unexpected error occurred." }) } - await db.update({ - table: "users", - records: [{ id: user.id, usage: { ...(user.usage ?? {}), fields: (user.usage?.fields ?? 0) + 1 } }], - }) + await harperdb.updateOne( + { id: user.id, usage: { ...(user.usage ?? {}), fields: (user.usage?.fields ?? 0) + 1 } }, + { + schema: "dev", + table: "users", + } + ) return res.status(201).json({ message: `Field ${key} created successfully.` }) } catch (err) { diff --git a/pages/api/store/[storeId]/product/[productId]/field/edit/[key].ts b/pages/api/store/[storeId]/product/[productId]/field/edit/[key].ts index 57a7153..eb4ab00 100644 --- a/pages/api/store/[storeId]/product/[productId]/field/edit/[key].ts +++ b/pages/api/store/[storeId]/product/[productId]/field/edit/[key].ts @@ -1,9 +1,9 @@ +import { Encrypt } from "@lib/encrypt" +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { Field, IField, ProductJSON } from "@models" +import { FieldError } from "@types" import { NextApiHandler, NextApiResponse } from "next" -import { Encrypt } from "../../../../../../../../lib/encrypt" -import { HarperDB } from "../../../../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../../../../lib/middlewares" -import { Field, IField, ProductJSON } from "../../../../../../../../lib/models" -import { FieldError } from "../../../../../../../../lib/types" const createField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const fieldErrors: FieldError[] = [] @@ -31,18 +31,16 @@ const createField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => fieldErrors.push({ field: "value", error: "Field value is required" }) } - const db = new HarperDB("dev") - - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product) { return res.status(400).json({ message: "No product exists with the provided product id." }) @@ -81,7 +79,7 @@ const createField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => const { id, fields } = product try { - await db.update({ table: "products", records: [{ id: id as string, fields }] }) + await harperdb.updateOne({ id: id as string, fields }, { schema: "dev", table: "products" }) return res.status(201).json({ message: `Field ${key} updated successfully.` }) } catch (err) { return res.status(500).json({ message: "Some unexpected error occurred." }) diff --git a/pages/api/store/[storeId]/product/[productId]/field/remove/[key].ts b/pages/api/store/[storeId]/product/[productId]/field/remove/[key].ts index 6576f7c..38e23b1 100644 --- a/pages/api/store/[storeId]/product/[productId]/field/remove/[key].ts +++ b/pages/api/store/[storeId]/product/[productId]/field/remove/[key].ts @@ -1,7 +1,7 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { ProductJSON } from "@models" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../../../../lib/middlewares" -import { IAppUser, ProductJSON } from "../../../../../../../../lib/models" const removeField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const { user, method } = req @@ -25,18 +25,16 @@ const removeField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => return res.status(400).json({ message: "Only alphabets, numbers and underscore is allowed." }) } - const db = new HarperDB("dev") - - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: user.id }, - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: user.id }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product) { return res.status(400).json({ message: "No product exists with the provided product id." }) @@ -53,16 +51,19 @@ const removeField = async (req: NextApiRequestWithAuth, res: NextApiResponse) => const { id, fields } = product try { - const [updatedProductId] = await db.update({ table: "products", records: [{ id: id as string, fields }] }) + const { update_hashes } = await harperdb.updateOne({ id: id as string, fields }, { schema: "dev", table: "products" }) - if (!updatedProductId) { + if (!update_hashes || !update_hashes[0]) { return res.status(500).json({ message: "Some unexpected error occurred." }) } - await db.update({ - table: "users", - records: [{ id: user.id, usage: { ...(user.usage ?? {}), fields: (user.usage?.fields ?? 1) - 1 } }], - }) + await harperdb.updateOne( + { id: user.id, usage: { ...(user.usage ?? {}), fields: (user.usage?.fields ?? 1) - 1 } }, + { + schema: "dev", + table: "users", + } + ) return res.status(201).json({ message: `Field ${key} removed successfully.` }) } catch (err) { diff --git a/pages/api/store/[storeId]/product/[productId]/index.ts b/pages/api/store/[storeId]/product/[productId]/index.ts index edbdb43..97ecccb 100644 --- a/pages/api/store/[storeId]/product/[productId]/index.ts +++ b/pages/api/store/[storeId]/product/[productId]/index.ts @@ -1,26 +1,24 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { Product, ProductJSON, StoreJSON } from "@models" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../../lib/middlewares" -import { IAppUser, IStore, Product, ProductJSON } from "../../../../../../lib/models" const getProduct = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const { storeId, productId } = req.query - const db = new HarperDB("dev") - const { user, method } = req if (method === "GET") { try { - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: user.id }, - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: user.id }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product) { return res.status(400).json({ message: "No product exists with the provided product id." }) @@ -32,46 +30,49 @@ const getProduct = async (req: NextApiRequestWithAuth, res: NextApiResponse) => } } else if (method === "DELETE") { try { - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: user.id }, - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: user.id }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product) { return res.status(400).json({ error: "No product exists with the provided product id." }) } - const [deletedProductId] = await db.delete([product.id as string], { table: "products" }) + const { deleted_hashes } = await harperdb.deleteOne(product.id as string, { schema: "dev", table: "products" }) - if (!deletedProductId) { + if (!deleted_hashes || !deleted_hashes[0]) { return res.status(500).json({ message: "Some unexpected error occurred." }) } const deletedFieldsCount = product.fields?.length ?? 0 - const [store] = await db.findByValue("storeId", storeId as string, { table: "stores" }) + const { + records: [store], + } = (await harperdb.searchByValue("storeId", storeId as string, { schema: "dev", table: "stores" })) as unknown as { records: StoreJSON[] } - if (store) await db.update({ table: "stores", records: [{ id: store.id as string, products: (store?.products ?? 1) - 1 }] }) + if (store) await harperdb.updateOne({ id: store.id as string, products: (store?.products ?? 1) - 1 }, { schema: "dev", table: "stores" }) - await db.update({ - table: "users", - records: [ - { - id: user.id, - usage: { - ...(user.usage ?? {}), - products: (user.usage?.products ?? 1) - 1, - fields: (user.usage?.fields ?? deletedFieldsCount) - deletedFieldsCount, - }, + await harperdb.updateOne( + { + id: user.id, + usage: { + ...(user.usage ?? {}), + products: (user.usage?.products ?? 1) - 1, + fields: (user.usage?.fields ?? deletedFieldsCount) - deletedFieldsCount, }, - ], - }) + }, + { + schema: "dev", + table: "users", + } + ) return res.status(200).json({ message: `Product ${productId} destroyed.` }) } catch (err) { diff --git a/pages/api/store/[storeId]/product/[productId]/regenerateProductKey.ts b/pages/api/store/[storeId]/product/[productId]/regenerateProductKey.ts index f6cb4f6..fd1217a 100644 --- a/pages/api/store/[storeId]/product/[productId]/regenerateProductKey.ts +++ b/pages/api/store/[storeId]/product/[productId]/regenerateProductKey.ts @@ -1,25 +1,24 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { ProductJSON } from "@models" import * as crypto from "crypto" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../../lib/middlewares" -import { ProductJSON } from "../../../../../../lib/models" const regenerateProductKey = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { if (req.method === "PATCH") { const { storeId, productId } = req.query - const db = new HarperDB("dev") try { - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product) { return res.status(400).json({ message: "No product exists with the provided product id." }) @@ -27,7 +26,7 @@ const regenerateProductKey = async (req: NextApiRequestWithAuth, res: NextApiRes const productKey = crypto.randomBytes(64).toString("base64") - await db.update({ table: "products", records: [{ id: product.id as string, productKey }] }) + await harperdb.updateOne({ id: product.id as string, productKey }, { schema: "dev", table: "products" }) return res.status(201).json({ message: `Key for product ${productId} regenerated successfully.` }) } catch (err) { return res.status(500).json({ message: "Some unexpected error occurred." }) diff --git a/pages/api/store/[storeId]/product/[productId]/settings/edit.ts b/pages/api/store/[storeId]/product/[productId]/settings/edit.ts index f00aea9..d3d72d4 100644 --- a/pages/api/store/[storeId]/product/[productId]/settings/edit.ts +++ b/pages/api/store/[storeId]/product/[productId]/settings/edit.ts @@ -1,8 +1,8 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { IProduct, ProductJSON } from "@models" import crypto from "crypto" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../../../lib/middlewares" -import { IProduct, ProductJSON } from "../../../../../../../lib/models" const updateProductSettings = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { if (req.method === "POST") { @@ -17,18 +17,16 @@ const updateProductSettings = async (req: NextApiRequestWithAuth, res: NextApiRe return res.status(400).json({ message: "A valid product id is required." }) } - const db = new HarperDB("dev") - - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product) { return res.status(400).json({ message: "No product exists with the provided product id." }) @@ -41,7 +39,7 @@ const updateProductSettings = async (req: NextApiRequestWithAuth, res: NextApiRe } try { - await db.update({ table: "products", records: [{ id: product.id as string, isPrivate, isUsingStoreKey, productKey }] }) + await harperdb.updateOne({ id: product.id as string, isPrivate, isUsingStoreKey, productKey }, { schema: "dev", table: "products" }) return res.status(201).json({ message: `Settings for product ${productId} updated successfully.` }) } catch (err) { return res.status(500).json({ message: "Some unexpected error occurred." }) diff --git a/pages/api/store/[storeId]/product/all.ts b/pages/api/store/[storeId]/product/all.ts index 6901ba2..8fd91a3 100644 --- a/pages/api/store/[storeId]/product/all.ts +++ b/pages/api/store/[storeId]/product/all.ts @@ -1,25 +1,21 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { Product, ProductJSON } from "@models" import orderBy from "lodash/orderBy" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../lib/middlewares" -import { Product, ProductJSON } from "../../../../../lib/models" const getAllProducts = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { if (req.method === "GET") { const { storeId } = req.query - const db = new HarperDB("dev") - try { - const products = await db.findByConditions( - "and", + const { records: products } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } return res.status(200).json(orderBy(products, ["__updatedtime__"], ["desc"]).map((product) => Product.fromJSON(product).toObject())) } catch (err) { diff --git a/pages/api/store/[storeId]/product/create.ts b/pages/api/store/[storeId]/product/create.ts index 377ddcb..b495014 100644 --- a/pages/api/store/[storeId]/product/create.ts +++ b/pages/api/store/[storeId]/product/create.ts @@ -1,8 +1,8 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { ProductJSON, StoreJSON } from "@models" +import { FieldError } from "@types" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../../lib/middlewares" -import { IAppUser, IStore, Product, ProductJSON, StoreJSON } from "../../../../../lib/models" -import { FieldError } from "../../../../../lib/types" const createProduct = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const { user } = req @@ -28,32 +28,28 @@ const createProduct = async (req: NextApiRequestWithAuth, res: NextApiResponse) fieldErrors.push({ field: "productId", error: "Only alphabets, numbers and underscore is allowed." }) } - const db = new HarperDB("dev") - - const [store] = await db.findByConditions( - "and", + const { + records: [store], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId }, ], - - { table: "stores" } - ) + { schema: "dev", table: "stores" } + )) as unknown as { records: StoreJSON[] } if (!store) { return res.status(400).json({ message: "No store exists with the provided store id." }) } - const products = await db.findByConditions( - "and", + const { records: products } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (products && products.length > 0) { fieldErrors.push({ field: "productId", error: "This product id is not available." }) @@ -63,30 +59,33 @@ const createProduct = async (req: NextApiRequestWithAuth, res: NextApiResponse) return res.status(400).json({ fieldErrors }) } - const product = new Product({ + const product = { productId: productId as string, storeId: storeId as string, - ownerId: req.session.id as string, + ownerId: user.id as string, isPrivate: true, isUsingStoreKey: true, isActive: true, - }) + } try { - const [newProductId] = await db.insert({ table: "products", records: [product] }) + const { inserted_hashes } = await harperdb.insert(product, { schema: "dev", table: "products" }) - if (!newProductId) { + if (!inserted_hashes || !inserted_hashes[0]) { return res.status(500).json({ message: "Some unexpected error occurred." }) } res.status(201).json({ message: `Product ${productId} created successfully.` }) - await db.update({ table: "stores", records: [{ id: store.id as string, products: (store?.products ?? 0) + 1 }] }) + await harperdb.updateOne({ id: store.id as string, products: (store?.products ?? 0) + 1 }, { schema: "dev", table: "stores" }) - return await db.update({ - table: "users", - records: [{ id: user.id, usage: { ...(user.usage ?? {}), products: (user.usage?.products ?? 0) + 1 } }], - }) + return await harperdb.updateOne( + { id: user.id, usage: { ...(user.usage ?? {}), products: (user.usage?.products ?? 0) + 1 } }, + { + schema: "dev", + table: "users", + } + ) } catch (err) { return res.status(500).json({ message: "Some unexpected error occurred." }) } diff --git a/pages/api/store/[storeId]/regenerateStoreKey.ts b/pages/api/store/[storeId]/regenerateStoreKey.ts index 55b5b9d..2adba82 100644 --- a/pages/api/store/[storeId]/regenerateStoreKey.ts +++ b/pages/api/store/[storeId]/regenerateStoreKey.ts @@ -1,24 +1,24 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { StoreJSON } from "@models" import * as crypto from "crypto" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../../lib/middlewares" -import { StoreJSON } from "../../../../lib/models" const regenerateStoreKey = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { if (req.method === "PATCH") { const { storeId } = req.query - const db = new HarperDB("dev") try { - const [store] = await db.findByConditions( - "and", + const { + records: [store], + } = (await harperdb.searchByConditions( [ - { attribute: "ownerId", type: "equals", value: req.session.id as string }, - { attribute: "storeId", type: "equals", value: storeId as string }, + { searchAttribute: "ownerId", searchType: "equals", searchValue: req.session.id as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, ], - { table: "stores" } - ) + { schema: "dev", table: "stores" } + )) as unknown as { records: StoreJSON[] } if (!store) { return res.status(404).json({ message: "No store exists with the provided store id." }) @@ -26,7 +26,7 @@ const regenerateStoreKey = async (req: NextApiRequestWithAuth, res: NextApiRespo const storeKey = crypto.randomBytes(64).toString("base64") - await db.update({ table: "stores", records: [{ id: store.id as string, storeKey }] }) + await harperdb.updateOne({ id: store.id as string, storeKey }, { schema: "dev", table: "stores" }) return res.status(201).json({ message: `Key for store ${storeId} regenerated successfully.` }) } catch (err) { return res.status(500).json({ message: "Some unexpected error occurred." }) diff --git a/pages/api/store/all.ts b/pages/api/store/all.ts index d17127f..b109dfc 100644 --- a/pages/api/store/all.ts +++ b/pages/api/store/all.ts @@ -1,15 +1,16 @@ import orderBy from "lodash/orderBy" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../lib/middlewares" -import { Store, StoreJSON } from "../../../lib/models" +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { Store, StoreJSON } from "@models" const getAllStores = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { if (req.method === "GET") { - const db = new HarperDB("dev") - try { - const stores = await db.findByValue("ownerId", req.session.id as string, { table: "stores" }) + const { records: stores } = (await harperdb.searchByValue("ownerId", req.session.id as string, { + schema: "dev", + table: "stores", + })) as unknown as { records: StoreJSON[] } return res.status(200).json(orderBy(stores, ["__updatedtime__"], ["desc"]).map((store) => Store.fromJSON(store))) } catch (err) { diff --git a/pages/api/store/create.ts b/pages/api/store/create.ts index 1965507..71dc6b8 100644 --- a/pages/api/store/create.ts +++ b/pages/api/store/create.ts @@ -1,9 +1,9 @@ +import { harperdb } from "@lib/harperDB" +import { NextApiRequestWithAuth, withAuthentication } from "@lib/middlewares" +import { Store, StoreJSON } from "@models" +import { FieldError } from "@types" import * as crypto from "crypto" import { NextApiHandler, NextApiResponse } from "next" -import { HarperDB } from "../../../lib/harperDB" -import { NextApiRequestWithAuth, withAuthentication } from "../../../lib/middlewares" -import { IAppUser, Store } from "../../../lib/models" -import { FieldError } from "../../../lib/types" const createStore = async (req: NextApiRequestWithAuth, res: NextApiResponse) => { const fieldErrors: FieldError[] = [] @@ -24,9 +24,9 @@ const createStore = async (req: NextApiRequestWithAuth, res: NextApiResponse) => fieldErrors.push({ field: "storeId", error: "Only alphabets, numbers and underscore is allowed." }) } - const db = new HarperDB("dev") - - const stores = await db.findByValue("storeId", storeId!, { table: "stores" }) + const { records: stores } = (await harperdb.searchByValue("storeId", storeId!, { schema: "dev", table: "stores" })) as unknown as { + records: StoreJSON[] + } if (stores && stores.length > 0) { fieldErrors.push({ field: "storeId", error: "This store id is not available." }) @@ -41,7 +41,13 @@ const createStore = async (req: NextApiRequestWithAuth, res: NextApiResponse) => const store = new Store({ storeId: storeId!, ownerId: user.id, storeKey, isActive: true }) try { - const [newStoreId] = await db.insert({ table: "stores", records: [store] }) + const { inserted_hashes } = await harperdb.insert(store, { schema: "dev", table: "stores" }) + + if (!inserted_hashes || !inserted_hashes?.[0]) { + return res.status(500).json({ message: "Some unexpected error occurred." }) + } + + const newStoreId = inserted_hashes?.[0] if (!newStoreId) { return res.status(500).json({ message: "Some unexpected error occurred." }) @@ -49,10 +55,13 @@ const createStore = async (req: NextApiRequestWithAuth, res: NextApiResponse) => res.status(201).json({ message: `Store ${storeId} created successfully.` }) - return await db.update({ - table: "users", - records: [{ id: user.id, usage: { ...(user.usage ?? {}), stores: (user.usage?.stores ?? 0) + 1 } }], - }) + return await harperdb.updateOne( + { id: user.id, usage: { ...(user.usage ?? {}), stores: (user.usage?.stores ?? 0) + 1 } }, + { + schema: "dev", + table: "users", + } + ) } catch (err) { return res.status(500).json({ message: "Some unexpected error occurred." }) } diff --git a/pages/api/v1/[productId]/index.ts b/pages/api/v1/[productId]/index.ts index ebaa360..8729dd7 100644 --- a/pages/api/v1/[productId]/index.ts +++ b/pages/api/v1/[productId]/index.ts @@ -1,4 +1,4 @@ -import { HarperDB } from "@lib/harperDB" +import { harperdb } from "@lib/harperDB" import { AppUser, AppUserJSON, Product, ProductJSON, StoreJSON } from "@models" import * as crypto from "crypto" import { NextApiHandler } from "next" @@ -10,7 +10,6 @@ const handleProduct: NextApiHandler = async (req, res) => { origin: "*", }) - const db = new HarperDB("dev") const { productId } = req.query if (req.method === "GET") { @@ -38,13 +37,17 @@ const handleProduct: NextApiHandler = async (req, res) => { return res.status(400).json({ error: { code: "400", message: "Store Id is required" } }) } - const [store] = await db.findByValue("storeId", storeId, { table: "stores" }) + const { + records: [store], + } = (await harperdb.searchByValue("storeId", storeId, { schema: "dev", table: "stores" })) as unknown as { records: StoreJSON[] } if (!store || !store.isActive) { return res.status(404).json({ error: { code: "404", message: "No store exists with the provided store id or the store might be inactive." } }) } - const [user] = await db.findByIds([store.ownerId], { table: "users" }) + const { + records: [user], + } = (await harperdb.searchByHash([store.ownerId], { schema: "dev", table: "users" })) as unknown as { records: AppUserJSON[] } if (!user) { return res.status(404).json({ error: { code: "404", message: "The owner of this store does not exist anymore." } }) @@ -58,15 +61,16 @@ const handleProduct: NextApiHandler = async (req, res) => { }) } - const [product] = await db.findByConditions( - "and", + const { + records: [product], + } = (await harperdb.searchByConditions( [ - { attribute: "storeId", type: "equals", value: storeId as string }, - { attribute: "productId", type: "equals", value: productId as string }, + { searchAttribute: "storeId", searchType: "equals", searchValue: storeId as string }, + { searchAttribute: "productId", searchType: "equals", searchValue: productId as string }, ], - { table: "products" } - ) + { schema: "dev", table: "products" } + )) as unknown as { records: ProductJSON[] } if (!product || !product.isActive) { return res diff --git a/yarn.lock b/yarn.lock index 1987ab1..824a13c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2198,6 +2198,14 @@ domain-browser@^1.1.1: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" @@ -2962,6 +2970,16 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +harperdbjs@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/harperdbjs/-/harperdbjs-0.1.0.tgz#57c5963bbb70bcb63973899d36bcb437a517d23c" + integrity sha512-FybIAd7xwA6zvjS6FpZrge6/vuwCScNqp9wrm1PP5rcMwiiLewEQKFhGq+7v6pFBhD0ba98rY5Iap0wleNaw9w== + dependencies: + axios "^0.21.1" + lodash.isundefined "^3.0.1" + lodash.omitby "^4.6.0" + snake-case "^3.0.4" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -3828,11 +3846,21 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= +lodash.isundefined@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz#23ef3d9535565203a66cefd5b830f848911afb48" + integrity sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g= + lodash.mergewith@4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== +lodash.omitby@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.omitby/-/lodash.omitby-4.6.0.tgz#5c15ff4754ad555016b53c041311e8f079204791" + integrity sha1-XBX/R1StVVAWtTwEExHo8HkgR5E= + lodash.once@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" @@ -3895,6 +3923,13 @@ lottie-web@^5.7.3: resolved "https://registry.yarnpkg.com/lottie-web/-/lottie-web-5.7.11.tgz#4ba74e8a629f76d3c0a0062ddc37d2b96e13765c" integrity sha512-Jvz3PQqwrDj1rXGqfeQtipH/WNtM/Y4l8t8NIQXe1xUI0nVooH2bTYJGef0UkdBcWUx1s3miKsRhyP196g9tvQ== +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -4254,6 +4289,14 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + node-fetch@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" @@ -5506,6 +5549,14 @@ slugify@^1.5.3: resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.5.3.tgz#36e009864f5476bfd5db681222643d92339c890d" integrity sha512-/HkjRdwPY3yHJReXu38NiusZw2+LLE2SrhkWJtmlPDB1fqFSvioYj62NkPcrKiNCgRLeGcGK7QBvr1iQwybeXw== +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" @@ -6084,7 +6135,7 @@ tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0: +tslib@^2.0.3, tslib@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==