feat(react): add a preset to generate a workspace with a single app at the root

This commit is contained in:
Victor Savkin 2022-11-11 08:51:50 -05:00
parent fc8de9a4d3
commit c4ebef2803
31 changed files with 300 additions and 87 deletions

View File

@ -113,7 +113,7 @@ Package manager to use
Type: `string` Type: `string`
Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular", "angular-nest", "react", "react-express", "react-native", "expo", "next", "nest", "express"]. To build your own see https://nx.dev/packages/nx-plugin#preset Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular", "angular-nest", "react", "react-experimental", "react-express", "react-native", "expo", "next", "nest", "express"]. To build your own see https://nx.dev/packages/nx-plugin#preset
### skipGit ### skipGit

View File

@ -111,6 +111,12 @@
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"description": "Do not add dependencies to `package.json`." "description": "Do not add dependencies to `package.json`."
},
"rootProject": {
"description": "Create a application at the root of the workspace",
"type": "boolean",
"default": false,
"hidden": true
} }
}, },
"required": ["name"], "required": ["name"],

View File

@ -10,7 +10,7 @@
"name": "create-nx-workspace", "name": "create-nx-workspace",
"id": "create-nx-workspace", "id": "create-nx-workspace",
"file": "generated/cli/create-nx-workspace", "file": "generated/cli/create-nx-workspace",
"content": "---\ntitle: 'create-nx-workspace - CLI command'\ndescription: 'Create a new Nx workspace'\n---\n\n# create-nx-workspace\n\nCreate a new Nx workspace\n\n## Usage\n\n```bash\ncreate-nx-workspace [name] [options]\n```\n\nInstall `create-nx-workspace` globally to invoke the command directly, or use `npx create-nx-workspace`, `yarn create nx-workspace`, or `pnpx create-nx-workspace`.\n\n## Options\n\n### allPrompts\n\nType: `boolean`\n\nDefault: `false`\n\nShow all prompts\n\n### appName\n\nType: `string`\n\nThe name of the application when a preset with pregenerated app is selected\n\n### ci\n\nType: `string`\n\nChoices: [github, circleci, azure]\n\nGenerate a CI workflow file\n\n### cli\n\nType: `string`\n\nChoices: [nx, angular]\n\nCLI to power the Nx workspace\n\n### commit.email\n\nType: `string`\n\nE-mail of the committer\n\n### commit.message\n\nType: `string`\n\nDefault: `Initial commit`\n\nCommit message\n\n### commit.name\n\nType: `string`\n\nName of the committer\n\n### defaultBase\n\nType: `string`\n\nDefault: `main`\n\nDefault base to use for new projects\n\n### help\n\nType: `boolean`\n\nShow help\n\n### interactive\n\nType: `boolean`\n\nEnable interactive mode with presets\n\n### name\n\nType: `string`\n\nWorkspace name (e.g. org name)\n\n### nxCloud\n\nType: `boolean`\n\nEnable distributed caching to make your CI faster\n\n### packageManager\n\nType: `string`\n\nChoices: [npm, pnpm, yarn]\n\nDefault: `npm`\n\nPackage manager to use\n\n### preset\n\nType: `string`\n\nCustomizes the initial content of your workspace. Default presets include: [\"apps\", \"empty\", \"core\", \"npm\", \"ts\", \"web-components\", \"angular\", \"angular-nest\", \"react\", \"react-express\", \"react-native\", \"expo\", \"next\", \"nest\", \"express\"]. To build your own see https://nx.dev/packages/nx-plugin#preset\n\n### skipGit\n\nType: `boolean`\n\nDefault: `false`\n\nSkip initializing a git repository.\n\n### style\n\nType: `string`\n\nStyle option to be used when a preset with pregenerated app is selected\n\n### version\n\nType: `boolean`\n\nShow version number\n" "content": "---\ntitle: 'create-nx-workspace - CLI command'\ndescription: 'Create a new Nx workspace'\n---\n\n# create-nx-workspace\n\nCreate a new Nx workspace\n\n## Usage\n\n```bash\ncreate-nx-workspace [name] [options]\n```\n\nInstall `create-nx-workspace` globally to invoke the command directly, or use `npx create-nx-workspace`, `yarn create nx-workspace`, or `pnpx create-nx-workspace`.\n\n## Options\n\n### allPrompts\n\nType: `boolean`\n\nDefault: `false`\n\nShow all prompts\n\n### appName\n\nType: `string`\n\nThe name of the application when a preset with pregenerated app is selected\n\n### ci\n\nType: `string`\n\nChoices: [github, circleci, azure]\n\nGenerate a CI workflow file\n\n### cli\n\nType: `string`\n\nChoices: [nx, angular]\n\nCLI to power the Nx workspace\n\n### commit.email\n\nType: `string`\n\nE-mail of the committer\n\n### commit.message\n\nType: `string`\n\nDefault: `Initial commit`\n\nCommit message\n\n### commit.name\n\nType: `string`\n\nName of the committer\n\n### defaultBase\n\nType: `string`\n\nDefault: `main`\n\nDefault base to use for new projects\n\n### help\n\nType: `boolean`\n\nShow help\n\n### interactive\n\nType: `boolean`\n\nEnable interactive mode with presets\n\n### name\n\nType: `string`\n\nWorkspace name (e.g. org name)\n\n### nxCloud\n\nType: `boolean`\n\nEnable distributed caching to make your CI faster\n\n### packageManager\n\nType: `string`\n\nChoices: [npm, pnpm, yarn]\n\nDefault: `npm`\n\nPackage manager to use\n\n### preset\n\nType: `string`\n\nCustomizes the initial content of your workspace. Default presets include: [\"apps\", \"empty\", \"core\", \"npm\", \"ts\", \"web-components\", \"angular\", \"angular-nest\", \"react\", \"react-experimental\", \"react-express\", \"react-native\", \"expo\", \"next\", \"nest\", \"express\"]. To build your own see https://nx.dev/packages/nx-plugin#preset\n\n### skipGit\n\nType: `boolean`\n\nDefault: `false`\n\nSkip initializing a git repository.\n\n### style\n\nType: `string`\n\nStyle option to be used when a preset with pregenerated app is selected\n\n### version\n\nType: `boolean`\n\nShow version number\n"
}, },
{ {
"name": "init", "name": "init",

View File

@ -141,7 +141,7 @@
"linter": { "linter": {
"description": "The tool to use for running lint checks.", "description": "The tool to use for running lint checks.",
"type": "string", "type": "string",
"enum": ["eslint"], "enum": ["eslint", "none"],
"default": "eslint" "default": "eslint"
}, },
"routing": { "routing": {
@ -228,6 +228,12 @@
"description": "Do not add dependencies to `package.json`.", "description": "Do not add dependencies to `package.json`.",
"type": "boolean", "type": "boolean",
"default": false "default": false
},
"rootProject": {
"description": "Create a application at the root of the workspace",
"type": "boolean",
"default": false,
"hidden": true
} }
}, },
"required": [], "required": [],
@ -314,7 +320,7 @@
"linter": { "linter": {
"description": "The tool to use for running lint checks.", "description": "The tool to use for running lint checks.",
"type": "string", "type": "string",
"enum": ["eslint"], "enum": ["eslint", "none"],
"default": "eslint" "default": "eslint"
}, },
"unitTestRunner": { "unitTestRunner": {

View File

@ -21,6 +21,20 @@ describe('create-nx-workspace', () => {
afterEach(() => cleanupProject()); afterEach(() => cleanupProject());
it('should create a workspace with a single react app', () => {
const wsName = uniq('react');
const appName = uniq('app');
runCreateWorkspace(wsName, {
preset: 'react-experimental',
appName,
style: 'css',
packageManager,
});
checkFilesExist('package.json');
});
it('should be able to create an empty workspace built for apps', () => { it('should be able to create an empty workspace built for apps', () => {
const wsName = uniq('apps'); const wsName = uniq('apps');
runCreateWorkspace(wsName, { runCreateWorkspace(wsName, {

View File

@ -54,6 +54,7 @@ enum Preset {
Angular = 'angular', Angular = 'angular',
AngularWithNest = 'angular-nest', AngularWithNest = 'angular-nest',
React = 'react', React = 'react',
ReactExperimental = 'react-experimental',
ReactWithExpress = 'react-express', ReactWithExpress = 'react-express',
ReactNative = 'react-native', ReactNative = 'react-native',
Expo = 'expo', Expo = 'expo',
@ -674,7 +675,14 @@ async function determineStyle(
}); });
} }
if ([Preset.ReactWithExpress, Preset.React, Preset.NextJs].includes(preset)) { if (
[
Preset.ReactWithExpress,
Preset.React,
Preset.ReactExperimental,
Preset.NextJs,
].includes(preset)
) {
choices.push( choices.push(
{ {
name: 'styled-components', name: 'styled-components',
@ -1030,6 +1038,7 @@ function pointToTutorialAndCourse(preset: Preset) {
break; break;
case Preset.React: case Preset.React:
case Preset.ReactExperimental:
case Preset.ReactWithExpress: case Preset.ReactWithExpress:
case Preset.NextJs: case Preset.NextJs:
output.addVerticalSeparator(); output.addVerticalSeparator();

View File

@ -268,16 +268,23 @@ export async function cypressProjectGenerator(host: Tree, schema: Schema) {
function normalizeOptions(host: Tree, options: Schema): CypressProjectSchema { function normalizeOptions(host: Tree, options: Schema): CypressProjectSchema {
const { appsDir } = getWorkspaceLayout(host); const { appsDir } = getWorkspaceLayout(host);
const projectName = filePathPrefix( let projectName, projectRoot;
options.directory ? `${options.directory}-${options.name}` : options.name
); if (options.rootProject) {
const projectRoot = options.directory projectName = options.name;
? joinPathFragments( projectRoot = options.name;
appsDir, } else {
names(options.directory).fileName, projectName = filePathPrefix(
options.name options.directory ? `${options.directory}-${options.name}` : options.name
) );
: joinPathFragments(appsDir, options.name); projectRoot = options.directory
? joinPathFragments(
appsDir,
names(options.directory).fileName,
options.name
)
: joinPathFragments(appsDir, options.name);
}
options.linter = options.linter || Linter.EsLint; options.linter = options.linter || Linter.EsLint;
return { return {

View File

@ -11,4 +11,5 @@ export interface Schema {
setParserOptionsProject?: boolean; setParserOptionsProject?: boolean;
standaloneConfig?: boolean; standaloneConfig?: boolean;
skipPackageJson?: boolean; skipPackageJson?: boolean;
rootProject?: boolean;
} }

View File

@ -59,6 +59,12 @@
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"description": "Do not add dependencies to `package.json`." "description": "Do not add dependencies to `package.json`."
},
"rootProject": {
"description": "Create a application at the root of the workspace",
"type": "boolean",
"default": false,
"hidden": true
} }
}, },
"required": ["name"], "required": ["name"],

View File

@ -20,4 +20,9 @@ describe('offsetFromRoot', () => {
const result = offsetFromRoot('apps/dirname/appname/'); const result = offsetFromRoot('apps/dirname/appname/');
expect(result).toBe('../../../'); expect(result).toBe('../../../');
}); });
it('should work for root', () => {
const result = offsetFromRoot('.');
expect(result).toBe('./');
});
}); });

View File

@ -13,6 +13,8 @@ import { normalize, sep } from 'path';
* @param fullPathToDir - directory path * @param fullPathToDir - directory path
*/ */
export function offsetFromRoot(fullPathToDir: string): string { export function offsetFromRoot(fullPathToDir: string): string {
if (fullPathToDir === '.') return './';
const parts = normalize(fullPathToDir).split(sep); const parts = normalize(fullPathToDir).split(sep);
let offset = ''; let offset = '';
for (let i = 0; i < parts.length; ++i) { for (let i = 0; i < parts.length; ++i) {

View File

@ -825,4 +825,23 @@ describe('app', () => {
}); });
}); });
}); });
describe('--root-project', () => {
it('should create files at the root', async () => {
await applicationGenerator(appTree, {
...schema,
rootProject: true,
});
expect(appTree.read('/src/main.tsx')).toBeDefined();
expect(appTree.read('/e2e/cypress.config.ts')).toBeDefined();
expect(readJson(appTree, '/tsconfig.json').extends).toEqual(
'./tsconfig.base.json'
);
expect(
readJson(appTree, '/workspace.json').projects['my-app'].architect[
'build'
].options['outputPath']
).toEqual('dist/my-app');
});
});
}); });

