-
Notifications
You must be signed in to change notification settings - Fork 151
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Refactored vue-nuxt project generator
- Loading branch information
1 parent
59af935
commit bc859c0
Showing
11 changed files
with
142 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 `/` | ||
} | ||
} |
Oops, something went wrong.