Skip to content

Commit

Permalink
refactor: code with some updates and allowing rebuild
Browse files Browse the repository at this point in the history
- Update of node builder
- Typescript Refactor
- Lint issues
- Changelog added
- @vtex/api updated
- Removed and renamed unused/unnecessary code and imports
  • Loading branch information
iago1501 authored Feb 27, 2025
2 parents f161d09 + 16a3fd6 commit 8872df8
Show file tree
Hide file tree
Showing 18 changed files with 1,811 additions and 349 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
coverage/
*.snap.ts
9 changes: 9 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "vtex",
"root": true,
"env": {
"node": true,
"es6": true,
"jest": true
}
}
7 changes: 1 addition & 6 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
{
"semi": false,
"singleQuote": true,
"trailingComma": "es5",
"eslintIntegration": true
}
"@vtex/prettier-config"
15 changes: 15 additions & 0 deletions .vtexignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.DS_Store
.git/
.happypack/
.vscode/
node_modules/
.editorconfig
.eslintrc
.gitignore
gulpfile.js
package.json
tsconfig.json
tslint.json
typings.d.ts
yarn.lock
node/node_modules/
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed
- Refactor code for proper build
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
"builders": {
"graphql": "1.x",
"node": "3.x",
"node": "7.x",
"docs": "0.x"
},
"credentialType": "absolute",
Expand Down
98 changes: 67 additions & 31 deletions node/FileManager.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,67 @@
import {HttpClient, IOContext, InstanceOptions} from '@vtex/api'
import {FileNotFound} from './exceptions/fileNotFound'
import {InternalServerError} from './exceptions/internalServerError'
import {pathEq, path, pick} from 'ramda'
import type { InstanceOptions, IOContext } from '@vtex/api'
import { ExternalClient } from '@vtex/api'

import { FileNotFound } from './exceptions/fileNotFound'
import { InternalServerError } from './exceptions/internalServerError'

const appId = process.env.VTEX_APP_ID
const [runningAppName] = appId ? appId.split('@') : ['']

const FORWARD_FIELDS = ['status', 'statusText', 'data', 'stack', 'stackTrace']

const pickForwardFields = (object: any) =>
({ ...Object.fromEntries(FORWARD_FIELDS.map(field => [field, object[field]])) })

const routes = {
Assets: () => `/assets/${runningAppName}`,
FileUpload: (bucket: string, path: string) => `${routes.Assets()}/save/${bucket}/${path}`,
FileUrl: (bucket: string, path: string) => `${routes.Assets()}/route/${bucket}/${path}`,
FileDelete: (bucket: string, path: string) => `${routes.Assets()}/delete/${bucket}/${path}`,
File: (path: string, width: number, height: number, aspect: boolean, bucket: string) => `${routes.Assets()}/${bucket}/${path}?width=${width}&height=${height}&aspect=${aspect}`
FileUpload: (bucket: string, path: string) =>
`${routes.Assets()}/save/${bucket}/${path}`,
FileUrl: (bucket: string, path: string) =>
`${routes.Assets()}/route/${bucket}/${path}`,
FileDelete: (bucket: string, path: string) =>
`${routes.Assets()}/delete/${bucket}/${path}`,
File: (
path: string,
width: number,
height: number,
aspect: boolean,
bucket: string
) =>
`${routes.Assets()}/${bucket}/${path}?width=${width}&height=${height}&aspect=${aspect}`,
}

