fix(misc): ensure exports are generated for several lib generators in ts solution setup (#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 #
This commit is contained in:
parent
cbea0623df
commit
9dbebbee20
@ -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(
|
||||
@ -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"`);
|
||||
}
|
||||
@ -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(
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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).
|
||||
|
||||
@ -55,6 +55,7 @@ export interface PackageJson {
|
||||
require?: string;
|
||||
import?: string;
|
||||
development?: string;
|
||||
default?: string;
|
||||
}
|
||||
>;
|
||||
dependencies?: Record<string, string>;
|
||||
|
||||
@ -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,
|
||||
@ -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'),
|
||||
@ -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`),
|
||||
@ -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;
|
||||
|
||||
@ -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',
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -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": {
|
||||
@ -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": {
|
||||
|
||||
@ -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, {
|
||||
@ -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',
|
||||
|
||||
@ -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": {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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',
|
||||
};
|
||||
}
|
||||
@ -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';
|
||||
@ -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 });
|
||||
@ -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,
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user