add migrations and service

This commit is contained in:
Lacey Pevey
2023-05-15 15:37:53 -05:00
parent e498701703
commit d744d291fe
8 changed files with 444 additions and 9 deletions
+1 -7
View File
@@ -18,15 +18,9 @@
],
"devDependencies": {
"@medusajs/medusa": "^1.10.1",
"@medusajs/types": "^1.8.5",
"@medusajs/utils": "^1.8.4",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"cross-env": "^5.2.1",
"express": "^4.17.2",
"medusa-interfaces": "^1.3.7",
"typeorm": "^0.3.16",
"typescript": "^4.9.5"
"typescript": "^4.4.4"
},
"scripts": {
"prepare": "cross-env NODE_ENV=production yarn run build",
+140
View File
@@ -0,0 +1,140 @@
import cors from "cors"
import configLoader from "@medusajs/medusa/dist/loaders/config"
import { Router } from "express"
import * as bodyParser from "body-parser"
//import { User, UserService, Customer, CustomerService } from "@medusajs/medusa"
import { authenticateCustomer } from "@medusajs/medusa"
import { MedusaError } from "@medusajs/utils"
import { z } from "zod"
export default (rootDirectory: string): Router | Router[] => {
const config = configLoader(rootDirectory)
const storeCorsOptions = { origin: config.projectConfig.store_cors.split(","), credentials: true, }
const adminCorsOptions = { origin: config.projectConfig.admin_cors.split(","), credentials: true, }
const router = Router()
// REVIEWS - GET ALL REVIEWS FOR A PRODUCT
//router.use("/store/products/:id/reviews", authenticateCustomer())
router.use(authenticateCustomer())
//router.get("/store/products/:id/reviews", cors(storeCorsOptions), authenticateCustomer(), async (req, res) => {
router.get("/store/products/:id/reviews", cors(storeCorsOptions), async (req, res) => {
// console.log('get reviews')
// console.log(req.user)
const productReviewService = req.scope.resolve("productReviewService")
productReviewService.getProductReviews(req.params.id).then((product_reviews) => {
return res.json({product_reviews})
})
})
// REVIEWS - GET ALL REVIEWS FOR A CUSTOMER
// router.use("/store/customers/:id/reviews", authenticate(), getCustomer)
router.get("/store/customers/:id/reviews", async (req, res) => {
const productReviewService = req.scope.resolve("productReviewService")
productReviewService.getCustomerProductReviews(req.params.id).then((product_reviews) => {
return res.json({product_reviews})
})
})
// REVIEWS - ADD A NEW REVIEW FOR A PRODUCT
//router.use("/store/products/:id/reviews", authenticate(), getCustomer, bodyParser.json())
router.use("/store/products/:id/reviews", bodyParser.json())
router.post("/store/products/:id/reviews", async (req, res) => {
const schema = z.object({
customer_id: z.string().min(1),
display_name: z.string().min(1),
content: z.string().min(1),
rating: z.coerce.number().min(0).max(5),
})
/* @ts-ignore */
const { success, error, data } = schema.safeParse(req.body)
if (!success) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error)
} else {
const productReviewService = req.scope.resolve("productReviewService")
productReviewService.addProductReview(req.params.id, data.customer_id, data.display_name, data.content, data.rating)
.then((product_review) => {
return res.json({product_review})
})
}
})
// REVIEWS - GET A SINGLE REVIEW
router.get("/store/reviews/:id", async (req, res) => {
const productReviewService = req.scope.resolve("productReviewService")
productReviewService.getReview(req.params.id).then((product_review) => {
return res.json({product_review})
})
})
// REVIEWS - UPDATE A REVIEW FOR A PRODUCT
//router.use("/store/reviews/:id", authenticate(), getCustomer, bodyParser.json())
router.use("/store/reviews/:id", bodyParser.json())
router.post("/store/reviews/:id", async (req, res) => {
const schema = z.object({
customer_id: z.string().min(1),
display_name: z.string().min(1),
content: z.string().min(1),
rating: z.coerce.number().min(0).max(5),
})
/* @ts-ignore */
const { success, error, data } = schema.safeParse(req.body)
if (!success) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error)
} else {
}
const productReviewService = req.scope.resolve("productReviewService")
const productReview = await productReviewService.getProductReviews(req.params.id)
if (productReview.customer_id !== req.body.userId) {
return res.status(401).json({ message: "Unauthorized" })
}
productReviewService.updateProductReview(req.params.id, req.body.display_name, req.body.content, req.body.rating)
.then((product_review) => {
return res.json({product_review})
})
})
// REVIEWS - ADMIN GET ALL REVIEWS FOR A PRODUCT
router.get("/admin/products/:id/reviews", async (req, res) => {
const productReviewService = req.scope.resolve("productReviewService")
productReviewService.getProductReviews(req.params.id).then((product_reviews) => {
return res.json({product_reviews})
})
})
// REVIEWS - ADMIN EDIT A REVIEW FOR A PRODUCT
//router.use("/admin/reviews/:id", bodyParser.json(), authenticate(), getUser)
router.use("/admin/reviews/:id", bodyParser.json())
router.post("/admin/reviews/:id", async (req, res) => {
const productReviewService = req.scope.resolve("productReviewService")
productReviewService.editProductReview(req.params.id, req.body.display_name, req.body.content, req.body.rating, req.body.approved)
.then((product_review) => {
return res.json({product_review})
})
})
return router
}
// async function getCustomer(req, res, next) {
// console.log('getCustomer')
// let loggedInCustomer: Customer | null = null
// if (req.customer && req.customer.customerId) {
// console.log(req.customer.customerId)
// const customerService = req.scope.resolve("customerService") as CustomerService
// loggedInCustomer = await customerService.retrieve(req.customer.customerId)
// }
// req.scope.register({ loggedInCustomer: { resolve: () => loggedInCustomer }})
// next()
// }
// async function getUser(req, res, next) {
// let loggedInUser: User | null = null
// if (req.user && req.user.userId) {
// const userService = req.scope.resolve("userService") as UserService
// loggedInUser = await userService.retrieve(req.user.userId)
// }
// req.scope.register({ loggedInUser: { resolve: () => loggedInUser }})
// next()
// }
+112
View File
@@ -0,0 +1,112 @@
import { MigrationInterface, QueryRunner, TableForeignKey } from "typeorm"
export class Blog1684173263726 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE IF NOT EXISTS "blog_category" ("id" character varying NOT NULL,
"handle" character varying,
"title" character varying NOT NULL,
"description" character varying,
"keywords" varchar[],
"metadata" jsonb)`
)
await queryRunner.createPrimaryKey("blog_category", ["id"])
await queryRunner.query(
`CREATE TABLE IF NOT EXISTS "blog_post" ("id" character varying NOT NULL,
"handle" character varying,
"title" character varying NOT NULL,
"author" character varying,
"published" boolean NOT NULL DEFAULT false,
"content" character varying,
"description" character varying,
"keywords" varchar[],
"category_id" character varying,
"metadata" jsonb,
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now())`
)
await queryRunner.createPrimaryKey("blog_post", ["id"])
await queryRunner.createForeignKey("blog_post", new TableForeignKey({
columnNames: ["category_id"],
referencedColumnNames: ["id"],
referencedTableName: "blog_category",
onDelete: "CASCADE",
onUpdate: "CASCADE"
}))
await queryRunner.query(
`CREATE TABLE IF NOT EXISTS "blog_tag" ("id" character varying NOT NULL,
"title" character varying NOT NULL)`
)
await queryRunner.createPrimaryKey("blog_tag", ["id"])
await queryRunner.query(
`CREATE TABLE IF NOT EXISTS "blog_tags" ("post_id" character varying NOT NULL,
"tag_id" character varying NOT NULL)`
)
await queryRunner.createForeignKey("blog_tags", new TableForeignKey({
columnNames: ["post_id"],
referencedColumnNames: ["id"],
referencedTableName: "blog_post",
onDelete: "CASCADE",
onUpdate: "CASCADE"
}))
await queryRunner.createForeignKey("blog_tags", new TableForeignKey({
columnNames: ["tag_id"],
referencedColumnNames: ["id"],
referencedTableName: "blog_tag",
onDelete: "CASCADE",
onUpdate: "CASCADE"
}))
await queryRunner.query(
`CREATE TABLE IF NOT EXISTS "blog_product_tags" ("post_id" character varying NOT NULL,
"product_id" character varying NOT NULL)`
)
await queryRunner.createForeignKey("blog_product_tags", new TableForeignKey({
columnNames: ["post_id"],
referencedColumnNames: ["id"],
referencedTableName: "blog_post",
onDelete: "CASCADE",
onUpdate: "CASCADE"
}))
await queryRunner.createForeignKey("blog_product_tags", new TableForeignKey({
columnNames: ["product_id"],
referencedColumnNames: ["id"],
referencedTableName: "product",
onDelete: "CASCADE",
onUpdate: "CASCADE"
}))
await queryRunner.query(
`CREATE TABLE IF NOT EXISTS "blog_collection_tags" ("post_id" character varying NOT NULL,
"collection_id" character varying NOT NULL)`
)
await queryRunner.createForeignKey("blog_collection_tags", new TableForeignKey({
columnNames: ["post_id"],
referencedColumnNames: ["id"],
referencedTableName: "blog_post",
onDelete: "CASCADE",
onUpdate: "CASCADE"
}))
await queryRunner.createForeignKey("blog_collection_tags", new TableForeignKey({
columnNames: ["collection_id"],
referencedColumnNames: ["id"],
referencedTableName: "collection",
onDelete: "CASCADE",
onUpdate: "CASCADE"
}))
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable("blog_category", true)
await queryRunner.dropTable("blog_post", true)
await queryRunner.dropTable("blog_tag", true)
await queryRunner.dropTable("blog_tags", true)
await queryRunner.dropTable("blog_product_tags", true)
await queryRunner.dropTable("blog_collection_tags", true)
}
}
+2 -2
View File
@@ -27,9 +27,9 @@ export class BlogPost extends BaseEntity {
description: string | null
@Column({ type: "text", nullable: true, array: true })
keywords: string | null
keywords: string[] | null
@Column({ type: "varchar", nullable: false })
@Column({ type: "varchar", nullable: true })
category_id: string
@ManyToOne(() => BlogCategory)
+4
View File
@@ -0,0 +1,4 @@
import { BlogCategory } from "../models/blog-category"
import { dataSource } from '@medusajs/medusa/dist/loaders/database'
export const BlogCategoryRepository = dataSource.getRepository(BlogCategory)
+4
View File
@@ -0,0 +1,4 @@
import { BlogPost } from "../models/blog-post"
import { dataSource } from '@medusajs/medusa/dist/loaders/database'
export const BlogPostRepository = dataSource.getRepository(BlogPost)
+4
View File
@@ -0,0 +1,4 @@
import { BlogTag } from "../models/blog-tag"
import { dataSource } from '@medusajs/medusa/dist/loaders/database'
export const BlogTagRepository = dataSource.getRepository(BlogTag)
+177
View File
@@ -0,0 +1,177 @@
import { TransactionBaseService } from '@medusajs/utils'
import { BlogCategoryRepository } from '../repositories/blog-category'
import { BlogPostRepository } from '../repositories/blog-post'
import { BlogTagRepository } from '../repositories/blog-tag'
export default class BlogService extends TransactionBaseService {
protected readonly blogCategoryRepository_: typeof BlogCategoryRepository
protected readonly blogPostRepository_: typeof BlogPostRepository
protected readonly blogTagRepository_: typeof BlogTagRepository
constructor({ blogCategoryRepository, blogPostRepository, blogTagRepository }) {
super(arguments[0])
this.blogCategoryRepository_ = blogCategoryRepository
this.blogPostRepository_ = blogPostRepository
this.blogTagRepository_ = blogTagRepository
}
async getBlogCategories() {
/* @ts-ignore */
const blogCategoryRepository = this.activeManager_.withRepository(this.blogCategoryRepository_)
return await blogCategoryRepository.find()
}
async getBlogCategory(id) {
/* @ts-ignore */
const blogCategoryRepository = this.activeManager_.withRepository(this.blogCategoryRepository_)
return await blogCategoryRepository.findOne({
where: { id }
})
}
async addBlogCategory (category) {
const { handle, title, description, keywords, metadata } = category
if (!title) throw new Error("Adding a blog category requires a title")
/* @ts-ignore */
const blogCategoryRepository = this.activeManager_.withRepository(this.blogCategoryRepository_)
const createdCategory = blogCategoryRepository.create({
handle,
title,
description,
keywords,
metadata
})
const blogCategory = await blogCategoryRepository.save(createdCategory)
return blogCategory
}
async updateBlogCategory (id, category) {
const { handle, title, description, keywords, metadata } = category
if (!id || !title) throw new Error("Updating a blog category requires an id and a title")
/* @ts-ignore */
const blogCategoryRepository = this.activeManager_.withRepository(this.blogCategoryRepository_)
const blogCategory = blogCategoryRepository.update(id, {
handle,
title,
description,
keywords,
metadata
})
return blogCategory
}
async deleteBlogCategory(id) {
if (!id) throw new Error("Deleting a blog category requires an id")
/* @ts-ignore */
const blogCategoryRepository = this.activeManager_.withRepository(this.blogCategoryRepository_)
return await blogCategoryRepository.delete(id)
}
async getBlogPosts() {
/* @ts-ignore */
const blogPostRepository = this.activeManager_.withRepository(this.blogPostRepository_)
return await blogPostRepository.find()
}
async getBlogCategoryPosts(category_id) {
/* @ts-ignore */
const blogPostRepository = this.activeManager_.withRepository(this.blogPostRepository_)
return await blogPostRepository.find({
where: { category_id }
})
}
async getBlogPost(id) {
/* @ts-ignore */
const blogPostRepository = this.activeManager_.withRepository(this.blogPostRepository_)
return await blogPostRepository.findOne({
where: { id }
})
}
async addBlogPost(post) {
const { handle, title, author, published, content, description, keywords, category_id, tags, products, collections, metadata } = post
if (!title) throw new Error("Adding a blog post requires a title")
/* @ts-ignore */
const blogPostRepository = this.activeManager_.withRepository(this.blogPostRepository_)
const createdPost = blogPostRepository.create({
handle,
title,
author,
published,
content,
description,
keywords,
category_id,
tags,
products,
collections,
metadata
})
const blogPost = await blogPostRepository.save(createdPost)
return blogPost
}
async updateBlogPost(id, post) {
const { handle, title, author, published, content, description, keywords, category_id, tags, products, collections, metadata } = post
if (!id || !title) throw new Error("Updating a blog post requires an id and a title")
/* @ts-ignore */
const blogPostRepository = this.activeManager_.withRepository(this.blogPostRepository_)
const blogPost = blogPostRepository.update(id, {
handle,
title,
author,
published,
content,
description,
keywords,
category_id,
tags,
products,
collections,
metadata
})
return blogPost
}
async deleteBlogPost(id) {
if (!id) throw new Error("Deleting a blog post requires an id")
/* @ts-ignore */
const blogPostRepository = this.activeManager_.withRepository(this.blogPostRepository_)
return await blogPostRepository.delete(id)
}
async getBlogTags() {
/* @ts-ignore */
const blogTagRepository = this.activeManager_.withRepository(this.blogTagRepository_)
return await blogTagRepository.find()
}
async addBlogTag(title) {
if (!title) throw new Error("Adding a blog tag requires a title")
/* @ts-ignore */
const blogTagRepository = this.activeManager_.withRepository(this.blogTagRepository_)
const createdTag = blogTagRepository.create({
title
})
const blogTag = await blogTagRepository.save(createdTag)
return blogTag
}
async updateBlogTag(id, title) {
if (!id || !title) throw new Error("Updating a blog tag requires an id and a title")
/* @ts-ignore */
const blogTagRepository = this.activeManager_.withRepository(this.blogTagRepository_)
const blogTag = blogTagRepository.update(id, {
title
})
return blogTag
}
async deleteBlogTag(id) {
if (!id) throw new Error("Deleting a blog tag requires an id")
/* @ts-ignore */
const blogTagRepository = this.activeManager_.withRepository(this.blogTagRepository_)
return await blogTagRepository.delete(id)
}
}