@shophost/rest-api 2.0.34 → 2.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/LICENSE +17 -13
  2. package/README.md +76 -66
  3. package/package.json +2 -2
  4. package/scripts/minify-dist.mjs +45 -0
  5. package/src/app.js +1 -53
  6. package/src/app.js.map +1 -1
  7. package/src/core/auth/auth.schema.js +1 -41
  8. package/src/core/auth/auth.util.js +1 -44
  9. package/src/core/auth/better-auth.lib.js +1 -100
  10. package/src/core/auth/generate-password-hash.util.js +1 -30
  11. package/src/core/auth/headers.schema.js +1 -22
  12. package/src/core/auth/user.schema.js +1 -30
  13. package/src/core/db/__generated__/client/browser.js +1 -18
  14. package/src/core/db/__generated__/client/client.js +1 -35
  15. package/src/core/db/__generated__/client/commonInputTypes.js +1 -11
  16. package/src/core/db/__generated__/client/enums.js +1 -200
  17. package/src/core/db/__generated__/client/internal/class.js +769 -55
  18. package/src/core/db/__generated__/client/internal/prismaNamespace.d.ts +2 -2
  19. package/src/core/db/__generated__/client/internal/prismaNamespace.js +1 -541
  20. package/src/core/db/__generated__/client/internal/prismaNamespaceBrowser.js +1 -512
  21. package/src/core/db/__generated__/client/models/Account.d.ts +0 -5
  22. package/src/core/db/__generated__/client/models/Account.js +1 -2
  23. package/src/core/db/__generated__/client/models/Address.d.ts +0 -5
  24. package/src/core/db/__generated__/client/models/Address.js +1 -2
  25. package/src/core/db/__generated__/client/models/Campaign.d.ts +0 -5
  26. package/src/core/db/__generated__/client/models/Campaign.js +1 -2
  27. package/src/core/db/__generated__/client/models/ClosingTimes.d.ts +0 -5
  28. package/src/core/db/__generated__/client/models/ClosingTimes.js +1 -2
  29. package/src/core/db/__generated__/client/models/File.d.ts +0 -5
  30. package/src/core/db/__generated__/client/models/File.js +1 -2
  31. package/src/core/db/__generated__/client/models/Invitation.d.ts +0 -5
  32. package/src/core/db/__generated__/client/models/Invitation.js +1 -2
  33. package/src/core/db/__generated__/client/models/LegalEntity.d.ts +0 -5
  34. package/src/core/db/__generated__/client/models/LegalEntity.js +1 -2
  35. package/src/core/db/__generated__/client/models/Manufacturer.d.ts +0 -5
  36. package/src/core/db/__generated__/client/models/Manufacturer.js +1 -2
  37. package/src/core/db/__generated__/client/models/ManufacturerTranslation.d.ts +0 -5
  38. package/src/core/db/__generated__/client/models/ManufacturerTranslation.js +1 -2
  39. package/src/core/db/__generated__/client/models/Member.d.ts +0 -5
  40. package/src/core/db/__generated__/client/models/Member.js +1 -2
  41. package/src/core/db/__generated__/client/models/Modifier.d.ts +0 -5
  42. package/src/core/db/__generated__/client/models/Modifier.js +1 -2
  43. package/src/core/db/__generated__/client/models/ModifierGroup.d.ts +0 -5
  44. package/src/core/db/__generated__/client/models/ModifierGroup.js +1 -2
  45. package/src/core/db/__generated__/client/models/ModifierGroupTranslation.d.ts +0 -5
  46. package/src/core/db/__generated__/client/models/ModifierGroupTranslation.js +1 -2
  47. package/src/core/db/__generated__/client/models/OpeningTimes.d.ts +0 -5
  48. package/src/core/db/__generated__/client/models/OpeningTimes.js +1 -2
  49. package/src/core/db/__generated__/client/models/Order.d.ts +0 -5
  50. package/src/core/db/__generated__/client/models/Order.js +1 -2
  51. package/src/core/db/__generated__/client/models/OrderItem.d.ts +0 -5
  52. package/src/core/db/__generated__/client/models/OrderItem.js +1 -2
  53. package/src/core/db/__generated__/client/models/OrderItemTranslation.d.ts +0 -5
  54. package/src/core/db/__generated__/client/models/OrderItemTranslation.js +1 -2
  55. package/src/core/db/__generated__/client/models/Organization.d.ts +0 -5
  56. package/src/core/db/__generated__/client/models/Organization.js +1 -2
  57. package/src/core/db/__generated__/client/models/OrganizationConfiguration.d.ts +0 -5
  58. package/src/core/db/__generated__/client/models/OrganizationConfiguration.js +1 -2
  59. package/src/core/db/__generated__/client/models/Payment.d.ts +0 -5
  60. package/src/core/db/__generated__/client/models/Payment.js +1 -2
  61. package/src/core/db/__generated__/client/models/PaymentSession.d.ts +0 -5
  62. package/src/core/db/__generated__/client/models/PaymentSession.js +1 -2
  63. package/src/core/db/__generated__/client/models/Product.d.ts +0 -5
  64. package/src/core/db/__generated__/client/models/Product.js +1 -2
  65. package/src/core/db/__generated__/client/models/ProductCategory.d.ts +0 -5
  66. package/src/core/db/__generated__/client/models/ProductCategory.js +1 -2
  67. package/src/core/db/__generated__/client/models/ProductCategoryTranslation.d.ts +0 -5
  68. package/src/core/db/__generated__/client/models/ProductCategoryTranslation.js +1 -2
  69. package/src/core/db/__generated__/client/models/ProductSnapshot.d.ts +0 -5
  70. package/src/core/db/__generated__/client/models/ProductSnapshot.js +1 -2
  71. package/src/core/db/__generated__/client/models/ProductTranslation.d.ts +0 -5
  72. package/src/core/db/__generated__/client/models/ProductTranslation.js +1 -2
  73. package/src/core/db/__generated__/client/models/Reservation.d.ts +0 -5
  74. package/src/core/db/__generated__/client/models/Reservation.js +1 -2
  75. package/src/core/db/__generated__/client/models/Session.d.ts +0 -5
  76. package/src/core/db/__generated__/client/models/Session.js +1 -2
  77. package/src/core/db/__generated__/client/models/ShippingMethod.d.ts +0 -5
  78. package/src/core/db/__generated__/client/models/ShippingMethod.js +1 -2
  79. package/src/core/db/__generated__/client/models/ShippingZone.d.ts +0 -5
  80. package/src/core/db/__generated__/client/models/ShippingZone.js +1 -2
  81. package/src/core/db/__generated__/client/models/User.d.ts +0 -5
  82. package/src/core/db/__generated__/client/models/User.js +1 -2
  83. package/src/core/db/__generated__/client/models/Verification.d.ts +0 -5
  84. package/src/core/db/__generated__/client/models/Verification.js +1 -2
  85. package/src/core/db/__generated__/client/models.js +1 -2
  86. package/src/core/db/index.js +1 -2
  87. package/src/core/email/components.d.ts +16 -0
  88. package/src/core/email/components.js +1 -0
  89. package/src/core/email/components.js.map +1 -0
  90. package/src/core/exceptions/http-exception.js +1 -9
  91. package/src/core/hono/hono.js +1 -123
  92. package/src/core/lib/prisma.d.ts +8 -8
  93. package/src/core/lib/prisma.js +1 -11
  94. package/src/core/logging/pino.js +1 -5
  95. package/src/core/notifications/email.service.js +1 -116
  96. package/src/core/openapi/openapi.lib.js +1 -26
  97. package/src/core/types/google-maps.types.js +1 -2
  98. package/src/core/utils/currency.util.js +1 -11
  99. package/src/core/utils/env.util.js +1 -8
  100. package/src/core/utils/object.util.js +1 -39
  101. package/src/core/utils/translations.util.js +0 -1
  102. package/src/core/utils/zod.util.js +1 -85
  103. package/src/db.js +1 -3
  104. package/src/features/access/access.handler.js +1 -91
  105. package/src/features/access/access.route.js +1 -220
  106. package/src/features/access/access.schema.js +1 -108
  107. package/src/features/access/access.service.js +1 -294
  108. package/src/features/analytics/analytics.handler.d.ts +2 -0
  109. package/src/features/analytics/analytics.handler.js +1 -0
  110. package/src/features/analytics/analytics.handler.js.map +1 -0
  111. package/src/features/analytics/analytics.route.d.ts +3 -0
  112. package/src/features/analytics/analytics.route.js +1 -0
  113. package/src/features/analytics/analytics.route.js.map +1 -0
  114. package/src/features/analytics/analytics.schema.d.ts +86 -0
  115. package/src/features/analytics/analytics.schema.js +1 -0
  116. package/src/features/analytics/analytics.schema.js.map +1 -0
  117. package/src/features/analytics/analytics.service.d.ts +45 -0
  118. package/src/features/analytics/analytics.service.js +1 -0
  119. package/src/features/analytics/analytics.service.js.map +1 -0
  120. package/src/features/cart/cart.handler.js +1 -17
  121. package/src/features/cart/cart.route.js +1 -32
  122. package/src/features/cart/cart.schema.d.ts +1 -1
  123. package/src/features/cart/cart.schema.js +1 -39
  124. package/src/features/cart/cart.service.d.ts +1 -1
  125. package/src/features/cart/cart.service.js +1 -97
  126. package/src/features/cart/cart.util.js +1 -76
  127. package/src/features/file/file.handler.js +1 -23
  128. package/src/features/file/file.route.js +1 -34
  129. package/src/features/file/file.schema.js +1 -77
  130. package/src/features/file/file.service.js +1 -66
  131. package/src/features/health/health.handler.js +1 -10
  132. package/src/features/health/health.route.js +1 -25
  133. package/src/features/index.d.ts +1 -0
  134. package/src/features/index.js +1 -16
  135. package/src/features/index.js.map +1 -1
  136. package/src/features/location/location.handler.js +1 -25
  137. package/src/features/location/location.route.js +1 -56
  138. package/src/features/location/location.schema.js +1 -50
  139. package/src/features/location/location.service.js +1 -141
  140. package/src/features/manufacturer/manufacturer.handler.js +1 -53
  141. package/src/features/manufacturer/manufacturer.route.js +1 -97
  142. package/src/features/manufacturer/manufacturer.schema.js +1 -125
  143. package/src/features/manufacturer/manufacturer.service.js +1 -190
  144. package/src/features/order/emails/order-confirmation.email.js +1 -229
  145. package/src/features/order/emails/order-confirmation.email.js.map +1 -1
  146. package/src/features/order/emails/order-notification.email.js +1 -229
  147. package/src/features/order/emails/order-notification.email.js.map +1 -1
  148. package/src/features/order/fulfilment.schema.js +1 -3
  149. package/src/features/order/order.handler.js +1 -54
  150. package/src/features/order/order.route.js +1 -111
  151. package/src/features/order/order.schema.d.ts +4 -4
  152. package/src/features/order/order.schema.js +1 -158
  153. package/src/features/order/order.service.d.ts +4 -4
  154. package/src/features/order/order.service.js +1 -306
  155. package/src/features/order/recipient.schema.js +1 -38
  156. package/src/features/organization/legal-entity.schema.js +1 -83
  157. package/src/features/organization/organization-configuration.schema.js +1 -115
  158. package/src/features/organization/organization.handler.js +1 -48
  159. package/src/features/organization/organization.route.js +1 -84
  160. package/src/features/organization/organization.schema.js +1 -64
  161. package/src/features/organization/organization.service.js +1 -334
  162. package/src/features/payment/payment.handler.js +1 -16
  163. package/src/features/payment/payment.route.js +1 -22
  164. package/src/features/payment/payment.schema.d.ts +3 -3
  165. package/src/features/payment/payment.schema.js +1 -46
  166. package/src/features/payment/payment.service.d.ts +1 -1
  167. package/src/features/payment/payment.service.js +1 -100
  168. package/src/features/payment/stripe.service.js +1 -164
  169. package/src/features/product/product-modifier.schema.js +1 -84
  170. package/src/features/product/product.handler.js +1 -87
  171. package/src/features/product/product.route.js +1 -179
  172. package/src/features/product/product.schema.d.ts +3 -3
  173. package/src/features/product/product.schema.js +1 -143
  174. package/src/features/product/product.service.d.ts +2 -2
  175. package/src/features/product/product.service.js +1 -440
  176. package/src/features/product-category/product-category.handler.js +1 -59
  177. package/src/features/product-category/product-category.route.js +1 -139
  178. package/src/features/product-category/product-category.schema.js +1 -86
  179. package/src/features/product-category/product-category.service.js +1 -220
  180. package/src/features/reservation/emails/reservation-cancellation.email.js +1 -82
  181. package/src/features/reservation/emails/reservation-cancellation.email.js.map +1 -1
  182. package/src/features/reservation/emails/reservation-confirmation.email.js +1 -82
  183. package/src/features/reservation/emails/reservation-confirmation.email.js.map +1 -1
  184. package/src/features/reservation/emails/reservation-notification.email.js +1 -93
  185. package/src/features/reservation/emails/reservation-notification.email.js.map +1 -1
  186. package/src/features/reservation/reservation.handler.js +1 -65
  187. package/src/features/reservation/reservation.route.js +1 -167
  188. package/src/features/reservation/reservation.schema.d.ts +1 -1
  189. package/src/features/reservation/reservation.schema.js +1 -51
  190. package/src/features/reservation/reservation.service.js +1 -231
  191. package/src/features/shipping/shipping.handler.js +1 -32
  192. package/src/features/shipping/shipping.route.js +1 -51
  193. package/src/features/shipping/shipping.service.js +1 -96
  194. package/src/features/shipping-method/shipping-method.handler.js +1 -60
  195. package/src/features/shipping-method/shipping-method.route.js +1 -144
  196. package/src/features/shipping-method/shipping-method.schema.js +1 -48
  197. package/src/features/shipping-method/shipping-method.service.js +1 -229
  198. package/src/features/shipping-method/shipping-zone.schema.js +1 -31
  199. package/src/features/webhook/webhook.handler.js +1 -50
  200. package/src/features/webhook/webhook.route.js +1 -33
  201. package/src/index.js +1 -6
  202. package/src/integrations/next.js +1 -82
  203. package/src/schemas/address.schema.js +1 -112
  204. package/src/schemas/currency.schema.js +1 -118
  205. package/src/schemas/error.schema.js +1 -12
  206. package/src/schemas/index.d.ts +1 -0
  207. package/src/schemas/index.js +1 -29
  208. package/src/schemas/index.js.map +1 -1
  209. package/src/schemas/locales.schema.js +1 -238
  210. package/src/schemas/number.schema.js +1 -29
  211. package/src/schemas/pagination.schema.js +1 -54
  212. package/src/schemas/params.schema.js +1 -20
  213. package/src/schemas/queries.schema.js +1 -6
  214. package/src/test/global-setup.js +1 -37
  215. package/src/test/integration/api-fixtures.js +1 -160
  216. package/src/test/integration/seed.js +1 -368
  217. package/src/test/integration/test-helpers.d.ts +2 -0
  218. package/src/test/integration/test-helpers.js +1 -154
  219. package/src/test/integration/test-helpers.js.map +1 -1
  220. package/src/test/setup-test-env.js +1 -7
