Skip to content

Commit

Permalink
feat: suffix command and new file organization for pull-components
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarosabu committed Dec 3, 2024
1 parent 15ff9f9 commit 6cabaab
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 31 deletions.
31 changes: 27 additions & 4 deletions src/commands/pull-components/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,37 @@ describe('pull components actions', () => {
await saveComponentsToFiles('12345', components, { path: '/path/to/components2', filename: 'custom' })

const files = vol.readdirSync('/path/to/components2')
expect(files).toEqual(['custom.json'])
expect(files).toEqual(['custom.12345.json'])
})

it('should save components to separate files', async () => {
it('should save components to files with custom suffix', async () => {
vol.fromJSON({
'/path/to/components3': null,
})

const components = [{
name: 'component-name',
display_name: 'Component Name',
created_at: '2021-08-09T12:00:00Z',
updated_at: '2021-08-09T12:00:00Z',
id: 12345,
schema: { type: 'object' },
color: null,
internal_tags_list: ['tag'],
interntal_tags_ids: [1],
}]

await saveComponentsToFiles('12345', components, { path: '/path/to/components3', suffix: 'custom' })

const files = vol.readdirSync('/path/to/components3')
expect(files).toEqual(['components.custom.json'])
})

it('should save components to separate files', async () => {
vol.fromJSON({
'/path/to/components4': null,
})

const components = [{
name: 'component-name',
display_name: 'Component Name',
Expand All @@ -154,9 +177,9 @@ describe('pull components actions', () => {
interntal_tags_ids: [1],
}]

await saveComponentsToFiles('12345', components, { path: '/path/to/components3', separateFiles: true })
await saveComponentsToFiles('12345', components, { path: '/path/to/components4', separateFiles: true })

const files = vol.readdirSync('/path/to/components3')
const files = vol.readdirSync('/path/to/components4')
expect(files).toEqual(['component-name-2.12345.json', 'component-name.12345.json'])
})
})
Expand Down
17 changes: 10 additions & 7 deletions src/commands/pull-components/actions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { ofetch } from 'ofetch'
import { handleAPIError, handleFileSystemError } from '../../utils'
import { regionsDomain } from '../../constants'
import { join, resolve } from 'node:path'
import { saveToFile } from '../../utils/filesystem'
import { join } from 'node:path'
import { resolvePath, saveToFile } from '../../utils/filesystem'
import type { PullComponentsOptions } from './constants'

export interface SpaceComponent {
name: string
Expand Down Expand Up @@ -30,6 +31,7 @@ export interface ComponentsSaveOptions {
path?: string
filename?: string
separateFiles?: boolean
suffix?: string
}

export const pullComponents = async (space: string, token: string, region: string): Promise<SpaceComponent[] | undefined> => {
Expand All @@ -46,17 +48,17 @@ export const pullComponents = async (space: string, token: string, region: strin
}
}

export const saveComponentsToFiles = async (space: string, components: SpaceComponent[], options: ComponentsSaveOptions) => {
const { path, filename } = options
export const saveComponentsToFiles = async (space: string, components: SpaceComponent[], options: PullComponentsOptions) => {
const { filename = 'components', suffix = space, path } = options

try {
const data = JSON.stringify(components, null, 2)
const resolvedPath = path ? resolve(process.cwd(), path) : process.cwd()
const resolvedPath = resolvePath(path, 'components')

if (options.separateFiles) {
for (const component of components) {
try {
const filePath = join(resolvedPath, `${component.name}.${space}.json`)
const filePath = join(resolvedPath, `${component.name}.${suffix}.json`)
await saveToFile(filePath, JSON.stringify(component, null, 2))
}
catch (error) {
Expand All @@ -67,7 +69,8 @@ export const saveComponentsToFiles = async (space: string, components: SpaceComp
}

// Default to saving all components to a single file
const filePath = join(resolvedPath, filename ? `${filename}.json` : `components.${space}.json`)
const name = `${filename}.${suffix}.json`
const filePath = join(resolvedPath, name)

// Check if the path exists, and create it if it doesn't
await saveToFile(filePath, data)
Expand Down
35 changes: 35 additions & 0 deletions src/commands/pull-components/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { CommandOptions } from '../../types'

/**
* Interface representing the options for the `pull-components` command.
*/
export interface PullComponentsOptions extends CommandOptions {
/**
* The path to save the components file to.
* Defaults to `.storyblok/components`.
* @default `.storyblok/components`
*/
path?: string
/**
* The space ID.
* @required true
*/
space: string
/**
* The filename to save the file as.
* Defaults to `components`. The file will be saved as `<filename>.<space>.json`.
* @default `components
*/
filename?: string
/**
* The suffix to add to the filename.
* Defaults to the space ID.
* @default space
*/
suffix?: string
/**
* Indicates whether to save each component to a separate file.
* @default false
*/
separateFiles?: boolean
}
16 changes: 8 additions & 8 deletions src/commands/pull-components/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ describe('pullComponents', () => {
await pullComponentsCommand.parseAsync(['node', 'test', '--space', '12345'])
expect(pullComponents).toHaveBeenCalledWith('12345', 'valid-token', 'eu')
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, {

space: '12345',
})
expect(konsola.ok).toHaveBeenCalledWith(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(`components.12345.json`)}`)
expect(konsola.ok).toHaveBeenCalledWith(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(`./storyblok/components/components.12345.json`)}`)
})

it('should throw an error if the user is not logged in', async () => {
Expand Down Expand Up @@ -150,7 +150,7 @@ describe('pullComponents', () => {

await pullComponentsCommand.parseAsync(['node', 'test', '--space', '12345', '--path', '/path/to/components'])
expect(pullComponents).toHaveBeenCalledWith('12345', 'valid-token', 'eu')
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, { path: '/path/to/components' })
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, { path: '/path/to/components', space: '12345' })
expect(konsola.ok).toHaveBeenCalledWith(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(`/path/to/components/components.12345.json`)}`)
})
})
Expand Down Expand Up @@ -179,8 +179,8 @@ describe('pullComponents', () => {

await pullComponentsCommand.parseAsync(['node', 'test', '--space', '12345', '--filename', 'custom'])
expect(pullComponents).toHaveBeenCalledWith('12345', 'valid-token', 'eu')
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, { filename: 'custom' })
expect(konsola.ok).toHaveBeenCalledWith(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(`custom.json`)}`)
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, { filename: 'custom', space: '12345' })
expect(konsola.ok).toHaveBeenCalledWith(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(`./storyblok/components/custom.12345.json`)}`)
})
})

Expand Down Expand Up @@ -218,8 +218,8 @@ describe('pullComponents', () => {

await pullComponentsCommand.parseAsync(['node', 'test', '--space', '12345', '--separate-files'])
expect(pullComponents).toHaveBeenCalledWith('12345', 'valid-token', 'eu')
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, { separateFiles: true })
expect(konsola.ok).toHaveBeenCalledWith(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(`./`)}`)
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, { separateFiles: true, space: '12345' })
expect(konsola.ok).toHaveBeenCalledWith(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(`./storyblok/components`)}`)
})

it('should warn the user if the --filename is used along', async () => {
Expand All @@ -245,7 +245,7 @@ describe('pullComponents', () => {

await pullComponentsCommand.parseAsync(['node', 'test', '--space', '12345', '--separate-files', '--filename', 'custom'])
expect(pullComponents).toHaveBeenCalledWith('12345', 'valid-token', 'eu')
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, { separateFiles: true, filename: 'custom' })
expect(saveComponentsToFiles).toHaveBeenCalledWith('12345', mockResponse, { separateFiles: true, filename: 'custom', space: '12345' })
expect(konsola.warn).toHaveBeenCalledWith(`The --filename option is ignored when using --separate-files`)
})
})
Expand Down
22 changes: 10 additions & 12 deletions src/commands/pull-components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@ import { session } from '../../session'
import { getProgram } from '../../program'
import { CommandError, handleError, konsola } from '../../utils'
import { pullComponents, saveComponentsToFiles } from './actions'
import type { PullComponentsOptions } from './constants'

const program = getProgram() // Get the shared singleton instance

export const pullComponentsCommand = program
.command('pull-components')
.description(`Download your space's components schema as json`)
.option('-s, --space <space>', 'space ID')
.option('-p, --path <path>', 'path to save the file')
.option('-p, --path <path>', 'path to save the file. Default is .storyblok/components')
.option('-f, --filename <filename>', 'custom name to be used in file(s) name instead of space id')
.option('--sf, --separate-files [value]', 'Argument to create a single file for each component')
.action(async (options) => {
.option('--su, --suffix <suffix>', 'suffix to add to the file name (e.g. components.<suffix>.json). By default, the space ID is used.')
.action(async (options: PullComponentsOptions) => {
konsola.title(` ${commands.PULL_COMPONENTS} `, colorPalette.PULL_COMPONENTS, 'Pulling components...')
// Global options
const verbose = program.opts().verbose
// Command options
const { space, path, filename, separateFiles } = options
const { space, path, filename = 'components', suffix = options.space, separateFiles } = options

const { state, initializeSession } = session()
await initializeSession()
Expand All @@ -40,21 +42,17 @@ export const pullComponentsCommand = program
konsola.warn(`No components found in the space ${space}`)
return
}
await saveComponentsToFiles(space, components, {
path,
filename,
separateFiles,
})
const msgFilename = filename ? `${filename}.json` : `components.${space}.json`
await saveComponentsToFiles(space, components, options)
const msgFilename = `${filename}.${suffix}.json`

if (separateFiles) {
if (filename) {
if (filename !== 'components') {
konsola.warn(`The --filename option is ignored when using --separate-files`)
}
konsola.ok(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(path ? `${path}` : './')}`)
konsola.ok(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(path ? `${path}` : './storyblok/components')}`)
return
}
konsola.ok(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(path ? `${path}/${msgFilename}` : `${msgFilename}`)}`)
konsola.ok(`Components downloaded successfully in ${chalk.hex(colorPalette.PRIMARY)(path ? `${path}/${msgFilename}` : `./storyblok/components/${msgFilename}`)}`)
}
catch (error) {
handleError(error as Error, verbose)
Expand Down

0 comments on commit 6cabaab

Please sign in to comment.