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

Initializers for samples (i.e. npm init sitecore-jss) #881

Merged
merged 106 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from 89 commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
08a1235
WIP: nextjs generator
Nov 15, 2021
0c22440
WIP: diy generator
Nov 16, 2021
1b063a6
WIP: nextjs generator - build templates
Nov 16, 2021
af1526c
Start of dedicated package 'create-sitecore-jss'
ambrauer Nov 16, 2021
95a9b8c
remove package-lock
ambrauer Nov 16, 2021
06143ae
Stubbed out build-templates.ts, added .gitignore
ambrauer Nov 16, 2021
9db0d7e
added build templates
addy-pathania Nov 17, 2021
d333ed8
WIP: nextjs initializer- ejs file render
Nov 17, 2021
f606310
Handling template command line parameter / prompt
ambrauer Nov 17, 2021
e046d58
Allow token replacement on file names
ambrauer Nov 17, 2021
d13a632
remove remaining disconnected files
ambrauer Nov 17, 2021
58a4e6e
Added check for empty directory
ambrauer Nov 17, 2021
d370675
Remove remaining styleguide code
ambrauer Nov 17, 2021
175bed0
test name change for lerna versioning
ambrauer Nov 17, 2021
0847304
updated yarn.lock
ambrauer Nov 17, 2021
451c35d
lerna test
ambrauer Nov 17, 2021
1036285
Revert "lerna test"
ambrauer Nov 17, 2021
3d18acf
get rid of mkdirp helper in favor of fs-extra
ambrauer Nov 17, 2021
4765263
Add support for 'add' positinal param
Nov 18, 2021
010a3b3
Initial watch script
ambrauer Nov 18, 2021
6ffd8cd
Fix templates, add prefix flag
Nov 18, 2021
ac78d03
added logs, detect initializer, feed args from json
addy-pathania Nov 19, 2021
c044535
refined the config file and added switch case to initializers
addy-pathania Nov 19, 2021
53b1dc1
merged with diy-generator-watch
addy-pathania Nov 19, 2021
9320377
Adding diffing to 'add'
Nov 19, 2021
066b79f
Fix merge conflict
Nov 19, 2021
ce6228d
Styleguide sub-initializer WIP: prompts for diffs working
Nov 22, 2021
d62357a
Update yes flag to override with passed in args
Nov 22, 2021
2a3eeef
WIP: Add dependencies/scripts to package.json during post-init
Nov 22, 2021
f592b84
Basic "next steps" introduced, some linting errors fixed
ambrauer Nov 22, 2021
029724e
WIP: Removing code duplication between files, start refactor package.…
Nov 22, 2021
d688043
Fix merge conflicts
Nov 22, 2021
082ceb3
WIP: package.json, lint
Nov 23, 2021
007a376
Add diff prompt to package.json, use diffJson method for .json files
Nov 23, 2021
64d0919
Add jss cli to base nextjs template and remove message about yarn
Nov 23, 2021
6be06ac
Add diff to package.json, add some missing template files
Nov 23, 2021
128a9d2
Move styleguide Navigation component to proper place in src, fix tsco…
Nov 23, 2021
d7972de
Remove unused stuff in cli package
Nov 24, 2021
804ea27
Diy generator yarn install (#861)
CobyPear Nov 24, 2021
b52ba85
Merge branch 'diy-generator' of github.com:Sitecore/jss into diy-gene…
Nov 24, 2021
a6a9696
Update error handling for transformFiles
Nov 24, 2021
d63f457
Start adding unit tests for shared functions
Nov 24, 2021
191cf82
Add test(s)
Nov 24, 2021
7b17dd1
Add error message when adding post-init to non-JSS app
Nov 29, 2021
709c748
Reorganize and refactor some base functionality
Nov 29, 2021
f3069e6
WIP: Unit tests for helpers
Nov 29, 2021
4e4992c
Add coverage script, add support for deep merge of package.json files
illiakovalenko Nov 30, 2021
c5271bc
Cover helpers by UT
illiakovalenko Nov 30, 2021
f47f486
Cover diffFiles by UT
illiakovalenko Nov 30, 2021
81c4bd2
Minor fixes
Nov 30, 2021
292ce78
Fix isJssApp UT
Nov 30, 2021
4497111
merged with dev
addy-pathania Nov 30, 2021
b7a544e
merge with dev and refactor
addy-pathania Nov 30, 2021
94e62f6
Update diffFiles test, fix sinon wrap error
Nov 30, 2021
6c93952
Add litFix command, add missing ejs logic to connected demo tsx
Nov 30, 2021
0a028d5
group tests
illiakovalenko Dec 1, 2021
205e898
Cover transform by UT
illiakovalenko Dec 1, 2021
db02682
Cover cmd by UT
illiakovalenko Dec 1, 2021
9e0e23d
Restructure folders, delay install
Dec 1, 2021
a9e474b
Fixes before demo
Dec 2, 2021
cffc43d
Merge branch 'dev' into diy-generator
ambrauer Dec 3, 2021
0ad2efe
NextjsAnswer cleanup (remove redundant props, move/rename file to fol…
ambrauer Dec 3, 2021
9642ce6
apply sitemap-fetcher plugin for disconnected
ambrauer Dec 3, 2021
06131ff
apply next.config plugin changes
ambrauer Dec 3, 2021
18813cd
Remove unnecessary devDependencies (main packages include own type de…
ambrauer Dec 3, 2021
9bd1354
Rename transformPostInit to writeFiles, fix some tests
Dec 3, 2021
f98485e
remove monorepo dev dependencies if dev environment
ambrauer Dec 3, 2021
3c746f3
Merge branch 'diy-generator' of https://github.com/Sitecore/jss into …
ambrauer Dec 3, 2021
dc1d1d4
Fix scaffold script
Dec 3, 2021
a25edd4
added tests for writePackageJson helper
ambrauer Dec 3, 2021
000cf2d
Revert "Fix scaffold script"
Dec 3, 2021
7adb382
Merge branch 'diy-generator' of github.com:Sitecore/jss into diy-gene…
Dec 3, 2021
636993b
scaffold-component updates for disconnected/styleguide
ambrauer Dec 6, 2021
907ad28
removed extra sitemapFetcher import
ambrauer Dec 6, 2021
f7f60b7
fix removeDevDependencies check, consolidation in [[...path]].tsx
ambrauer Dec 6, 2021
9a9f5f2
added _app.tsx (with bootstrap, nprogress) for nextjs-styleguide
ambrauer Dec 6, 2021
77720aa
"yes" handling for subsequent initializers (don't prompt for diffs wh…
ambrauer Dec 6, 2021
073f05d
only pass along __true__ "yes" answers
ambrauer Dec 6, 2021
677833d
Initializers internationalization (#868)
illiakovalenko Dec 7, 2021
4306bdb
[NextJS] Refactor scaffold script to make it pluggable (#870)
illiakovalenko Dec 8, 2021
36fb787
[Initializers] Refactor prompts and answers (#872)
illiakovalenko Dec 8, 2021
c3aa4b2
Update some ejs closing tags to trim unwanted newline
Dec 8, 2021
39dad38
Refactor post-initializer flow (#874)
ambrauer Dec 8, 2021
81aa5f8
Fixed watch mode
ambrauer Dec 8, 2021
8d2e075
* #511292 fixed issue where transform wasn't occurring on package.jso…
ambrauer Dec 8, 2021
06a0c81
only run lint --fix if a lint script exists
ambrauer Dec 8, 2021
4c1480d
[Initializers] Split `force`, `yes` flags (#877)
illiakovalenko Dec 9, 2021
63288cb
Add dynamic logic to init factory and base templates prompt choices
Dec 9, 2021
4b270d9
Add silent option to run
Dec 9, 2021
86e469e
Add getAppPrefix helper to ejs data
Dec 10, 2021
56e347e
remove 'yes' on initializer result (force now handling)
ambrauer Dec 10, 2021
90a8d66
updates from pr feedback (error handling, language, defaults)
ambrauer Dec 10, 2021
ca5a827
Resolve PR comments
Dec 10, 2021
0fa83b2
Merge branch 'diy-generator' of github.com:Sitecore/jss into diy-gene…
Dec 10, 2021
9bd4f92
bump hostname prompt before fetchWith (better flow when nextjs adds p…
ambrauer Dec 10, 2021
7e812b0
use template name for default folder name (if appName not provided)
ambrauer Dec 10, 2021
f3ac55d
Resolve more PR comments
Dec 10, 2021
f458ae5
Merge branch 'diy-generator' of github.com:Sitecore/jss into diy-gene…
Dec 10, 2021
6b7dc43
Add error handling for 'en' language input
Dec 10, 2021
f908f76
more PR feedback updates
ambrauer Dec 10, 2021
dd4363b
Resolve comments, make tests green
Dec 10, 2021
69d9c0b
Merge branch 'diy-generator' of github.com:Sitecore/jss into diy-gene…
Dec 10, 2021
5b6f71f
Update yarn.lock - fix CI
Dec 10, 2021
f628974
Add del-cli
Dec 10, 2021
0b20589
Dynamically import watch.json, error when not there
Dec 10, 2021
93abaa1
added tests for getBaseTemplates. fixed/improved "unkown template" er…
ambrauer Dec 13, 2021
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
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
{
CobyPear marked this conversation as resolved.
Show resolved Hide resolved
"editor.fontSize": 13,
"launch": {
"name": "Launch via npm",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/",
"runtimeArgs": ["run-script", "debug"],
at
}
}
10 changes: 10 additions & 0 deletions packages/create-sitecore-jss/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": [
"../../.eslintrc",
"../../eslint-configs/typescript"
],
"ignorePatterns": [
"src/templates/**/*",
"src/common/test-data/**/*"
]
}
2 changes: 2 additions & 0 deletions packages/create-sitecore-jss/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
types/
package-lock.json
18 changes: 18 additions & 0 deletions packages/create-sitecore-jss/.nycrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extension": [
".ts"
],
"exclude": [
"**/*.d.ts",
"**/*.test.ts",
"src/templates/**/*",
"src/common/test-data",
"dist"
],
"all": true,
"reporter": [
"json-summary",
"text"
],
"require": ["ts-node/register"]
}
59 changes: 59 additions & 0 deletions packages/create-sitecore-jss/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"name": "create-sitecore-jss",
"version": "20.0.0-canary.55",
"description": "Sitecore JSS initializer",
"bin": "./dist/index.js",
"scripts": {
"build": "npm run clean && tsc && ts-node ./scripts/build-templates.ts",
"clean": "npx rimraf -rf dist types",
"lint": "eslint --no-eslintrc -c .eslintrc ./src/**/*.ts",
"watch": "ts-node ./scripts/watch-templates.ts",
"test": "mocha --require ts-node/register \"./src/**/*.test.ts\"",
"coverage": "nyc npm test"
},
"repository": {
"type": "git",
"url": "https://github.com/Sitecore/jss.git",
"directory": "packages/create-sitecore-jss"
},
"homepage": "https://jss.sitecore.com",
"author": "Sitecore Corporation",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/Sitecore/jss/issues"
},
"files": [
"dist"
],
"dependencies": {
"chalk": "^4.1.2",
"cross-spawn": "^7.0.0",
"diff": "^5.0.0",
"ejs": "^3.1.6",
"fs-extra": "^10.0.0",
"glob": "^7.2.0",
"inquirer": "^8.2.0",
"minimist": "^1.2.5"
},
"devDependencies": {
"@types/chai": "^4.2.22",
"@types/cross-spawn": "^6.0.0",
"@types/diff": "^5.0.1",
"@types/ejs": "^3.1.0",
"@types/fs-extra": "^9.0.13",
"@types/glob": "^7.2.0",
"@types/inquirer": "^8.1.3",
"@types/minimist": "^1.2.2",
"@types/mocha": "^9.0.0",
"@types/node": "^16.11.7",
"@types/sinon": "^10.0.6",
"chai": "^4.3.4",
"chokidar": "^3.5.2",
"eslint": "^7.15.0",
"mocha": "^9.1.3",
"nyc": "^15.1.0",
"sinon": "^12.0.1",
"ts-node": "^10.4.0",
"typescript": "~4.3.5"
}
}
12 changes: 12 additions & 0 deletions packages/create-sitecore-jss/scripts/build-templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import path from 'path';
import fs from 'fs-extra';
const templatesFolder = path.resolve(__dirname, '../src/templates');
const distFolder = path.resolve(__dirname, '../dist/templates');

// Copy templates to dist
fs.copy(templatesFolder, distFolder, (err: Error) => {
if (err) {
console.log('An error occurred while copying the folder.');
throw err;
}
});
27 changes: 27 additions & 0 deletions packages/create-sitecore-jss/scripts/watch-templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import chalk from 'chalk';
import chokidar from 'chokidar';
import path from 'path';
import watch from '../watch.json';
import { initRunner } from '../src/init-runner';

chokidar
.watch(path.join(process.cwd(), '.\\src\\templates'), { ignoreInitial: true })
.on('ready', () => ready())
.on('all', (event, path) => callback(event, path));

async function ready() {
console.log(chalk.green('Initializing app...'));
await initializeApps(false);
console.log(chalk.green('Initializing app complete. Watching for changes...'));
}

async function callback(event?: string, path?: string) {
const color = event === 'add' ? chalk.green : event === 'unlink' ? chalk.red : chalk.white;
console.table(color(`${event} ${path}`));
await initializeApps(true);
}

const initializeApps = async (noInstall: boolean) => {
const initializers = watch.initializers || [];
await initRunner(initializers, { ...watch.args, templates: initializers, noInstall });
ambrauer marked this conversation as resolved.
Show resolved Hide resolved
};
17 changes: 17 additions & 0 deletions packages/create-sitecore-jss/src/InitializerFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import path from 'path';
import chalk from 'chalk';
import { Initializer } from './common/Initializer';

export class InitializerFactory {
async create(name: string): Promise<Initializer> {
try {
const { default: Initializer } = await import(
path.resolve(__dirname, 'initializers', name, 'index')
);
return new Initializer();
} catch (error) {
console.error(chalk.red(`Unsupported template '${name}'`));
throw error;
}
}
}
12 changes: 12 additions & 0 deletions packages/create-sitecore-jss/src/common/Initializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { BaseArgs } from './args/base';

export interface InitializerResults {
appName: string;
initializers?: string[];
nextSteps?: string[];
yes?: boolean;
ambrauer marked this conversation as resolved.
Show resolved Hide resolved
}
export interface Initializer {
isBase: boolean;
init: (args: BaseArgs) => Promise<InitializerResults>;
}
18 changes: 18 additions & 0 deletions packages/create-sitecore-jss/src/common/args/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ClientAppAnswer } from '../prompts/base';

type Arg = string | number | boolean;

export interface BaseArgs {
[key: string]: Arg | Arg[] | undefined;
templates: string[];
destination: string;
silent?: boolean;
force?: boolean;
yes?: boolean;
}

export interface ClientAppArgs extends BaseArgs, Partial<ClientAppAnswer> {
appPrefix?: boolean;
}

export type NodeAppArgs = BaseArgs;
CobyPear marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 4 additions & 0 deletions packages/create-sitecore-jss/src/common/args/styleguide.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { StyleguideAnswer } from '../prompts/styleguide';
import { ClientAppArgs } from './base';

export interface StyleguideArgs extends ClientAppArgs, Partial<StyleguideAnswer> {}
CobyPear marked this conversation as resolved.
Show resolved Hide resolved
49 changes: 49 additions & 0 deletions packages/create-sitecore-jss/src/common/prompts/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import chalk from 'chalk';
import { DistinctQuestion } from 'inquirer';

export enum FetchWith {
GraphQL = 'GraphQL',
REST = 'REST',
}

export interface ClientAppAnswer {
appName: string;
fetchWith: FetchWith;
hostName: string;
}

export const clientAppPrompts: DistinctQuestion[] = [
{
type: 'input',
name: 'appName',
message: 'What is the name of your app?',
default: 'sitecore-jss-app',
validate: (input: string): boolean => {
if (!/^[a-z\-_.]+$/.test(input)) {
console.error(
chalk.red(
`${input} is not a valid name; you may use lowercase letters, hyphens, and underscores only.`
)
);
return false;
}
return true;
},
},
{
type: 'list',
name: 'fetchWith',
message: 'How would you like to fetch Layout and Dictionary data?',
choices: Object.values(FetchWith),
default: FetchWith.GraphQL,
},
{
type: 'input',
name: 'hostName',
message: 'What is your Sitecore hostname?',
default: 'https://cm.jss.localhost',
},
];

// node-headless-proxy, headless-ssr-exp-edge
export const nodeAppPrompts: { [key: string]: unknown }[] = [];
CobyPear marked this conversation as resolved.
Show resolved Hide resolved
31 changes: 31 additions & 0 deletions packages/create-sitecore-jss/src/common/prompts/styleguide.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Answers, DistinctQuestion } from 'inquirer';
import chalk from 'chalk';

export interface StyleguideAnswer extends Answers {
language?: string;
}

const LANGUAGE_REGEXP = /^(([a-z]{2}-[A-Z]{2})|([a-z]{2}))$/;

export const styleguidePrompts: DistinctQuestion<StyleguideAnswer>[] = [
{
type: 'input',
name: 'language',
message:
'Which additional language do you want to support (en is default and required)? Leave empty if not needed',
Copy link
Contributor Author

@CobyPear CobyPear Dec 10, 2021

Choose a reason for hiding this comment

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

Review wording for this question. @ancaemcken, thoughts?

validate: (input: string): boolean => {
CobyPear marked this conversation as resolved.
Show resolved Hide resolved
if (!input) return true;

if (!LANGUAGE_REGEXP.test(input)) {
console.error(
chalk.red(
`${input} is not a valid code; you may use language identifier, for example 'en',\nor you can add country code, for example 'US'. The language code is then 'en-US'.`
)
);
return false;
}

return true;
},
},
];
3 changes: 3 additions & 0 deletions packages/create-sitecore-jss/src/common/steps/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { installPackages, lintFix } from './install';
export { nextSteps } from './next';
export { diffFiles, merge, transform, transformFilename } from './transform';
51 changes: 51 additions & 0 deletions packages/create-sitecore-jss/src/common/steps/install.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import path from 'path';
import chalk from 'chalk';
import { run } from '../utils/cmd';
import { isDevEnvironment, openPackageJson } from '../utils/helpers';

/**
* @param {string} projectFolder
* @param {boolean} [silent]
*/
export const installPackages = (projectFolder: string, silent?: boolean) => {
silent || console.log(chalk.cyan('Installing packages...'));

if (isDevEnvironment(projectFolder)) {
silent || console.log(chalk.yellow('Detected development environment.'));

run(
'yarn',
['install'],
{
cwd: projectFolder,
encoding: 'utf8',
},
silent
);
} else {
run(
'npm',
['install'],
{
cwd: projectFolder,
encoding: 'utf8',
},
silent
);
}
};

/**
* @param {string} projectFolder
* @param {boolean} [silent]
*/
export const lintFix = (projectFolder: string, silent?: boolean) => {
const packagePath = path.join(projectFolder, 'package.json');
const pkg = openPackageJson(packagePath);
if (!pkg?.scripts?.lint) {
return;
}

silent || console.log(chalk.cyan('Linting app...'));
run('npm', ['run', 'lint', '--', '--fix'], { cwd: projectFolder, encoding: 'utf8' });
};
45 changes: 45 additions & 0 deletions packages/create-sitecore-jss/src/common/steps/next.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import chalk from 'chalk';

export const nextSteps = async (appName: string, nextStepsArr: string[]) => {
console.log(chalk.red(' -/oyhdmNNNNmdhyo/- '));
console.log(chalk.red(' :sdMMMMMMMMMMMMMMMMMMMMds: '));
console.log(chalk.red(' :yNMMMMMMMMMMMMMMMMMMMMMMMMMMNy: '));
console.log(chalk.red(' /mMMMMMMMMMNdyo+//://+shmMMMMMMMMMm/ '));
console.log(chalk.red(' :mMMMMMMMMh+. `:smMMMMMMMm: '));
console.log(chalk.red(' `yMMMMMMMm+` :yMMMMMMMs` '));
console.log(chalk.red(' `dMMMMMMN/ .hMMMMMMd` '));
console.log(chalk.red(' `mMMMMMMh` -s/+MMMMMMd` '));
console.log(chalk.red(' yMMMMMMh `:yNMMMs/MMMMMMy '));
console.log(chalk.red(' :MMMMMMm` `hMMMMMMMsoMMMMMM-'));
console.log(chalk.red(' yMMMMMM/ dMMMMMMM:mMMMMMy'));
console.log(chalk.red(' NMMMMMN` oMyossss:sMMMMMm'));
console.log(chalk.red(' MMMMMMN yM:NMMMMyoMMMMMN'));
console.log(chalk.red(' mMMMMMM` :Md+MMMMMoyMMMMMm'));
console.log(chalk.red(' yMMMMMM+ :NN+NMMMMM-NMMMMMy'));
console.log(chalk.red(' :MMMMMMN:- `sMdyMNymMMosMMMMMM-'));
console.log(chalk.red(' yMMMMMMd/o` .oNdhmMhhMmh++MMMMMMy '));
console.log(chalk.red(' `dMMMMMMm+do.- ./oyhhhNNhyNMMNosMMMMMMd` '));
console.log(chalk.red(' `dMMMMMMMssNdhsoo+/+oyyyydMmhhhMMMNs+mMMMMMMd` '));
console.log(chalk.red(' `yMMMMMMMNyydMNddddddddddhmMMMMho+dMMMMMMMy` '));
console.log(chalk.red(' :mMMMMMMMMmhhhdNMMMMMMMMmhssohMMMMMMMMm: '));
console.log(chalk.red(' /mMMMMMMMMMMNdhyyyyyyyhmMMMMMMMMMMm/ '));
console.log(chalk.red(' :yNMMMMMMMMMMMMMMMMMMMMMMMMMMNy: '));
console.log(chalk.red(' :sdMMMMMMMMMMMMMMMMMMMMds: '));
console.log(chalk.red(' `-/oyhdmNNNNmdhyo/- '));
console.log();
console.log(chalk.white(' __________'));
console.log(chalk.white(' __ / / __/ __/'));
console.log(chalk.white(' / // /\\ \\_\\ \\ '));
console.log(chalk.white(' \\___/___/___/'));
console.log();
console.log(`JSS application ${chalk.green(appName)} is ready!`);
console.log();
console.log(chalk.yellow('Next steps:'));
nextStepsArr.forEach((step) => {
console.log(step);
});
console.log('* Enable source control (i.e. git init) (optional)');
console.log('* Check out the JSS documentation at https://jss.sitecore.com');
console.log();
console.log(chalk.green('Enjoy!'));
};
Loading