View File

@ -23,47 +23,48 @@ import {
} from '@nrwl/devkit'; } from '@nrwl/devkit';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial'; import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
import reactInitGenerator from '../init/init'; import reactInitGenerator from '../init/init';
import { lintProjectGenerator } from '@nrwl/linter'; import { Linter, lintProjectGenerator } from '@nrwl/linter';
import { swcCoreVersion } from '@nrwl/js/src/utils/versions'; import { swcCoreVersion } from '@nrwl/js/src/utils/versions';
import { swcLoaderVersion } from '@nrwl/webpack/src/utils/versions'; import { swcLoaderVersion } from '@nrwl/webpack/src/utils/versions';
async function addLinting(host: Tree, options: NormalizedSchema) { async function addLinting(host: Tree, options: NormalizedSchema) {
const tasks: GeneratorCallback[] = []; const tasks: GeneratorCallback[] = [];
const lintTask = await lintProjectGenerator(host, { if (options.linter === Linter.EsLint) {
linter: options.linter, const lintTask = await lintProjectGenerator(host, {
project: options.projectName, linter: options.linter,
tsConfigPaths: [ project: options.projectName,
joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'), tsConfigPaths: [
], joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
unitTestRunner: options.unitTestRunner, ],
eslintFilePatterns: [`${options.appProjectRoot}/**/*.{ts,tsx,js,jsx}`], unitTestRunner: options.unitTestRunner,
skipFormat: true, eslintFilePatterns: [`${options.appProjectRoot}/**/*.{ts,tsx,js,jsx}`],
}); skipFormat: true,
tasks.push(lintTask); });
tasks.push(lintTask);
const reactEslintJson = createReactEslintJson( const reactEslintJson = createReactEslintJson(
options.appProjectRoot, options.appProjectRoot,
options.setParserOptionsProject options.setParserOptionsProject
); );
updateJson( updateJson(
host, host,
joinPathFragments(options.appProjectRoot, '.eslintrc.json'), joinPathFragments(options.appProjectRoot, '.eslintrc.json'),
() => reactEslintJson () => reactEslintJson
); );
const installTask = await addDependenciesToPackageJson(
host,
extraEslintDependencies.dependencies,
{
...extraEslintDependencies.devDependencies,
...(options.compiler === 'swc'
? { '@swc/core': swcCoreVersion, 'swc-loader': swcLoaderVersion }
: {}),
}
);
tasks.push(installTask);
const installTask = await addDependenciesToPackageJson(
host,
extraEslintDependencies.dependencies,
{
...extraEslintDependencies.devDependencies,
...(options.compiler === 'swc'
? { '@swc/core': swcCoreVersion, 'swc-loader': swcLoaderVersion }
: {}),
}
);
tasks.push(installTask);
}
return runTasksInSerial(...tasks); return runTasksInSerial(...tasks);
} }

