@things-factory/integration-sellercraft 8.0.0-beta.1 → 8.0.0-beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. package/package.json +13 -13
  2. package/server/constants/index.ts +0 -2
  3. package/server/constants/order-status-mapping.ts +0 -28
  4. package/server/constants/platform.ts +0 -6
  5. package/server/controllers/index.ts +0 -5
  6. package/server/controllers/sellercraft/apis/add-inbound-order.ts +0 -50
  7. package/server/controllers/sellercraft/apis/echo.ts +0 -14
  8. package/server/controllers/sellercraft/apis/fetch-order-document.ts +0 -18
  9. package/server/controllers/sellercraft/apis/index.ts +0 -8
  10. package/server/controllers/sellercraft/apis/initiate-order-document.ts +0 -17
  11. package/server/controllers/sellercraft/apis/initiate-order-shipment.ts +0 -29
  12. package/server/controllers/sellercraft/apis/pack-marketplace-order.ts +0 -35
  13. package/server/controllers/sellercraft/apis/update-marketplace-order.ts +0 -14
  14. package/server/controllers/sellercraft/apis/update-product.ts +0 -21
  15. package/server/controllers/sellercraft/index.ts +0 -7
  16. package/server/controllers/sellercraft/platform-action.ts +0 -39
  17. package/server/controllers/sellercraft/sellercraft.ts +0 -109
  18. package/server/controllers/sellercraft-api/decorators.ts +0 -52
  19. package/server/controllers/sellercraft-api/index.ts +0 -51
  20. package/server/controllers/sellercraft-api/types.ts +0 -0
  21. package/server/controllers/sellercraft-channel-integration/apis/echo.ts +0 -14
  22. package/server/controllers/sellercraft-channel-integration/apis/index.ts +0 -6
  23. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-categories.ts +0 -37
  24. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-category-attributes.ts +0 -65
  25. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-order-package.ts +0 -62
  26. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-order.ts +0 -92
  27. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-product.ts +0 -97
  28. package/server/controllers/sellercraft-channel-integration/index.ts +0 -7
  29. package/server/controllers/sellercraft-channel-integration/platform-action.ts +0 -39
  30. package/server/controllers/sellercraft-channel-integration/sellercraft-channel-integration.ts +0 -115
  31. package/server/controllers/sellercraft-channel-integration-api/decorators.ts +0 -45
  32. package/server/controllers/sellercraft-channel-integration-api/index.ts +0 -45
  33. package/server/controllers/sellercraft-channel-integration-api/types.ts +0 -0
  34. package/server/index.ts +0 -7
  35. package/server/middlewares/index.ts +0 -3
  36. package/server/migrations/index.ts +0 -9
  37. package/server/routers/sellercraft-router.ts +0 -326
  38. package/server/routes.ts +0 -32
  39. package/server/service/index.ts +0 -23
  40. package/server/service/marketplace-channel/index.ts +0 -6
  41. package/server/service/marketplace-channel/marketplace-channel-order-mutation.ts +0 -456
  42. package/server/service/marketplace-channel/marketplace-channel-product-mutation.ts +0 -282
  43. package/server/service/marketplace-channel/marketplace-channel.ts +0 -76
  44. package/server/service/sellercraft/index.ts +0 -6
  45. package/server/service/sellercraft/sellercraft-mutation.ts +0 -126
  46. package/server/service/sellercraft/sellercraft-query.ts +0 -43
  47. package/server/service/sellercraft/sellercraft-type.ts +0 -54
  48. package/server/service/sellercraft/sellercraft.ts +0 -96
  49. package/server/utils/tokencraft-util.ts +0 -60
  50. package/tsconfig.json +0 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/integration-sellercraft",
