@things-factory/integration-marketplace 4.2.3 → 4.2.8

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 (79) hide show
  1. package/dist-server/controllers/index.js +1 -0
  2. package/dist-server/controllers/index.js.map +1 -1
  3. package/dist-server/controllers/magento/apis/get-store-orders.js +2 -1
  4. package/dist-server/controllers/magento/apis/get-store-orders.js.map +1 -1
  5. package/dist-server/controllers/magento/apis/get-store-products.js +8 -9
  6. package/dist-server/controllers/magento/apis/get-store-products.js.map +1 -1
  7. package/dist-server/controllers/magento/apis/update-order-status.js +39 -14
  8. package/dist-server/controllers/magento/apis/update-order-status.js.map +1 -1
  9. package/dist-server/controllers/store-api/index.js +14 -0
  10. package/dist-server/controllers/store-api/index.js.map +1 -1
  11. package/dist-server/controllers/tiktok/apis/echo.js +19 -0
  12. package/dist-server/controllers/tiktok/apis/echo.js.map +1 -0
  13. package/dist-server/controllers/tiktok/apis/get-store-order-document.js +27 -0
  14. package/dist-server/controllers/tiktok/apis/get-store-order-document.js.map +1 -0
  15. package/dist-server/controllers/tiktok/apis/get-store-order-package.js +47 -0
  16. package/dist-server/controllers/tiktok/apis/get-store-order-package.js.map +1 -0
  17. package/dist-server/controllers/tiktok/apis/get-store-order-packages.js +39 -0
  18. package/dist-server/controllers/tiktok/apis/get-store-order-packages.js.map +1 -0
  19. package/dist-server/controllers/tiktok/apis/get-store-order.js +137 -0
  20. package/dist-server/controllers/tiktok/apis/get-store-order.js.map +1 -0
  21. package/dist-server/controllers/tiktok/apis/get-store-orders.js +47 -0
  22. package/dist-server/controllers/tiktok/apis/get-store-orders.js.map +1 -0
  23. package/dist-server/controllers/tiktok/apis/get-store-product-attributes.js +30 -0
  24. package/dist-server/controllers/tiktok/apis/get-store-product-attributes.js.map +1 -0
  25. package/dist-server/controllers/tiktok/apis/get-store-product-categories.js +28 -0
  26. package/dist-server/controllers/tiktok/apis/get-store-product-categories.js.map +1 -0
  27. package/dist-server/controllers/tiktok/apis/get-store-product.js +91 -0
  28. package/dist-server/controllers/tiktok/apis/get-store-product.js.map +1 -0
  29. package/dist-server/controllers/tiktok/apis/get-store-products.js +36 -0
  30. package/dist-server/controllers/tiktok/apis/get-store-products.js.map +1 -0
  31. package/dist-server/controllers/tiktok/apis/index.js +26 -0
  32. package/dist-server/controllers/tiktok/apis/index.js.map +1 -0
  33. package/dist-server/controllers/tiktok/apis/update-order-status.js +27 -0
  34. package/dist-server/controllers/tiktok/apis/update-order-status.js.map +1 -0
  35. package/dist-server/controllers/tiktok/apis/update-store-product-variation-price.js +28 -0
  36. package/dist-server/controllers/tiktok/apis/update-store-product-variation-price.js.map +1 -0
  37. package/dist-server/controllers/tiktok/apis/update-store-product-variation-stock.js +32 -0
  38. package/dist-server/controllers/tiktok/apis/update-store-product-variation-stock.js.map +1 -0
  39. package/dist-server/controllers/tiktok/client/index.js +15 -0
  40. package/dist-server/controllers/tiktok/client/index.js.map +1 -0
  41. package/dist-server/controllers/tiktok/client/signature.js +63 -0
  42. package/dist-server/controllers/tiktok/client/signature.js.map +1 -0
  43. package/dist-server/controllers/tiktok/client/tiktok.js +93 -0
  44. package/dist-server/controllers/tiktok/client/tiktok.js.map +1 -0
  45. package/dist-server/controllers/tiktok/client/types.js +3 -0
  46. package/dist-server/controllers/tiktok/client/types.js.map +1 -0
  47. package/dist-server/controllers/tiktok/index.js +30 -0
  48. package/dist-server/controllers/tiktok/index.js.map +1 -0
  49. package/dist-server/controllers/tiktok/platform-action.js +44 -0
  50. package/dist-server/controllers/tiktok/platform-action.js.map +1 -0
  51. package/dist-server/controllers/woocommerce/apis/get-store-products.js +17 -6
  52. package/dist-server/controllers/woocommerce/apis/get-store-products.js.map +1 -1
  53. package/package.json +2 -2
  54. package/server/controllers/index.ts +1 -0
  55. package/server/controllers/magento/apis/get-store-orders.ts +3 -1
  56. package/server/controllers/magento/apis/get-store-products.ts +1 -2
  57. package/server/controllers/magento/apis/update-order-status.ts +43 -15
  58. package/server/controllers/store-api/index.ts +6 -0
  59. package/server/controllers/tiktok/apis/echo.ts +14 -0
  60. package/server/controllers/tiktok/apis/get-store-order-document.ts +26 -0
  61. package/server/controllers/tiktok/apis/get-store-order-package.ts +46 -0
  62. package/server/controllers/tiktok/apis/get-store-order-packages.ts +43 -0
  63. package/server/controllers/tiktok/apis/get-store-order.ts +169 -0
  64. package/server/controllers/tiktok/apis/get-store-orders.ts +52 -0
  65. package/server/controllers/tiktok/apis/get-store-product-attributes.ts +29 -0
  66. package/server/controllers/tiktok/apis/get-store-product-categories.ts +27 -0
  67. package/server/controllers/tiktok/apis/get-store-product.ts +95 -0
  68. package/server/controllers/tiktok/apis/get-store-products.ts +38 -0
  69. package/server/controllers/tiktok/apis/index.ts +13 -0
  70. package/server/controllers/tiktok/apis/update-order-status.ts +22 -0
  71. package/server/controllers/tiktok/apis/update-store-product-variation-price.ts +24 -0
  72. package/server/controllers/tiktok/apis/update-store-product-variation-stock.ts +28 -0
  73. package/server/controllers/tiktok/client/index.ts +2 -0
  74. package/server/controllers/tiktok/client/signature.ts +78 -0
  75. package/server/controllers/tiktok/client/tiktok.ts +139 -0
  76. package/server/controllers/tiktok/client/types.ts +20 -0
  77. package/server/controllers/tiktok/index.ts +8 -0
  78. package/server/controllers/tiktok/platform-action.ts +48 -0
  79. package/server/controllers/woocommerce/apis/get-store-products.ts +33 -22
