-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from sandeep-vedam/feature/create-app-2
Feature/create app 2
- Loading branch information
Showing
32 changed files
with
3,881 additions
and
174 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
import { green, bold, red } from 'kolorist' | ||
import path from 'path' | ||
import { execa } from 'execa' | ||
import fs from 'fs' | ||
import replaceInFile from 'replace-in-file' | ||
import ora from 'ora' | ||
const spinner = ora() | ||
|
||
/** | ||
* This function copies Lightning fixtures to the target directory for creating a L3 application. | ||
*/ | ||
|
||
export const copyLightningFixtures = (config) => { | ||
return new Promise((resolve) => { | ||
const targetDir = config.appFolder || '' | ||
if (config.appFolder && fs.existsSync(targetDir)) { | ||
exit(red(bold('The target directory ' + targetDir + ' already exists'))) | ||
} | ||
//this will be removed once ts support is added | ||
fs.cpSync(path.join(path.join(config.fixturesBase, 'js'), 'default'), targetDir, { | ||
recursive: true, | ||
}) | ||
fs.cpSync(path.join(config.fixturesBase, 'common/public'), path.join(targetDir, 'public'), { | ||
recursive: true, | ||
}) | ||
|
||
resolve(targetDir) | ||
}) | ||
} | ||
|
||
/** | ||
* This function adds eslint related configuration to the project folder to be created | ||
* @param config | ||
* @returns {boolean} | ||
*/ | ||
export const addESlint = (config) => { | ||
// Make husky dir | ||
fs.mkdirSync(path.join(config.targetDir, '.husky'), { recursive: true }) | ||
|
||
// Copy husky hook | ||
fs.copyFileSync( | ||
path.join(config.fixturesBase, 'common/eslint/husky/pre-commit'), | ||
path.join(config.targetDir, '.husky/pre-commit') | ||
) | ||
|
||
// Copy editor config from common | ||
fs.copyFileSync( | ||
path.join(config.fixturesBase, 'common/eslint/.editorconfig'), | ||
path.join(config.targetDir, '.editorconfig') | ||
) | ||
|
||
// Copy eslintignore from common | ||
fs.copyFileSync( | ||
path.join(config.fixturesBase, 'common/eslint/.eslintignore'), | ||
path.join(config.targetDir, '.eslintignore') | ||
) | ||
|
||
// Copy eslintrc.js from fixtured specfic directory | ||
fs.copyFileSync( | ||
path.join(config.fixturesBase, 'common/eslint/.eslintrc.cjs'), | ||
path.join(config.targetDir, '.eslintrc.cjs') | ||
) | ||
|
||
// Copy IDE stuff from fixture base | ||
fs.cpSync(path.join(config.fixturesBase, 'common/ide'), path.join(config.targetDir), { | ||
recursive: true, | ||
}) | ||
|
||
// Copy and merge fixture specific package.json | ||
const origPackageJson = JSON.parse(fs.readFileSync(path.join(config.targetDir, 'package.json'))) | ||
const eslintPackageJson = JSON.parse( | ||
fs.readFileSync(path.join(config.fixturesBase, 'common/eslint/package.json')) | ||
) | ||
fs.writeFileSync( | ||
path.join(config.targetDir, 'package.json'), | ||
JSON.stringify( | ||
{ | ||
...origPackageJson, | ||
...eslintPackageJson, | ||
devDependencies: { | ||
...(origPackageJson.devDependencies || {}), | ||
...(eslintPackageJson.devDependencies || {}), | ||
}, | ||
}, | ||
null, | ||
2 | ||
) | ||
) | ||
|
||
return true | ||
} | ||
|
||
/** | ||
* This function sets the version by fetching the latest blits version | ||
* @param config | ||
* @returns {Promise<unknown>} | ||
*/ | ||
export const setBlitsVersion = (config) => { | ||
return new Promise((resolve, reject) => { | ||
execa('npm', ['view', '@lightningjs/blits', 'version']) | ||
.then(({ stdout }) => { | ||
replaceInFile.sync({ | ||
files: config.targetDir + '/*', | ||
from: /\{\$blitsVersion\}/g, | ||
to: '^' + stdout, | ||
}) | ||
resolve() | ||
}) | ||
.catch((e) => { | ||
spinnerMsg.fail(`Error occurred while setting blits version\n\n${e}`) | ||
reject() | ||
}) | ||
}) | ||
} | ||
|
||
/** | ||
* Display a message and start a spinner with the specified message. | ||
* | ||
* @param {string} msg - The message to display while starting the spinner. | ||
*/ | ||
export const spinnerMsg = { | ||
start(msg) { | ||
console.log(' ') | ||
spinner.start(msg) | ||
}, | ||
stop() { | ||
spinner.stop() | ||
}, | ||
succeed(msg) { | ||
spinner.succeed(msg) | ||
}, | ||
fail(msg) { | ||
spinner.fail(msg) | ||
console.log(' ') | ||
}, | ||
warn(msg) { | ||
spinner.warn(msg) | ||
}, | ||
} | ||
|
||
/** | ||
* This function replaces placeholders like '{$appName}' and '{$appPackage}' in files within the target directory | ||
* with the actual values from the configuration object. | ||
* | ||
* @param {Object} config - The configuration object containing application data. | ||
*/ | ||
export const setAppData = (config) => { | ||
replaceInFile.sync({ | ||
files: config.targetDir + '/*', | ||
from: /\{\$appPackage\}/g, | ||
to: config.appPackage, | ||
}) | ||
|
||
replaceInFile.sync({ | ||
files: config.targetDir + '/*', | ||
from: /\{\$appName\}/g, | ||
to: config.appName, | ||
}) | ||
} | ||
|
||
/** | ||
* Display an error message and exit the program with an error status. | ||
* | ||
* @param {string} msg - The error message to display before exiting the program. | ||
*/ | ||
export const exit = (msg) => { | ||
spinnerMsg.fail(msg) | ||
process.exit() | ||
} | ||
|
||
/** | ||
* Initialize an empty Git repository in the specified directory and copy a .gitignore file. | ||
* | ||
* @param {string} cwd - The current working directory where the Git repository will be created. | ||
* @param {string} fixturesBase - The base directory for fixtures. | ||
* @returns {Promise} A Promise that resolves when the Git initialization and file copying are completed successfully | ||
*/ | ||
export const gitInit = (cwd, fixturesBase) => { | ||
spinnerMsg.start('Initializing empty GIT repository') | ||
let msg | ||
return execa('git', ['init'], { cwd }) | ||
.then(({ stdout }) => (msg = stdout)) | ||
.then(() => { | ||
return fs.copyFileSync( | ||
path.join(fixturesBase, 'common/git/.gitignore'), | ||
path.join(cwd, '.gitignore') | ||
) | ||
}) | ||
.then(() => spinnerMsg.succeed(msg)) | ||
.catch((e) => spinnerMsg.fail(`Error occurred while creating git repository\n\n${e}`)) | ||
} | ||
|
||
/** | ||
* Checks whether the give path is valid | ||
* @param path | ||
* @returns {boolean} | ||
*/ | ||
export const isValidPath = (path) => { | ||
try { | ||
// Check if the path exists | ||
fs.accessSync(path, fs.constants.F_OK) | ||
return true | ||
} catch (err) { | ||
// The path does not exist or is not accessible | ||
return false | ||
} | ||
} | ||
|
||
export const done = (config) => { | ||
console.log('') | ||
console.log('--------------------------------------------------------------------') | ||
console.log(' Your new boilerplate Lightning 3 App has been created! ⚡️') | ||
console.log('--------------------------------------------------------------------') | ||
console.log('') | ||
console.log('Follow the steps below to get started:') | ||
console.log('') | ||
console.log(` ${green(bold(`cd ${config.appFolder}`))}`) | ||
console.log(` ${green(bold('npm install'))}`) | ||
console.log(` ${green(bold('npm run dev'))}`) | ||
} |
This file was deleted.
Oops, something went wrong.
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 |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#!/usr/bin/env node | ||
import path from 'path' | ||
import process from 'process' | ||
import { dirname } from 'path' | ||
import prompts from 'prompts' | ||
import { fileURLToPath } from 'url' | ||
import fs from 'fs' | ||
import { red, bold } from 'kolorist' | ||
import sequence from '../src/helpers/sequence.js' | ||
import validatePackage from 'validate-npm-package-name' | ||
import { | ||
addESlint, | ||
copyLightningFixtures, | ||
setAppData, | ||
setBlitsVersion, | ||
gitInit, | ||
done, spinnerMsg | ||
} from './helpers.js' | ||
|
||
const defaultBanner = ` | ||
-------------------------------------------------------------------- | ||
Welcome to Blits - The App development framework for Lightning 3 ⚡️ | ||
-------------------------------------------------------------------- | ||
Answer the questions below to set up a new Lightning 3 Blits App | ||
` | ||
|
||
console.log(defaultBanner) | ||
|
||
const __filename = fileURLToPath(import.meta.url) | ||
const __dirname = dirname(__filename) | ||
|
||
const fixturesBase = path.join( | ||
__dirname, | ||
'../boilerplate') | ||
|
||
const questions = [ | ||
{ | ||
type: 'text', | ||
name: 'appName', | ||
message: 'What is the name of your App?', | ||
format: val => { | ||
// Check if the provided application name is empty | ||
if (!val.trim()) { | ||
spinnerMsg.fail(red(bold("Please provide a name for the App"))) | ||
return process.exit(1) | ||
} else { | ||
return val | ||
} | ||
}, | ||
initial: 'My Blits App', // Default value for the application name | ||
}, | ||
{ | ||
type: 'text', | ||
name: 'appPackage', | ||
message: 'What is the package name of your App?', | ||
format: val => { | ||
// Validate the package name using validate-npm-package-name | ||
if (!validatePackage(val).validForNewPackages) { | ||
spinnerMsg.fail(red(bold("Please provide a valid package name"))) | ||
return process.exit(1) | ||
} else { | ||
return val | ||
} | ||
}, | ||
initial: prev => `${prev.replace(/[\sA-Z]/g, str => str === ' ' ? '-' : str.toLowerCase())}`, | ||
}, | ||
{ | ||
type: 'text', | ||
name: 'appFolder', | ||
message: 'In what folder (relative to the current location) should the App be generated?', | ||
format: (val, prev) => { | ||
// Regular expression to validate whether the path is Unix/Windows-based | ||
const pathRegex = /([A-Za-z]:)?([\\/]+\w+)+/ | ||
// Check if the provided path matches the defined regex | ||
if (pathRegex.test(val)) { | ||
try { | ||
// Check if the path exists | ||
if (fs.statSync(val)) { | ||
// Return the resolved file path using path.join | ||
return `${path.join(val, prev.appPackage)}` | ||
} | ||
} catch (e) { | ||
// Handle case where an error occurred during file system interaction | ||
if (e.code === 'ENOENT') { | ||
spinnerMsg.fail(red(bold("Entered directory path is invalid, please enter a valid directory!"))) | ||
process.exit() | ||
} | ||
} | ||
} else if (val === prev.appPackage) { | ||
return path.join(process.cwd(), prev.appPackage) | ||
} | ||
}, | ||
initial: (prev, val) => val.appPackage, | ||
}, | ||
{ | ||
type: 'toggle', | ||
name: 'esLint', | ||
message: 'Do you want to enable eslint?', | ||
initial: 'true', | ||
active: 'Yes', | ||
inactive: 'No', | ||
}, | ||
{ | ||
type: 'toggle', | ||
name: 'gitInit', | ||
message: 'Do you want to generate an git repository?', | ||
initial: 'true', | ||
active: 'Yes', | ||
inactive: 'No', | ||
}, | ||
] | ||
|
||
|
||
const createApp = () => { | ||
return new Promise(resolve => { | ||
let config | ||
sequence([ | ||
async () => { | ||
const onCancel = () => { | ||
process.exit() | ||
} | ||
config = await prompts(questions, { onCancel }) | ||
config.fixturesBase = fixturesBase | ||
return config | ||
}, | ||
() => { | ||
spinnerMsg.start(`Generating new App "${config.appName}" ...`) | ||
copyLightningFixtures(config).then(targetDir => (config.targetDir = targetDir)) | ||
spinnerMsg.succeed() | ||
}, | ||
() => setAppData(config), | ||
() => setBlitsVersion(config), | ||
() => config.esLint && addESlint(config), | ||
() => config.gitInit && gitInit(config.targetDir, config.fixturesBase), | ||
() => done(config) | ||
]) | ||
}) | ||
} | ||
|
||
createApp() |
This file was deleted.
Oops, something went wrong.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Oops, something went wrong.