Skip to content

Commit

Permalink
fix(misc): ensure exports are generated for several lib generators …
Browse files Browse the repository at this point in the history
…in ts solution setup (nrwl#29588)

- Update React Native, React, Remix and Vue library generators to
produce `exports` in the `package.json` for the TS solution setup
- Fix an issue in `@nx/rollup/with-nx` where an unhandled `undefined`
plugin was causing an error to be thrown
- Fix output path of the build task for React Native libraries in the TS
solution setup

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
  • Loading branch information
leosvelperez authored Jan 10, 2025
1 parent cbea062 commit 9dbebbe
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 45 deletions.
20 changes: 14 additions & 6 deletions e2e/nx/src/affected-graph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ describe('Nx Affected and Graph Tests', () => {
const mylib = uniq('mylib');
const mylib2 = uniq('mylib2');
const mypublishablelib = uniq('mypublishablelib');
runCLI(`generate @nx/web:app apps/${myapp}`);
runCLI(`generate @nx/web:app apps/${myapp2}`);
runCLI(`generate @nx/web:app apps/${myapp} --unitTestRunner=vitest`);
runCLI(`generate @nx/web:app apps/${myapp2} --unitTestRunner=vitest`);
runCLI(`generate @nx/js:lib libs/${mylib}`);
runCLI(`generate @nx/js:lib libs/${mylib2}`);
runCLI(
Expand Down Expand Up @@ -193,8 +193,12 @@ describe('Nx Affected and Graph Tests', () => {
});

function generateAll() {
runCLI(`generate @nx/web:app apps/${myapp}`);
runCLI(`generate @nx/web:app apps/${myapp2}`);
runCLI(
`generate @nx/web:app apps/${myapp} --bundler=webpack --unitTestRunner=vitest`
);
runCLI(
`generate @nx/web:app apps/${myapp2} --bundler=webpack --unitTestRunner=vitest`
);
runCLI(`generate @nx/js:lib libs/${mylib}`);
runCommand(`git add . && git commit -am "add all"`);
}
Expand Down Expand Up @@ -536,8 +540,12 @@ describe('show projects --affected', () => {
const mylib2 = uniq('mylib2');
const mypublishablelib = uniq('mypublishablelib');

runCLI(`generate @nx/web:app ${myapp} --directory=apps/${myapp}`);
runCLI(`generate @nx/web:app ${myapp2} --directory=apps/${myapp2}`);
runCLI(
`generate @nx/web:app ${myapp} --directory=apps/${myapp} --unitTestRunner=vitest`
);
runCLI(
`generate @nx/web:app ${myapp2} --directory=apps/${myapp2} --unitTestRunner=vitest`
);
runCLI(`generate @nx/js:lib ${mylib} --directory=libs/${mylib}`);
runCLI(`generate @nx/js:lib ${mylib2} --directory=libs/${mylib2}`);
runCLI(
Expand Down
6 changes: 4 additions & 2 deletions e2e/nx/src/misc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ describe('Nx Commands', () => {

it('should show detailed project info', () => {
const app = uniq('myapp');
runCLI(`generate @nx/web:app apps/${app}`);
runCLI(
`generate @nx/web:app apps/${app} --bundler=webpack --unitTestRunner=vitest --linter=eslint`
);
const project: ProjectConfiguration = JSON.parse(
runCLI(`show project ${app}`)
runCLI(`show project ${app} --json`)
);
expect(project.targets.build).toBeDefined();
expect(project.targets.lint).toBeDefined();
Expand Down
8 changes: 6 additions & 2 deletions e2e/nx/src/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -728,8 +728,12 @@ describe('Nx Running Tests', () => {
it('should run multiple targets', () => {
const myapp1 = uniq('myapp');
const myapp2 = uniq('myapp');
runCLI(`generate @nx/web:app ${myapp1} --directory=apps/${myapp1}`);
runCLI(`generate @nx/web:app ${myapp2} --directory=apps/${myapp2}`);
runCLI(
`generate @nx/web:app ${myapp1} --directory=apps/${myapp1} --unitTestRunner=vitest`
);
runCLI(
`generate @nx/web:app ${myapp2} --directory=apps/${myapp2} --unitTestRunner=vitest`
);

let outputs = runCLI(
// Options with lists can be specified using multiple args or with a delimiter (comma or space).
Expand Down
1 change: 1 addition & 0 deletions packages/nx/src/utils/package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export interface PackageJson {
require?: string;
import?: string;
development?: string;
default?: string;
}
>;
dependencies?: Record<string, string>;
Expand Down
51 changes: 42 additions & 9 deletions packages/react-native/src/generators/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
updateTsconfigFiles,
} from '@nx/js/src/utils/typescript/ts-solution-setup';
import { getImportPath } from '@nx/js/src/utils/get-import-path';
import type { PackageJson } from 'nx/src/utils/package-json';

export async function reactNativeLibraryGenerator(
host: Tree,
Expand Down Expand Up @@ -162,17 +163,15 @@ async function addProject(
targets: {},
};

const packageJsonPath = joinPathFragments(
options.projectRoot,
'package.json'
);
if (options.isUsingTsSolutionConfig) {
const sourceEntry = !options.buildable
? options.js
? './src/index.js'
: './src/index.ts'
: undefined;
writeJson(host, joinPathFragments(options.projectRoot, 'package.json'), {
writeJson(host, packageJsonPath, {
name: getImportPath(host, options.name),
version: '0.0.1',
main: sourceEntry,
types: sourceEntry,
...determineEntryFields(options),
nx: {
name: options.name,
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
Expand All @@ -198,13 +197,24 @@ async function addProject(
skipFormat: true,
});

updateJson(host, packageJsonPath, (json) => {
if (json.type === 'module') {
// The @nx/rollup:configuration generator can set the type to 'module' which would
// potentially break this library.
delete json.type;
}
return json;
});

const external = ['react/jsx-runtime', 'react-native', 'react', 'react-dom'];

project.targets.build = {
executor: '@nx/rollup:rollup',
outputs: ['{options.outputPath}'],
options: {
outputPath: `dist/${options.projectRoot}`,
outputPath: options.isUsingTsSolutionConfig
? `${options.projectRoot}/dist`
: `dist/${options.projectRoot}`,
tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
project: `${options.projectRoot}/package.json`,
entryFile: maybeJs(options, `${options.projectRoot}/src/index.ts`),
Expand Down Expand Up @@ -293,4 +303,27 @@ function maybeJs(options: NormalizedSchema, path: string): string {
: path;
}

function determineEntryFields(
options: NormalizedSchema
): Pick<PackageJson, 'main' | 'types' | 'exports'> {
if (options.buildable) {
return {};
}

return {
main: options.js ? './src/index.js' : './src/index.ts',
types: options.js ? './src/index.js' : './src/index.ts',
exports: {
'.': options.js
? './src/index.js'
: {
types: './src/index.ts',
import: './src/index.ts',
default: './src/index.ts',
},
'./package.json': './package.json',
},
};
}

export default reactNativeLibraryGenerator;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { PackageJson } from 'nx/src/utils/package-json';
import type { NormalizedSchema } from '../schema';

export function determineEntryFields(
options: NormalizedSchema
): Pick<PackageJson, 'main' | 'types' | 'exports'> {
if (options.bundler !== 'none') {
return {};
}

return {
main: options.js ? './src/index.js' : './src/index.ts',
types: options.js ? './src/index.js' : './src/index.ts',
exports: {
'.': options.js
? './src/index.js'
: {
types: './src/index.ts',
import: './src/index.ts',
default: './src/index.ts',
},
'./package.json': './package.json',
},
};
}
12 changes: 12 additions & 0 deletions packages/react/src/generators/library/library.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,14 @@ module.exports = withNx(

expect(readJson(tree, 'mylib/package.json')).toMatchInlineSnapshot(`
{
"exports": {
".": {
"default": "./src/index.ts",
"import": "./src/index.ts",
"types": "./src/index.ts",
},
"./package.json": "./package.json",
},
"main": "./src/index.ts",
"name": "@proj/mylib",
"nx": {
Expand All @@ -1157,6 +1165,10 @@ module.exports = withNx(
`);
expect(readJson(tree, 'myjslib/package.json')).toMatchInlineSnapshot(`
{
"exports": {
".": "./src/index.js",
"./package.json": "./package.json",
},
"main": "./src/index.js",
"name": "@proj/myjslib",
"nx": {
Expand Down
10 changes: 2 additions & 8 deletions packages/react/src/generators/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
addProjectToTsSolutionWorkspace,
updateTsconfigFiles,
} from '@nx/js/src/utils/typescript/ts-solution-setup';
import { determineEntryFields } from './lib/determine-entry-fields';

export async function libraryGenerator(host: Tree, schema: Schema) {
return await libraryGeneratorInternal(host, {
Expand Down Expand Up @@ -69,17 +70,10 @@ export async function libraryGeneratorInternal(host: Tree, schema: Schema) {
tasks.push(initTask);

if (options.isUsingTsSolutionConfig) {
const sourceEntry =
options.bundler === 'none'
? options.js
? './src/index.js'
: './src/index.ts'
: undefined;
writeJson(host, `${options.projectRoot}/package.json`, {
name: options.importPath,
version: '0.0.1',
main: sourceEntry,
types: sourceEntry,
...determineEntryFields(options),
nx: {
name: options.importPath === options.name ? undefined : options.name,
projectType: 'library',
Expand Down
8 changes: 8 additions & 0 deletions packages/remix/src/generators/library/library.impl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ describe('Remix Library Generator', () => {
expect(readJson(tree, 'packages/foo/package.json'))
.toMatchInlineSnapshot(`
{
"exports": {
".": {
"default": "./src/index.ts",
"import": "./src/index.ts",
"types": "./src/index.ts",
},
"./package.json": "./package.json",
},
"main": "./src/index.ts",
"name": "@proj/foo",
"nx": {
Expand Down
2 changes: 1 addition & 1 deletion packages/rollup/src/plugins/with-nx/with-nx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export function withNx(
commonjs(),
analyze(),
options.generatePackageJson && generatePackageJson(options, packageJson),
];
].filter(Boolean);
if (Array.isArray(rollupConfig.plugins)) {
finalConfig.plugins.push(...rollupConfig.plugins);
}
Expand Down
28 changes: 28 additions & 0 deletions packages/vue/src/generators/library/lib/determine-entry-fields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { PackageJson } from 'nx/src/utils/package-json';
import type { NormalizedSchema } from '../schema';

export function determineEntryFields(
options: NormalizedSchema
): Pick<PackageJson, 'module' | 'types' | 'exports'> {
if (options.bundler === 'none') {
return {
module: options.js ? './src/index.js' : './src/index.ts',
types: options.js ? './src/index.js' : './src/index.ts',
exports: {
'.': options.js
? './src/index.js'
: {
types: './src/index.ts',
import: './src/index.ts',
default: './src/index.ts',
},
'./package.json': './package.json',
},
};
}

return {
module: './dist/index.mjs',
types: './dist/index.d.ts',
};
}
20 changes: 3 additions & 17 deletions packages/vue/src/generators/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import {
GeneratorCallback,
installPackagesTask,
joinPathFragments,
readNxJson,
runTasksInSerial,
toJS,
Tree,
updateJson,
updateNxJson,
writeJson,
} from '@nx/devkit';
import { addTsConfigPath, initGenerator as jsInitGenerator } from '@nx/js';
Expand All @@ -30,6 +28,7 @@ import {
addProjectToTsSolutionWorkspace,
updateTsconfigFiles,
} from '@nx/js/src/utils/typescript/ts-solution-setup';
import { determineEntryFields } from './lib/determine-entry-fields';

export function libraryGenerator(tree: Tree, schema: Schema) {
return libraryGeneratorInternal(tree, { addPlugin: false, ...schema });
Expand All @@ -48,28 +47,15 @@ export async function libraryGeneratorInternal(tree: Tree, schema: Schema) {
}

if (options.isUsingTsSolutionConfig) {
const moduleFile =
options.bundler === 'none'
? options.js
? './src/index.js'
: './src/index.ts'
: './dist/index.mjs';
const typesFile =
options.bundler === 'none'
? options.js
? './src/index.js'
: './src/index.ts'
: './dist/index.d.ts';
writeJson(tree, joinPathFragments(options.projectRoot, 'package.json'), {
name: getImportPath(tree, options.name),
version: '0.0.1',
private: true,
module: moduleFile,
types: typesFile,
...determineEntryFields(options),
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
nx: {
name: options.name,
projectType: 'application',
projectType: 'library',
sourceRoot: `${options.projectRoot}/src`,
tags: options.parsedTags?.length ? options.parsedTags : undefined,
},
Expand Down

0 comments on commit 9dbebbe

Please sign in to comment.