@things-factory/integration-sftp 8.0.0-beta.9 → 8.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/server/controllers/herbalife/apis/create-serial-number.ts +51 -0
- package/server/controllers/herbalife/apis/create-shipment.ts +88 -0
- package/server/controllers/herbalife/apis/echo.ts +14 -0
- package/server/controllers/herbalife/apis/get-outbound-order.ts +119 -0
- package/server/controllers/herbalife/apis/index.ts +4 -0
- package/server/controllers/herbalife/herbalife.ts +53 -0
- package/server/controllers/herbalife/index.ts +7 -0
- package/server/controllers/herbalife/platform-action.ts +34 -0
- package/server/controllers/index.ts +3 -0
- package/server/controllers/sftp-api/decorators.ts +43 -0
- package/server/controllers/sftp-api/index.ts +39 -0
- package/server/controllers/sftp-api/types.ts +0 -0
- package/server/index.ts +7 -0
- package/server/middlewares/index.ts +3 -0
- package/server/routes.ts +28 -0
- package/server/service/index.ts +18 -0
- package/server/service/sftp/index.ts +6 -0
- package/server/service/sftp/sftp-mutation.ts +241 -0
- package/server/service/sftp/sftp-query.ts +44 -0
- package/server/service/sftp/sftp-type.ts +78 -0
- package/server/service/sftp/sftp.ts +143 -0
- package/server/sftp-const.ts +13 -0
- package/server/sftp-s3.ts +92 -0
- package/server/util/generate-files.ts +33 -0
- package/server/util/get-permitted-directories.ts +15 -0
- package/server/util/index.ts +2 -0
- package/tsconfig.json +9 -0
@@ -0,0 +1,241 @@
|
|
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
|
+
}
|
@@ -0,0 +1,44 @@
|
|
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
|
+
}
|
@@ -0,0 +1,78 @@
|
|
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
|
+
}
|
@@ -0,0 +1,143 @@
|
|
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
|
+
}
|
@@ -0,0 +1,13 @@
|
|
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/'
|
@@ -0,0 +1,92 @@
|
|
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
|
+
}
|
@@ -0,0 +1,33 @@
|
|
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
|
+
}
|
@@ -0,0 +1,15 @@
|
|
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
|
+
}
|