Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/image to media migration #11

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $ npm install -g @tiagonapoli/vtex-scripts
$ vtex-dev COMMAND
running command...
$ vtex-dev (-v|--version|version)
@tiagonapoli/vtex-scripts/0.0.7 linux-x64 node-v12.16.2
@tiagonapoli/vtex-scripts/0.0.7 darwin-x64 node-v12.18.0
$ vtex-dev --help [COMMAND]
USAGE
$ vtex-dev COMMAND
Expand All @@ -27,6 +27,7 @@ USAGE

<!-- commands -->
* [`vtex-dev app:bundle APPID`](#vtex-dev-appbundle-appid)
* [`vtex-dev app:imageToMedia [WORKSPACE]`](#vtex-dev-appimagetomedia-workspace)
* [`vtex-dev app:types APPID`](#vtex-dev-apptypes-appid)
* [`vtex-dev help [COMMAND]`](#vtex-dev-help-command)

Expand All @@ -50,6 +51,23 @@ EXAMPLES
vtex-dev app:bundle [email protected] --linked
```

## `vtex-dev app:imageToMedia [WORKSPACE]`

Migrate image content to media content

```
USAGE
$ vtex-dev app:imageToMedia [WORKSPACE]

OPTIONS
-h, --help show CLI help
-o, --override Override existing media content if an image with the same treePath can be migrated

EXAMPLES
vtex-dev workspace:migrateToImage
vtex-dev workspace:migrateToImage "myworkspace"
```

## `vtex-dev app:types APPID`

Download app types
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tiagonapoli/vtex-scripts",
"version": "0.0.7",
"version": "0.0.8-beta.0",
"author": "Tiago Nápoli <[email protected]>",
"license": "ISC",
"files": [
Expand Down
5 changes: 5 additions & 0 deletions src/clients/HttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ export class HttpClient {
console.debug(`GET stream from ${this.buildFullURL(url)}`)
return this.http.get(url, { ...config, responseType: 'stream' })
}

public putRaw = <T = any>(url: string, data?: any, config: AxiosRequestConfig = {}): Promise<T> => {
console.debug(`PUT to ${this.buildFullURL(url)}`)
return this.http.put(url, data, config)
}
}
52 changes: 52 additions & 0 deletions src/clients/Templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { IOContext } from '@vtex/api'
import { AxiosRequestConfig } from 'axios'
import { HttpClient } from './HttpClient'

const createRoutes = ({ account, workspace }: IOContext) => {
const routes = {
Templates: (argWorkspace: string) =>
`/${account}/${argWorkspace || workspace}/buckets/vtex.pages-graphql/userData/files/store/templates.json`,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user doesn't pass workspace and he is @master workspace, he will put a file into the master workspace, am I right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, you're right. Actually, the user is going to edit an existing file, but yes, they will migrate de master workspace

}
return routes
}

export class Templates {
private http: HttpClient
private _routes: ReturnType<typeof createRoutes>

constructor(ctx: IOContext, options?: AxiosRequestConfig) {
const { authToken } = ctx
this.http = new HttpClient({
...options,
authToken,
baseURL: `https://infra.io.vtex.com/vbase/v2`,
})
this._routes = createRoutes(ctx)
}

private get routes() {
return this._routes
}

public getWorkspaceTemplate = (workspace?: string) => {
return this.http.get<TemplatesJSON>(this.routes.Templates(workspace), {
headers: {
Accept: 'application/json',
},
})
}

public updateWorkspaceTemplate = (migratedTemplate: TemplatesJSON, workspace?: string) => {
return this.http.putRaw<string>(this.routes.Templates(workspace), migratedTemplate, {
headers: {
'Content-Type': 'application/json',
},
})
}
}

export type TemplatesJSON = Record<string, TreePathContainer>

export interface TreePathContainer {
treePathContentMap: Record<string, string>
}
100 changes: 100 additions & 0 deletions src/commands/app/imageToMedia.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { flags as oclifFlags } from '@oclif/command'
import { AxiosError } from 'axios'
import { createContext } from '../../clients'
import { Templates, TemplatesJSON } from '../../clients/Templates'
import { CustomCommand } from '../../oclif/CustomCommand'
import { VtexConfig } from '../../VtexConfig'

function objectHasImageContent(object: any) {
return valueHasImageContent(JSON.stringify(object))
}

function valueHasImageContent(value: string) {
return value.search('/image') !== -1
}

function replaceImageTreepath(imageTreePath: string) {
return imageTreePath.replace('/image', '/media')
}

function getMediaTemplates(jsonTemplates: TemplatesJSON, overrideMedia: boolean) {
const mediaTemplates = jsonTemplates

if (!objectHasImageContent(jsonTemplates)) {
return null
}

Object.entries(jsonTemplates).forEach(([pageId, container]) => {
if (!objectHasImageContent(container)) {
return
}

const migratedContainer = container

Object.entries(container.treePathContentMap).forEach(([treePath, contentValue]) => {
// If it doesn't have an image content or (already has a media content defined and cannot override), just pass
if (!valueHasImageContent(treePath) || (valueHasImageContent(replaceImageTreepath(treePath)) && !overrideMedia)) {
return
}

const migratedTreePath = replaceImageTreepath(treePath)
migratedContainer.treePathContentMap[migratedTreePath] = contentValue
})

mediaTemplates[pageId] = migratedContainer
})

return mediaTemplates
}

export default class AppBundle extends CustomCommand {
static description = 'Migrate image content to media content'

static examples = ['vtex-dev workspace:migrateToImage', 'vtex-dev workspace:migrateToImage "myworkspace"']

static flags = {
help: oclifFlags.help({ char: 'h' }),
override: oclifFlags.boolean({
char: 'o',
description: 'Override existing media content if an image with the same treePath can be migrated',
default: false,
}),
}

static args = [{ name: 'workspace', required: false }]

async run() {
const { flags, args } = this.parse(AppBundle)
const { workspace: workspaceArg } = args
const { override: overrideMedia } = flags
const ioContext = createContext(VtexConfig)

const { account, workspace } = ioContext
const templates = new Templates(createContext(VtexConfig), { timeout: 30000 })

console.log(`Downloading template from account ${account} and workspace ${workspaceArg || workspace}`)

try {
const jsonTemplates = await templates.getWorkspaceTemplate(workspaceArg)

console.log(`Finding image content...`)

const mediaTemplates = getMediaTemplates(jsonTemplates, overrideMedia)

if (!mediaTemplates) {
console.log('There was no image content to migrate')
return
}

console.log(`Migrating image content to media...`)

await templates.updateWorkspaceTemplate(mediaTemplates, workspaceArg)

console.log('All done!')
return
} catch (err) {
const axiosErr: AxiosError = err
console.log(axiosErr.response.status, axiosErr.response.statusText, axiosErr.message, axiosErr.stack)
}
}
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5830,7 +5830,7 @@ static-extend@^0.1.1:
define-property "^0.2.5"
object-copy "^0.1.0"

"stats-lite@github:vtex/node-stats-lite#dist":
stats-lite@vtex/node-stats-lite#dist:
version "2.2.0"
resolved "https://codeload.github.com/vtex/node-stats-lite/tar.gz/1b0d39cc41ef7aaecfd541191f877887a2044797"
dependencies:
Expand Down