Skip to content

Commit

Permalink
refactor: Refactored vue-nuxt project generator
Browse files Browse the repository at this point in the history
  • Loading branch information
pascaionut12345 committed Mar 28, 2019
1 parent 59af935 commit bc859c0
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 178 deletions.
6 changes: 3 additions & 3 deletions src/project-generators/react-basic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {})

// Step 4: The generated page and component files are joined
const joinedPageFiles = joinComponentFiles(createdPageFiles)
const pageFiles: GeneratedFile[] = joinedPageFiles.files
const pageFiles = joinedPageFiles.files

const joinedComponentFiles = joinComponentFiles(createdComponentFiles)
const componentFiles: GeneratedFile[] = joinedComponentFiles.files
const componentFiles = joinedComponentFiles.files

// Step 5: Global settings are transformed into the root html file and the manifest file for PWA support
const manifestFile = createManifestJSONFile(uidl, ASSETS_PREFIX)
Expand Down Expand Up @@ -110,9 +110,9 @@ export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {})
const distFolder = buildFolderStructure({
componentFiles,
pageFiles,
staticFiles,
srcFiles,
distFiles,
publicFiles: staticFiles,
distFolderName: options.distPath || DEFAULT_OUTPUT_FOLDER,
})

Expand Down
17 changes: 4 additions & 13 deletions src/project-generators/react-basic/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,13 @@ import createRouterComponentGenerator from '../../component-generators/react/rea
import { createFolder, createFile } from '../../shared/utils/project-utils'
import { FILE_EXTENSIONS } from '../../shared/constants'

interface ReactFolderStructureParams {
componentFiles: GeneratedFile[]
pageFiles: GeneratedFile[]
staticFiles: GeneratedFile[]
srcFiles: GeneratedFile[]
distFiles: GeneratedFile[]
distFolderName: string
}

export const buildFolderStructure = (params: ReactFolderStructureParams): GeneratedFolder => {
const { componentFiles, pageFiles, staticFiles, srcFiles, distFiles } = params
export const buildFolderStructure = (params: FolderStructureParams): GeneratedFolder => {
const { componentFiles, pageFiles, publicFiles, srcFiles, distFiles } = params
const { distFolderName } = params

const componentsFolder = createFolder('components', componentFiles)
const pagesFolder = createFolder('pages', pageFiles)
const staticFolder = createFolder('static', staticFiles)
const componentsFolder = createFolder('components', componentFiles)
const staticFolder = createFolder('static', publicFiles)
const srcFolder = createFolder('src', srcFiles, [componentsFolder, pagesFolder, staticFolder])

return createFolder(distFolderName, distFiles, [srcFolder])
Expand Down
2 changes: 1 addition & 1 deletion src/project-generators/react-next/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {})
const distFolder = buildFolderStructure({
pageFiles,
componentFiles,
staticFiles,
distFiles,
publicFiles: staticFiles,
distFolderName: options.distPath || DEFAULT_OUTPUT_FOLDER,
})

Expand Down
16 changes: 4 additions & 12 deletions src/project-generators/react-next/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,21 +160,13 @@ export const createDocumentComponentFile = (uidl: ProjectUIDL): GeneratedFile |
return createFile('_document', FILE_EXTENSIONS.JS, documentComponent)
}

interface NextFolderStructureParams {
componentFiles: GeneratedFile[]
pageFiles: GeneratedFile[]
staticFiles: GeneratedFile[]
distFiles: GeneratedFile[]
distFolderName: string
}

