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

feat(nest): use nrwl/js to generate library #9164

Merged
merged 11 commits into from Mar 3, 2022
8 changes: 8 additions & 0 deletions docs/generated/api-js/generators/library.md
Expand Up @@ -115,6 +115,14 @@ Type: `boolean`

Use pascal case file names.

### publishable

Default: `false`

Type: `boolean`

Generate a publishable library.

### setParserOptionsProject

Default: `false`
Expand Down
2 changes: 2 additions & 0 deletions docs/generated/api-nest/generators/library.md
Expand Up @@ -135,6 +135,8 @@ Do not update tsconfig.base.json for development experience.

### standaloneConfig

Default: `true`

Type: `boolean`

Split the project configuration into <projectRoot>/project.json rather than including it inside workspace.json
Expand Down
6 changes: 4 additions & 2 deletions docs/generated/api-node/executors/webpack.md
Expand Up @@ -159,11 +159,13 @@ Type: `boolean`

Generates a 'stats.json' file which can be analyzed using tools such as: 'webpack-bundle-analyzer' or <https://webpack.github.io/analyse>.

### tsPlugins
### transformers

Alias(es): tsPlugins

Type: `array`

List of TypeScript Compiler Plugins.
List of TypeScript Compiler Transfomers Plugins.

### verbose

