Skip to content

Commit 4dff9d1

Browse files
CobyPearambraueraddy-pathaniailliakovalenko
authored
Initializers for samples (i.e. npm init sitecore-jss) (#881)
* WIP: nextjs generator * WIP: diy generator * WIP: nextjs generator - build templates * Start of dedicated package 'create-sitecore-jss' * remove package-lock * Stubbed out build-templates.ts, added .gitignore * added build templates * WIP: nextjs initializer- ejs file render * Handling template command line parameter / prompt * Allow token replacement on file names * remove remaining disconnected files * Added check for empty directory * Remove remaining styleguide code * test name change for lerna versioning * updated yarn.lock * lerna test * Revert "lerna test" This reverts commit 451c35d. * get rid of mkdirp helper in favor of fs-extra * Add support for 'add' positinal param * Initial watch script * Fix templates, add prefix flag * added logs, detect initializer, feed args from json * refined the config file and added switch case to initializers * Adding diffing to 'add' * Styleguide sub-initializer WIP: prompts for diffs working * Update yes flag to override with passed in args * WIP: Add dependencies/scripts to package.json during post-init * Basic "next steps" introduced, some linting errors fixed * WIP: Removing code duplication between files, start refactor package.json logic * WIP: package.json, lint * Add diff prompt to package.json, use diffJson method for .json files * Add jss cli to base nextjs template and remove message about yarn * Add diff to package.json, add some missing template files * Move styleguide Navigation component to proper place in src, fix tsconfig * Remove unused stuff in cli package * Diy generator yarn install (#861) * yarn install * added yarn.lock * added chalk, added initialized flag * Add yarn.lock Co-authored-by: Addy Pathania <[email protected]> * Update error handling for transformFiles * Start adding unit tests for shared functions * Add test(s) * Add error message when adding post-init to non-JSS app * Reorganize and refactor some base functionality * WIP: Unit tests for helpers * Add coverage script, add support for deep merge of package.json files * Cover helpers by UT * Cover diffFiles by UT * Minor fixes - Fix default appName for styleguide init - Remove stray console.log from a template - Move sinon to devDependencies * Fix isJssApp UT * merge with dev and refactor * Update diffFiles test, fix sinon wrap error * Add litFix command, add missing ejs logic to connected demo tsx * group tests * Cover transform by UT * Cover cmd by UT * Restructure folders, delay install - Folder structure is now leaner - Watch and main() now use the same function to loop through multiple inits -> initRunner() * Fixes before demo * NextjsAnswer cleanup (remove redundant props, move/rename file to follow base Answer naming) * apply sitemap-fetcher plugin for disconnected * apply next.config plugin changes * Remove unnecessary devDependencies (main packages include own type definitions) * Rename transformPostInit to writeFiles, fix some tests * remove monorepo dev dependencies if dev environment * Fix scaffold script * added tests for writePackageJson helper * Revert "Fix scaffold script" This reverts commit dc1d1d4. * scaffold-component updates for disconnected/styleguide * removed extra sitemapFetcher import * fix removeDevDependencies check, consolidation in [[...path]].tsx * added _app.tsx (with bootstrap, nprogress) for nextjs-styleguide * "yes" handling for subsequent initializers (don't prompt for diffs when init on an empty directory) * only pass along __true__ "yes" answers * Initializers internationalization (#868) * Update template * Merge changes * fix answer type * Fix configs * add changes * make appPrefix false as default * update * fix indent * add HostName to NextJSAnswer * Fix issues after review * [NextJS] Refactor scaffold script to make it pluggable (#870) * Make bootstrap silent and refactor * Remove scaffold-component script * update PR * revert changes * revert * Refactor * Refactor scaffold script * Fix indent * [Initializers] Refactor prompts and answers (#872) * Refactoring * remove line * Update default app name Co-authored-by: Coby Sher <[email protected]> Co-authored-by: Coby Sher <[email protected]> * Update some ejs closing tags to trim unwanted newline * Refactor post-initializer flow (#874) * #511113 Refactored post-initializer flow * Fixes after merge. Added templates to BaseArgs (needed in order to suppress post-initializer prompt) * Added "Initializing ..." console message. Expanded silent suppression. * Fixed watch mode * * #511292 fixed issue where transform wasn't occurring on package.json file when existing file * fixed issue where package.json config values weren't being used in styleguide if args.yes == true * isJssApp now returns boolean * added tests, fixed broken ones * only run lint --fix if a lint script exists * [Initializers] Split `force`, `yes` flags (#877) * refactor yes/force flags * Fix unit tests * Use argv.destination by default * Add dynamic logic to init factory and base templates prompt choices * Add silent option to run * Add getAppPrefix helper to ejs data * remove 'yes' on initializer result (force now handling) * updates from pr feedback (error handling, language, defaults) * Resolve PR comments * bump hostname prompt before fetchWith (better flow when nextjs adds prerender) * use template name for default folder name (if appName not provided) * Resolve more PR comments * Add error handling for 'en' language input * more PR feedback updates * Resolve comments, make tests green * Update yarn.lock - fix CI * Add del-cli * Dynamically import watch.json, error when not there * added tests for getBaseTemplates. fixed/improved "unkown template" error handling. Co-authored-by: Adam Brauer <[email protected]> Co-authored-by: Addy Pathania <[email protected]> Co-authored-by: illiakovalenko <[email protected]> Co-authored-by: Illia Kovalenko <[email protected]>
1 parent d245ebd commit 4dff9d1

File tree

184 files changed

+30756
-86
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

184 files changed

+30756
-86
lines changed
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"extends": [
3+
"../../.eslintrc",
4+
"../../eslint-configs/typescript"
5+
],
6+
"ignorePatterns": [
7+
"src/templates/**/*",
8+
"src/common/test-data/**/*"
9+
]
10+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
types/
2+
package-lock.json
3+
watch.json

packages/create-sitecore-jss/.nycrc

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"extension": [
3+
".ts"
4+
],
5+
"exclude": [
6+
"**/*.d.ts",
7+
"**/*.test.ts",
8+
"src/templates/**/*",
9+
"src/common/test-data",
10+
"dist"
11+
],
12+
"all": true,
13+
"reporter": [
14+
"json-summary",
15+
"text"
16+
],
17+
"require": ["ts-node/register"]
18+
}
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"name": "create-sitecore-jss",
3+
"version": "20.0.0-canary.55",
4+
"description": "Sitecore JSS initializer",
5+
"bin": "./dist/index.js",
6+
"scripts": {
7+
"build": "npm run clean && tsc && ts-node ./scripts/build-templates.ts",
8+
"clean": "del-cli dist types",
9+
"lint": "eslint --no-eslintrc -c .eslintrc ./src/**/*.ts",
10+
"watch": "ts-node ./scripts/watch-templates.ts",
11+
"test": "mocha --require ts-node/register \"./src/**/*.test.ts\"",
12+
"coverage": "nyc npm test"
13+
},
14+
"repository": {
15+
"type": "git",
16+
"url": "https://github.com/Sitecore/jss.git",
17+
"directory": "packages/create-sitecore-jss"
18+
},
19+
"homepage": "https://jss.sitecore.com",
20+
"author": "Sitecore Corporation",
21+
"license": "Apache-2.0",
22+
"bugs": {
23+
"url": "https://github.com/Sitecore/jss/issues"
24+
},
25+
"files": [
26+
"dist"
27+
],
28+
"dependencies": {
29+
"chalk": "^4.1.2",
30+
"cross-spawn": "^7.0.0",
31+
"diff": "^5.0.0",
32+
"ejs": "^3.1.6",
33+
"fs-extra": "^10.0.0",
34+
"glob": "^7.2.0",
35+
"inquirer": "^8.2.0",
36+
"minimist": "^1.2.5"
37+
},
38+
"devDependencies": {
39+
"@types/chai": "^4.2.22",
40+
"@types/cross-spawn": "^6.0.0",
41+
"@types/diff": "^5.0.1",
42+
"@types/ejs": "^3.1.0",
43+
"@types/fs-extra": "^9.0.13",
44+
"@types/glob": "^7.2.0",
45+
"@types/inquirer": "^8.1.3",
46+
"@types/minimist": "^1.2.2",
47+
"@types/mocha": "^9.0.0",
48+
"@types/node": "^16.11.7",
49+
"@types/sinon": "^10.0.6",
50+
"chai": "^4.3.4",
51+
"chokidar": "^3.5.2",
52+
"del-cli": "^4.0.1",
53+
"eslint": "^7.15.0",
54+
"mocha": "^9.1.3",
55+
"nyc": "^15.1.0",
56+
"sinon": "^12.0.1",
57+
"ts-node": "^10.4.0",
58+
"typescript": "~4.3.5"
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import path from 'path';
2+
import fs from 'fs-extra';
3+
const templatesFolder = path.resolve(__dirname, '../src/templates');
4+
const distFolder = path.resolve(__dirname, '../dist/templates');
5+
6+
// Copy templates to dist
7+
fs.copy(templatesFolder, distFolder, (err: Error) => {
8+
if (err) {
9+
console.log('An error occurred while copying the folder.');
10+
throw err;
11+
}
12+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import chalk from 'chalk';
2+
import chokidar from 'chokidar';
3+
import path from 'path';
4+
import { initRunner } from '../src/init-runner';
5+
6+
chokidar
7+
.watch(path.join(process.cwd(), '.\\src\\templates'), { ignoreInitial: true })
8+
.on('ready', () => ready())
9+
.on('all', (event, path) => callback(event, path));
10+
11+
async function ready() {
12+
console.log(chalk.green('Initializing app...'));
13+
await initializeApps(false);
14+
console.log(chalk.green('Initializing app complete. Watching for changes...'));
15+
}
16+
17+
async function callback(event?: string, path?: string) {
18+
const color = event === 'add' ? chalk.green : event === 'unlink' ? chalk.red : chalk.white;
19+
console.table(color(`${event} ${path}`));
20+
await initializeApps(true);
21+
}
22+
23+
const initializeApps = async (noInstall: boolean) => {
24+
let watch;
25+
try {
26+
watch = await import(path.resolve('watch.json'));
27+
const initializers = watch.initializers || [];
28+
await initRunner(initializers, { ...watch.args, templates: initializers, noInstall });
29+
} catch (error) {
30+
console.log(chalk.red('An error occurred: ', error));
31+
if (!watch) {
32+
console.log(
33+
chalk.red('Could not find config. Did you create a watch.json file at the root?')
34+
);
35+
process.exit(1);
36+
}
37+
}
38+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import path from 'path';
2+
import { Initializer } from './common/Initializer';
3+
4+
export class InitializerFactory {
5+
async create(name: string): Promise<Initializer | undefined> {
6+
try {
7+
const { default: Initializer } = await import(
8+
path.resolve(__dirname, 'initializers', name, 'index')
9+
);
10+
return new Initializer();
11+
} catch (error) {
12+
return undefined;
13+
}
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { BaseArgs } from './args/base';
2+
3+
export interface InitializerResults {
4+
appName: string;
5+
initializers?: string[];
6+
nextSteps?: string[];
7+
}
8+
export interface Initializer {
9+
isBase: boolean;
10+
init: (args: BaseArgs) => Promise<InitializerResults>;
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ClientAppAnswer } from '../prompts/base';
2+
3+
type Arg = string | number | boolean;
4+
5+
export interface BaseArgs {
6+
[key: string]: Arg | Arg[] | undefined;
7+
templates: string[];
8+
destination: string;
9+
silent?: boolean;
10+
force?: boolean;
11+
yes?: boolean;
12+
}
13+
14+
export interface ClientAppArgs extends BaseArgs, Partial<ClientAppAnswer> {
15+
appPrefix?: boolean;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { StyleguideAnswer } from '../prompts/styleguide';
2+
3+
export type StyleguideArgs = Partial<StyleguideAnswer>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import chalk from 'chalk';
2+
import { DistinctQuestion } from 'inquirer';
3+
4+
export enum FetchWith {
5+
GraphQL = 'GraphQL',
6+
REST = 'REST',
7+
}
8+
9+
export interface ClientAppAnswer {
10+
appName: string;
11+
fetchWith: FetchWith;
12+
hostName: string;
13+
}
14+
15+
export const clientAppPrompts: DistinctQuestion[] = [
16+
{
17+
type: 'input',
18+
name: 'appName',
19+
message: 'What is the name of your app?',
20+
default: 'sitecore-jss-app',
21+
validate: (input: string): boolean => {
22+
if (!/^[a-z\-_.]+$/.test(input)) {
23+
console.error(
24+
chalk.red(
25+
`${input} is not a valid name; you may use lowercase letters, hyphens, and underscores only.`
26+
)
27+
);
28+
return false;
29+
}
30+
return true;
31+
},
32+
},
33+
{
34+
type: 'input',
35+
name: 'hostName',
36+
message: 'What is your Sitecore hostname?',
37+
default: 'https://cm.jss.localhost',
38+
},
39+
{
40+
type: 'list',
41+
name: 'fetchWith',
42+
message: 'How would you like to fetch Layout and Dictionary data?',
43+
choices: Object.values(FetchWith),
44+
default: FetchWith.GraphQL,
45+
},
46+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Answers, DistinctQuestion } from 'inquirer';
2+
import chalk from 'chalk';
3+
4+
export interface StyleguideAnswer extends Answers {
5+
language?: string;
6+
}
7+
8+
const LANGUAGE_REGEXP = /^(([a-z]{2}-[A-Z]{2})|([a-z]{2}))$/;
9+
10+
export const styleguidePrompts: DistinctQuestion<StyleguideAnswer>[] = [
11+
{
12+
type: 'input',
13+
name: 'language',
14+
message:
15+
'Which additional language do you want to support (en is default and required)? Leave empty if not needed',
16+
validate: (input: string): boolean => {
17+
if (!input) return true;
18+
19+
if (!LANGUAGE_REGEXP.test(input)) {
20+
console.error(
21+
chalk.red(
22+
`\n${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'.`
23+
)
24+
);
25+
return false;
26+
} else if (input === 'en') {
27+
console.error(
28+
chalk.red(
29+
`\nen is included in the Styleguide by default. \nYou ${chalk.italic(
30+
'may'
31+
)} however add an en-* locale, for example 'en-UK'.`
32+
)
33+
);
34+
return false;
35+
}
36+
37+
return true;
38+
},
39+
},
40+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { installPackages, lintFix } from './install';
2+
export { nextSteps } from './next';
3+
export { diffFiles, merge, transform, transformFilename } from './transform';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import path from 'path';
2+
import chalk from 'chalk';
3+
import { run } from '../utils/cmd';
4+
import { isDevEnvironment, openPackageJson } from '../utils/helpers';
5+
6+
/**
7+
* @param {string} projectFolder
8+
* @param {boolean} [silent]
9+
*/
10+
export const installPackages = (projectFolder: string, silent?: boolean) => {
11+
silent || console.log(chalk.cyan('Installing packages...'));
12+
13+
if (isDevEnvironment(projectFolder)) {
14+
silent || console.log(chalk.yellow('Detected development environment.'));
15+
16+
run(
17+
'yarn',
18+
['install'],
19+
{
20+
cwd: projectFolder,
21+
encoding: 'utf8',
22+
},
23+
silent
24+
);
25+
} else {
26+
run(
27+
'npm',
28+
['install'],
29+
{
30+
cwd: projectFolder,
31+
encoding: 'utf8',
32+
},
33+
silent
34+
);
35+
}
36+
};
37+
38+
/**
39+
* @param {string} projectFolder
40+
* @param {boolean} [silent]
41+
*/
42+
export const lintFix = (projectFolder: string, silent?: boolean) => {
43+
const packagePath = path.join(projectFolder, 'package.json');
44+
const pkg = openPackageJson(packagePath);
45+
if (!pkg?.scripts?.lint) {
46+
return;
47+
}
48+
49+
silent || console.log(chalk.cyan('Linting app...'));
50+
run('npm', ['run', 'lint', '--', '--fix'], { cwd: projectFolder, encoding: 'utf8' });
51+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import chalk from 'chalk';
2+
3+
export const nextSteps = async (appName: string, nextStepsArr: string[]) => {
4+
console.log(chalk.red(' -/oyhdmNNNNmdhyo/- '));
5+
console.log(chalk.red(' :sdMMMMMMMMMMMMMMMMMMMMds: '));
6+
console.log(chalk.red(' :yNMMMMMMMMMMMMMMMMMMMMMMMMMMNy: '));
7+
console.log(chalk.red(' /mMMMMMMMMMNdyo+//://+shmMMMMMMMMMm/ '));
8+
console.log(chalk.red(' :mMMMMMMMMh+. `:smMMMMMMMm: '));
9+
console.log(chalk.red(' `yMMMMMMMm+` :yMMMMMMMs` '));
10+
console.log(chalk.red(' `dMMMMMMN/ .hMMMMMMd` '));
11+
console.log(chalk.red(' `mMMMMMMh` -s/+MMMMMMd` '));
12+
console.log(chalk.red(' yMMMMMMh `:yNMMMs/MMMMMMy '));
13+
console.log(chalk.red(' :MMMMMMm` `hMMMMMMMsoMMMMMM-'));
14+
console.log(chalk.red(' yMMMMMM/ dMMMMMMM:mMMMMMy'));
15+
console.log(chalk.red(' NMMMMMN` oMyossss:sMMMMMm'));
16+
console.log(chalk.red(' MMMMMMN yM:NMMMMyoMMMMMN'));
17+
console.log(chalk.red(' mMMMMMM` :Md+MMMMMoyMMMMMm'));
18+
console.log(chalk.red(' yMMMMMM+ :NN+NMMMMM-NMMMMMy'));
19+
console.log(chalk.red(' :MMMMMMN:- `sMdyMNymMMosMMMMMM-'));
20+
console.log(chalk.red(' yMMMMMMd/o` .oNdhmMhhMmh++MMMMMMy '));
21+
console.log(chalk.red(' `dMMMMMMm+do.- ./oyhhhNNhyNMMNosMMMMMMd` '));
22+
console.log(chalk.red(' `dMMMMMMMssNdhsoo+/+oyyyydMmhhhMMMNs+mMMMMMMd` '));
23+
console.log(chalk.red(' `yMMMMMMMNyydMNddddddddddhmMMMMho+dMMMMMMMy` '));
24+
console.log(chalk.red(' :mMMMMMMMMmhhhdNMMMMMMMMmhssohMMMMMMMMm: '));
25+
console.log(chalk.red(' /mMMMMMMMMMMNdhyyyyyyyhmMMMMMMMMMMm/ '));
26+
console.log(chalk.red(' :yNMMMMMMMMMMMMMMMMMMMMMMMMMMNy: '));
27+
console.log(chalk.red(' :sdMMMMMMMMMMMMMMMMMMMMds: '));
28+
console.log(chalk.red(' `-/oyhdmNNNNmdhyo/- '));
29+
console.log();
30+
console.log(chalk.white(' __________'));
31+
console.log(chalk.white(' __ / / __/ __/'));
32+
console.log(chalk.white(' / // /\\ \\_\\ \\ '));
33+
console.log(chalk.white(' \\___/___/___/'));
34+
console.log();
35+
console.log(`JSS application ${chalk.green(appName)} is ready!`);
36+
console.log();
37+
console.log(chalk.yellow('Next steps:'));
38+
nextStepsArr.forEach((step) => {
39+
console.log(step);
40+
});
41+
console.log('* Enable source control (i.e. git init) (optional)');
42+
console.log('* Check out the JSS documentation at https://jss.sitecore.com');
43+
console.log();
44+
console.log(chalk.green('Enjoy!'));
45+
};

0 commit comments

Comments
 (0)