3
- "version": "8.0.0-beta.1",
3
+ "version": "8.0.0-beta.2",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -25,17 +25,17 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@operato/data-grist": "^8.0.0-beta",
28
- "@things-factory/apptool-ui": "^8.0.0-beta.1",
29
- "@things-factory/auth-ui": "^8.0.0-beta.1",
30
- "@things-factory/biz-base": "^8.0.0-beta.1",
31
- "@things-factory/code-ui": "^8.0.0-beta.1",
32
- "@things-factory/context-ui": "^8.0.0-beta.1",
33
- "@things-factory/i18n-base": "^8.0.0-beta.1",
34
- "@things-factory/integration-marketplace": "^8.0.0-beta.1",
35
- "@things-factory/integration-ui": "^8.0.0-beta.1",
36
- "@things-factory/more-ui": "^8.0.0-beta.1",
37
- "@things-factory/resource-ui": "^8.0.0-beta.1",
38
- "@things-factory/setting-ui": "^8.0.0-beta.1",
28
+ "@things-factory/apptool-ui": "^8.0.0-beta.2",
29
+ "@things-factory/auth-ui": "^8.0.0-beta.2",
30
+ "@things-factory/biz-base": "^8.0.0-beta.2",
31
+ "@things-factory/code-ui": "^8.0.0-beta.2",
32
+ "@things-factory/context-ui": "^8.0.0-beta.2",
33
+ "@things-factory/i18n-base": "^8.0.0-beta.2",
34
+ "@things-factory/integration-marketplace": "^8.0.0-beta.2",
35
+ "@things-factory/integration-ui": "^8.0.0-beta.2",
36
+ "@things-factory/more-ui": "^8.0.0-beta.2",
37
+ "@things-factory/resource-ui": "^8.0.0-beta.2",
38
+ "@things-factory/setting-ui": "^8.0.0-beta.2",
39
39
  "debug": "^4.1.1",
40
40
  "node-fetch": "^2.6.0"
41
41
  },
@@ -49,5 +49,5 @@
49
49
  "nock": "^13.0.2",
50
50
  "should": "^13.2.3"
51
51
  },
52
- "gitHead": "36c494e587640c1490318ef7b95adab02606e0c2"
52
+ "gitHead": "f03431a09435511b2595515658f9cb8f78ba4ebb"
53
53
  }