Expand Down
16 changes: 7 additions & 9 deletions e2e/node/src/node.test.ts
@@ -1,6 +1,4 @@
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
import { exec, execSync } from 'child_process';
import * as http from 'http';
import {
checkFilesDoNotExist,
checkFilesExist,
Expand All @@ -18,6 +16,8 @@ import {
updateFile,
updateProjectConfig,
} from '@nrwl/e2e/utils';
import { exec, execSync } from 'child_process';
import * as http from 'http';

function getData(port): Promise<any> {
return new Promise((resolve) => {
Expand Down Expand Up @@ -291,8 +291,7 @@ describe('Build Node apps', () => {
const nestapp = uniq('nestapp');
runCLI(`generate @nrwl/nest:app ${nestapp} --linter=eslint`);

// TODO: update to v5 when Nest8 is supported
packageInstall('@nestjs/swagger', undefined, '4.8.2');
packageInstall('@nestjs/swagger', undefined, '~5.0.0');

updateProjectConfig(nestapp, (config) => {
config.targets.build.options.tsPlugins = ['@nestjs/swagger/plugin'];
Expand Down Expand Up @@ -370,9 +369,9 @@ describe('nest libraries', function () {
},
testEnvironment: 'node',
transform: {
'^.+\\.[tj]sx?$': 'ts-jest',
'^.+\\.[tj]s$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/libs/${nestlib}',
};
`
Expand Down Expand Up @@ -424,13 +423,12 @@ describe('nest libraries', function () {
);
}, 200000);

it('should have plugin output if specified in `tsPlugins`', async () => {
it('should have plugin output if specified in `transformers`', async () => {
newProject();
const nestlib = uniq('nestlib');
runCLI(`generate @nrwl/nest:lib ${nestlib} --buildable`);

// TODO: update to v5 when Nest8 is supported
packageInstall('@nestjs/swagger', undefined, '4.8.2');
packageInstall('@nestjs/swagger', undefined, '~5.0.0');

updateProjectConfig(nestlib, (config) => {
config.targets.build.options.transformers = [
Expand Down
23 changes: 11 additions & 12 deletions e2e/utils/index.ts
@@ -1,4 +1,12 @@
import {
joinPathFragments,
parseJson,
ProjectConfiguration,
WorkspaceJsonConfiguration,
} from '@nrwl/devkit';
import { detectPackageManager } from '@nrwl/tao/src/shared/package-manager';
import { Workspaces } from '@nrwl/tao/src/shared/workspace';
import { angularCliVersion } from '@nrwl/workspace/src/utils/versions';
import { ChildProcess, exec, execSync } from 'child_process';
import {
copySync,
Expand All @@ -14,21 +22,12 @@ import {
} from 'fs-extra';
import * as path from 'path';
import { join } from 'path';
import { dirSync } from 'tmp';
import { coerce } from 'semver';
import { check as portCheck } from 'tcp-port-used';
import {
joinPathFragments,
parseJson,
ProjectConfiguration,
WorkspaceJsonConfiguration,
} from '@nrwl/devkit';
import { dirSync } from 'tmp';
import { promisify } from 'util';
import { Workspaces } from '@nrwl/tao/src/shared/workspace';
import { angularCliVersion } from '@nrwl/workspace/src/utils/versions';
import { coerce } from 'semver';
import isCI = require('is-ci');

import chalk = require('chalk');
import isCI = require('is-ci');
import treeKill = require('tree-kill');

const kill = require('kill-port');
Expand Down
@@ -1,14 +1,14 @@
import { readProjectConfiguration, Tree } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { join } from 'path';
import { GeneratorSchema } from '../../utils/schema';
import { LibraryGeneratorSchema } from '../../utils/schema';
import { libraryGenerator } from '../library/library';
import { convertToSwcGenerator } from './convert-to-swc';

describe('convert to swc', () => {
let tree: Tree;

const defaultLibGenerationOptions: Omit<GeneratorSchema, 'name'> = {
const defaultLibGenerationOptions: Omit<LibraryGeneratorSchema, 'name'> = {
skipTsConfig: false,
unitTestRunner: 'jest',
skipFormat: false,
Expand Down
4 changes: 2 additions & 2 deletions packages/js/src/generators/library/library.spec.ts
Expand Up @@ -6,12 +6,12 @@ import {
updateJson,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { GeneratorSchema } from '../../utils/schema';
import { LibraryGeneratorSchema } from '../../utils/schema';
import libraryGenerator from './library';

describe('lib', () => {
let tree: Tree;
const defaultOptions: Omit<GeneratorSchema, 'name'> = {
const defaultOptions: Omit<LibraryGeneratorSchema, 'name'> = {
skipTsConfig: false,
unitTestRunner: 'jest',
skipFormat: false,
Expand Down
22 changes: 17 additions & 5 deletions packages/js/src/generators/library/library.ts
Expand Up @@ -14,21 +14,24 @@ import {
updateJson,
} from '@nrwl/devkit';
import { join } from 'path';
import { GeneratorSchema } from '../../utils/schema';
import { LibraryGeneratorSchema } from '../../utils/schema';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
import { Linter, lintProjectGenerator } from '@nrwl/linter';
import { jestProjectGenerator } from '@nrwl/jest';
import { addSwcDependencies } from '../../utils/swc/add-swc-dependencies';
import { addSwcConfig } from '../../utils/swc/add-swc-config';

export async function libraryGenerator(tree: Tree, schema: GeneratorSchema) {
export async function libraryGenerator(
tree: Tree,
schema: LibraryGeneratorSchema
) {
const { libsDir } = getWorkspaceLayout(tree);
return projectGenerator(tree, schema, libsDir, join(__dirname, './files'));
}

export async function projectGenerator(
tree: Tree,
schema: GeneratorSchema,
schema: LibraryGeneratorSchema,
destinationDir: string,
filesDir: string
) {
Expand Down Expand Up @@ -60,7 +63,7 @@ export async function projectGenerator(
return runTasksInSerial(...tasks);
}

export interface NormalizedSchema extends GeneratorSchema {
export interface NormalizedSchema extends LibraryGeneratorSchema {
name: string;
fileName: string;
projectRoot: string;
Expand Down Expand Up @@ -221,9 +224,18 @@ async function addJest(

function normalizeOptions(
tree: Tree,
options: GeneratorSchema,
options: LibraryGeneratorSchema,
destinationDir: string
): NormalizedSchema {
if (options.publishable) {
if (!options.importPath) {
throw new Error(
`For publishable libs you have to provide a proper "--importPath" which needs to be a valid npm package name (e.g. my-awesome-lib or @myorg/my-lib)`
);
}
options.buildable = true;
}

if (options.config === 'npm-scripts') {
options.unitTestRunner = 'none';
options.linter = Linter.None;
Expand Down
5 changes: 5 additions & 0 deletions packages/js/src/generators/library/schema.json
Expand Up @@ -77,6 +77,11 @@
"description": "Whether to enable tsconfig strict mode or not.",
"default": true
},
"publishable": {
"type": "boolean",
"default": false,
"description": "Generate a publishable library."
},
"buildable": {
"type": "boolean",
"default": true,
Expand Down
3 changes: 2 additions & 1 deletion packages/js/src/utils/schema.d.ts
Expand Up @@ -8,7 +8,7 @@ import { TransformerEntry } from './typescript/types';

export type Compiler = 'tsc' | 'swc';

export interface GeneratorSchema {
export interface LibraryGeneratorSchema {
name: string;
directory?: string;
skipFormat?: boolean;
Expand All @@ -22,6 +22,7 @@ export interface GeneratorSchema {
js?: boolean;
pascalCaseFiles?: boolean;
strict?: boolean;
publishable?: boolean;
buildable?: boolean;
setParserOptionsProject?: boolean;
config?: 'workspace' | 'project' | 'npm-scripts';
Expand Down
Expand Up @@ -12,7 +12,7 @@ import type {
} from 'typescript';
import { createAsyncIterable } from '../create-async-iterable/create-async-iteratable';
import { NormalizedExecutorOptions } from '../schema';
import { loadTsPlugins } from './load-ts-plugins';
import { loadTsTransformers } from './load-ts-transformers';

export async function* compileTypeScriptFiles(
normalizedOptions: NormalizedExecutorOptions,
Expand All @@ -24,7 +24,9 @@ export async function* compileTypeScriptFiles(
outfile: normalizedOptions.mainOutputPath,
});

const { compilerPluginHooks } = loadTsPlugins(normalizedOptions.transformers);
const { compilerPluginHooks } = loadTsTransformers(
normalizedOptions.transformers
);

const getCustomTransformers = (program: Program): CustomTransformers => ({
before: compilerPluginHooks.beforeHooks.map(
Expand Down
@@ -1,22 +1,22 @@
import { loadTsPlugins } from './load-ts-plugins';
import { loadTsTransformers } from './load-ts-transformers';

jest.mock('plugin-a');
jest.mock('plugin-b');
const mockRequireResolve = jest.fn((path) => path);

describe('loadTsPlugins', () => {
describe('loadTsTransformers', () => {
it('should return empty hooks if plugins is falsy', () => {
const result = loadTsPlugins(undefined);
const result = loadTsTransformers(undefined);
assertEmptyResult(result);
});

it('should return empty hooks if plugins is []', () => {
const result = loadTsPlugins([]);
const result = loadTsTransformers([]);
assertEmptyResult(result);
});

it('should return correct compiler hooks', () => {
const result = loadTsPlugins(
const result = loadTsTransformers(
['plugin-a', 'plugin-b'],
mockRequireResolve as any
);
Expand All @@ -29,7 +29,7 @@ describe('loadTsPlugins', () => {
});
});

function assertEmptyResult(result: ReturnType<typeof loadTsPlugins>) {
function assertEmptyResult(result: ReturnType<typeof loadTsTransformers>) {
expect(result.hasPlugin).toEqual(false);
expect(result.compilerPluginHooks).toEqual({
beforeHooks: [],
Expand Down
Expand Up @@ -3,11 +3,11 @@ import { join } from 'path';
import {
CompilerPlugin,
CompilerPluginHooks,
TransformerPlugin,
TransformerEntry,
TransformerPlugin,
} from './types';

export function loadTsPlugins(
export function loadTsTransformers(
plugins: TransformerEntry[],
moduleResolver: typeof require.resolve = require.resolve
): {
Expand Down
1 change: 1 addition & 0 deletions packages/nest/package.json
Expand Up @@ -32,6 +32,7 @@
"@nrwl/devkit": "*",
"@nrwl/linter": "*",
"@nrwl/node": "*",
"@nrwl/js": "*",
"@nrwl/jest": "*",
"@nestjs/schematics": "^8.0.0"
}
Expand Down
Expand Up @@ -9,11 +9,10 @@ exports[`lib --testEnvironment should set target jest testEnvironment to jsdom 1
tsconfig: '<rootDir>/tsconfig.spec.json',
}
},
testEnvironment: 'node',
transform: {
'^.+\\\\\\\\.[tj]sx?$': 'ts-jest'
'^.+\\\\\\\\.[tj]s$': 'ts-jest'
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/libs/my-lib'
};
"
Expand All @@ -30,16 +29,19 @@ exports[`lib --testEnvironment should set target jest testEnvironment to node by
},
testEnvironment: 'node',
transform: {
'^.+\\\\\\\\.[tj]sx?$': 'ts-jest'
'^.+\\\\\\\\.[tj]s$': 'ts-jest'
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/libs/my-lib'
};
"
`;

exports[`lib --unit-test-runner none should not generate test configuration 1`] = `
Object {
"compilerOptions": Object {
"module": "CommonJS",
},
"extends": "../../tsconfig.base.json",
"files": Array [],
"include": Array [],
Expand Down Expand Up @@ -67,6 +69,9 @@ Object {

exports[`lib nested should create a local tsconfig.json 1`] = `
Object {
"compilerOptions": Object {
"module": "CommonJS",
},
"extends": "../../../tsconfig.base.json",
"files": Array [],
"include": Array [],
Expand Down Expand Up @@ -96,6 +101,9 @@ export class MyLibModule {}

exports[`lib not nested should create a local tsconfig.json 1`] = `
Object {
"compilerOptions": Object {
"module": "CommonJS",
},
"extends": "../../tsconfig.base.json",
"files": Array [],
"include": Array [],
Expand Down