@@ -1,143 +1 @@
1
- import { z } from "@hono/zod-openapi";
2
- import { validateRequiredForDefaultLocale } from "../../core/utils/zod.util";
3
- import { locale } from "../../schemas/locales.schema";
4
- import { optionalNumber, requiredNumber } from "../../schemas/number.schema";
5
- import { FileSchema } from "../file/file.schema";
6
- import { ProductCategorySchema } from "../product-category/product-category.schema";
7
- import { CreateOrUpdateModifierGroupSchema, LocalizedModifierGroupSchema, ModifierGroupSchema, } from "./product-modifier.schema";
8
- export const ProductSchema = z
9
- .object({
10
- id: z.string().cuid().openapi({
11
- example: "clf9876543210abcdef",
12
- description: "ID of the product",
13
- }),
14
- slug: z.string().optional().openapi({
15
- example: "premium-watch",
16
- description: "Unique slug for the product",
17
- }),
18
- sku: z.string().optional().openapi({
19
- example: "PRM-WATCH-01",
20
- description: "Stock Keeping Unit identifier",
21
- }),
22
- basePrice: requiredNumber,
23
- discountedBasePrice: optionalNumber,
24
- currency: z.string().openapi({
25
- example: "USD",
26
- description: "Currency code for pricing",
27
- }),
28
- images: z.array(FileSchema).optional().openapi({
29
- description: "List of product images",
30
- }),
31
- modifierGroups: z.array(ModifierGroupSchema).optional().openapi({
32
- description: "List of product modifier groups",
33
- }),
34
- categories: z.array(ProductCategorySchema).openapi({
35
- example: ["cju0z9k4z0000l1qg5z1z1z"],
36
- description: "IDs of associated product categories",
37
- }),
38
- manufacturerId: z.string().cuid().nullable().optional().openapi({
39
- description: "ID of associated manufacturer",
40
- }),
41
- createdAt: z.date(),
42
- publishedAt: z.date().nullable().optional(),
43
- translations: z
44
- .array(z.object({
45
- locale,
46
- title: z.coerce.string().optional().openapi({
47
- example: "Premium Watch",
48
- description: "Product name in specified locale",
49
- }),
50
- description: z.string().nullable().optional().openapi({
51
- example: "High-quality premium watch",
52
- description: "Product description in specified locale",
53
- }),
54
- }))
55
- .optional(),
56
- metadata: z
57
- .record(z
58
- .string()
59
- .min(1, "Key cannot be empty")
60
- .max(50, "Key too long")
61
- .regex(/^[a-zA-Z][a-zA-Z0-9_-]*$/, "Key must start with letter and contain only letters, numbers, underscore, or dash"), z.string().min(1, "Value cannot be empty").max(200, "Value too long"))
62
- .optional()
63
- .nullable(),
64
- })
65
- .openapi("Product");
66
- export const LocalizedProductSchema = ProductSchema.extend({
67
- title: z.string().default(""),
68
- description: z.string().nullable().default(""),
69
- modifierGroups: z.array(LocalizedModifierGroupSchema),
70
- categories: z
71
- .array(z.object({
72
- id: z.string().cuid().openapi({
73
- example: "cju0z9k4z0000l1qg5z1z1z",
74
- description: "ID of the product category",
75
- }),
76
- }))
77
- .default([]),
78
- })
79
- .omit({
80
- translations: true,
81
- })
82
- .openapi("LocalizedProduct");
83
- const BaseProductFormData = ProductSchema.pick({
84
- slug: true,
85
- sku: true,
86
- basePrice: true,
87
- discountedBasePrice: true,
88
- currency: true,
89
- images: true,
90
- manufacturerId: true,
91
- translations: true,
92
- metadata: true,
93
- }).extend({
94
- defaultLocale: z.string().min(1, "Default locale is required").openapi({
95
- example: "en-US",
96
- description: "Default translation locale",
97
- }),
98
- modifierGroups: z
99
- .array(CreateOrUpdateModifierGroupSchema)
100
- .optional()
101
- .openapi({
102
- description: "List of product modifier groups",
103
- }),
104
- categories: z
105
- .array(z.string())
106
- .optional()
107
- .openapi({
108
- example: ["cju0z9k4z0000l1qg5z1z1z"],
109
- description: "IDs of associated product categories",
110
- }),
111
- });
112
- export const CreateProductSchema = BaseProductFormData.superRefine((data, ctx) => {
113
- // Check if discountedBasePrice is greater than basePrice
114
- if (data.discountedBasePrice !== null &&
115
- data.discountedBasePrice !== undefined &&
116
- data.discountedBasePrice > data.basePrice) {
117
- ctx.addIssue({
118
- code: z.ZodIssueCode.custom,
119
- path: ["discountedBasePrice"],
120
- message: "Discounted price cannot exceed base price",
121
- });
122
- }
123
- // Existing validation for default locale
124
- return validateRequiredForDefaultLocale("title")(data, ctx);
125
- }).openapi("CreateProduct");
126
- export const UpdateProductSchema = BaseProductFormData.partial()
127
- .superRefine((data, ctx) => {
128
- // Check if discountedBasePrice is greater than basePrice
129
- if (data.discountedBasePrice !== null &&
130
- data.discountedBasePrice !== undefined &&
131
- data.basePrice &&
132
- data.discountedBasePrice > data.basePrice) {
133
- ctx.addIssue({
134
- code: z.ZodIssueCode.custom,
135
- path: ["discountedBasePrice"],
136
- message: "Discounted price cannot exceed base price",
137
- });
138
- }
139
- // Existing validation for default locale
140
- return validateRequiredForDefaultLocale("title")(data, ctx);
141
- })
142
- .openapi("UpdateProduct");
143
- //# sourceMappingURL=product.schema.js.map
1
+ import{z as e}from"@hono/zod-openapi";import{validateRequiredForDefaultLocale as r}from"../../core/utils/zod.util";import{locale as a}from"../../schemas/locales.schema";import{optionalNumber as c,requiredNumber as n}from"../../schemas/number.schema";import{FileSchema as s}from"../file/file.schema";import{ProductCategorySchema as p}from"../product-category/product-category.schema";import{CreateOrUpdateModifierGroupSchema as d,LocalizedModifierGroupSchema as u,ModifierGroupSchema as l}from"./product-modifier.schema";export const ProductSchema=e.object({id:e.string().cuid().openapi({example:"clf9876543210abcdef",description:"ID of the product"}),slug:e.string().optional().openapi({example:"premium-watch",description:"Unique slug for the product"}),sku:e.string().optional().openapi({example:"PRM-WATCH-01",description:"Stock Keeping Unit identifier"}),basePrice:n,discountedBasePrice:c,currency:e.string().openapi({example:"USD",description:"Currency code for pricing"}),images:e.array(s).optional().openapi({description:"List of product images"}),modifierGroups:e.array(l).optional().openapi({description:"List of product modifier groups"}),categories:e.array(p).openapi({example:["cju0z9k4z0000l1qg5z1z1z"],description:"IDs of associated product categories"}),manufacturerId:e.string().cuid().nullable().optional().openapi({description:"ID of associated manufacturer"}),createdAt:e.date(),publishedAt:e.date().nullable().optional(),translations:e.array(e.object({locale:a,title:e.coerce.string().optional().openapi({example:"Premium Watch",description:"Product name in specified locale"}),description:e.string().nullable().optional().openapi({example:"High-quality premium watch",description:"Product description in specified locale"})})).optional(),metadata:e.record(e.string().min(1,"Key cannot be empty").max(50,"Key too long").regex(/^[a-zA-Z][a-zA-Z0-9_-]*$/,"Key must start with letter and contain only letters, numbers, underscore, or dash"),e.string().min(1,"Value cannot be empty").max(200,"Value too long")).optional().nullable()}).openapi("Product"),LocalizedProductSchema=ProductSchema.extend({title:e.string().default(""),description:e.string().nullable().default(""),modifierGroups:e.array(u),categories:e.array(e.object({id:e.string().cuid().openapi({example:"cju0z9k4z0000l1qg5z1z1z",description:"ID of the product category"})})).default([])}).omit({translations:!0}).openapi("LocalizedProduct");const t=ProductSchema.pick({slug:!0,sku:!0,basePrice:!0,discountedBasePrice:!0,currency:!0,images:!0,manufacturerId:!0,translations:!0,metadata:!0}).extend({defaultLocale:e.string().min(1,"Default locale is required").openapi({example:"en-US",description:"Default translation locale"}),modifierGroups:e.array(d).optional().openapi({description:"List of product modifier groups"}),categories:e.array(e.string()).optional().openapi({example:["cju0z9k4z0000l1qg5z1z1z"],description:"IDs of associated product categories"})});export const CreateProductSchema=t.superRefine((i,o)=>(i.discountedBasePrice!==null&&i.discountedBasePrice!==void 0&&i.discountedBasePrice>i.basePrice&&o.addIssue({code:e.ZodIssueCode.custom,path:["discountedBasePrice"],message:"Discounted price cannot exceed base price"}),r("title")(i,o))).openapi("CreateProduct"),UpdateProductSchema=t.partial().superRefine((i,o)=>(i.discountedBasePrice!==null&&i.discountedBasePrice!==void 0&&i.basePrice&&i.discountedBasePrice>i.basePrice&&o.addIssue({code:e.ZodIssueCode.custom,path:["discountedBasePrice"],message:"Discounted price cannot exceed base price"}),r("title")(i,o))).openapi("UpdateProduct");
@@ -79,11 +79,11 @@ declare class ProductService {
79
79
  }): Promise<{
80
80
  description: string | null;
81
81
  title: string;
82
+ currency: string;
82
83
  id: string;
83
84
  createdAt: Date;
84
85
  basePrice: number;
85
86
  discountedBasePrice: number | null;
86
- currency: string;
87
87
  modifierGroups: {
88
88
  title: string | null;
89
89
  id: string;
@@ -260,11 +260,11 @@ declare class ProductService {
260
260
  list: {
261
261
  description: string | null;
262
262
  title: string;
263
+ currency: string;
263
264
  id: string;
264
265
  createdAt: Date;
265
266
  basePrice: number;
266
267
  discountedBasePrice: number | null;
267
- currency: string;
268
268
  modifierGroups: {
269
269
  title: string | null;
270
270
  id: string;
@@ -1,440 +1 @@
1
- import { __awaiter } from "tslib";
2
- import { z } from "@hono/zod-openapi";
3
- import { HttpException } from "../../core/exceptions/http-exception";
4
- import { flattenTranslationData } from "../../core/utils/zod.util";
5
- import { LocalizedProductSchema, PaginationMetaSchema, ProductSchema, } from "../../schemas";
6
- class ProductService {
7
- constructor(prisma) {
8
- this.prisma = prisma;
9
- }
10
- /**
11
- * Find a product by ID and organization ID
12
- * @throws HttpException with 404 status if product is not found
13
- */
14
- findProduct(id, organizationId, options) {
15
- return __awaiter(this, void 0, void 0, function* () {
16
- const product = yield this.prisma.product.findUnique({
17
- where: {
18
- id,
19
- organizationId,
20
- deletedAt: null,
21
- },
22
- include: options === null || options === void 0 ? void 0 : options.include,
23
- });
24
- if (!product) {
25
- throw new HttpException(404, "Product not found");
26
- }
27
- return product;
28
- });
29
- }
30
- /**
31
- * Create a new product
32
- */
33
- createProduct(organizationId, userId, body) {
34
- return __awaiter(this, void 0, void 0, function* () {
35
- const product = yield this.prisma.$transaction((tx) => __awaiter(this, void 0, void 0, function* () {
36
- var _a, _b;
37
- // Create the product
38
- const product = yield tx.product.create({
39
- data: Object.assign(Object.assign({ slug: body.slug, sku: body.sku, basePrice: body.basePrice, discountedBasePrice: body.discountedBasePrice, currency: body.currency, organizationId: organizationId, manufacturerId: body.manufacturerId, createdBy: userId, translations: {
40
- create: body.translations,
41
- }, images: {
42
- connect: (_a = body.images) === null || _a === void 0 ? void 0 : _a.map((image) => ({ id: image.id })),
43
- }, modifierGroups: {
44
- create: (_b = body.modifierGroups) === null || _b === void 0 ? void 0 : _b.map((group) => ({
45
- selectMin: group.selectMin,
46
- selectMax: group.selectMax,
47
- translations: {
48
- create: group.translations,
49
- },
50
- modifiers: {
51
- create: group.modifiers,
52
- },
53
- })),
54
- } }, (body.categories
55
- ? {
56
- categories: {
57
- connect: body.categories.map((id) => ({ id })),
58
- },
59
- }
60
- : undefined)), { metadata: body.metadata || {} }),
61
- include: {
62
- translations: true,
63
- images: true,
64
- categories: {
65
- include: {
66
- translations: true,
67
- },
68
- },
69
- modifierGroups: {
70
- include: {
71
- translations: true,
72
- modifiers: true,
73
- },
74
- },
75
- },
76
- });
77
- // Create the product snapshot
78
- const snapshot = yield tx.productSnapshot.create({
79
- data: {
80
- productId: product.id,
81
- data: product,
82
- createdBy: userId,
83
- },
84
- });
85
- // Update the product with the snapshot id as latestSnapshotId
86
- yield tx.product.update({
87
- where: { id: product.id },
88
- data: {
89
- latestSnapshotId: snapshot.id,
90
- },
91
- });
92
- return product;
93
- }));
94
- return ProductSchema.parse(product);
95
- });
96
- }
97
- /**
98
- * Get a product by ID
99
- */
100
- getProduct(organizationId, id, query) {
101
- return __awaiter(this, void 0, void 0, function* () {
102
- const { locale } = query;
103
- const product = yield this.findProduct(id, organizationId, Object.assign(Object.assign({}, (query.published && {
104
- publishedAt: {
105
- not: null,
106
- },
107
- })), { include: {
108
- translations: locale
109
- ? {
110
- where: { locale },
111
- }
112
- : true,
113
- images: true,
114
- categories: {
115
- include: {
116
- translations: locale
117
- ? {
118
- where: { locale },
119
- }
120
- : true,
121
- },
122
- },
123
- modifierGroups: {
124
- include: {
125
- translations: locale
126
- ? {
127
- where: { locale },
128
- }
129
- : true,
130
- modifiers: true,
131
- },
132
- },
133
- } }));
134
- if (!locale) {
135
- return ProductSchema.parse(product);
136
- }
137
- return LocalizedProductSchema.parse(flattenTranslationData(product));
138
- });
139
- }
140
- /**
141
- * Get a paginated list of products
142
- */
143
- getProducts(organizationId, query) {
144
- return __awaiter(this, void 0, void 0, function* () {
145
- const { page = 1, limit = 10, search, locale, published } = query;
146
- const [list, meta] = yield this.prisma.product
147
- .paginate({
148
- orderBy: {
149
- createdAt: "desc",
150
- },
151
- where: Object.assign(Object.assign({ organizationId, deletedAt: null }, (search && {
152
- translations: {
153
- some: {
154
- title: {
155
- contains: search,
156
- mode: "insensitive",
157
- },
158
- },
159
- },
160
- })), (published && {
161
- publishedAt: {
162
- not: null,
163
- },
164
- })),
165
- include: {
166
- translations: locale
167
- ? {
168
- where: { locale },
169
- }
170
- : true,
171
- images: true,
172
- categories: {
173
- include: {
174
- translations: locale
175
- ? {
176
- where: { locale },
177
- }
178
- : true,
179
- },
180
- },
181
- modifierGroups: {
182
- include: {
183
- translations: locale
184
- ? {
185
- where: { locale },
186
- }
187
- : true,
188
- modifiers: true,
189
- },
190
- },
191
- },
192
- })
193
- .withPages({
194
- page,
195
- limit,
196
- });
197
- if (!locale) {
198
- // Return standard response with ProductSchema
199
- return z
200
- .object({
201
- meta: PaginationMetaSchema,
202
- list: z.array(ProductSchema),
203
- })
204
- .parse({
205
- meta,
206
- list,
207
- });
208
- }
209
- // Process the list for localization
210
- const localizedList = list.map((item) => flattenTranslationData(item));
211
- // Return localized response with LocalizedProductSchema
212
- return z
213
- .object({
214
- meta: PaginationMetaSchema,
215
- list: z.array(LocalizedProductSchema),
216
- })
217
- .parse({
218
- meta,
219
- list: localizedList,
220
- });
221
- });
222
- }
223
- /**
224
- * Get products by category
225
- */
226
- getProductsByCategory(organizationId, categoryId, query) {
227
- return __awaiter(this, void 0, void 0, function* () {
228
- const { page = 1, limit = 10, search, locale } = query;
229
- const [list, meta] = yield this.prisma.product
230
- .paginate({
231
- orderBy: {
232
- createdAt: "desc",
233
- },
234
- where: Object.assign({ organizationId, deletedAt: null, categories: {
235
- some: {
236
- id: categoryId,
237
- },
238
- } }, (search && {
239
- translations: {
240
- some: {
241
- title: {
242
- contains: search,
243
- mode: "insensitive",
244
- },
245
- },
246
- },
247
- })),
248
- include: {
249
- translations: locale
250
- ? {
251
- where: { locale },
252
- }
253
- : true,
254
- images: true,
255
- categories: {
256
- include: {
257
- translations: locale
258
- ? {
259
- where: { locale },
260
- }
261
- : true,
262
- },
263
- },
264
- modifierGroups: {
265
- include: {
266
- translations: locale
267
- ? {
268
- where: { locale },
269
- }
270
- : true,
271
- modifiers: true,
272
- },
273
- },
274
- },
275
- })
276
- .withPages({
277
- page,
278
- limit,
279
- });
280
- // For getProductsByCategory, we always use ProductSchema as specified in the contract
281
- const processedList = locale
282
- ? list.map((item) => ProductSchema.parse(flattenTranslationData(item)))
283
- : list.map((item) => ProductSchema.parse(item));
284
- return z
285
- .object({
286
- meta: PaginationMetaSchema,
287
- list: z.array(ProductSchema),
288
- })
289
- .parse({
290
- meta,
291
- list: processedList,
292
- });
293
- });
294
- }
295
- /**
296
- * Update a product
297
- */
298
- updateProduct(organizationId, id, userId, body) {
299
- return __awaiter(this, void 0, void 0, function* () {
300
- // Fetch the product by id
301
- yield this.findProduct(id, organizationId);
302
- const updatedProduct = yield this.prisma.$transaction((tx) => __awaiter(this, void 0, void 0, function* () {
303
- var _a, _b, _c;
304
- // Update the product
305
- const product = yield tx.product.update({
306
- where: {
307
- id,
308
- organizationId,
309
- deletedAt: null,
310
- },
311
- data: {
312
- slug: body.slug,
313
- sku: body.sku,
314
- basePrice: body.basePrice,
315
- discountedBasePrice: body.discountedBasePrice,
316
- currency: body.currency,
317
- manufacturerId: body.manufacturerId,
318
- updatedBy: userId,
319
- translations: {
320
- deleteMany: {},
321
- create: body.translations || [],
322
- },
323
- images: {
324
- set: ((_a = body.images) === null || _a === void 0 ? void 0 : _a.map((image) => ({ id: image.id }))) || [],
325
- },
326
- modifierGroups: {
327
- deleteMany: {},
328
- create: (_b = body.modifierGroups) === null || _b === void 0 ? void 0 : _b.map((group) => ({
329
- selectMin: group.selectMin,
330
- selectMax: group.selectMax,
331
- translations: {
332
- create: group.translations,
333
- },
334
- modifiers: {
335
- create: group.modifiers,
336
- },
337
- })),
338
- },
339
- categories: {
340
- set: ((_c = body.categories) === null || _c === void 0 ? void 0 : _c.map((id) => ({ id }))) || [],
341
- },
342
- metadata: body.metadata || {},
343
- },
344
- include: {
345
- translations: true,
346
- images: true,
347
- categories: {
348
- include: {
349
- translations: true,
350
- },
351
- },
352
- modifierGroups: {
353
- include: {
354
- translations: true,
355
- modifiers: true,
356
- },
357
- },
358
- },
359
- });
360
- // Create a new product snapshot
361
- const snapshot = yield tx.productSnapshot.create({
362
- data: {
363
- productId: product.id,
364
- data: product,
365
- createdBy: userId,
366
- },
367
- });
368
- // Update the product with the new snapshot id
369
- yield tx.product.update({
370
- where: { id: product.id },
371
- data: {
372
- latestSnapshotId: snapshot.id,
373
- },
374
- });
375
- return product;
376
- }));
377
- return ProductSchema.parse(updatedProduct);
378
- });
379
- }
380
- /**
381
- * Update product status (publish/unpublish)
382
- */
383
- updateProductStatus(organizationId, id, operation, userId) {
384
- return __awaiter(this, void 0, void 0, function* () {
385
- // Fetch the product by id
386
- yield this.findProduct(id, organizationId);
387
- const updatedProduct = yield this.prisma.product.update({
388
- where: {
389
- id,
390
- organizationId,
391
- deletedAt: null,
392
- },
393
- data: {
394
- publishedAt: operation === "publish" ? new Date() : null,
395
- publishedBy: operation === "publish" ? userId : null,
396
- updatedBy: userId,
397
- },
398
- include: {
399
- translations: true,
400
- images: true,
401
- categories: {
402
- include: {
403
- translations: true,
404
- },
405
- },
406
- modifierGroups: {
407
- include: {
408
- translations: true,
409
- modifiers: true,
410
- },
411
- },
412
- },
413
- });
414
- return ProductSchema.parse(updatedProduct);
415
- });
416
- }
417
- /**
418
- * Delete a product (soft delete)
419
- */
420
- deleteProduct(organizationId, id, userId) {
421
- return __awaiter(this, void 0, void 0, function* () {
422
- // Fetch the product by id
423
- yield this.findProduct(id, organizationId);
424
- yield this.prisma.product.update({
425
- where: {
426
- id,
427
- organizationId,
428
- deletedAt: null,
429
- },
430
- data: {
431
- deletedAt: new Date(),
432
- deletedBy: userId,
433
- },
434
- });
435
- return;
436
- });
437
- }
438
- }
439
- export { ProductService };
440
- //# sourceMappingURL=product.service.js.map
1
+ import{__awaiter as u}from"tslib";import{z as h}from"@hono/zod-openapi";import{HttpException as P}from"../../core/exceptions/http-exception";import{flattenTranslationData as f}from"../../core/utils/zod.util";import{LocalizedProductSchema as g,PaginationMetaSchema as v,ProductSchema as p}from"../../schemas";class w{constructor(i){this.prisma=i}findProduct(i,r,e){return u(this,void 0,void 0,function*(){const t=yield this.prisma.product.findUnique({where:{id:i,organizationId:r,deletedAt:null},include:e?.include});if(!t)throw new P(404,"Product not found");return t})}createProduct(i,r,e){return u(this,void 0,void 0,function*(){const t=yield this.prisma.$transaction(d=>u(this,void 0,void 0,function*(){var a,s;const o=yield d.product.create({data:Object.assign(Object.assign({slug:e.slug,sku:e.sku,basePrice:e.basePrice,discountedBasePrice:e.discountedBasePrice,currency:e.currency,organizationId:i,manufacturerId:e.manufacturerId,createdBy:r,translations:{create:e.translations},images:{connect:(a=e.images)===null||a===void 0?void 0:a.map(n=>({id:n.id}))},modifierGroups:{create:(s=e.modifierGroups)===null||s===void 0?void 0:s.map(n=>({selectMin:n.selectMin,selectMax:n.selectMax,translations:{create:n.translations},modifiers:{create:n.modifiers}}))}},e.categories?{categories:{connect:e.categories.map(n=>({id:n}))}}:void 0),{metadata:e.metadata||{}}),include:{translations:!0,images:!0,categories:{include:{translations:!0}},modifierGroups:{include:{translations:!0,modifiers:!0}}}}),c=yield d.productSnapshot.create({data:{productId:o.id,data:o,createdBy:r}});return yield d.product.update({where:{id:o.id},data:{latestSnapshotId:c.id}}),o}));return p.parse(t)})}getProduct(i,r,e){return u(this,void 0,void 0,function*(){const{locale:t}=e,d=yield this.findProduct(r,i,Object.assign(Object.assign({},e.published&&{publishedAt:{not:null}}),{include:{translations:t?{where:{locale:t}}:!0,images:!0,categories:{include:{translations:t?{where:{locale:t}}:!0}},modifierGroups:{include:{translations:t?{where:{locale:t}}:!0,modifiers:!0}}}}));return t?g.parse(f(d)):p.parse(d)})}getProducts(i,r){return u(this,void 0,void 0,function*(){const{page:e=1,limit:t=10,search:d,locale:a,published:s}=r,[o,c]=yield this.prisma.product.paginate({orderBy:{createdAt:"desc"},where:Object.assign(Object.assign({organizationId:i,deletedAt:null},d&&{translations:{some:{title:{contains:d,mode:"insensitive"}}}}),s&&{publishedAt:{not:null}}),include:{translations:a?{where:{locale:a}}:!0,images:!0,categories:{include:{translations:a?{where:{locale:a}}:!0}},modifierGroups:{include:{translations:a?{where:{locale:a}}:!0,modifiers:!0}}}}).withPages({page:e,limit:t});if(!a)return h.object({meta:v,list:h.array(p)}).parse({meta:c,list:o});const n=o.map(m=>f(m));return h.object({meta:v,list:h.array(g)}).parse({meta:c,list:n})})}getProductsByCategory(i,r,e){return u(this,void 0,void 0,function*(){const{page:t=1,limit:d=10,search:a,locale:s}=e,[o,c]=yield this.prisma.product.paginate({orderBy:{createdAt:"desc"},where:Object.assign({organizationId:i,deletedAt:null,categories:{some:{id:r}}},a&&{translations:{some:{title:{contains:a,mode:"insensitive"}}}}),include:{translations:s?{where:{locale:s}}:!0,images:!0,categories:{include:{translations:s?{where:{locale:s}}:!0}},modifierGroups:{include:{translations:s?{where:{locale:s}}:!0,modifiers:!0}}}}).withPages({page:t,limit:d}),n=s?o.map(m=>p.parse(f(m))):o.map(m=>p.parse(m));return h.object({meta:v,list:h.array(p)}).parse({meta:c,list:n})})}updateProduct(i,r,e,t){return u(this,void 0,void 0,function*(){yield this.findProduct(r,i);const d=yield this.prisma.$transaction(a=>u(this,void 0,void 0,function*(){var s,o,c;const n=yield a.product.update({where:{id:r,organizationId:i,deletedAt:null},data:{slug:t.slug,sku:t.sku,basePrice:t.basePrice,discountedBasePrice:t.discountedBasePrice,currency:t.currency,manufacturerId:t.manufacturerId,updatedBy:e,translations:{deleteMany:{},create:t.translations||[]},images:{set:((s=t.images)===null||s===void 0?void 0:s.map(l=>({id:l.id})))||[]},modifierGroups:{deleteMany:{},create:(o=t.modifierGroups)===null||o===void 0?void 0:o.map(l=>({selectMin:l.selectMin,selectMax:l.selectMax,translations:{create:l.translations},modifiers:{create:l.modifiers}}))},categories:{set:((c=t.categories)===null||c===void 0?void 0:c.map(l=>({id:l})))||[]},metadata:t.metadata||{}},include:{translations:!0,images:!0,categories:{include:{translations:!0}},modifierGroups:{include:{translations:!0,modifiers:!0}}}}),m=yield a.productSnapshot.create({data:{productId:n.id,data:n,createdBy:e}});return yield a.product.update({where:{id:n.id},data:{latestSnapshotId:m.id}}),n}));return p.parse(d)})}updateProductStatus(i,r,e,t){return u(this,void 0,void 0,function*(){yield this.findProduct(r,i);const d=yield this.prisma.product.update({where:{id:r,organizationId:i,deletedAt:null},data:{publishedAt:e==="publish"?new Date:null,publishedBy:e==="publish"?t:null,updatedBy:t},include:{translations:!0,images:!0,categories:{include:{translations:!0}},modifierGroups:{include:{translations:!0,modifiers:!0}}}});return p.parse(d)})}deleteProduct(i,r,e){return u(this,void 0,void 0,function*(){yield this.findProduct(r,i),yield this.prisma.product.update({where:{id:r,organizationId:i,deletedAt:null},data:{deletedAt:new Date,deletedBy:e}})})}}export{w as ProductService};