@@ -1,2 +0,0 @@
1
- export * from './platform'
2
- export * from './order-status-mapping'
@@ -1,28 +0,0 @@
1
- export const ORDER_STATUS = {
2
- pending: 'CONFIRMED',
3
- payment_pending: 'PAYMENT_PENDING',
4
- ready_to_ship: 'READY_TO_SHIP',
5
- processing: 'CONFIRMED',
6
- shipped: 'SHIPPED',
7
- completed: 'DELIVERED',
8
- cancelled: 'CANCELLED',
9
- canceled: 'CANCELLED',
10
- refunded: 'REFUND_COMPLETE',
11
- failed: 'SHIPMENT_LOST_OR_DAMAGED',
12
- refund: 'REFUND_COMPLETE',
13
- ttk_100: 'PAYMENT_PENDING', // UNPAID
14
- ttk_111: 'CONFIRMED', // AWAITING_SHIPMENT
15
- ttk_112: 'READY_TO_SHIP', // AWAITING_COLLECTION
16
- ttk_121: 'SHIPPED', // IN_TRANSIT
17
- ttk_122: 'DELIVERED', // DELIVERED
18
- ttk_130: 'CLOSED', // COMPLETED
19
- ttk_140: 'CANCELLED', // CANCELLED
20
- ttk_201: 'INITIATED_CANCELLATION', // CANCEL_PENDING
21
- ttk_202: '', // CANCEL_REJECT
22
- ttk_203: 'CANCELLED' // CANCEL_COMPLETED
23
- }
24
-
25
- export const SHIPPING_TYPE = {
26
- DROP_SHIPPING: 'DROP_SHIPPING',
27
- CROSS_DOCKING_PICKUP: 'CROSS_DOCKING_PICKUP'
28
- }
@@ -1,6 +0,0 @@
1
- export const PLATFORM = {
2
- WCM: 'woocommerce',
3
- MGT: 'magento',
4
- TTK: 'tiktok',
5
- SPF: 'shopify'
6
- }
@@ -1,5 +0,0 @@
1
- import './sellercraft'
2
-
3
- export * from './sellercraft-api'
4
- export * from './sellercraft-channel-integration'
5
- export * from './sellercraft-channel-integration-api'
@@ -1,50 +0,0 @@
1
- /* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY3OTk0Mjg-register-product-inbound */
2
-
3
- export function addInboundOrder() {
4
- return {
5
- method: 'post',
6
- path: '/product/inbound',
7
- denormalize(req) {
8
- const { accountId, inboundId, inboundTime, inboundType, purchaseOrderId, sellercraftOPs } = req
9
-
10
- let orderInformation: any = {}
11
- orderInformation.account_id = accountId
12
- orderInformation.inbound_id = inboundId
13
- orderInformation.inbound_time = inboundTime
14
- orderInformation.inbound_type = inboundType
15
- orderInformation.purchase_order_id = purchaseOrderId
16
-
17
- let products: any[] = sellercraftOPs.map(orderProduct => {
18
- const { packageDimension, forceCreateProduct } = orderProduct
19
- let sellercraftOP: any = {}
20
- sellercraftOP.sku = orderProduct.sku
21
- sellercraftOP.unit_of_measure = orderProduct.uom
22
- sellercraftOP.purchase_order_quantity = orderProduct.purchaseOrderQty
23
- sellercraftOP.received_quantity = orderProduct.receivedQty
24
- sellercraftOP.batch_number = orderProduct.batchId
25
- sellercraftOP.expiry_time = orderProduct?.expiryTime ? orderProduct.expiryTime : 0
26
- sellercraftOP.force_create_product = forceCreateProduct
27
- sellercraftOP.product_name = orderProduct.productName
28
- sellercraftOP.gtin = orderProduct.gtin
29
- sellercraftOP.package_weight_gm = orderProduct.weight
30
- sellercraftOP.package_dimensions = {
31
- length_mm: packageDimension.length,
32
- width_mm: packageDimension.width,
33
- height_mm: packageDimension.height
34
- }
35
-
36
- return sellercraftOP
37
- })
38
-
39
- return {
40
- payload: {
41
- ...orderInformation,
42
- products
43
- }
44
- }
45
- },
46
- normalize(res) {
47
- return res
48
- }
49
- }
50
- }
@@ -1,14 +0,0 @@
1
- export function echo() {
2
- return {
3
- path: '/echo',
4
- denormalize(req) {
5
- return { ...req }
6
- },
7
- normalize(res) {
8
- return { ...res }
9
- },
10
- action({ store, method, path, request, platformAction }) {
11
- return { ...request }
12
- }
13
- }
14
- }
@@ -1,18 +0,0 @@
1
- /* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY4ODQxNTc-fetch-order-documents */
2
-
3
- export function fetchOrderDocument() {
4
- return {
5
- method: 'get',
6
- path: '/order/documents',
7
- denormalize(req) {
8
- const { accountId: account_id, orderId: order_id, packageId: package_id } = req
9
- return {
10
- payload: { account_id, order_id, package_id }
11
- }
12
- },
13
- normalize(res) {
14
- const { documents, tracking_no: trackingNo, shipper_name: transporter } = res.data
15
- return { documents, trackingNo, transporter }
16
- }
17
- }
18
- }
@@ -1,8 +0,0 @@
1
- export * from './echo'
2
- export * from './add-inbound-order'
3
- export * from './fetch-order-document'
4
- export * from './initiate-order-document'
5
- export * from './initiate-order-shipment'
6
- export * from './pack-marketplace-order'
7
- export * from './update-marketplace-order'
8
- export * from './update-product'
@@ -1,17 +0,0 @@
1
- /* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY4ODAzMjg-initiate-order-documents */
2
-
3
- export function initiateOrderDocument() {
4
- return {
5
- method: 'post',
6
- path: '/order/documents',
7
- denormalize(req) {
8
- const { accountId: account_id, orderId: order_id, packageId: package_id } = req
9
- return {
10
- payload: { account_id, order_id, package_id }
11
- }
12
- },
13
- normalize(res) {
14
- return res
15
- }
16
- }
17
- }
@@ -1,29 +0,0 @@
1
- /* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY4NjQxODU-initiate-order-shipment */
2
-
3
- export function initiateOrderShipment() {
4
- return {
5
- method: 'post',
6
- path: '/order/ship',
7
- denormalize(req) {
8
- const { accountId: account_id, orderId: order_id, packageId: package_id } = req
9
- return {
10
- payload: { account_id, order_id, package_id }
11
- }
12
- },
13
- normalize(res) {
14
- const {
15
- handover_type: handOverType,
16
- pickup_time: pickupTime,
17
- pickup_address: pickupAddress,
18
- dropoff_address: dropoffAddress
19
- } = res.data
20
-
21
- return {
22
- handOverType,
23
- pickupTime,
24
- pickupAddress,
25
- dropoffAddress
26
- }
27
- }
28
- }
29
- }
@@ -1,35 +0,0 @@
1
- /* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY4NTc0NjI-pack-an-order */
2
-
3
- export function packMarketplaceOrder() {
4
- return {
5
- method: 'post',
6
- path: '/order/pack',
7
- denormalize(req) {
8
- const { accountId: account_id, orderId: order_id, sellercraftOPs } = req
9
-
10
- const items: any[] = sellercraftOPs.map(orderProduct => {
11
- return {
12
- sku: orderProduct.sku,
13
- quantity: orderProduct.releaseQty,
14
- unit_of_measure: orderProduct.uom
15
- }
16
- })
17
-
18
- let packages: any[] = []
19
- packages.push({ items })
20
-
21
- return {
22
- payload: {
23
- account_id,
24
- order_id,
25
- packages
26
- }
27
- }
28
- },
29
- normalize(res) {
30
- const { packages } = res.data
31
- const packageId: string = packages[0].package_id
32
- return packageId
33
- }
34
- }
35
- }
@@ -1,14 +0,0 @@
1
- /* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY4OTA0NDM-amend-an-order */
2
-
3
- export function updateMarketplaceOrder() {
4
- return {
5
- method: 'put',
6
- path: '/order',
7
- denormalize(req) {
8
- return req
9
- },
10
- normalize(res) {
11
- return res
12
- }
13
- }
14
- }
@@ -1,21 +0,0 @@
1
- /* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY4OTE3MTA-update-product */
2
-
3
- export function updateProduct() {
4
- return {
5
- method: 'put',
6
- path: '/product',
7
- denormalize(req) {
8
- const { accountId, sellercraftInv } = req
9
-
10
- return {
11
- payload: {
12
- account_id: accountId,
13
- products: sellercraftInv
14
- }
15
- }
16
- },
17
- normalize(res) {
18
- return res
19
- }
20
- }
21
- }
@@ -1,7 +0,0 @@
1
- import { SellercraftAPI } from '../sellercraft-api'
2
- import * as APIS from './apis'
3
- import { action } from './platform-action'
4
-
5
- export * from './sellercraft'
6
-
7
- SellercraftAPI.registerPlatform('sellercraft', action, APIS)
@@ -1,39 +0,0 @@
1
- import { config } from '@things-factory/env'
2
-
3
- import { Sellercraft } from './sellercraft'
4
-
5
- const sellercraftConfig = config.get('sellercraftIntegrationConfig', {})
6
- const { apiKey } = sellercraftConfig
7
-
8
- function substitute(path, obj) {
9
- var props = []
10
- var re = /{([^}]+)}/g
11
- var text
12
-
13
- while ((text = re.exec(path))) {
14
- props.push(text[1])
15
- }
16
-
17
- var result = path
18
- props.forEach(prop => {
19
- let value = obj[prop.trim()]
20
- result = result.replace(`{${prop}}`, value === undefined ? '' : value)
21
- })
22
-
23
- return result
24
- }
25
-
26
- export const action = async ({ method = 'get', path, request }) => {
27
- const client = new Sellercraft({ apiKey })
28
-
29
- const { resource = {}, payload = {} } = request
30
-
31
- path = substitute(path, resource)
32
-
33
- var response = await client[method](path, payload)
34
- if (response.errors) {
35
- throw response
36
- }
37
-
38
- return response
39
- }
@@ -1,109 +0,0 @@
1
- import fetch from 'node-fetch'
2
- import { v4 as uuidv4 } from 'uuid'
3
-
4
- const debug = require('debug')('things-factory:integration-sellercraft:sellercraft')
5
-
6
- export type SellercraftConfig = {
7
- apiKey: string
8
- }
9
-
10
- export class Sellercraft {
11
- private config: SellercraftConfig
12
-
13
- constructor(config: SellercraftConfig) {
14
- this.config = {
15
- ...config
16
- }
17
- }
18
-
19
- getBaseUrl() {
20
- return `https://open.sellercraft.co/v1`
21
- }
22
-
23
- generateRequestId() {
24
- return uuidv4()
25
- }
26
-
27
- async post(path: string, data: any = {}) {
28
- const { apiKey } = this.config
29
-
30
- debug('data', data)
31
-
32
- const jsondata = JSON.stringify(data)
33
- const requestId: string = this.generateRequestId()
34
- const fullPath: string = `${this.getBaseUrl()}${path}`
35
-
36
- const response: any = await fetch(fullPath, {
37
- method: 'post',
38
- headers: {
39
- 'Content-Type': 'application/json',
40
- request_id: requestId,
41
- 'x-api-key': apiKey
42
- },
43
- body: jsondata
44
- })
45
-
46
- if (response.ok) {
47
- return await response.json()
48
- } else {
49
- const result = await response.text()
50
- throw new Error(`(${response.status}) ${result}`)
51
- }
52
- }
53
-
54
- async put(path: string, data: any = {}) {
55
- const { apiKey } = this.config
56
-
57
- const jsondata = JSON.stringify(data)
58
- const requestId: string = this.generateRequestId()
59
- const fullPath: string = `${this.getBaseUrl()}${path}`
60
- debug('data', data)
61
-
62
- const response: any = await fetch(fullPath, {
63
- method: 'put',
64
- headers: {
65
- 'Content-Type': 'application/json',
66
- request_id: requestId,
67
- 'x-api-key': apiKey
68
- },
69
- body: jsondata
70
- })
71
-
72
- if (response.ok) {
73
- return await response.json()
74
- } else {
75
- const result = await response.text()
76
- throw new Error(`(${response.status}) ${result}`)
77
- }
78
- }
79
-
80
- async get(path: string, data: any = {}) {
81
- const { apiKey } = this.config
82
-
83
- const qs = Object.entries(data)
84
- .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`)
85
- .join('&')
86
-
87
- const fullPath: string = `${this.getBaseUrl()}${path}`
88
- const endpoint = `${fullPath}${qs ? '?' + qs : ''}`
89
- debug('endpoint', endpoint)
90
-
91
- const requestId: string = this.generateRequestId()
92
-
93
- const response: any = await fetch(endpoint, {
94
- method: 'get',
95
- headers: {
96
- 'Content-Type': 'application/json',
97
- request_id: requestId,
98
- 'x-api-key': apiKey
99
- }
100
- })
101
-
102
- if (response.ok) {
103
- return await response.json()
104
- } else {
105
- const result = await response.text()
106
- throw new Error(`(${response.status}) ${result}`)
107
- }
108
- }
109
- }
@@ -1,52 +0,0 @@
1
- import Debug from 'debug'
2
- const debug = Debug('things-factory:integration-marketplace:store-api-decorator')
3
-
4
- import { Sellercraft } from '../../service'
5
- import { createPayloadLog } from '@things-factory/integration-base'
6
-
7
- const NOOP = v => v
8
-
9
- export const api = (target: Object, property: string, descriptor: TypedPropertyDescriptor<any>): any => {
10
- const method = descriptor.value
11
-
12
- descriptor.value = async function (store: Sellercraft, request) {
13
- const SellercraftAPI = this
14
-
15
- var { platform } = store
16
-
17
- var { action: platformAction, apis } = SellercraftAPI.getPlatform(platform)
18
-
19
- var m = apis[method.name]
20
- if (!m) {
21
- throw Error(`Sellercraft doesn't have API ${method.name}`)
22
- }
23
-
24
- var {
25
- path,
26
- method: httpMethod = 'post',
27
- denormalize = NOOP,
28
- normalize = NOOP,
29
- action = platformAction
30
- } = m.apply(this, [request])
31
-
32
- var denormalized = await denormalize(request || {}, { store })
33
- debug('request', denormalized)
34
-
35
- try {
36
- var response = await action.apply(this, [
37
- { store, method: httpMethod, path, request: denormalized, platformAction }
38
- ])
39
-
40
- createPayloadLog(store.accountId, path, denormalized, response, request?.context)
41
-
42
- debug('response', response)
43
-
44
- return await normalize(response, { store })
45
- } catch (error) {
46
- createPayloadLog(store.accountId, path, denormalized, error, request?.context)
47
- throw error
48
- }
49
- }
50
-
51
- return descriptor
52
- }
@@ -1,51 +0,0 @@
1
- import { getRepository } from '@things-factory/shell'
2
-
3
- import { Sellercraft } from '../../service'
4
- import { api } from './decorators'
5
-
6
- export class SellercraftAPI {
7
- static platforms = {}
8
-
9
- static registerPlatform(name, action, apis) {
10
- SellercraftAPI.platforms[name] = {
11
- action,
12
- apis
13
- }
14
- }
15
-
16
- static getPlatform(name) {
17
- return SellercraftAPI.platforms[name]
18
- }
19
-
20
- static async getSellercraft(id) {
21
- const repository = getRepository(Sellercraft)
22
- return await repository.findOne({
23
- where: { id },
24
- relations: ['domain']
25
- })
26
- }
27
-
28
- @api
29
- static echo(sellercraft, req): any {}
30
-
31
- @api
32
- static addInboundOrder(sellercraft, req): any {}
33
-
34
- @api
35
- static fetchOrderDocument(sellercraft, req): any {}
36
-
37
- @api
38
- static initiateOrderDocument(sellercraft, req): any {}
39
-
40
- @api
41
- static initiateOrderShipment(sellercraft, req): any {}
42
-
43
- @api
44
- static packMarketplaceOrder(sellercraft, req): any {}
45
-
46
- @api
47
- static updateMarketplaceOrder(sellercraft, req): any {}
48
-
49
- @api
50
- static updateProduct(sellercraft, req): any {}
51
- }
File without changes
@@ -1,14 +0,0 @@
1
- export function echo() {
2
- return {
3
- path: '/echo',
4
- denormalize(req) {
5
- return { ...req }
6
- },
7
- normalize(res) {
8
- return { ...res }
9
- },
10
- action({ store, method, path, request, platformAction }) {
11
- return { ...request }
12
- }
13
- }
14
- }
@@ -1,6 +0,0 @@
1
- export * from './echo'
2
- export * from './ingest-channel-categories'
3
- export * from './ingest-channel-category-attributes'
4
- export * from './ingest-channel-order-package'
5
- export * from './ingest-channel-order'
6
- export * from './ingest-channel-product'
@@ -1,37 +0,0 @@
1
- /* https://docs.sellercraft.co/docs/api-integrations/b3A6MTY4NjQxODU-initiate-order-shipment */
2
-
3
- export function ingestChannelCategories() {
4
- return {
5
- method: 'post',
6
- path: '/channel/ingest/category',
7
- denormalize(req) {
8
- const { categories } = req
9
-
10
- let newCategories = mapCategories(categories)
11
-
12
- return {
13
- payload: [...newCategories]
14
- }
15
- },
16
- normalize(res) {
17
- return res
18
- }
19
- }
20
- }
21
-
22
- function mapCategories(categories) {
23
- if (!categories) return null
24
- categories = categories.map(category => {
25
- let children_categories = mapCategories(category.childrenCategories)
26
- return {
27
- native_category_id: category.categoryId.toString(),
28
- channel_code: category.channelCode,
29
- channel_country: category.countryCode,
30
- category_name: category.categoryName,
31
- is_leaf: children_categories.length == 0 ? true : false,
32
- is_active: category.isActive,
33
- children_categories
34
- }
35
- })
36
- return categories
37
- }