@things-factory/integration-sftp 8.0.0-beta.0 → 8.0.0-beta.2
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.
- package/package.json +7 -7
- package/server/controllers/herbalife/apis/create-serial-number.ts +0 -51
- package/server/controllers/herbalife/apis/create-shipment.ts +0 -88
- package/server/controllers/herbalife/apis/echo.ts +0 -14
- package/server/controllers/herbalife/apis/get-outbound-order.ts +0 -119
- package/server/controllers/herbalife/apis/index.ts +0 -4
- package/server/controllers/herbalife/herbalife.ts +0 -53
- package/server/controllers/herbalife/index.ts +0 -7
- package/server/controllers/herbalife/platform-action.ts +0 -34
- package/server/controllers/index.ts +0 -3
- package/server/controllers/sftp-api/decorators.ts +0 -43
- package/server/controllers/sftp-api/index.ts +0 -39
- package/server/controllers/sftp-api/types.ts +0 -0
- package/server/index.ts +0 -7
- package/server/middlewares/index.ts +0 -3
- package/server/routes.ts +0 -28
- package/server/service/index.ts +0 -18
- package/server/service/sftp/index.ts +0 -6
- package/server/service/sftp/sftp-mutation.ts +0 -241
- package/server/service/sftp/sftp-query.ts +0 -44
- package/server/service/sftp/sftp-type.ts +0 -78
- package/server/service/sftp/sftp.ts +0 -143
- package/server/sftp-const.ts +0 -13
- package/server/sftp-s3.ts +0 -92
- package/server/util/generate-files.ts +0 -33
- package/server/util/get-permitted-directories.ts +0 -15
- package/server/util/index.ts +0 -2
- package/tsconfig.json +0 -9
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@things-factory/integration-sftp",
|
3
|
-
"version": "8.0.0-beta.
|
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,
|
@@ -24,13 +24,13 @@
|
|
24
24
|
"migration:create": "node ../../node_modules/typeorm/cli.js migration:create ./server/migrations/migration"
|
25
25
|
},
|
26
26
|
"dependencies": {
|
27
|
-
"@things-factory/auth-base": "^8.0.0-beta.
|
28
|
-
"@things-factory/biz-base": "^8.0.0-beta.
|
29
|
-
"@things-factory/env": "^8.0.0-beta.
|
30
|
-
"@things-factory/integration-fulfillment": "^8.0.0-beta.
|
31
|
-
"@things-factory/shell": "^8.0.0-beta.
|
27
|
+
"@things-factory/auth-base": "^8.0.0-beta.2",
|
28
|
+
"@things-factory/biz-base": "^8.0.0-beta.2",
|
29
|
+
"@things-factory/env": "^8.0.0-beta.2",
|
30
|
+
"@things-factory/integration-fulfillment": "^8.0.0-beta.2",
|
31
|
+
"@things-factory/shell": "^8.0.0-beta.2",
|
32
32
|
"aws-sdk": "^2.960.0",
|
33
33
|
"xml-js": "^1.6.11"
|
34
34
|
},
|
35
|
-
"gitHead": "
|
35
|
+
"gitHead": "f03431a09435511b2595515658f9cb8f78ba4ebb"
|
36
36
|
}
|
@@ -1,51 +0,0 @@
|
|
1
|
-
import { BACKUPPATH, SNSUBMITDATAPATH } from '../../../sftp-const'
|
2
|
-
|
3
|
-
export function createSerialNumber() {
|
4
|
-
return {
|
5
|
-
method: 'post',
|
6
|
-
path: '{folderPath}/{folderType}{snPath}',
|
7
|
-
denormalize(req) {
|
8
|
-
let { releaseGood, inventoryItems, sftp } = req
|
9
|
-
let { folderPath, platform } = sftp
|
10
|
-
const folderType: string = sftp.isDevelopment ? `dev` : `prd`
|
11
|
-
const snPath: string = SNSUBMITDATAPATH
|
12
|
-
const backupPath: string = `${BACKUPPATH}${platform}/${folderType}`
|
13
|
-
|
14
|
-
let responseFilePattern: any = JSON.parse(sftp.responseFilePattern)
|
15
|
-
const { snSuffix, fileExtension, snRunningNumberDigit, snSequence } = responseFilePattern
|
16
|
-
let newSeq: number = parseFloat(snSequence) + 1
|
17
|
-
let newSequence = newSeq.toString().padStart(snRunningNumberDigit, '0')
|
18
|
-
let newResponseFilePattern: string = JSON.stringify({
|
19
|
-
...responseFilePattern,
|
20
|
-
snSequence: newSeq.toString()
|
21
|
-
})
|
22
|
-
sftp = { ...sftp, responseFilePattern: newResponseFilePattern }
|
23
|
-
|
24
|
-
const today = new Date()
|
25
|
-
const year = today.getFullYear().toString()
|
26
|
-
const month = (today.getMonth() + 1).toString().padStart(2, '0')
|
27
|
-
const day = today.getDate().toString().padStart(2, '0')
|
28
|
-
const newDate = day + month + year
|
29
|
-
|
30
|
-
let title: string = snSuffix ? snSuffix : ``
|
31
|
-
title += `_` + newDate
|
32
|
-
title += `_` + newSequence
|
33
|
-
title += fileExtension ? `.` + fileExtension : ``
|
34
|
-
|
35
|
-
let content: string = ''
|
36
|
-
const orderNo: string = releaseGood.refNo
|
37
|
-
for (let i = 0; i < inventoryItems.length; i++) {
|
38
|
-
let serialNumber: string = inventoryItems[i].serialNumber
|
39
|
-
content += orderNo + '|' + serialNumber + '\n'
|
40
|
-
}
|
41
|
-
|
42
|
-
return {
|
43
|
-
resource: { folderPath, folderType, snPath },
|
44
|
-
payload: { title, content, sftp, backupPath }
|
45
|
-
}
|
46
|
-
},
|
47
|
-
normalize(res) {
|
48
|
-
return res
|
49
|
-
}
|
50
|
-
}
|
51
|
-
}
|
@@ -1,88 +0,0 @@
|
|
1
|
-
import { BACKUPPATH, COMPLETEDATAPATH } from '../../../sftp-const'
|
2
|
-
|
3
|
-
export function createShipment() {
|
4
|
-
return {
|
5
|
-
method: 'post',
|
6
|
-
path: '{folderPath}/{folderType}{shipmentCompletePath}',
|
7
|
-
denormalize(req) {
|
8
|
-
let { releaseGoods, sftp } = req
|
9
|
-
let { folderPath, platform } = sftp
|
10
|
-
const folderType: string = sftp.isDevelopment ? `dev` : `prd`
|
11
|
-
const shipmentCompletePath: string = COMPLETEDATAPATH
|
12
|
-
const backupPath: string = `${BACKUPPATH}${platform}/${folderType}`
|
13
|
-
|
14
|
-
let responseFilePattern: any = JSON.parse(sftp.responseFilePattern)
|
15
|
-
const { suffix, fileExtension, runningNumberDigit, sequence } = responseFilePattern
|
16
|
-
let newSeq: number = parseFloat(sequence) + 1
|
17
|
-
let newSequence = newSeq.toString().padStart(runningNumberDigit, '0')
|
18
|
-
let newResponseFilePattern: string = JSON.stringify({
|
19
|
-
...responseFilePattern,
|
20
|
-
sequence: newSeq.toString()
|
21
|
-
})
|
22
|
-
sftp = { ...sftp, responseFilePattern: newResponseFilePattern }
|
23
|
-
|
24
|
-
const warehouseNumber: string = releaseGoods[0].refNo2
|
25
|
-
let title: string = suffix ? suffix : ``
|
26
|
-
title += newSequence
|
27
|
-
title += warehouseNumber ? `_` + warehouseNumber : ``
|
28
|
-
title += fileExtension ? `.` + fileExtension : ``
|
29
|
-
|
30
|
-
let backupTitle: string = releaseGoods[0].refNo + '_' + title
|
31
|
-
const orderNoColumn: number = 15
|
32
|
-
const shipmentColumn: number = 27
|
33
|
-
const trackingNoColumn: number = 20
|
34
|
-
let bulkContent = ''
|
35
|
-
for (let releaseGood of releaseGoods) {
|
36
|
-
const refNoLength: number = releaseGood.refNo.length
|
37
|
-
let content: string = `1710` + releaseGood.refNo
|
38
|
-
let spaceNeeded: number = orderNoColumn - refNoLength
|
39
|
-
for (let i = 0; i < spaceNeeded; i++) {
|
40
|
-
content += ` `
|
41
|
-
}
|
42
|
-
content += warehouseNumber
|
43
|
-
content += `001000001`
|
44
|
-
for (let i = 0; i < shipmentColumn; i++) {
|
45
|
-
content += ` `
|
46
|
-
}
|
47
|
-
content += `000000 `
|
48
|
-
for (let i = 0; i < trackingNoColumn; i++) {
|
49
|
-
content += ` `
|
50
|
-
}
|
51
|
-
content += `000000000000 `
|
52
|
-
const today = new Date()
|
53
|
-
const year = today.getFullYear().toString()
|
54
|
-
const month = (today.getMonth() + 1).toString().padStart(2, '0')
|
55
|
-
const day = today.getDate().toString().padStart(2, '0')
|
56
|
-
const newDate = year + month + day
|
57
|
-
content += newDate + '\n'
|
58
|
-
|
59
|
-
for (let i = 0; i < releaseGood.orderInventories.length; i++) {
|
60
|
-
const orderInventory: any = releaseGood.orderInventories[i]
|
61
|
-
let sku: string = orderInventory.product.brandSku
|
62
|
-
content += `1810` + releaseGood.refNo
|
63
|
-
for (let i = 0; i < spaceNeeded; i++) {
|
64
|
-
content += ` `
|
65
|
-
}
|
66
|
-
const idx = (i + 1).toString().padStart(2, '0')
|
67
|
-
const productCode: string = sku.substring(0, 4)
|
68
|
-
content += idx + `000000` + productCode
|
69
|
-
let productCodeSpaceNeeded = 7 - productCode.length
|
70
|
-
for (let i = 0; i < productCodeSpaceNeeded; i++) {
|
71
|
-
content += ` `
|
72
|
-
}
|
73
|
-
const orderedQty = orderInventory.releaseQty.toString().padStart(4, '0')
|
74
|
-
const pickedQty = orderInventory.pickedQty.toString().padStart(4, '0')
|
75
|
-
content += orderedQty + pickedQty + '\n'
|
76
|
-
}
|
77
|
-
bulkContent += content
|
78
|
-
}
|
79
|
-
return {
|
80
|
-
resource: { folderPath, folderType, shipmentCompletePath },
|
81
|
-
payload: { title, backupTitle, content: bulkContent, sftp, backupPath }
|
82
|
-
}
|
83
|
-
},
|
84
|
-
normalize(res) {
|
85
|
-
return res
|
86
|
-
}
|
87
|
-
}
|
88
|
-
}
|
@@ -1,119 +0,0 @@
|
|
1
|
-
export function getOutboundOrder() {
|
2
|
-
return {
|
3
|
-
method: 'get',
|
4
|
-
path: '{folderPath}/{folderType}/sob/data/{fileKey}',
|
5
|
-
denormalize(req) {
|
6
|
-
const { folderPath, folderType, fileKey } = req
|
7
|
-
return {
|
8
|
-
resource: { folderPath, folderType, fileKey }
|
9
|
-
}
|
10
|
-
},
|
11
|
-
normalize(res, { sftp }) {
|
12
|
-
const { Order } = res
|
13
|
-
let isAccept: boolean = false
|
14
|
-
|
15
|
-
const responseFilePattern = JSON.parse(sftp.responseFilePattern)
|
16
|
-
const acceptOrderTypes = responseFilePattern.acceptOrderTypes // ['RSO', 'MSO', 'MSBO']
|
17
|
-
const acceptNTSStatuses = responseFilePattern.acceptNTSStatuses //['', 'BACKORDER']
|
18
|
-
const acceptWarehouseNumber = responseFilePattern.acceptWarehouseNumber //['NK']
|
19
|
-
const acceptCommand = responseFilePattern.acceptCommand //['NTS', '']
|
20
|
-
const acceptFreightCode = responseFilePattern.acceptFreightCode // ['PU']
|
21
|
-
|
22
|
-
let orderHeader: any = Order.OrderHeader
|
23
|
-
let generalInfo: any = orderHeader.General
|
24
|
-
let distributorDetails: any = orderHeader.DistributorDetails
|
25
|
-
let shippingInstructions: any = Order.ShippingInstructions
|
26
|
-
|
27
|
-
let orderType: string = generalInfo.OrderType._text
|
28
|
-
let ntsStatus: string = generalInfo.NTSStatus._text || ''
|
29
|
-
let command: string = generalInfo.Command._text || ''
|
30
|
-
let warehouseNumber: string = generalInfo.WarehouseNumber._text
|
31
|
-
let freightCode: string = shippingInstructions.FreightCode._text
|
32
|
-
|
33
|
-
if (
|
34
|
-
acceptWarehouseNumber.includes(warehouseNumber) &&
|
35
|
-
acceptOrderTypes.includes(orderType) &&
|
36
|
-
acceptNTSStatuses.includes(ntsStatus) &&
|
37
|
-
acceptCommand.includes(command) &&
|
38
|
-
acceptFreightCode.includes(freightCode)
|
39
|
-
) {
|
40
|
-
isAccept = true
|
41
|
-
}
|
42
|
-
|
43
|
-
let shippingInstruction: string = shippingInstructions.ShippingInstructions._text
|
44
|
-
let ntsDateParts = generalInfo.NTS_Date._text.split('/')
|
45
|
-
let releaseDate: string = ntsDateParts[2] + '-' + ntsDateParts[1] + '-' + ntsDateParts[0]
|
46
|
-
let orderInfo: any = {
|
47
|
-
refNo: generalInfo.OrderNumber._text,
|
48
|
-
refNo2: warehouseNumber,
|
49
|
-
type: 'b2b',
|
50
|
-
releaseDate,
|
51
|
-
collectionOrderNo: generalInfo.OrderNumber._text,
|
52
|
-
marketplaceOrderStatus: ntsStatus,
|
53
|
-
ownTransport: true,
|
54
|
-
exportOption: false,
|
55
|
-
packingOption: false,
|
56
|
-
remark: shippingInstruction,
|
57
|
-
billTo: {
|
58
|
-
billingAddress: distributorDetails.BillTo.BillToAddress._text
|
59
|
-
},
|
60
|
-
deliverTo: {
|
61
|
-
deliveryAddress1: distributorDetails.ShipTo.Address1._text,
|
62
|
-
deliveryAddress2: distributorDetails.ShipTo.Address2._text,
|
63
|
-
deliveryAddress3: distributorDetails.ShipTo.Address3._text,
|
64
|
-
attentionTo: distributorDetails.ShipTo.Name._text,
|
65
|
-
city: distributorDetails.ShipTo.City._text,
|
66
|
-
state: distributorDetails.ShipTo.ShipToState._text,
|
67
|
-
postalCode: distributorDetails.ShipTo.Zipcode._text,
|
68
|
-
country: distributorDetails.ShipTo.Country._text,
|
69
|
-
phone1: distributorDetails.ShipTo.Phone._text
|
70
|
-
}
|
71
|
-
}
|
72
|
-
|
73
|
-
let OrderLine = Order.PickList
|
74
|
-
let totalItems: number = parseFloat(Order.PickList.LinesInPickList._text)
|
75
|
-
let itemsToPick: any[] = []
|
76
|
-
let checkDuplicationValidation
|
77
|
-
if (totalItems == 1) {
|
78
|
-
if (parseFloat(OrderLine.Item.QuantityReleased._text) > 0) {
|
79
|
-
itemsToPick.push({
|
80
|
-
product: {
|
81
|
-
sku: OrderLine.Item.StockingSKU._text
|
82
|
-
},
|
83
|
-
releaseQty: parseFloat(OrderLine.Item.QuantityReleased._text)
|
84
|
-
})
|
85
|
-
}
|
86
|
-
} else {
|
87
|
-
OrderLine.Item.map(line => {
|
88
|
-
if (parseFloat(line.QuantityReleased._text) > 0) {
|
89
|
-
itemsToPick.push({
|
90
|
-
product: {
|
91
|
-
sku: line.StockingSKU._text
|
92
|
-
},
|
93
|
-
releaseQty: parseFloat(line.QuantityReleased._text)
|
94
|
-
})
|
95
|
-
}
|
96
|
-
})
|
97
|
-
}
|
98
|
-
|
99
|
-
if (ntsStatus == 'BACKORDER' && OrderLine.Item.some(itm => itm.QuantityReleased._text == 0)) {
|
100
|
-
checkDuplicationValidation = false
|
101
|
-
}
|
102
|
-
|
103
|
-
if (itemsToPick.length == 0) {
|
104
|
-
isAccept = false
|
105
|
-
}
|
106
|
-
|
107
|
-
let orderItems: any[] = itemsToPick
|
108
|
-
|
109
|
-
let result: any = {
|
110
|
-
...orderInfo,
|
111
|
-
orderInventories: orderItems,
|
112
|
-
isAccept,
|
113
|
-
checkDuplicationValidation
|
114
|
-
}
|
115
|
-
|
116
|
-
return result
|
117
|
-
}
|
118
|
-
}
|
119
|
-
}
|
@@ -1,53 +0,0 @@
|
|
1
|
-
import '../../sftp-s3'
|
2
|
-
|
3
|
-
import { xml2js } from 'xml-js'
|
4
|
-
|
5
|
-
import { Sftp } from '../../service'
|
6
|
-
import { SFTPFILESTORAGE } from '../../sftp-const'
|
7
|
-
import { generateFiles } from '../../util/generate-files'
|
8
|
-
|
9
|
-
const debug = require('debug')('things-factory:integration-sftp:herbalife')
|
10
|
-
|
11
|
-
export type HerbalifeConfig = {}
|
12
|
-
|
13
|
-
export class Herbalife {
|
14
|
-
constructor() {}
|
15
|
-
|
16
|
-
async get(path: string, data: any = {}) {
|
17
|
-
const fileResult: any = await SFTPFILESTORAGE.readFile(path, 'utf-8')
|
18
|
-
const item: any = xml2js(fileResult, {
|
19
|
-
compact: true
|
20
|
-
})
|
21
|
-
const result: any = { ...item }
|
22
|
-
return result
|
23
|
-
}
|
24
|
-
|
25
|
-
async post(path: string, data: any = {}) {
|
26
|
-
const {
|
27
|
-
title,
|
28
|
-
backupTitle,
|
29
|
-
content,
|
30
|
-
sftp,
|
31
|
-
backupPath
|
32
|
-
}: { title: string; backupTitle: string; content: string; sftp: Sftp; backupPath: string } = data
|
33
|
-
|
34
|
-
let params: any[] = [
|
35
|
-
{
|
36
|
-
title,
|
37
|
-
uploadPath: path,
|
38
|
-
content
|
39
|
-
}
|
40
|
-
]
|
41
|
-
|
42
|
-
if (backupPath) {
|
43
|
-
params.push({
|
44
|
-
title: backupTitle,
|
45
|
-
uploadPath: backupPath,
|
46
|
-
content
|
47
|
-
})
|
48
|
-
}
|
49
|
-
await generateFiles(params)
|
50
|
-
|
51
|
-
return sftp
|
52
|
-
}
|
53
|
-
}
|
@@ -1,34 +0,0 @@
|
|
1
|
-
import { Herbalife } from './herbalife'
|
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
|
-
export const action = async ({ method = 'get', path, request }) => {
|
22
|
-
const client = new Herbalife()
|
23
|
-
|
24
|
-
const { resource = {}, payload = {} } = request
|
25
|
-
|
26
|
-
path = substitute(path, resource)
|
27
|
-
|
28
|
-
var response = await client[method](path, payload)
|
29
|
-
if (response.errors) {
|
30
|
-
throw response
|
31
|
-
}
|
32
|
-
|
33
|
-
return response
|
34
|
-
}
|
@@ -1,43 +0,0 @@
|
|
1
|
-
import Debug from 'debug'
|
2
|
-
|
3
|
-
import { Sftp } from '../../service'
|
4
|
-
|
5
|
-
const debug = Debug('things-factory:integration-sftp:sftp-api-decorator')
|
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 (sftp: Sftp, request) {
|
13
|
-
const SftpAPI = this
|
14
|
-
|
15
|
-
var { platform } = sftp
|
16
|
-
|
17
|
-
var { action: platformAction, apis } = SftpAPI.getPlatform(platform)
|
18
|
-
|
19
|
-
var m = apis[method.name]
|
20
|
-
if (!m) {
|
21
|
-
throw Error(`SFTP 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 || {}, { sftp })
|
33
|
-
debug('request', denormalized)
|
34
|
-
|
35
|
-
var response = await action.apply(this, [{ sftp, method: httpMethod, path, request: denormalized, platformAction }])
|
36
|
-
|
37
|
-
debug('response', response)
|
38
|
-
|
39
|
-
return await normalize(response, { sftp })
|
40
|
-
}
|
41
|
-
|
42
|
-
return descriptor
|
43
|
-
}
|
@@ -1,39 +0,0 @@
|
|
1
|
-
import { getRepository } from '@things-factory/shell'
|
2
|
-
|
3
|
-
import { Sftp } from '../../service'
|
4
|
-
import { api } from './decorators'
|
5
|
-
|
6
|
-
export class SftpAPI {
|
7
|
-
static platforms = {}
|
8
|
-
|
9
|
-
static registerPlatform(name, action, apis) {
|
10
|
-
SftpAPI.platforms[name] = {
|
11
|
-
action,
|
12
|
-
apis
|
13
|
-
}
|
14
|
-
}
|
15
|
-
|
16
|
-
static getPlatform(name) {
|
17
|
-
return SftpAPI.platforms[name]
|
18
|
-
}
|
19
|
-
|
20
|
-
static async getSftp(id) {
|
21
|
-
const repository = getRepository(Sftp)
|
22
|
-
return await repository.findOne({
|
23
|
-
where: { id },
|
24
|
-
relations: ['domain']
|
25
|
-
})
|
26
|
-
}
|
27
|
-
|
28
|
-
@api
|
29
|
-
static echo(sftp, req): any {}
|
30
|
-
|
31
|
-
@api
|
32
|
-
static getOutboundOrder(sftp, req): any {}
|
33
|
-
|
34
|
-
@api
|
35
|
-
static createShipment(sftp, req): any {}
|
36
|
-
|
37
|
-
@api
|
38
|
-
static createSerialNumber(sftp, req): any {}
|
39
|
-
}
|
File without changes
|
package/server/index.ts
DELETED
package/server/routes.ts
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
const debug = require('debug')('things-factory:integration-sftp:routes')
|
2
|
-
|
3
|
-
process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
|
4
|
-
/*
|
5
|
-
* can add global public routes to application (auth not required, tenancy not required)
|
6
|
-
*
|
7
|
-
* ex) routes.get('/path', async(context, next) => {})
|
8
|
-
* ex) routes.post('/path', async(context, next) => {})
|
9
|
-
*/
|
10
|
-
})
|
11
|
-
|
12
|
-
process.on('bootstrap-module-global-private-route' as any, (app, globalPrivateRouter) => {
|
13
|
-
/*
|
14
|
-
* can add global private routes to application (auth required, tenancy not required)
|
15
|
-
*/
|
16
|
-
})
|
17
|
-
|
18
|
-
process.on('bootstrap-module-domain-public-route' as any, (app, domainPublicRouter) => {
|
19
|
-
/*
|
20
|
-
* can add domain public routes to application (auth not required, tenancy required)
|
21
|
-
*/
|
22
|
-
})
|
23
|
-
|
24
|
-
process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRouter) => {
|
25
|
-
/*
|
26
|
-
* can add domain private routes to application (auth required, tenancy required)
|
27
|
-
*/
|
28
|
-
})
|
package/server/service/index.ts
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
/* EXPORT ENTITY TYPES */
|
2
|
-
export * from './sftp/sftp'
|
3
|
-
|
4
|
-
/* IMPORT ENTITIES AND RESOLVERS */
|
5
|
-
import { entities as SftpEntities, resolvers as SftpResolvers } from './sftp'
|
6
|
-
|
7
|
-
export const entities = [
|
8
|
-
/* ENTITIES */
|
9
|
-
...SftpEntities,
|
10
|
-
]
|
11
|
-
|
12
|
-
|
13
|
-
export const schema = {
|
14
|
-
resolverClasses: [
|
15
|
-
/* RESOLVER CLASSES */
|
16
|
-
...SftpResolvers,
|
17
|
-
]
|
18
|
-
}
|
@@ -1,241 +0,0 @@
|
|
1
|
-
import '../../sftp-s3'
|
2
|
-
|
3
|
-
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
4
|
-
import { EntityManager, getConnection, In } from 'typeorm'
|
5
|
-
|
6
|
-
import { Bizplace } from '@things-factory/biz-base'
|
7
|
-
import { FulfillmentAPI, FulfillmentCenter } from '@things-factory/integration-fulfillment'
|
8
|
-
import { Domain } from '@things-factory/shell'
|
9
|
-
|
10
|
-
import { SftpAPI } from '../../controllers'
|
11
|
-
import { FAILEDDATAPATH, SFTPFILESTORAGE, SUBMITDATAPATH, SUCCESSDATAPATH } from '../../sftp-const'
|
12
|
-
import { getPermittedDirectories } from '../../util'
|
13
|
-
import { Sftp, SftpStatus } from './sftp'
|
14
|
-
import { NewSftp, SftpPatch } from './sftp-type'
|
15
|
-
|
16
|
-
@Resolver(Sftp)
|
17
|
-
export class SftpMutation {
|
18
|
-
@Directive('@transaction')
|
19
|
-
@Mutation(returns => Sftp, { description: 'To create new Sftp' })
|
20
|
-
async createSftp(@Arg('sftp') sftp: NewSftp, @Ctx() context: ResolverContext): Promise<Sftp> {
|
21
|
-
const { domain, user, tx } = context.state
|
22
|
-
|
23
|
-
return await tx.getRepository(Sftp).save({
|
24
|
-
...sftp,
|
25
|
-
domain,
|
26
|
-
creator: user,
|
27
|
-
updater: user
|
28
|
-
})
|
29
|
-
}
|
30
|
-
|
31
|
-
@Directive('@transaction')
|
32
|
-
@Mutation(returns => Sftp, { description: 'To modify Sftp information' })
|
33
|
-
async updateSftp(
|
34
|
-
@Arg('id') id: string,
|
35
|
-
@Arg('patch') patch: SftpPatch,
|
36
|
-
@Ctx() context: ResolverContext
|
37
|
-
): Promise<Sftp> {
|
38
|
-
const { domain, user, tx } = context.state
|
39
|
-
|
40
|
-
const repository = tx.getRepository(Sftp)
|
41
|
-
const sftp = await repository.findOne({
|
42
|
-
where: { domain: { id: domain.id }, id }
|
43
|
-
})
|
44
|
-
|
45
|
-
return await repository.save({
|
46
|
-
...sftp,
|
47
|
-
...patch,
|
48
|
-
updater: user
|
49
|
-
})
|
50
|
-
}
|
51
|
-
|
52
|
-
@Directive('@transaction')
|
53
|
-
@Mutation(returns => [Sftp], { description: "To modify multiple Sftps' information" })
|
54
|
-
async updateMultipleSftp(
|
55
|
-
@Arg('patches', type => [SftpPatch]) patches: SftpPatch[],
|
56
|
-
@Ctx() context: ResolverContext
|
57
|
-
): Promise<Sftp[]> {
|
58
|
-
const { domain, user, tx } = context.state
|
59
|
-
|
60
|
-
let results = []
|
61
|
-
const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
|
62
|
-
const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
|
63
|
-
const sftpRepo = tx.getRepository(Sftp)
|
64
|
-
|
65
|
-
if (_createRecords.length > 0) {
|
66
|
-
for (let i = 0; i < _createRecords.length; i++) {
|
67
|
-
const newRecord = _createRecords[i]
|
68
|
-
|
69
|
-
const result = await sftpRepo.save({
|
70
|
-
...newRecord,
|
71
|
-
domain,
|
72
|
-
creator: user,
|
73
|
-
updater: user
|
74
|
-
})
|
75
|
-
|
76
|
-
results.push({ ...result, cuFlag: '+' })
|
77
|
-
}
|
78
|
-
}
|
79
|
-
|
80
|
-
if (_updateRecords.length > 0) {
|
81
|
-
for (let i = 0; i < _updateRecords.length; i++) {
|
82
|
-
const newRecord = _updateRecords[i]
|
83
|
-
const sftp = await sftpRepo.findOneBy({ id: newRecord.id })
|
84
|
-
|
85
|
-
const result = await sftpRepo.save({
|
86
|
-
...sftp,
|
87
|
-
...newRecord,
|
88
|
-
updater: user
|
89
|
-
})
|
90
|
-
|
91
|
-
results.push({ ...result, cuFlag: 'M' })
|
92
|
-
}
|
93
|
-
}
|
94
|
-
|
95
|
-
return results
|
96
|
-
}
|
97
|
-
|
98
|
-
@Directive('@transaction')
|
99
|
-
@Mutation(returns => Boolean, { description: 'To delete Sftp' })
|
100
|
-
async deleteSftp(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
|
101
|
-
const { domain, tx } = context.state
|
102
|
-
|
103
|
-
await tx.getRepository(Sftp).delete({ domain: { id: domain.id }, id })
|
104
|
-
return true
|
105
|
-
}
|
106
|
-
|
107
|
-
@Directive('@transaction')
|
108
|
-
@Mutation(returns => Boolean, { description: 'To delete multiple sftps' })
|
109
|
-
async deleteSftps(@Arg('ids', type => [String]) ids: string[], @Ctx() context: ResolverContext): Promise<boolean> {
|
110
|
-
const { domain, tx } = context.state
|
111
|
-
|
112
|
-
await tx.getRepository(Sftp).delete({
|
113
|
-
domain: { id: domain.id },
|
114
|
-
id: In(ids)
|
115
|
-
})
|
116
|
-
|
117
|
-
return true
|
118
|
-
}
|
119
|
-
|
120
|
-
@Mutation(returns => Boolean, { description: 'To sync all orders from sftp' })
|
121
|
-
async syncSftpOrders(
|
122
|
-
@Arg('customerDomainId', type => String) customerDomainId: string,
|
123
|
-
@Ctx() context: ResolverContext
|
124
|
-
): Promise<boolean> {
|
125
|
-
await getConnection().transaction(async (tx: EntityManager) => {
|
126
|
-
const customerDomain: Domain = await tx.getRepository(Domain).findOneBy({ id: customerDomainId })
|
127
|
-
|
128
|
-
const customerBizplace: Bizplace = await getCustomerBizplace(customerDomainId, tx)
|
129
|
-
|
130
|
-
const sftpUsers: Sftp[] = await tx.getRepository(Sftp).find({
|
131
|
-
where: { domain: { id: customerDomainId }, status: SftpStatus.ACTIVE },
|
132
|
-
relations: ['fulfillmentCenter']
|
133
|
-
})
|
134
|
-
|
135
|
-
for (var i = 0; i < sftpUsers.length; i++) {
|
136
|
-
const sftpUser: Sftp = sftpUsers[i]
|
137
|
-
processSftp(sftpUser, context, customerBizplace.id)
|
138
|
-
}
|
139
|
-
})
|
140
|
-
|
141
|
-
return true
|
142
|
-
}
|
143
|
-
|
144
|
-
@Directive('@transaction')
|
145
|
-
@Mutation(returns => Boolean, { description: 'Calls syncSftpOrders for all domain Ids' })
|
146
|
-
async syncAllSftpOrders(@Ctx() context: ResolverContext): Promise<Boolean> {
|
147
|
-
try {
|
148
|
-
await getConnection().transaction(async tx => {
|
149
|
-
const sftps = await tx
|
150
|
-
.getRepository(Sftp)
|
151
|
-
.createQueryBuilder('s')
|
152
|
-
.where('s.status = :status', { status: 'ACTIVE' })
|
153
|
-
.getMany()
|
154
|
-
|
155
|
-
if (sftps.length === 0) return
|
156
|
-
for (const sftp of sftps) {
|
157
|
-
const customerBizplace = await getCustomerBizplace(sftp.domainId, tx)
|
158
|
-
await processSftp(sftp, context, customerBizplace.id)
|
159
|
-
}
|
160
|
-
})
|
161
|
-
} catch (e) {
|
162
|
-
console.log(e)
|
163
|
-
}
|
164
|
-
return true
|
165
|
-
}
|
166
|
-
}
|
167
|
-
|
168
|
-
export async function processSftp(sftpUser, context, customerBizplaceId) {
|
169
|
-
const fulfilmentCenter: FulfillmentCenter = sftpUser.fulfillmentCenter
|
170
|
-
const isDevelopment: boolean = sftpUser.isDevelopment
|
171
|
-
const folderPath: string = sftpUser.folderPath
|
172
|
-
const folderType: string = isDevelopment ? 'dev' : 'prd'
|
173
|
-
let initialDataPath: string = `${sftpUser.folderPath}/${folderType}${SUBMITDATAPATH}/`
|
174
|
-
const results: any[] = await getPermittedDirectories({ path: initialDataPath }, context)
|
175
|
-
const filesDirectories: any[] = results.filter(result => result.Size > 0)
|
176
|
-
|
177
|
-
for await (let fileDirectory of filesDirectories) {
|
178
|
-
let dataPath: string = `${sftpUser.folderPath}/${folderType}${SUBMITDATAPATH}/`
|
179
|
-
let successPath: string = `${sftpUser.folderPath}/${folderType}${SUCCESSDATAPATH}/`
|
180
|
-
let failedPath: string = `${sftpUser.folderPath}/${folderType}${FAILEDDATAPATH}/`
|
181
|
-
const fileKey: string = fileDirectory.Key
|
182
|
-
const lastSlashIdx = fileKey.lastIndexOf('/')
|
183
|
-
const fileString: string = fileKey.substring(lastSlashIdx + 1, fileKey.length)
|
184
|
-
try {
|
185
|
-
const sftp: any = sftpUser
|
186
|
-
let result: any = await SftpAPI.getOutboundOrder(sftp, { folderPath, folderType, fileKey: fileString })
|
187
|
-
let isAccept: boolean = result.isAccept
|
188
|
-
|
189
|
-
if (isAccept) {
|
190
|
-
delete result.isAccept
|
191
|
-
if (result) {
|
192
|
-
let { items: releaseOrders }: any = await FulfillmentAPI.getOutboundOrders(fulfilmentCenter, {
|
193
|
-
customerBizplaceId,
|
194
|
-
refNo: result.refNo
|
195
|
-
})
|
196
|
-
|
197
|
-
if (releaseOrders) {
|
198
|
-
result.collectionOrderNo = result.collectionOrderNo + ' - ' + (releaseOrders.length + 1)
|
199
|
-
}
|
200
|
-
|
201
|
-
result.requiredDraft = false
|
202
|
-
|
203
|
-
const releaseOrder: any = await FulfillmentAPI.createOutboundOrder(fulfilmentCenter, {
|
204
|
-
customerBizplaceId,
|
205
|
-
releaseOrder: result
|
206
|
-
})
|
207
|
-
|
208
|
-
if (releaseOrder) {
|
209
|
-
let movePaths = {
|
210
|
-
source: (dataPath += fileString),
|
211
|
-
destination: (successPath += fileString)
|
212
|
-
}
|
213
|
-
await SFTPFILESTORAGE.moveFile(movePaths)
|
214
|
-
}
|
215
|
-
}
|
216
|
-
} else {
|
217
|
-
let movePaths = {
|
218
|
-
source: (dataPath += fileString),
|
219
|
-
destination: (failedPath += fileString)
|
220
|
-
}
|
221
|
-
await SFTPFILESTORAGE.moveFile(movePaths)
|
222
|
-
}
|
223
|
-
} catch (e) {
|
224
|
-
let movePaths = {
|
225
|
-
source: (dataPath += fileString),
|
226
|
-
destination: (failedPath += fileString)
|
227
|
-
}
|
228
|
-
await SFTPFILESTORAGE.moveFile(movePaths)
|
229
|
-
}
|
230
|
-
}
|
231
|
-
}
|
232
|
-
|
233
|
-
export async function getCustomerBizplace(customerDomainId, tx): Promise<Bizplace> {
|
234
|
-
const customerDomain: Domain = await tx.getRepository(Domain).findOneBy({ id: customerDomainId })
|
235
|
-
|
236
|
-
const customerBizplace: Bizplace = await tx.getRepository(Bizplace).findOne({
|
237
|
-
where: { domain: { id: customerDomain.id } }
|
238
|
-
})
|
239
|
-
|
240
|
-
return customerBizplace
|
241
|
-
}
|
@@ -1,44 +0,0 @@
|
|
1
|
-
import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
2
|
-
|
3
|
-
import { User } from '@things-factory/auth-base'
|
4
|
-
import { convertListParams, Domain, getRepository, ListParam } from '@things-factory/shell'
|
5
|
-
|
6
|
-
import { Sftp } from './sftp'
|
7
|
-
import { SftpList } from './sftp-type'
|
8
|
-
|
9
|
-
@Resolver(Sftp)
|
10
|
-
export class SftpQuery {
|
11
|
-
@Query(returns => Sftp, { description: 'To fetch a Sftp' })
|
12
|
-
async sftp(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Sftp> {
|
13
|
-
const { domain } = context.state
|
14
|
-
|
15
|
-
return await getRepository(Sftp).findOne({
|
16
|
-
where: { domain: { id: domain.id }, id }
|
17
|
-
})
|
18
|
-
}
|
19
|
-
|
20
|
-
@Query(returns => SftpList, { description: 'To fetch multiple Sftps' })
|
21
|
-
async sftps(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<SftpList> {
|
22
|
-
const { domain } = context.state
|
23
|
-
|
24
|
-
const convertedParams = convertListParams(params, { domain })
|
25
|
-
const [items, total] = await getRepository(Sftp).findAndCount(convertedParams)
|
26
|
-
|
27
|
-
return { items, total }
|
28
|
-
}
|
29
|
-
|
30
|
-
@FieldResolver(type => Domain)
|
31
|
-
async domain(@Root() sftp: Sftp): Promise<Domain> {
|
32
|
-
return await getRepository(Domain).findOneBy({ id: sftp.domainId })
|
33
|
-
}
|
34
|
-
|
35
|
-
@FieldResolver(type => User)
|
36
|
-
async updater(@Root() sftp: Sftp): Promise<User> {
|
37
|
-
return await getRepository(User).findOneBy({ id: sftp.updaterId })
|
38
|
-
}
|
39
|
-
|
40
|
-
@FieldResolver(type => User)
|
41
|
-
async creator(@Root() sftp: Sftp): Promise<User> {
|
42
|
-
return await getRepository(User).findOneBy({ id: sftp.creatorId })
|
43
|
-
}
|
44
|
-
}
|
@@ -1,78 +0,0 @@
|
|
1
|
-
import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'
|
2
|
-
|
3
|
-
import { Sftp, SftpStatus } from './sftp'
|
4
|
-
|
5
|
-
@InputType()
|
6
|
-
export class NewSftp {
|
7
|
-
@Field()
|
8
|
-
name: string
|
9
|
-
|
10
|
-
@Field({ nullable: true })
|
11
|
-
description?: string
|
12
|
-
|
13
|
-
@Field(type => SftpStatus, { nullable: true })
|
14
|
-
status?: SftpStatus
|
15
|
-
|
16
|
-
@Field({ nullable: true })
|
17
|
-
username?: string
|
18
|
-
|
19
|
-
@Field({ nullable: true })
|
20
|
-
publicKey?: string
|
21
|
-
|
22
|
-
@Field({ nullable: true })
|
23
|
-
privateKey?: string
|
24
|
-
|
25
|
-
@Field({ nullable: true })
|
26
|
-
folderPath?: string
|
27
|
-
|
28
|
-
@Field({ nullable: true })
|
29
|
-
isDevelopment?: boolean
|
30
|
-
|
31
|
-
@Field({ nullable: true })
|
32
|
-
platform?: string
|
33
|
-
}
|
34
|
-
|
35
|
-
@InputType()
|
36
|
-
export class SftpPatch {
|
37
|
-
@Field(type => ID, { nullable: true })
|
38
|
-
id?: string
|
39
|
-
|
40
|
-
@Field({ nullable: true })
|
41
|
-
name?: string
|
42
|
-
|
43
|
-
@Field({ nullable: true })
|
44
|
-
description?: string
|
45
|
-
|
46
|
-
@Field(type => SftpStatus, { nullable: true })
|
47
|
-
status?: SftpStatus
|
48
|
-
|
49
|
-
@Field({ nullable: true })
|
50
|
-
username?: string
|
51
|
-
|
52
|
-
@Field({ nullable: true })
|
53
|
-
publicKey?: string
|
54
|
-
|
55
|
-
@Field({ nullable: true })
|
56
|
-
privateKey?: string
|
57
|
-
|
58
|
-
@Field({ nullable: true })
|
59
|
-
folderPath?: string
|
60
|
-
|
61
|
-
@Field({ nullable: true })
|
62
|
-
isDevelopment?: boolean
|
63
|
-
|
64
|
-
@Field({ nullable: true })
|
65
|
-
platform?: string
|
66
|
-
|
67
|
-
@Field()
|
68
|
-
cuFlag: string
|
69
|
-
}
|
70
|
-
|
71
|
-
@ObjectType()
|
72
|
-
export class SftpList {
|
73
|
-
@Field(type => [Sftp])
|
74
|
-
items: Sftp[]
|
75
|
-
|
76
|
-
@Field(type => Int)
|
77
|
-
total: number
|
78
|
-
}
|
@@ -1,143 +0,0 @@
|
|
1
|
-
import { Field, ID, ObjectType, registerEnumType } from 'type-graphql'
|
2
|
-
import {
|
3
|
-
Column,
|
4
|
-
CreateDateColumn,
|
5
|
-
Entity,
|
6
|
-
Index,
|
7
|
-
ManyToOne,
|
8
|
-
PrimaryGeneratedColumn,
|
9
|
-
RelationId,
|
10
|
-
UpdateDateColumn
|
11
|
-
} from 'typeorm'
|
12
|
-
|
13
|
-
import { User } from '@things-factory/auth-base'
|
14
|
-
import { FulfillmentCenter } from '@things-factory/integration-fulfillment'
|
15
|
-
import { Domain } from '@things-factory/shell'
|
16
|
-
|
17
|
-
export enum SftpStatus {
|
18
|
-
ACTIVE = 'ACTIVE',
|
19
|
-
INACTIVE = 'INACTIVE',
|
20
|
-
TERMINATED = 'TERMINATED'
|
21
|
-
}
|
22
|
-
|
23
|
-
registerEnumType(SftpStatus, {
|
24
|
-
name: 'SftpStatus',
|
25
|
-
description: 'state enumeration of a sftp'
|
26
|
-
})
|
27
|
-
|
28
|
-
@Entity()
|
29
|
-
@Index('ix_sftp_0', (sftp: Sftp) => [sftp.domain, sftp.name], { unique: true })
|
30
|
-
@ObjectType({ description: 'Entity for Sftp' })
|
31
|
-
export class Sftp {
|
32
|
-
@PrimaryGeneratedColumn('uuid')
|
33
|
-
@Field(type => ID)
|
34
|
-
readonly id: string
|
35
|
-
|
36
|
-
@ManyToOne(type => Domain)
|
37
|
-
@Field(type => Domain)
|
38
|
-
domain?: Domain
|
39
|
-
|
40
|
-
@RelationId((sftp: Sftp) => sftp.domain)
|
41
|
-
domainId?: string
|
42
|
-
|
43
|
-
@Column()
|
44
|
-
@Field()
|
45
|
-
name: string
|
46
|
-
|
47
|
-
@Column({
|
48
|
-
nullable: true
|
49
|
-
})
|
50
|
-
@Field({ nullable: true })
|
51
|
-
description?: string
|
52
|
-
|
53
|
-
@Column({ nullable: true })
|
54
|
-
@Field({ nullable: true })
|
55
|
-
status?: SftpStatus
|
56
|
-
|
57
|
-
@Column({
|
58
|
-
nullable: true
|
59
|
-
})
|
60
|
-
@Field({ nullable: true })
|
61
|
-
username?: string
|
62
|
-
|
63
|
-
@Column({
|
64
|
-
nullable: true
|
65
|
-
})
|
66
|
-
@Field({ nullable: true })
|
67
|
-
publicKey?: string
|
68
|
-
|
69
|
-
@Column({
|
70
|
-
nullable: true
|
71
|
-
})
|
72
|
-
@Field({ nullable: true })
|
73
|
-
privateKey?: string
|
74
|
-
|
75
|
-
@Column({
|
76
|
-
nullable: true
|
77
|
-
})
|
78
|
-
@Field({ nullable: true })
|
79
|
-
folderPath?: string
|
80
|
-
|
81
|
-
@Column({
|
82
|
-
nullable: true
|
83
|
-
})
|
84
|
-
@Field({ nullable: true })
|
85
|
-
isDevelopment?: boolean
|
86
|
-
|
87
|
-
@Column({
|
88
|
-
nullable: true
|
89
|
-
})
|
90
|
-
@Field({ nullable: true })
|
91
|
-
platform?: string
|
92
|
-
|
93
|
-
@ManyToOne(type => FulfillmentCenter, { nullable: true })
|
94
|
-
fulfillmentCenter: FulfillmentCenter
|
95
|
-
|
96
|
-
@Column({
|
97
|
-
nullable: true
|
98
|
-
})
|
99
|
-
@Field({ nullable: true })
|
100
|
-
responseType: string
|
101
|
-
|
102
|
-
@Column({
|
103
|
-
nullable: true
|
104
|
-
})
|
105
|
-
@Field({ nullable: true })
|
106
|
-
responseFilePattern: string
|
107
|
-
|
108
|
-
@Column({
|
109
|
-
nullable: true
|
110
|
-
})
|
111
|
-
@Field({ nullable: true })
|
112
|
-
responseFileTypes: string
|
113
|
-
|
114
|
-
@Column({ nullable: true })
|
115
|
-
@Field({ nullable: true })
|
116
|
-
lastTimeSync?: Date
|
117
|
-
|
118
|
-
@CreateDateColumn()
|
119
|
-
@Field({ nullable: true })
|
120
|
-
createdAt?: Date
|
121
|
-
|
122
|
-
@UpdateDateColumn()
|
123
|
-
@Field({ nullable: true })
|
124
|
-
updatedAt?: Date
|
125
|
-
|
126
|
-
@ManyToOne(type => User, {
|
127
|
-
nullable: true
|
128
|
-
})
|
129
|
-
@Field(type => User, { nullable: true })
|
130
|
-
creator?: User
|
131
|
-
|
132
|
-
@RelationId((sftp: Sftp) => sftp.creator)
|
133
|
-
creatorId?: string
|
134
|
-
|
135
|
-
@ManyToOne(type => User, {
|
136
|
-
nullable: true
|
137
|
-
})
|
138
|
-
@Field(type => User, { nullable: true })
|
139
|
-
updater?: User
|
140
|
-
|
141
|
-
@RelationId((sftp: Sftp) => sftp.updater)
|
142
|
-
updaterId?: string
|
143
|
-
}
|
package/server/sftp-const.ts
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
import { config } from '@things-factory/env'
|
2
|
-
|
3
|
-
export var SFTPFILESTORAGE: any = config.get('sftpFileStorage')
|
4
|
-
export var SUBMITDATAPATH: string = '/sob/data'
|
5
|
-
export var SUCCESSDATAPATH: string = '/sob/success'
|
6
|
-
export var FAILEDDATAPATH: string = '/sob/failed'
|
7
|
-
export var COMPLETEDATAPATH: string = '/oc/data01'
|
8
|
-
export var COMPLETESUCCESSDATAPATH: string = '/oc/success'
|
9
|
-
export var COMPLETEFAILEDDATAPATH: string = '/oc/failed'
|
10
|
-
export var SNSUBMITDATAPATH: string = '/sn/data'
|
11
|
-
export var SNSUCCESSDATAPATH: string = '/sn/success'
|
12
|
-
export var SNFAILEDDATAPATH: string = '/sn/failed'
|
13
|
-
export var BACKUPPATH: string = 'hatiosea/'
|
package/server/sftp-s3.ts
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
import AWS from 'aws-sdk'
|
2
|
-
|
3
|
-
import { logger } from '@things-factory/env'
|
4
|
-
|
5
|
-
import { SFTPFILESTORAGE } from './sftp-const'
|
6
|
-
|
7
|
-
const crypto = require('crypto')
|
8
|
-
|
9
|
-
const { PassThrough } = require('stream')
|
10
|
-
|
11
|
-
if (SFTPFILESTORAGE && SFTPFILESTORAGE.type == 's3') {
|
12
|
-
const S3 = new AWS.S3({
|
13
|
-
accessKeyId: SFTPFILESTORAGE.accessKeyId,
|
14
|
-
secretAccessKey: SFTPFILESTORAGE.secretAccessKey
|
15
|
-
})
|
16
|
-
|
17
|
-
SFTPFILESTORAGE.readFolders = async (params, encoding) => {
|
18
|
-
let S3params = {
|
19
|
-
Bucket: SFTPFILESTORAGE.bucketName,
|
20
|
-
Delimiter: '/',
|
21
|
-
Prefix: params.path
|
22
|
-
}
|
23
|
-
|
24
|
-
const result = await S3.listObjects(S3params).promise()
|
25
|
-
|
26
|
-
let body = result.Contents
|
27
|
-
|
28
|
-
return body
|
29
|
-
}
|
30
|
-
|
31
|
-
SFTPFILESTORAGE.readFile = async (path, encoding) => {
|
32
|
-
const result = await S3.getObject({
|
33
|
-
Bucket: SFTPFILESTORAGE.bucketName,
|
34
|
-
Key: path
|
35
|
-
}).promise()
|
36
|
-
|
37
|
-
var body = result.Body
|
38
|
-
|
39
|
-
if (encoding) {
|
40
|
-
return body.toString(encoding)
|
41
|
-
}
|
42
|
-
|
43
|
-
return body
|
44
|
-
}
|
45
|
-
|
46
|
-
SFTPFILESTORAGE.moveFile = async (path, encoding) => {
|
47
|
-
const copyResult = await S3.copyObject({
|
48
|
-
Bucket: SFTPFILESTORAGE.bucketName,
|
49
|
-
CopySource: SFTPFILESTORAGE.bucketName + '/' + path.source,
|
50
|
-
Key: path.destination
|
51
|
-
}).promise()
|
52
|
-
|
53
|
-
const copyBody = copyResult.CopyObjectResult
|
54
|
-
|
55
|
-
const deleteResult = await S3.deleteObject({
|
56
|
-
Bucket: SFTPFILESTORAGE.bucketName,
|
57
|
-
Key: path.source
|
58
|
-
}).promise()
|
59
|
-
|
60
|
-
return true
|
61
|
-
}
|
62
|
-
|
63
|
-
/* upload file */
|
64
|
-
SFTPFILESTORAGE.uploadFile = ({ stream, filename, uploadPath }) => {
|
65
|
-
const id = crypto.randomUUID()
|
66
|
-
let size: number = 0
|
67
|
-
|
68
|
-
return new Promise<{ id: string; path: string; size: number }>((resolve, reject) =>
|
69
|
-
stream
|
70
|
-
.pipe(
|
71
|
-
(() => {
|
72
|
-
var pass = new PassThrough()
|
73
|
-
|
74
|
-
S3.upload(
|
75
|
-
{
|
76
|
-
Bucket: SFTPFILESTORAGE.bucketName,
|
77
|
-
Key: uploadPath + '/' + filename,
|
78
|
-
Body: pass
|
79
|
-
},
|
80
|
-
(err, data) => (err ? reject(err) : resolve({ id, path: uploadPath, size }))
|
81
|
-
)
|
82
|
-
|
83
|
-
return pass
|
84
|
-
})()
|
85
|
-
)
|
86
|
-
.on('error', error => reject(error))
|
87
|
-
.on('data', chunk => (size += chunk.length))
|
88
|
-
)
|
89
|
-
}
|
90
|
-
|
91
|
-
logger.info('S3 Bucket Storage is Ready.')
|
92
|
-
}
|
@@ -1,33 +0,0 @@
|
|
1
|
-
import '../sftp-s3'
|
2
|
-
|
3
|
-
import { SFTPFILESTORAGE } from '../sftp-const'
|
4
|
-
|
5
|
-
const fs = require('fs')
|
6
|
-
|
7
|
-
export async function generateFiles(params: any[]) {
|
8
|
-
const fileDirectory = './uploaded-files'
|
9
|
-
for (let i = 0; i < params.length; i++) {
|
10
|
-
let param: any = params[i]
|
11
|
-
const { uploadPath, content, title } = param
|
12
|
-
|
13
|
-
if (!fs.existsSync(fileDirectory)) {
|
14
|
-
fs.mkdirSync(fileDirectory)
|
15
|
-
}
|
16
|
-
|
17
|
-
const filePath = fileDirectory + '/' + title
|
18
|
-
|
19
|
-
fs.writeFile(filePath, content, function (err) {
|
20
|
-
if (err) throw err
|
21
|
-
console.log('File is created successfully.')
|
22
|
-
})
|
23
|
-
|
24
|
-
if (uploadPath) {
|
25
|
-
const stream = fs.createReadStream(filePath)
|
26
|
-
await SFTPFILESTORAGE.uploadFile({ stream, filename: title, uploadPath })
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
fs.rm(fileDirectory, { recursive: true })
|
31
|
-
|
32
|
-
return true
|
33
|
-
}
|
@@ -1,15 +0,0 @@
|
|
1
|
-
import '../sftp-s3'
|
2
|
-
|
3
|
-
import { SFTPFILESTORAGE } from '../sftp-const'
|
4
|
-
|
5
|
-
export async function getPermittedDirectories(params: any, context: ResolverContext) {
|
6
|
-
const sftpDirectories: any[] = await SFTPFILESTORAGE.readFolders(params)
|
7
|
-
|
8
|
-
return sftpDirectories
|
9
|
-
}
|
10
|
-
|
11
|
-
export async function readFile(fileKey: any) {
|
12
|
-
const file: any = await SFTPFILESTORAGE.readFile(fileKey, 'utf-8')
|
13
|
-
|
14
|
-
return file
|
15
|
-
}
|
package/server/util/index.ts
DELETED