export default class FileManager {
private http: HttpClient

constructor (ioContext: IOContext, opts: InstanceOptions = {}) {
if (runningAppName === '') {
throw new InternalServerError(`Invalid path to access FileManger. Variable VTEX_APP_ID is not available.`)
}
this.http = HttpClient.forWorkspace('file-manager.vtex', ioContext, opts)
export default class FileManager extends ExternalClient {

constructor(protected context: IOContext, options?: InstanceOptions) {
super(
`http://app.io.vtex.com/vtex.file-manager/v0/${context.account}/${context.workspace}`,
context,
{
...(options ?? {}),
headers: {
...(options?.headers ?? {}),
'VtexIdclientAutCookie': context.authToken,
'Content-Type': 'application/json',
'X-Vtex-Use-Https': 'true',
},
}
)
}

getFile = async (path: string, width: number, height: number, aspect: boolean, bucket: string) => {
getFile = async (
path: string,
width: number,
height: number,
aspect: boolean,
bucket: string
) => {
try {
return await this.http.get(routes.File(path, width, height, aspect, bucket))
} catch (e) {
if (e.statusCode === 404 || pathEq(['response', 'status'], 404, e)) {
throw new FileNotFound(pick(FORWARD_FIELDS, e.response))
return await this.http.get(
routes.File(path, width, height, aspect, bucket)
)
} catch (e) {
if (e.statusCode === 404 || e.response?.status === 404) {
throw new FileNotFound(pickForwardFields(e.response))
} else {
throw e
}
Expand All @@ -40,27 +70,33 @@ export default class FileManager {

getFileUrl = async (path: string, bucket: string) => {
try {
return await this.http.get(routes.FileUrl(bucket, path))
const fileUrl = routes.FileUrl(bucket, path)
const file = await this.http.get(fileUrl)
return file
} catch (e) {
if (e.statusCode === 404 || pathEq(['response', 'status'], 404, e)) {
throw new FileNotFound(pick(FORWARD_FIELDS, e.response))
if (e.statusCode === 404 || e.response?.status === 404) {
throw new FileNotFound(pickForwardFields(e.response))
} else {
throw e
}
}
}

saveFile = async (file: IncomingFile, stream, bucket: string) => {
saveFile = async (file: IncomingFile, stream: any, bucket: string) => {
try {
const {filename, encoding, mimetype} = file
const { filename, encoding, mimetype } = file
const headers = {
'Content-Type': mimetype,
'Content-Encoding': encoding,
}
return await this.http.put(routes.FileUpload(bucket, filename), stream, {headers})

return await this.http.put(routes.FileUpload(bucket, filename), stream, {
headers,
})
} catch (e) {
const status = e.statusCode || path(['response', 'status'], e) || 500
const extensions = pick(FORWARD_FIELDS, e.response)
const status = e.statusCode || e.response?.status || 500
const extensions = pickForwardFields(e.response)

throw new InternalServerError(extensions, 'Fail to save file', status)
}
}
Expand All @@ -69,8 +105,8 @@ export default class FileManager {
try {
return await this.http.delete(routes.FileDelete(bucket, path))
} catch (e) {
if (e.statusCode === 404 || pathEq(['response', 'status'], 404, e)) {
throw new FileNotFound(pick(FORWARD_FIELDS, e.response))
if (e.statusCode === 404 || e.response?.status === 404) {
throw new FileNotFound(pickForwardFields(e.response))
} else {
throw e
}
Expand Down
4 changes: 2 additions & 2 deletions node/exceptions/fileNotFound.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export class FileNotFound extends Error {
constructor(
public extensions,
public extensions: any,
public message = 'File Not Found',
public statusCode = 404,
public statusCode = 404
) {
super(message)
}
Expand Down
4 changes: 2 additions & 2 deletions node/exceptions/internalServerError.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export class InternalServerError extends Error {
constructor(
public extensions,
public extensions: any,
public message = 'Internal Server Error',
public statusCode = 500,
public statusCode = 500
) {
super(message)
}
Expand Down
11 changes: 7 additions & 4 deletions node/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import {resolvers} from './resolvers'
import { resolvers } from './resolvers'
import { Service } from '@vtex/api'

export default {
graphql: resolvers
}
export default new Service({
graphql: {
resolvers
}
})
17 changes: 12 additions & 5 deletions node/package.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
{
"name": "vtex.product-review-graphql-example",
"name": "vtex.file-manager-graphql",
"description": "GraphQL resolvers. Any required dependencies should be defined in this file.",
"version": "0.3.0",
"dependencies": {
"@vtex/api": "^0.40.0",
"@vtex/api": "6.48.0",
"apollo-upload-server": "^5.0.0",
"ramda": "^0.25.0",
"uuid": "^8.2.0"
},
"resolutions": {
"@types/express": "4.16.0",
"@types/express-serve-static-core": "4.16.0"
},
"devDependencies": {
"@types/bluebird-global": "^3.5.12",
"@types/jest": "^24.0.24",
"@types/node": "^10.3.2",
"@types/random-js": "^1.0.30"
"@types/node": "^20.0.0",
"@types/uuid": "^10.0.0",
"tslint": "^5.14.0",
"tslint-config-vtex": "^2.1.0",
"typescript": "5.5.3",
"vtex.file-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.file-manager@0.11.0/public/_types/react"
},
"scripts": {
"lint": "tsc --noEmit && tslint -c tslint.json './**/*.ts'"
Expand Down
56 changes: 40 additions & 16 deletions node/resolvers/index.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,66 @@
import { v4 as uuidv4 } from 'uuid'

import FileManager from '../FileManager'
import { ServiceContext } from '@vtex/api'

type FileManagerArgs = {
path: string
width: number
height: number
aspect: boolean
bucket: string
}

type UploadFileArgs = {
file: Promise<any>
bucket: string
}

export const resolvers = {
Query: {
getFile: async (root, args, ctx, info) => {
getFile: async (_: unknown, args: FileManagerArgs, ctx: ServiceContext) => {
const fileManager = new FileManager(ctx.vtex)
const {path, width, height, aspect, bucket} = args
return await fileManager.getFile(path, width, height, aspect, bucket)
const { path, width, height, aspect, bucket } = args

const file = await fileManager.getFile(path, width, height, aspect, bucket)
return file
},
getFileUrl: async (root, args, ctx, info) => {
getFileUrl: async (_: unknown, args: FileManagerArgs, ctx: ServiceContext) => {
const fileManager = new FileManager(ctx.vtex)
const {path, bucket} = args
return await fileManager.getFileUrl(path, bucket)
const { path, bucket } = args

const file = await fileManager.getFileUrl(path, bucket)
return file
},
settings: async (root, args, ctx, info) => ({
maxFileSizeMB: 4
settings: async () => ({
maxFileSizeMB: 4,
}),
},
Mutation: {
uploadFile: async (obj, args, ctx, info) => {
uploadFile: async (_: unknown, args: UploadFileArgs, ctx: ServiceContext) => {
const fileManager = new FileManager(ctx.vtex)
const {file, bucket} = args
const {stream, filename: name, mimetype, encoding} = await file
const { file, bucket } = args
const loadedFile = await file
const {filename: name, mimetype, encoding } = loadedFile
const [extension] = name?.split('.')?.reverse()
const filename = `${uuidv4()}.${extension}`
const stream = loadedFile.createReadStream(filename)

const incomingFile = { filename, mimetype, encoding }

const incomingFile = {filename, mimetype, encoding}
return {
encoding,
mimetype,
fileUrl: await fileManager.saveFile(incomingFile, stream, bucket),
}
},
deleteFile: async (obj, args, ctx, info) => {
deleteFile: async (_: unknown, args: FileManagerArgs, ctx: ServiceContext) => {
const fileManager = new FileManager(ctx.vtex)
const {path, bucket} = args
const { path, bucket } = args

await fileManager.deleteFile(path, bucket)

return true
}
}
},
},
}
Loading

0 comments on commit 8872df8

Please sign in to comment.