export const buildFolderStructure = (params: NextFolderStructureParams): GeneratedFolder => {
const { componentFiles, pageFiles, staticFiles, distFiles } = params
export const buildFolderStructure = (params: FolderStructureParams): GeneratedFolder => {
const { componentFiles, pageFiles, publicFiles, distFiles } = params
const { distFolderName } = params

const componentsFolder = createFolder('components', componentFiles)
const pagesFolder = createFolder('pages', pageFiles)
const staticFolder = createFolder('static', staticFiles)
const componentsFolder = createFolder('components', componentFiles)
const staticFolder = createFolder('static', publicFiles)

return createFolder(distFolderName, distFiles, [pagesFolder, componentsFolder, staticFolder])
}
14 changes: 10 additions & 4 deletions src/project-generators/vue-basic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@ import vueProjectMapping from './vue-project-mapping.json'
import { FILE_EXTENSIONS } from '../../shared/constants'
import { createRouterFile, buildFolderStructure } from './utils'

const initGenerator = (): ComponentGenerator => {
return createVueGenerator({
const initGenerator = (options: ProjectGeneratorOptions): ComponentGenerator => {
const vueGenerator = createVueGenerator({
customMapping: vueProjectMapping,
})

if (options.customMapping) {
vueGenerator.addMapping(options.customMapping)
}

return vueGenerator
}

export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {}) => {
// Step 0: Create component generators, this will be removed later when we have factory functions for proj generators
const vueGenerator = initGenerator()
// Step 0: Initialize the component generator
const vueGenerator = initGenerator(options)

const { components = {}, root } = uidl
const { states = [] } = root.content
Expand Down
11 changes: 1 addition & 10 deletions src/project-generators/vue-basic/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,7 @@ import createVueRouterFileGenerator from '../../component-generators/vue/vue-rou
import { createFile, createFolder } from '../../shared/utils/project-utils'
import { FILE_EXTENSIONS } from '../../shared/constants'

interface VuewFolderStructureParams {
componentFiles: GeneratedFile[]
pageFiles: GeneratedFile[]
publicFiles: GeneratedFile[]
srcFiles: GeneratedFile[]
distFiles: GeneratedFile[]
distFolderName: string
}

export const buildFolderStructure = (params: VuewFolderStructureParams): GeneratedFolder => {
export const buildFolderStructure = (params: FolderStructureParams): GeneratedFolder => {
const { componentFiles, pageFiles, publicFiles, srcFiles, distFiles } = params
const { distFolderName } = params

Expand Down
2 changes: 2 additions & 0 deletions src/project-generators/vue-nuxt/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export const APP_ROOT_OVERRIDE = '{{ APP }}'
export const ASSETS_PREFIX = '/assets'
export const LOCAL_DEPENDENCIES_PREFIX = '../components/'
export const DEFAULT_OUTPUT_FOLDER = 'dist'
export const DEFAULT_PACKAGE_JSON = {
name: 'teleportHQ Project',
Expand Down
228 changes: 94 additions & 134 deletions src/project-generators/vue-nuxt/index.ts
Original file line number Diff line number Diff line change
@@ -1,159 +1,119 @@
import { extractPageMetadata } from '../../shared/utils/uidl-utils'
import { sanitizeVariableName } from '../../shared/utils/string-utils'
import createVueGenerator from '../../component-generators/vue/vue-component'
import { buildFolderStructure } from './utils'
import nuxtMapping from './nuxt-mapping.json'
import { ASSETS_PREFIX, DEFAULT_OUTPUT_FOLDER } from './constants'
import { createManifestJSON, createHtmlIndex } from '../../shared/utils/project-utils'

export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {}) => {
// Step 0: Create component generators, this will be removed later when we have factory functions for proj generators
import {
ASSETS_PREFIX,
DEFAULT_OUTPUT_FOLDER,
LOCAL_DEPENDENCIES_PREFIX,
DEFAULT_PACKAGE_JSON,
APP_ROOT_OVERRIDE,
} from './constants'
import { FILE_EXTENSIONS } from '../../shared/constants'

import {
createPageFile,
createComponentFile,
createManifestJSONFile,
createHtmlIndexFile,
createPackageJSONFile,
joinComponentFiles,
} from '../../shared/utils/project-utils'

const initGenerator = (options: ProjectGeneratorOptions): ComponentGenerator => {
const vueGenerator = createVueGenerator({
customMapping: { ...nuxtMapping },
})

// Step 1: Building the folder structure (rooted in dist by default) for the Nuxt project
const pagesFolder: GeneratedFolder = {
name: 'pages',
files: [],
subFolders: [],
}

const componentsFolder: GeneratedFolder = {
name: 'components',
files: [],
subFolders: [],
}

const staticFolder: GeneratedFolder = {
name: 'static',
files: [],
subFolders: [],
}

const distFolder: GeneratedFolder = {
name: options.distPath || DEFAULT_OUTPUT_FOLDER,
files: [],
subFolders: [pagesFolder, componentsFolder],
}

// Step 2: Initialization with project specific mappings and of other data structures
const { components, root } = uidl
const { states } = root.content
let collectedDependencies = {}
const result = {
outputFolder: distFolder,
assetsPath: ASSETS_PREFIX.slice(1), // remove the leading `/`
if (options.customMapping) {
vueGenerator.addMapping(options.customMapping)
}

const stateDefinitions = root.stateDefinitions
if (!states || !stateDefinitions) {
return result
}
return vueGenerator
}

const routerDefinitions = stateDefinitions.router
if (!routerDefinitions) {
return result
}
export default async (uidl: ProjectUIDL, options: ProjectGeneratorOptions = {}) => {
// Step 0: Initialize the component generator
const vueGenerator = initGenerator(options)

const { components = {}, root } = uidl
const { states = [] } = root.content

const stateDefinitions = root.stateDefinitions || {}
const routerDefinitions = stateDefinitions.router || null

// Step 1: The first level stateBranches (the pages) transformation in react components is started
const pagePromises = states.map(async (stateBranch) => {
const pageParams: PageFactoryParams = {
componentGenerator: vueGenerator,
stateBranch,
routerDefinitions,
componentOptions: {
assetsPrefix: ASSETS_PREFIX,
localDependenciesPrefix: LOCAL_DEPENDENCIES_PREFIX,
},
pageExtension: FILE_EXTENSIONS.VUE,
pageMetadataOptions: {
usePathAsFileName: true,
convertDefaultToIndex: true,
},
}
return createPageFile(pageParams)
})

// Step 3: Global settings are transformed into the root html file and the manifest file for PWA support
if (uidl.globals.manifest) {
const manifestJSON = createManifestJSON(uidl.globals.manifest, uidl.name, ASSETS_PREFIX)
const manifestFile: GeneratedFile = {
name: 'manifest',
extension: '.json',
content: JSON.stringify(manifestJSON, null, 2),
// Step 2: The components generation process is started
const componentPromises = Object.keys(components).map(async (componentName) => {
const componentUIDL = components[componentName]
const componentParams: ComponentFactoryParams = {
componentUIDL,
componentExtension: FILE_EXTENSIONS.VUE,
componentGenerator: vueGenerator,
componentOptions: { assetsPrefix: ASSETS_PREFIX },
}
return createComponentFile(componentParams)
})

staticFolder.files.push(manifestFile)
}
// Step 3: The process of creating the pages and the components is awaited
const createdPageFiles = await Promise.all(pagePromises)
const createdComponentFiles = await Promise.all(componentPromises)

const htmlIndexContent = createHtmlIndex(uidl, ASSETS_PREFIX, '{{ APP }}')
if (htmlIndexContent) {
const htmlFile: GeneratedFile = {
name: 'app',
extension: '.html',
content: htmlIndexContent,
}
// Step 4: The generated page and component files are joined
const joinedPageFiles = joinComponentFiles(createdPageFiles)
const pageFiles = joinedPageFiles.files

distFolder.files.push(htmlFile)
}
const joinedComponentFiles = joinComponentFiles(createdComponentFiles)
const componentFiles = joinedComponentFiles.files

// Step 4: Iterating through the first level state branches in the root and generating the components in the "/pages" folder
await Promise.all(
states.map(async (stateBranch) => {
const { value: pageKey, content: pageContent } = stateBranch
// Step 5: Global settings are transformed into the manifest file for PWA support
const manifestFile = createManifestJSONFile(uidl, ASSETS_PREFIX)
const staticFiles: GeneratedFile[] = [].concat(manifestFile)

if (typeof pageKey !== 'string' || typeof pageContent === 'string') {
return
}
const htmlIndexFile = createHtmlIndexFile(uidl, ASSETS_PREFIX, 'app', APP_ROOT_OVERRIDE)

const { componentName, fileName } = extractPageMetadata(routerDefinitions, pageKey, {
usePathAsFileName: true,
convertDefaultToIndex: true,
})
const pageComponent = {
name: componentName,
content: pageContent,
meta: {
fileName,
},
}

const pageResult = await vueGenerator.generateComponent(pageComponent, {
localDependenciesPrefix: '../components/',
})

collectedDependencies = { ...collectedDependencies, ...pageResult.externalDependencies }

const file: GeneratedFile = {
name: fileName,
content: pageResult.code,
extension: '.vue',
}

pagesFolder.files.push(file)
})
)

// Step 5: Components are generated into a separate /components folder
if (components) {
const [...generatedComponentFiles] = await Promise.all(
Object.keys(components).map(async (componentName) => {
const component = components[componentName]
const componentResult = await vueGenerator.generateComponent(component)
collectedDependencies = {
...collectedDependencies,
...componentResult.externalDependencies,
}

const file: GeneratedFile = {
name: sanitizeVariableName(component.name),
extension: '.vue',
content: componentResult.code,
}
return file
})
)

componentsFolder.files.push(...generatedComponentFiles)
const collectedDependencies = {
...joinedPageFiles.dependencies,
...joinedComponentFiles.dependencies,
}

// Step 6: External dependencies are added to the package.json file from the template project
const { sourcePackageJson } = options
if (sourcePackageJson) {
sourcePackageJson.dependencies = {
...sourcePackageJson.dependencies,
...collectedDependencies,
}
const packageFile = createPackageJSONFile(options.sourcePackageJson || DEFAULT_PACKAGE_JSON, {
dependencies: collectedDependencies,
projectName: uidl.name,
})

const packageFile: GeneratedFile = {
name: 'package',
extension: '.json',
content: JSON.stringify(sourcePackageJson, null, 2),
}
const distFiles = [htmlIndexFile, packageFile]

distFolder.files.push(packageFile)
}
// Step 7: Build the folder structure
const folderStructure = buildFolderStructure({
pageFiles,
componentFiles,
publicFiles: staticFiles,
distFiles,
distFolderName: options.distPath || DEFAULT_OUTPUT_FOLDER,
})

return result
return {
outputFolder: folderStructure,
assetsPath: ASSETS_PREFIX.slice(1), // remove the leading `/`
}
}
Loading

0 comments on commit bc859c0

Please sign in to comment.