Compare commits

...

7 Commits

15 changed files with 156 additions and 67 deletions
+30
View File
@@ -0,0 +1,30 @@
#!/bin/sh
if [ -z "$husky_skip_init" ]; then
debug () {
[ "$HUSKY_DEBUG" = "1" ] && echo "husky (debug) - $1"
}
readonly hook_name="$(basename "$0")"
debug "starting $hook_name..."
if [ "$HUSKY" = "0" ]; then
debug "HUSKY env variable is set to 0, skipping hook"
exit 0
fi
if [ -f ~/.huskyrc ]; then
debug "sourcing ~/.huskyrc"
. ~/.huskyrc
fi
export readonly husky_skip_init=1
sh -e "$0" "$@"
exitCode="$?"
if [ $exitCode != 0 ]; then
echo "husky - $hook_name hook exited with code $exitCode (error)"
exit $exitCode
fi
exit 0
fi
+13 -2
View File
@@ -68,9 +68,9 @@
"description": "Do not update tsconfig.json for development experience.",
"default": false
},
"includeBabelRc": {
"skipBabelrc": {
"type": "boolean",
"description": "Include a .babelrc configuration to compile TypeScript files"
"description": "Do not generate `.babelrc` file. Useful for Node libraries that are not compiled by Babel."
},
"testEnvironment": {
"type": "string",
@@ -78,6 +78,11 @@
"description": "The test environment to use if unitTestRunner is set to jest.",
"default": "jsdom"
},
"supportTsx": {
"type": "boolean",
"description": "Setup `tsx` support.",
"default": false
},
"importPath": {
"type": "string",
"description": "The library name used to import it, like @myorg/my-awesome-lib."
@@ -125,6 +130,12 @@
"default": "tsc",
"description": "The compiler used by the build and test targets"
},
"module": {
"type": "string",
"enum": ["cjs", "none"],
"default": "cjs",
"description": "The module type to use for this library"
},
"skipTypeCheck": {
"type": "boolean",
"description": "Whether to skip TypeScript type checking for SWC compiler.",
+1 -3
View File
@@ -262,9 +262,7 @@ describe('js e2e', () => {
it('should not create a `.babelrc` file when creating libs with js executors (--compiler=tsc)', () => {
const lib = uniq('lib');
runCLI(
`generate @nrwl/js:lib ${lib} --compiler=tsc --includeBabelRc=false`
);
runCLI(`generate @nrwl/js:lib ${lib} --compiler=tsc --skipBabelrc`);
checkFilesDoNotExist(`libs/${lib}/.babelrc`);
});
+2
View File
@@ -0,0 +1,2 @@
export { libraryGenerator } from './src/generators/library/library';
export { convertToSwcGenerator } from './src/generators/convert-to-swc/convert-to-swc';
@@ -0,0 +1,3 @@
{
"presets": [["@nrwl/web/babel", { "useBuiltIns": "usage" }]]
}
@@ -1,5 +1,5 @@
{
"name": "<%= importPath %>",
"version": "0.0.1",
"type": "commonjs"
"version": "0.0.1"<% if (module != 'none') {%>,
"type": <% if (module === 'cjs') { %>"commonjs"<% } %><% } %>
}
@@ -1,7 +1,7 @@
{
"extends": "<%= rootTsConfigPath %>",
"compilerOptions": {
"module": "commonjs"<% if (js) { %>,
"compilerOptions": {<% if (module === 'cjs') { %>
"module": "commonjs"<% } %><% if (js) { %><% if (module !== 'none') { %>,<% } %>
"allowJs": true<% } %>
},
"files": [],
@@ -13,7 +13,7 @@ describe('lib', () => {
let tree: Tree;
const defaultOptions: Omit<LibraryGeneratorSchema, 'name'> = {
skipTsConfig: false,
includeBabelRc: false,
skipBabelrc: true,
unitTestRunner: 'jest',
skipFormat: false,
linter: 'eslint',
@@ -877,39 +877,39 @@ describe('lib', () => {
});
});
describe('--includeBabelRc', () => {
it('should generate a .babelrc when flag is set to true', async () => {
describe('--skipBabelrc', () => {
it('should generate a .babelrc when flag is set to false', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: true,
skipBabelrc: false,
});
expect(tree.exists('libs/my-lib/.babelrc')).toBeTruthy();
});
it('should not generate a .babelrc when flag is set to false', async () => {
it('should not generate a .babelrc when flag is set to true', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: false,
skipBabelrc: true,
});
expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
});
it('should not generate a .babelrc when compiler is swc (even if flag is set to true)', async () => {
it('should not generate a .babelrc when compiler is swc (even if flag is set to false)', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
compiler: 'swc',
includeBabelRc: true,
skipBabelrc: false,
});
expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
});
it('should generate a .babelrc when flag is set to true (even if there is no `@nrwl/web` plugin installed)', async () => {
it('should generate a .babelrc when flag is set to false (even if there is no `@nrwl/web` plugin installed)', async () => {
updateJson(tree, 'package.json', (json) => {
json.devDependencies = {};
return json;
@@ -918,7 +918,7 @@ describe('lib', () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: true,
skipBabelrc: false,
});
expect(tree.exists('libs/my-lib/.babelrc')).toBeTruthy();
@@ -951,7 +951,7 @@ describe('lib', () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: undefined,
skipBabelrc: undefined,
});
expect(tree.exists('libs/my-lib/.babelrc')).toBeTruthy();
@@ -970,6 +970,7 @@ describe('lib', () => {
}
`);
});
it('should not generate a .babelrc when flag is not set and there is NOT a `@nrwl/web` package installed', async () => {
updateJson(tree, 'package.json', (json) => {
json.devDependencies = {
@@ -982,11 +983,27 @@ describe('lib', () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'myLib',
includeBabelRc: undefined,
skipBabelrc: undefined,
});
expect(tree.exists('libs/my-lib/.babelrc')).toBeFalsy();
});
});
describe('--module', () => {
it('should generate commonjs library', async () => {
await libraryGenerator(tree, {
...defaultOptions,
name: 'cjsLib',
buildable: true,
});
const packageJson = readJson(tree, 'libs/cjs-lib/package.json');
expect(packageJson.type).toEqual('commonjs');
const tsconfigJson = readJson(tree, 'libs/cjs-lib/tsconfig.json');
expect(tsconfigJson.compilerOptions.module).toEqual('commonjs');
});
});
});
});
+26 -26
View File
@@ -9,11 +9,10 @@ import {
names,
offsetFromRoot,
ProjectConfiguration,
readJson,
toJS,
Tree,
updateJson,
readJson,
writeJson,
} from '@nrwl/devkit';
import { jestProjectGenerator } from '@nrwl/jest';
import { Linter, lintProjectGenerator } from '@nrwl/linter';
@@ -162,6 +161,9 @@ export function addLint(
}
function updateTsConfig(tree: Tree, options: NormalizedSchema) {
const tsConfigJson = tree
.read(join(options.projectRoot, 'tsconfig.json'), 'utf-8')
.toString();
updateJson(tree, join(options.projectRoot, 'tsconfig.json'), (json) => {
if (options.strict) {
json.compilerOptions = {
@@ -187,36 +189,26 @@ function updateTsConfig(tree: Tree, options: NormalizedSchema) {
* You can find more details on why this is necessary here:
* https://github.com/nrwl/nx/pull/10055
*/
function shouldAddBabelRc(tree: Tree, options: NormalizedSchema) {
if (typeof options.includeBabelRc === 'undefined') {
const webPluginName = '@nrwl/web';
function shouldSkipBabelRc(
tree: Tree,
options: LibraryGeneratorSchema
): boolean {
if (options.skipBabelrc == null) {
const packageJson = readJson(tree, 'package.json');
const hasNxWebPlugin = Object.keys(
packageJson.devDependencies as Record<string, string>
).includes(webPluginName);
return hasNxWebPlugin;
return (
!packageJson['devDependencies']?.['@nrwl/web'] &&
!packageJson['dependencies']?.['@nrwl/web']
);
}
return options.includeBabelRc;
}
function addBabelRc(tree: Tree, options: NormalizedSchema) {
const filename = '.babelrc';
const babelrc = {
presets: [['@nrwl/web/babel', { useBuiltIns: 'usage' }]],
};
writeJson(tree, join(options.projectRoot, filename), babelrc);
return options.skipBabelrc;
}
function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) {
const { className, name, propertyName } = names(options.name);
generateFiles(tree, filesDir, options.projectRoot, {
...options,
module: options.module,
dot: '.',
className,
name,
@@ -234,8 +226,10 @@ function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) {
if (options.compiler === 'swc') {
addSwcDependencies(tree);
addSwcConfig(tree, options.projectRoot);
} else if (shouldAddBabelRc(tree, options)) {
addBabelRc(tree, options);
}
if (options.skipBabelrc || options.compiler === 'swc') {
tree.delete(join(options.projectRoot, '.babelrc'));
}
if (options.unitTestRunner === 'none') {
@@ -275,7 +269,7 @@ async function addJest(
...options,
project: options.name,
setupFile: 'none',
supportTsx: false,
supportTsx: options.supportTsx,
skipSerializers: true,
testEnvironment: options.testEnvironment,
skipFormat: true,
@@ -332,6 +326,12 @@ function normalizeOptions(
options.skipTypeCheck = false;
}
if (options.module == null) {
options.module = 'cjs';
}
options.skipBabelrc = shouldSkipBabelRc(tree, options);
const name = names(options.name).fileName;
const projectDirectory = options.directory
? `${names(options.directory).fileName}/${name}`
+13 -2
View File
@@ -52,9 +52,9 @@
"description": "Do not update tsconfig.json for development experience.",
"default": false
},
"includeBabelRc": {
"skipBabelrc": {
"type": "boolean",
"description": "Include a .babelrc configuration to compile TypeScript files"
"description": "Do not generate `.babelrc` file. Useful for Node libraries that are not compiled by Babel."
},
"testEnvironment": {
"type": "string",
@@ -62,6 +62,11 @@
"description": "The test environment to use if unitTestRunner is set to jest.",
"default": "jsdom"
},
"supportTsx": {
"type": "boolean",
"description": "Setup `tsx` support.",
"default": false
},
"importPath": {
"type": "string",
"description": "The library name used to import it, like @myorg/my-awesome-lib."
@@ -109,6 +114,12 @@
"default": "tsc",
"description": "The compiler used by the build and test targets"
},
"module": {
"type": "string",
"enum": ["cjs", "none"],
"default": "cjs",
"description": "The module type to use for this library"
},
"skipTypeCheck": {
"type": "boolean",
"description": "Whether to skip TypeScript type checking for SWC compiler.",
+4 -1
View File
@@ -7,6 +7,7 @@ import type {
import { TransformerEntry } from './typescript/types';
export type Compiler = 'tsc' | 'swc';
export type Module = 'cjs' | 'none';
export interface LibraryGeneratorSchema {
name: string;
@@ -15,10 +16,11 @@ export interface LibraryGeneratorSchema {
tags?: string;
simpleModuleName?: boolean;
skipTsConfig?: boolean;
includeBabelRc?: boolean;
skipBabelrc?: boolean;
unitTestRunner?: 'jest' | 'none';
linter?: Linter;
testEnvironment?: 'jsdom' | 'node';
supportTsx?: boolean;
importPath?: string;
js?: boolean;
pascalCaseFiles?: boolean;
@@ -28,6 +30,7 @@ export interface LibraryGeneratorSchema {
setParserOptionsProject?: boolean;
config?: 'workspace' | 'project' | 'npm-scripts';
compiler?: Compiler;
module?: Module;
skipTypeCheck?: boolean;
}
+1 -3
View File
@@ -1,6 +1,4 @@
// TODO(chau): change back to 2015 when https://github.com/swc-project/swc/issues/1108 is solved
// target: 'es2015'
import { logger, readJson, Tree, updateJson } from '@nrwl/devkit';
import { Tree } from '@nrwl/devkit';
import { join } from 'path';
export const defaultExclude = [
@@ -1,14 +1,13 @@
import {
getProjects,
NxJsonConfiguration,
readJson,
readProjectConfiguration,
Tree,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { libraryGenerator } from './library';
import { Schema } from './schema.d';
import { libraryGenerator } from './library';
const baseLibraryConfig = {
name: 'myLib',
@@ -85,6 +84,7 @@ describe('lib', () => {
const tsconfigJson = readJson(tree, 'libs/my-lib/tsconfig.json');
expect(tsconfigJson).toMatchInlineSnapshot(`
Object {
"compilerOptions": Object {},
"extends": "../../tsconfig.base.json",
"files": Array [],
"include": Array [],
@@ -12,10 +12,11 @@ import {
updateProjectConfiguration,
updateTsConfigsToJs,
} from '@nrwl/devkit';
import { libraryGenerator as jsLibraryGenerator } from '@nrwl/js/generators';
import { shouldDefaultToUsingStandaloneConfigs } from 'nx/src/generators/utils/project-configuration';
import { join } from 'path';
import { Schema } from './schema';
import { libraryGenerator as workspaceLibraryGenerator } from '@nrwl/workspace/generators';
import { join } from 'path';
export interface NormalizedSchema extends Schema {
name: string;
@@ -36,12 +37,15 @@ export async function libraryGenerator(tree: Tree, schema: Schema) {
);
}
const libraryInstall = await workspaceLibraryGenerator(tree, {
const libraryInstall = await jsLibraryGenerator(tree, {
...schema,
importPath: options.importPath,
testEnvironment: 'node',
skipFormat: true,
setParserOptionsProject: options.setParserOptionsProject,
module: 'none',
supportTsx: true,
config: options.standaloneConfig === false ? 'workspace' : 'project',
});
createFiles(tree, options);
@@ -82,6 +86,9 @@ function normalizeOptions(tree: Tree, options: Schema): NormalizedSchema {
const importPath =
options.importPath || `@${defaultPrefix}/${projectDirectory}`;
options.standaloneConfig =
options.standaloneConfig ?? shouldDefaultToUsingStandaloneConfigs(tree);
return {
...options,
prefix: defaultPrefix, // we could also allow customizing this
@@ -5,20 +5,18 @@ import {
generateFiles,
installPackagesTask,
names,
PackageManager,
readWorkspaceConfiguration,
Tree,
updateJson,
updateWorkspaceConfiguration,
} from '@nrwl/devkit';
import { Schema } from './schema';
import { libraryGenerator } from '../library/library';
import { shouldDefaultToUsingStandaloneConfigs } from 'nx/src/generators/utils/project-configuration';
import { join } from 'path';
import { insertImport } from '../utils/insert-import';
import { insertStatement } from '../utils/insert-statement';
import { Preset } from '../utils/presets';
import { join } from 'path';
import { Schema } from './schema';
export async function presetGenerator(tree: Tree, options: Schema) {
options = normalizeOptions(options);
@@ -33,6 +31,9 @@ export const presetSchematic = convertNxGenerator(presetGenerator);
export default presetGenerator;
async function createPreset(tree: Tree, options: Schema) {
options.standaloneConfig =
options.standaloneConfig ?? shouldDefaultToUsingStandaloneConfigs(tree);
if (options.preset === Preset.Empty || options.preset === Preset.Apps) {
return;
} else if (options.preset === Preset.Angular) {
@@ -95,6 +96,8 @@ async function createPreset(tree: Tree, options: Schema) {
} = require('@nrwl' + '/angular/generators');
const { applicationGenerator: nestApplicationGenerator } = require('@nrwl' +
'/nest');
const { libraryGenerator: jsLibraryGenerator } = require('@nrwl' +
'/js/generators');
await angularApplicationGenerator(tree, {
name: options.name,
@@ -109,11 +112,13 @@ async function createPreset(tree: Tree, options: Schema) {
linter: options.linter,
standaloneConfig: options.standaloneConfig,
});
await libraryGenerator(tree, {
await jsLibraryGenerator(tree, {
name: 'api-interfaces',
unitTestRunner: 'none',
linter: options.linter,
standaloneConfig: options.standaloneConfig,
module: 'none',
supportTsx: true,
config: options.standaloneConfig === false ? 'workspace' : 'project',
});
connectAngularAndNest(tree, options);
} else if (options.preset === Preset.ReactWithExpress) {
@@ -123,6 +128,8 @@ async function createPreset(tree: Tree, options: Schema) {
const {
applicationGenerator: reactApplicationGenerator,
} = require('@nrwl' + '/react');
const { libraryGenerator: jsLibraryGenerator } = require('@nrwl' +
'/js/generators');
await reactApplicationGenerator(tree, {
name: options.name,
@@ -136,11 +143,13 @@ async function createPreset(tree: Tree, options: Schema) {
linter: options.linter,
standaloneConfig: options.standaloneConfig,
});
await libraryGenerator(tree, {
await jsLibraryGenerator(tree, {
name: 'api-interfaces',
unitTestRunner: 'none',
linter: options.linter,
standaloneConfig: options.standaloneConfig,
module: 'none',
supportTsx: true,
config: options.standaloneConfig === false ? 'workspace' : 'project',
});
connectReactAndExpress(tree, options);
} else if (options.preset === Preset.Nest) {