@@ -0,0 +1,95 @@
1
+ /* https://bytedance.feishu.cn/docs/doccnDyz5Bbk26iOdejbBRBlLrb#ytBXoS */
2
+
3
+ /* status: 0-all, 1-draft, 2-pending, 3-failed, 4-live, 5-seller_deactivated,
4
+ 6-platform-deactivated, 7-freeze, 8-deleted
5
+ */
6
+
7
+ export function getStoreProduct() {
8
+ return {
9
+ method: 'get',
10
+ path: '/api/products/details',
11
+ denormalize(req) {
12
+ var { productId } = req || {}
13
+
14
+ return { payload: { product_id: productId } }
15
+ },
16
+ async normalize(res) {
17
+ const { data } = res
18
+
19
+ const productVariations: any[] = data.skus
20
+
21
+ let variants: any[] = []
22
+ if (productVariations && productVariations?.length > 0) {
23
+ variants = productVariations.map(variant => {
24
+ let totalProductQty: number = 0
25
+ let stockInfos = variant.stock_infos
26
+ stockInfos.map(stockInfo => {
27
+ totalProductQty += stockInfo.available_stock
28
+ })
29
+
30
+ return {
31
+ variationId: variant.id,
32
+ variationSku: variant.seller_sku || variant.id.toString(),
33
+ channelSku: variant.seller_sku || variant.id.toString(),
34
+ name: data.product_name,
35
+ qty: totalProductQty,
36
+ primaryUnit: 'N/A',
37
+ primaryUnitValue: data.package_weight === '' ? null : parseFloat(data.package_weight),
38
+ costPrice: variant.price.original_price === '' ? null : parseFloat(variant.price.original_price),
39
+ sellPrice: variant.price.original_price === '' ? null : parseFloat(variant.price.original_price),
40
+ isEnabled: data.product_status == 4 ? true : false,
41
+ length: data?.package_length ? data.package_length * 10 : 1,
42
+ width: data?.package_width ? data.package_width * 10 : 1,
43
+ height: data?.package_height ? data.package_height * 10 : 1,
44
+ weight: data.package_weight === '' ? null : parseFloat(data.package_weight)
45
+ }
46
+ })
47
+ } else {
48
+ variants = [
49
+ {
50
+ variationId: data.product_id,
51
+ variationSku: data.product_name,
52
+ channelSku: data.product_name,
53
+ name: data.product_name,
54
+ qty: 0,
55
+ primaryUnit: 'N/A',
56
+ primaryUnitValue: data.package_weight === '' ? null : parseFloat(data.package_weight),
57
+ costPrice: null,
58
+ sellPrice: null,
59
+ isEnabled: data.product_status == 4 ? true : false,
60
+ length: data?.package_length ? data.package_length * 10 : 1,
61
+ width: data?.package_width ? data.package_width * 10 : 1,
62
+ height: data?.package_height ? data.package_height * 10 : 1,
63
+ weight: data.package_weight === '' ? null : parseFloat(data.package_weight)
64
+ }
65
+ ]
66
+ }
67
+
68
+ const result = {
69
+ itemId: data.product_id,
70
+ name: data.product_name,
71
+ brand: data?.brand?.name || null,
72
+ isVerified: data.product_status == 4 ? true : false,
73
+ categoryId: data?.category_list?.length > 0 ? data.category_list[0].id : '',
74
+ images: getImageUrl(data.images),
75
+ variations: variants
76
+ }
77
+
78
+ return result
79
+ }
80
+ }
81
+ }
82
+
83
+ function getImageUrl(images) {
84
+ let imageSrc: any = []
85
+
86
+ if (images) {
87
+ images.map(image => {
88
+ image.url_list.map(url => {
89
+ imageSrc.push(url)
90
+ })
91
+ })
92
+ }
93
+
94
+ return imageSrc
95
+ }
@@ -0,0 +1,38 @@
1
+ /* https://bytedance.feishu.cn/docs/doccnDyz5Bbk26iOdejbBRBlLrb#ytBXoS */
2
+
3
+ /* status: 0-all, 1-draft, 2-pending, 3-failed, 4-live, 5-seller_deactivated,
4
+ 6-platform-deactivated, 7-freeze, 8-deleted
5
+ */
6
+
7
+ import { StoreAPI } from '../../store-api'
8
+
9
+ export function getStoreProducts() {
10
+ return {
11
+ method: 'post',
12
+ path: '/api/products/search',
13
+ denormalize(req) {
14
+ var { pagination } = req || {}
15
+ var { page, limit } = pagination || { page: 0, limit: 100 }
16
+
17
+ return {
18
+ payload: { page_size: limit, page_number: page + 1, search_status: 0 },
19
+ resource: {}
20
+ }
21
+ },
22
+ async normalize(res, { store }) {
23
+ const { data } = res
24
+
25
+ const products: any[] = data?.products || []
26
+ const total: number = data?.total || 0
27
+
28
+ let results: any[] = []
29
+ for (let i = 0; i < products.length; i++) {
30
+ const product: any = products[i]
31
+ const productDetails = await StoreAPI.getStoreProduct(store, { productId: product.id })
32
+ results.push({ ...productDetails })
33
+ }
34
+
35
+ return { results, total }
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,13 @@
1
+ export * from './echo'
2
+ export * from './get-store-order'
3
+ export * from './get-store-orders'
4
+ export * from './get-store-order-document'
5
+ export * from './get-store-order-packages'
6
+ export * from './get-store-order-package'
7
+ export * from './get-store-product-attributes'
8
+ export * from './get-store-product-categories'
9
+ export * from './get-store-product'
10
+ export * from './get-store-products'
11
+ export * from './update-store-product-variation-stock'
12
+ export * from './update-store-product-variation-price'
13
+ export * from './update-order-status'
@@ -0,0 +1,22 @@
1
+ export function updateOrderStatus() {
2
+ return {
3
+ path: '/api/order/rts',
4
+ method: 'post',
5
+ async denormalize(req, { store }) {
6
+ let { orderId, status } = req
7
+
8
+ if (status == 'ready_to_ship') {
9
+ return {
10
+ payload: {
11
+ order_id: orderId
12
+ }
13
+ }
14
+ } else {
15
+ return
16
+ }
17
+ },
18
+ normalize(res) {
19
+ return res
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,24 @@
1
+ export function updateStoreProductVariationPrice() {
2
+ return {
3
+ path: '/api/products/prices',
4
+ method: 'put',
5
+ denormalize(req) {
6
+ const { variationId, sellPrice, productId } = (Array.isArray(req) ? req[0] : req) || {}
7
+
8
+ return {
9
+ payload: {
10
+ product_id: productId,
11
+ skus: [
12
+ {
13
+ id: variationId,
14
+ original_price: sellPrice.toString()
15
+ }
16
+ ]
17
+ }
18
+ }
19
+ },
20
+ normalize(res) {
21
+ return res
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,28 @@
1
+ export function updateStoreProductVariationStock() {
2
+ return {
3
+ method: 'put',
4
+ path: '/api/products/stocks',
5
+ denormalize(req) {
6
+ const { variationId, qty, itemId } = (Array.isArray(req) ? req[0] : req) || {}
7
+
8
+ return {
9
+ payload: {
10
+ product_id: itemId,
11
+ skus: [
12
+ {
13
+ id: variationId,
14
+ stock_infos: [
15
+ {
16
+ available_stock: qty
17
+ }
18
+ ]
19
+ }
20
+ ]
21
+ }
22
+ }
23
+ },
24
+ normalize(res) {
25
+ return res
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,2 @@
1
+ export * from './types'
2
+ export * from './tiktok'
@@ -0,0 +1,78 @@
1
+ import crypto from 'crypto'
2
+ import { Parameter, PublicRequestParameters } from './types'
3
+
4
+ /**
5
+ * { key: value } => 'keyvalue'
6
+ * @param {Object} parameters
7
+ * @return {string} concatString
8
+ */
9
+ const concatObjectKeyValue = (parameters: Parameter): string => {
10
+ if (!parameters) return ''
11
+ return Object.entries(parameters)
12
+ .sort(([k1, v1], [k2, v2]) => (k2 > k1 ? -1 : 1))
13
+ .map(([k, v]) => `${k}${v}`)
14
+ .join('')
15
+ }
16
+
17
+ /**
18
+ * Calculate a signature hash
19
+ * @param {string} appSecret
20
+ * @param {string} apiPath e.g. /order/get
21
+ * @param {Object} params
22
+ * @return {string} signature hash
23
+ */
24
+ export const signRequest = (appSecret: string, apiPath: string, params: Parameter): string => {
25
+ const hash = crypto
26
+ .createHmac('sha256', appSecret)
27
+ .update(appSecret + apiPath + concatObjectKeyValue(params) + appSecret)
28
+ .digest('hex')
29
+
30
+ return hash
31
+ }
32
+
33
+ /**
34
+ * Gather system and business parameters to compute signature
35
+ * @param {string} appKey
36
+ * @param {string} appSecret
37
+ * @param {string} apiPath
38
+ * @param {string?} accessToken
39
+ * @param {Parameter?} payload
40
+ * @return {SystemParameters}
41
+ */
42
+ export function makePublicRequestParameters(
43
+ appKey: string,
44
+ appSecret: string,
45
+ apiPath: string,
46
+ accessToken: string,
47
+ shopId: string,
48
+ payload?: Parameter
49
+ ): PublicRequestParameters {
50
+ const ts = Math.floor(new Date(new Date().toUTCString()).getTime() / 1000).toString()
51
+
52
+ const publicRequestParams: {
53
+ app_key: string
54
+ timestamp: string
55
+ access_token: string
56
+ shop_id?: string
57
+ } = {
58
+ app_key: appKey,
59
+ timestamp: ts,
60
+ access_token: accessToken
61
+ }
62
+
63
+ let signatureParams: any = {
64
+ app_key: publicRequestParams.app_key,
65
+ timestamp: publicRequestParams.timestamp
66
+ }
67
+
68
+ if (shopId) {
69
+ publicRequestParams.shop_id = shopId
70
+
71
+ signatureParams.shop_id = shopId
72
+ }
73
+
74
+ return {
75
+ ...publicRequestParams,
76
+ sign: signRequest(appSecret, apiPath, { ...payload, ...signatureParams })
77
+ }
78
+ }
@@ -0,0 +1,139 @@
1
+ import fetch from 'node-fetch'
2
+
3
+ import { makePublicRequestParameters } from './signature'
4
+ import { Parameter } from './types'
5
+
6
+ const debug = require('debug')('things-factory:integration-marketplace:tiktok')
7
+
8
+ export type TiktokConfig = {
9
+ appKey: string
10
+ appSecret: string
11
+ accessToken: string
12
+ channelShopId: string
13
+ }
14
+
15
+ export class Tiktok {
16
+ private config: TiktokConfig
17
+
18
+ constructor(config: TiktokConfig) {
19
+ this.config = {
20
+ ...config
21
+ }
22
+ }
23
+
24
+ getBaseURL() {
25
+ return `https://open-api.tiktokglobalshop.com`
26
+ }
27
+
28
+ /**
29
+ * @summary Get Method
30
+ * @description Using v3 API, map the consumer_key, consumer_secret to the endpoint path.
31
+ * X-WP-Total is to get the total items from the response
32
+ */
33
+ async get(path: string, params: Parameter) {
34
+ const { appKey, appSecret, accessToken, channelShopId } = this.config
35
+
36
+ const qs = Object.entries({
37
+ ...params,
38
+ ...makePublicRequestParameters(appKey, appSecret, path, accessToken, channelShopId, params)
39
+ })
40
+ .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
41
+ .join('&')
42
+
43
+ const endpoint = `${this.getBaseURL()}${path}?${qs ? qs : ''}`
44
+ debug('endpoint', endpoint)
45
+
46
+ const response = await fetch(endpoint, {
47
+ headers: {
48
+ 'Content-Type': 'application/json'
49
+ }
50
+ })
51
+
52
+ var result: any = {}
53
+ const resResult: any = await response.json()
54
+ result.data = resResult.data
55
+
56
+ debug('response result', result)
57
+
58
+ return result
59
+ }
60
+
61
+ async post(path: string, data: any = {}) {
62
+ const { appKey, appSecret, accessToken, channelShopId } = this.config
63
+
64
+ debug('data', data)
65
+
66
+ const jsondata = JSON.stringify(data)
67
+
68
+ const { app_key, timestamp, access_token, sign, shop_id } = makePublicRequestParameters(
69
+ appKey,
70
+ appSecret,
71
+ path,
72
+ accessToken,
73
+ channelShopId
74
+ )
75
+
76
+ const qs = Object.entries({
77
+ app_key,
78
+ timestamp,
79
+ access_token,
80
+ sign,
81
+ shop_id
82
+ })
83
+ .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
84
+ .join('&')
85
+
86
+ const endpoint = `${this.getBaseURL()}${path}?${qs ? '&' + qs : ''}`
87
+ const response = await fetch(endpoint, {
88
+ method: 'post',
89
+ headers: {
90
+ 'Content-Type': 'application/json'
91
+ },
92
+ body: jsondata
93
+ })
94
+
95
+ const result = await response.json()
96
+ debug('response result', result)
97
+
98
+ return result
99
+ }
100
+
101
+ async put(path: string, data: any = {}) {
102
+ const { appKey, appSecret, accessToken, channelShopId } = this.config
103
+
104
+ debug('data', data)
105
+
106
+ const jsondata = JSON.stringify(data)
107
+
108
+ const { app_key, timestamp, access_token, sign } = makePublicRequestParameters(
109
+ appKey,
110
+ appSecret,
111
+ path,
112
+ accessToken,
113
+ channelShopId
114
+ )
115
+
116
+ const qs = Object.entries({
117
+ app_key,
118
+ timestamp,
119
+ access_token,
120
+ sign
121
+ })
122
+ .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
123
+ .join('&')
124
+
125
+ const endpoint = `${this.getBaseURL()}${path}?${qs ? '&' + qs : ''}`
126
+ const response = await fetch(endpoint, {
127
+ method: 'put',
128
+ headers: {
129
+ 'Content-Type': 'application/json'
130
+ },
131
+ body: jsondata
132
+ })
133
+
134
+ const result = await response.json()
135
+ debug('response result', result)
136
+
137
+ return result
138
+ }
139
+ }
@@ -0,0 +1,20 @@
1
+ export type Parameter = {
2
+ [key: string]: any
3
+ }
4
+
5
+ /**
6
+ * Tiktok Open Platform Public Request Parameters
7
+ * @typedef PublicRequestParameters
8
+ * @property {string} timestamp :mandatory
9
+ * @property {string} app_key :mandatory
10
+ * @property {string} access_token :mandatory
11
+ * @property {string} shop_id :mandatory
12
+ * @property {string} sign :mandatory
13
+ */
14
+ export interface PublicRequestParameters {
15
+ timestamp: string
16
+ app_key: string
17
+ access_token: string
18
+ sign: string
19
+ shop_id?: string
20
+ }
@@ -0,0 +1,8 @@
1
+ export * from './client'
2
+
3
+ import { StoreAPI } from '../store-api'
4
+
5
+ import { action } from './platform-action'
6
+ import * as APIS from './apis'
7
+
8
+ StoreAPI.registerPlatform('tiktok', action, APIS)
@@ -0,0 +1,48 @@
1
+ import { Tiktok } from './client/tiktok'
2
+
3
+ function substitute(path, obj) {
4
+ var props = []
5
+ var re = /{([^}]+)}/g
6
+ var text
7
+
8
+ while ((text = re.exec(path))) {
9
+ props.push(text[1])
10
+ }
11
+
12
+ var result = path
13
+ props.forEach(prop => {
14
+ let value = obj[prop.trim()]
15
+ result = result.replace(`{${prop}}`, value === undefined ? '' : value)
16
+ })
17
+
18
+ return result
19
+ }
20
+
21
+ /**
22
+ * @summary Building Path Method and Payload
23
+ * @description After denormalise of data is done,
24
+ * platform API method will be called with its path and payload,
25
+ * this section is to build path and substitution of the resource in url as well as the payload for body request.
26
+ * Every Tiktok API call requires consumer_key, consumer_secret, access_token.
27
+ * consumer_key, consumer_secret, access_token are retrieved from tokencraft
28
+ * to avoid permission error from TikTok.
29
+ */
30
+ export const action = async ({ store, method = 'get', path, request }) => {
31
+ const client = new Tiktok({
32
+ appKey: store.accessKey || '5p6q6g',
33
+ appSecret: store.accessSecret || 'c30cf452265ab418514bb81fa49fc333aecbf081',
34
+ accessToken: store.accessToken,
35
+ channelShopId: store.channelShopId
36
+ })
37
+
38
+ const { resource = {}, payload = {} } = request
39
+
40
+ path = substitute(path, resource)
41
+
42
+ var response = await client[method](path, payload)
43
+ if (response.code) {
44
+ throw response
45
+ }
46
+
47
+ return response
48
+ }
@@ -17,7 +17,6 @@ export function getStoreProducts() {
17
17
  return { payload }
18
18
  },
19
19
  async normalize(res, { store }) {
20
-
21
20
  const { items, totalItems: totalProducts } = res
22
21
 
23
22
  let results: any[] = []
@@ -36,13 +35,17 @@ export function getStoreProducts() {
36
35
  images: product.images.map(image => {
37
36
  return image.src
38
37
  }),
39
- attributes: product.attributes.map(attribute => {
40
- return {
41
- native_attribute_id: attribute.id,
42
- attribute_key: attribute.name,
43
- values: attribute.options
44
- }
45
- }),
38
+ attributes:
39
+ product?.attributes?.map(attribute => {
40
+ return {
41
+ attributeId: attribute.id,
42
+ name: attribute.name,
43
+ originalValue: attribute.options,
44
+ native_attribute_id: attribute.id,
45
+ attribute_key: attribute.name,
46
+ values: attribute.options
47
+ }
48
+ }) || [],
46
49
  isVerified: product.purchasable,
47
50
  variations:
48
51
  productVariations.length === 0
@@ -57,13 +60,17 @@ export function getStoreProducts() {
57
60
  primaryUnitValue: product.weight === '' ? null : parseFloat(product.weight),
58
61
  costPrice: product.price === '' ? null : parseFloat(product.price),
59
62
  sellPrice: product.sale_price === '' ? null : parseFloat(product.sale_price),
60
- attributes: product.attributes.map(attribute => {
61
- return {
62
- native_attribute_id: attribute.id,
63
- attribute_key: attribute.name,
64
- values: attribute.options
65
- }
66
- }),
63
+ attributes:
64
+ product?.attributes?.map(attribute => {
65
+ return {
66
+ attributeId: attribute.id,
67
+ name: attribute.name,
68
+ originalValue: attribute.options,
69
+ native_attribute_id: attribute.id,
70
+ attribute_key: attribute.name,
71
+ values: attribute.options
72
+ }
73
+ }) || [],
67
74
  isEnabled: product.purchasable,
68
75
  length: product.dimensions.length * 10,
69
76
  width: product.dimensions.width * 10,
@@ -83,13 +90,17 @@ export function getStoreProducts() {
83
90
  primaryUnitValue: variant.weight === '' ? null : parseFloat(variant.weight),
84
91
  costPrice: variant.price === '' ? null : parseFloat(variant.price),
85
92
  sellPrice: variant.sale_price === '' ? null : parseFloat(variant.sale_price),
86
- attributes: variant.attributes.map(attribute => {
87
- return {
88
- native_attribute_id: attribute.id,
89
- attribute_key: attribute.name,
90
- values: [attribute.option]
91
- }
92
- }),
93
+ attributes:
94
+ variant?.attributes?.map(attribute => {
95
+ return {
96
+ attributeId: attribute.id,
97
+ name: attribute.name,
98
+ originalValue: attribute.options,
99
+ native_attribute_id: attribute.id,
100
+ attribute_key: attribute.name,
101
+ values: [attribute.option]
102
+ }
103
+ }) || [],
93
104
  isEnabled: variant.purchasable,
94
105
  length: variant.dimensions.length * 10,
95
106
  width: variant.dimensions.width * 10,