View File

@ -9,7 +9,7 @@ export async function addCypress(host: Tree, options: NormalizedSchema) {
return await cypressProjectGenerator(host, { return await cypressProjectGenerator(host, {
...options, ...options,
name: `${options.name}-e2e`, name: options.e2eProjectName,
directory: options.directory, directory: options.directory,
project: options.projectName, project: options.projectName,
}); });

View File

@ -41,7 +41,12 @@ function createBuildTarget(options: NormalizedSchema): TargetConfiguration {
defaultConfiguration: 'production', defaultConfiguration: 'production',
options: { options: {
compiler: options.compiler ?? 'babel', compiler: options.compiler ?? 'babel',
outputPath: joinPathFragments('dist', options.appProjectRoot), outputPath: joinPathFragments(
'dist',
options.appProjectRoot != '.'
? options.appProjectRoot
: options.projectName
),
index: joinPathFragments(options.appProjectRoot, 'src/index.html'), index: joinPathFragments(options.appProjectRoot, 'src/index.html'),
baseHref: '/', baseHref: '/',
main: joinPathFragments( main: joinPathFragments(

View File

@ -19,10 +19,14 @@ export function normalizeOptions(
): NormalizedSchema { ): NormalizedSchema {
const appDirectory = normalizeDirectory(options); const appDirectory = normalizeDirectory(options);
const appProjectName = normalizeProjectName(options); const appProjectName = normalizeProjectName(options);
const e2eProjectName = `${appProjectName}-e2e`; const e2eProjectName = options.rootProject
? 'e2e'
: `${names(options.name).fileName}-e2e`;
const { appsDir } = getWorkspaceLayout(host); const { appsDir } = getWorkspaceLayout(host);
const appProjectRoot = normalizePath(`${appsDir}/${appDirectory}`); const appProjectRoot = options.rootProject
? '.'
: normalizePath(`${appsDir}/${appDirectory}`);
const parsedTags = options.tags const parsedTags = options.tags
? options.tags.split(',').map((s) => s.trim()) ? options.tags.split(',').map((s) => s.trim())

View File

@ -28,6 +28,7 @@ export function setDefaults(host: Tree, options: NormalizedSchema) {
...prev, ...prev,
application: { application: {
style: options.style, style: options.style,
unitTestRunner: options.unitTestRunner,
linter: options.linter, linter: options.linter,
...prev.application, ...prev.application,
}, },
@ -37,6 +38,7 @@ export function setDefaults(host: Tree, options: NormalizedSchema) {
}, },
library: { library: {
style: options.style, style: options.style,
unitTestRunner: options.unitTestRunner,
linter: options.linter, linter: options.linter,
...prev.library, ...prev.library,
}, },

View File

@ -28,6 +28,7 @@ export interface Schema {
devServerPort?: number; devServerPort?: number;
skipDefaultProject?: boolean; skipDefaultProject?: boolean;
skipPackageJson?: boolean; skipPackageJson?: boolean;
rootProject?: boolean;
} }
export interface NormalizedSchema extends Schema { export interface NormalizedSchema extends Schema {

View File

@ -82,7 +82,7 @@
"linter": { "linter": {
"description": "The tool to use for running lint checks.", "description": "The tool to use for running lint checks.",
"type": "string", "type": "string",
"enum": ["eslint"], "enum": ["eslint", "none"],
"default": "eslint" "default": "eslint"
}, },
"routing": { "routing": {
@ -169,6 +169,12 @@
"description": "Do not add dependencies to `package.json`.", "description": "Do not add dependencies to `package.json`.",
"type": "boolean", "type": "boolean",
"default": false "default": false
},
"rootProject": {
"description": "Create a application at the root of the workspace",
"type": "boolean",
"default": false,
"hidden": true
} }
}, },
"required": [] "required": []

View File

@ -19,7 +19,7 @@ import {
import { getImportPath } from 'nx/src/utils/path'; import { getImportPath } from 'nx/src/utils/path';
import { jestProjectGenerator } from '@nrwl/jest'; import { jestProjectGenerator } from '@nrwl/jest';
import { swcCoreVersion } from '@nrwl/js/src/utils/versions'; import { swcCoreVersion } from '@nrwl/js/src/utils/versions';
import { lintProjectGenerator } from '@nrwl/linter'; import { Linter, lintProjectGenerator } from '@nrwl/linter';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial'; import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
import { import {
getRelativePathToRootTsConfig, getRelativePathToRootTsConfig,
@ -143,39 +143,43 @@ export async function libraryGenerator(host: Tree, schema: Schema) {
} }
async function addLinting(host: Tree, options: NormalizedSchema) { async function addLinting(host: Tree, options: NormalizedSchema) {
const lintTask = await lintProjectGenerator(host, { if (options.linter === Linter.EsLint) {
linter: options.linter, const lintTask = await lintProjectGenerator(host, {
project: options.name, linter: options.linter,
tsConfigPaths: [ project: options.name,
joinPathFragments(options.projectRoot, 'tsconfig.lib.json'), tsConfigPaths: [
], joinPathFragments(options.projectRoot, 'tsconfig.lib.json'),
unitTestRunner: options.unitTestRunner, ],
eslintFilePatterns: [`${options.projectRoot}/**/*.{ts,tsx,js,jsx}`], unitTestRunner: options.unitTestRunner,
skipFormat: true, eslintFilePatterns: [`${options.projectRoot}/**/*.{ts,tsx,js,jsx}`],
skipPackageJson: options.skipPackageJson, skipFormat: true,
}); skipPackageJson: options.skipPackageJson,
});
const reactEslintJson = createReactEslintJson( const reactEslintJson = createReactEslintJson(
options.projectRoot, options.projectRoot,
options.setParserOptionsProject options.setParserOptionsProject
);
updateJson(
host,
joinPathFragments(options.projectRoot, '.eslintrc.json'),
() => reactEslintJson
);
let installTask = () => {};
if (!options.skipPackageJson) {
installTask = await addDependenciesToPackageJson(
host,
extraEslintDependencies.dependencies,
extraEslintDependencies.devDependencies
); );
}
return runTasksInSerial(lintTask, installTask); updateJson(
host,
joinPathFragments(options.projectRoot, '.eslintrc.json'),
() => reactEslintJson
);
let installTask = () => {};
if (!options.skipPackageJson) {
installTask = await addDependenciesToPackageJson(
host,
extraEslintDependencies.dependencies,
extraEslintDependencies.devDependencies
);
}
return runTasksInSerial(lintTask, installTask);
} else {
return () => {};
}
} }
function addProject(host: Tree, options: NormalizedSchema) { function addProject(host: Tree, options: NormalizedSchema) {
@ -192,7 +196,7 @@ function addProject(host: Tree, options: NormalizedSchema) {
} }
targets.build = { targets.build = {
builder: '@nrwl/web:rollup', executor: '@nrwl/web:rollup',
outputs: ['{options.outputPath}'], outputs: ['{options.outputPath}'],
options: { options: {
outputPath: `dist/${libsDir}/${options.projectDirectory}`, outputPath: `dist/${libsDir}/${options.projectDirectory}`,

View File

@ -75,7 +75,7 @@
"linter": { "linter": {
"description": "The tool to use for running lint checks.", "description": "The tool to use for running lint checks.",
"type": "string", "type": "string",
"enum": ["eslint"], "enum": ["eslint", "none"],
"default": "eslint" "default": "eslint"
}, },
"unitTestRunner": { "unitTestRunner": {

View File

@ -36,6 +36,11 @@
"glob": "**/files-npm/**", "glob": "**/files-npm/**",
"output": "/" "output": "/"
}, },
{
"input": "packages/workspace",
"glob": "**/files-root-app/**",
"output": "/"
},
{ {
"input": "packages/workspace", "input": "packages/workspace",
"glob": "**/files-npm/**/.gitkeep", "glob": "**/files-npm/**/.gitkeep",

View File

@ -194,6 +194,9 @@ function getPresetDependencies(preset: string, version?: string) {
case Preset.React: case Preset.React:
return { dependencies: {}, dev: { '@nrwl/react': nxVersion } }; return { dependencies: {}, dev: { '@nrwl/react': nxVersion } };
case Preset.ReactExperimental:
return { dependencies: {}, dev: { '@nrwl/react': nxVersion } };
case Preset.ReactWithExpress: case Preset.ReactWithExpress:
return { return {
dependencies: {}, dependencies: {},

View File

@ -56,6 +56,19 @@ async function createPreset(tree: Tree, options: Schema) {
linter: options.linter, linter: options.linter,
standaloneConfig: options.standaloneConfig, standaloneConfig: options.standaloneConfig,
}); });
} else if (options.preset === Preset.ReactExperimental) {
const {
applicationGenerator: reactApplicationGenerator,
} = require('@nrwl' + '/react');
await reactApplicationGenerator(tree, {
name: options.name,
style: options.style,
linter: 'none',
unitTestRunner: 'none',
standaloneConfig: options.standaloneConfig,
rootProject: true,
});
} else if (options.preset === Preset.NextJs) { } else if (options.preset === Preset.NextJs) {
const { applicationGenerator: nextApplicationGenerator } = require('@nrwl' + const { applicationGenerator: nextApplicationGenerator } = require('@nrwl' +
'/next'); '/next');

View File

@ -8,6 +8,7 @@ export enum Preset {
Angular = 'angular', Angular = 'angular',
AngularWithNest = 'angular-nest', AngularWithNest = 'angular-nest',
React = 'react', React = 'react',
ReactExperimental = 'react-experimental',
ReactWithExpress = 'react-express', ReactWithExpress = 'react-express',
ReactNative = 'react-native', ReactNative = 'react-native',
Expo = 'expo', Expo = 'expo',

View File

@ -0,0 +1,39 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
dist
tmp
/out-tsc
# dependencies
node_modules
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

View File

@ -0,0 +1,4 @@
# Add files here to ignore them from prettier formatting
/dist
/coverage

View File

@ -0,0 +1,9 @@
{
"recommendations": [
<% if(cli === 'angular') { %>
"angular.ng-template",<% }
%>
"nrwl.angular-console",
"esbenp.prettier-vscode"
]
}

View File

@ -0,0 +1,17 @@
{
"name": "<%= formattedNames.fileName %>",
"version": "0.0.0",
"license": "MIT",
"scripts": {
},
"private": true,
"dependencies": {
},
"devDependencies": {
"nx": "<%= nxVersion %>",
"@nrwl/cli": "<%= nxVersion %>",
"@nrwl/workspace": "<%= nxVersion %>",
"typescript": "<%= typescriptVersion %>",
"prettier": "<%= prettierVersion %>"
}
}

View File

@ -0,0 +1,20 @@
{
"compileOnSave": false,
"compilerOptions": {
"rootDir": ".",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"module": "esnext",
"lib": ["es2017", "dom"],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {}
},
"exclude": ["node_modules", "tmp"]
}

View File

@ -54,6 +54,8 @@ function createAppsAndLibsFolders(host: Tree, options: Schema) {
options.preset === Preset.NPM options.preset === Preset.NPM
) { ) {
host.write(join(options.directory, 'packages/.gitkeep'), ''); host.write(join(options.directory, 'packages/.gitkeep'), '');
} else if (options.preset === Preset.ReactExperimental) {
// don't generate any folders
} else { } else {
host.write(join(options.directory, 'apps/.gitkeep'), ''); host.write(join(options.directory, 'apps/.gitkeep'), '');
host.write(join(options.directory, 'libs/.gitkeep'), ''); host.write(join(options.directory, 'libs/.gitkeep'), '');
@ -114,7 +116,9 @@ function createNxJson(
function createFiles(host: Tree, options: Schema) { function createFiles(host: Tree, options: Schema) {
const formattedNames = names(options.name); const formattedNames = names(options.name);
const filesDirName = const filesDirName =
options.preset === Preset.NPM || options.preset === Preset.Core options.preset === Preset.ReactExperimental
? './files-root-app'
: options.preset === Preset.NPM || options.preset === Preset.Core
? './files-npm' ? './files-npm'
: './files'; : './files';
generateFiles(host, pathJoin(__dirname, filesDirName), options.directory, { generateFiles(host, pathJoin(__dirname, filesDirName), options.directory, {