@things-factory/integration-sftp 8.0.0-beta.0 → 8.0.0-beta.2
Sign up to get free protection for your applications and to get access to all the features.
- 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