fix(js): generate pacakge.json for non-buildable nest and expo libs (#29891)
This PR fixes a couple of issues for TS solution setup: 1. Expo library should generate with correct `package.json` file (e.g. `exports` maps either to source or dist). See [spec file](https://github.com/nrwl/nx/pull/29891/files#diff-ae2eb3d10d58786c17aa21f5603043b68043faaebafaec77912f3d69ac0c5295). 2. Nest library should generate `package.json` when non-buildable. See [spec file](https://github.com/nrwl/nx/pull/29891/files#diff-368467bcd2215def98ef14aaff9dcb056a915b0a724d0eb857f3a0badef8b40a). **Notes:** - Also removed an unsupported `standaloneConfig` option from `@nx/nest:lib` generator. This was removed a long time ago in other generators. - Expo lib generator isn't crystalized when using Rollup for build. This is a separate issue and we'll handle it in another task. ## Current Behavior - Non-buildable Expo libs generate without `exports` - Buildable Expo libs fail to generate due to error - Non-buildable Nest libs do not generate `package.json` ## Expected Behavior Expo and Nest libs generate correct `package.json` files depending on whether they are build or non-buildable. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
d62b94f6a7
commit
8bd0bcdd97
@ -118,12 +118,6 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"standaloneConfig": {
|
|
||||||
"description": "Split the project configuration into <projectRoot>/project.json rather than including it inside workspace.json",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true,
|
|
||||||
"x-deprecated": "Nx only supports standaloneConfig"
|
|
||||||
},
|
|
||||||
"setParserOptionsProject": {
|
"setParserOptionsProject": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint \"parserOptions.project\" option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint \"parserOptions.project\" option. We do not do this by default for lint performance reasons.",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "<%= name %>",
|
"name": "<%= projectName %>",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"main": "<%= appMain %>"
|
"main": "<%= appMain %>"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,12 @@ import {
|
|||||||
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
} from '@nx/devkit/src/generators/project-name-and-root-utils';
|
||||||
import { Schema } from '../schema';
|
import { Schema } from '../schema';
|
||||||
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
name: string;
|
name: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
|
projectName: string;
|
||||||
projectRoot: string;
|
projectRoot: string;
|
||||||
routePath: string;
|
routePath: string;
|
||||||
parsedTags: string[];
|
parsedTags: string[];
|
||||||
@ -43,16 +45,20 @@ export async function normalizeOptions(
|
|||||||
: [];
|
: [];
|
||||||
const appMain = options.js ? 'src/index.js' : 'src/index.ts';
|
const appMain = options.js ? 'src/index.js' : 'src/index.ts';
|
||||||
|
|
||||||
|
const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
|
||||||
const normalized: NormalizedSchema = {
|
const normalized: NormalizedSchema = {
|
||||||
...options,
|
...options,
|
||||||
fileName: projectName,
|
fileName: projectName,
|
||||||
routePath: `/${projectNames.projectSimpleName}`,
|
routePath: `/${projectNames.projectSimpleName}`,
|
||||||
name: projectName,
|
name: projectName,
|
||||||
|
projectName: isUsingTsSolutionConfig
|
||||||
|
? getImportPath(host, projectName)
|
||||||
|
: projectName,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
importPath,
|
importPath,
|
||||||
appMain,
|
appMain,
|
||||||
isUsingTsSolutionConfig: isUsingTsSolutionSetup(host),
|
isUsingTsSolutionConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
return normalized;
|
return normalized;
|
||||||
|
|||||||
@ -504,6 +504,22 @@ describe('lib', () => {
|
|||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
// Make sure keys are in idiomatic order
|
// Make sure keys are in idiomatic order
|
||||||
|
expect(readJson(appTree, 'my-lib/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/my-lib",
|
||||||
|
"types": "./src/index.ts",
|
||||||
|
"version": "0.0.1",
|
||||||
|
}
|
||||||
|
`);
|
||||||
expect(Object.keys(readJson(appTree, 'my-lib/package.json')))
|
expect(Object.keys(readJson(appTree, 'my-lib/package.json')))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
[
|
[
|
||||||
@ -511,7 +527,7 @@ describe('lib', () => {
|
|||||||
"version",
|
"version",
|
||||||
"main",
|
"main",
|
||||||
"types",
|
"types",
|
||||||
"nx",
|
"exports",
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
expect(readJson(appTree, 'my-lib/tsconfig.json')).toMatchInlineSnapshot(`
|
expect(readJson(appTree, 'my-lib/tsconfig.json')).toMatchInlineSnapshot(`
|
||||||
@ -608,5 +624,69 @@ describe('lib', () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate buildable library', async () => {
|
||||||
|
await expoLibraryGenerator(appTree, {
|
||||||
|
...defaultSchema,
|
||||||
|
buildable: true,
|
||||||
|
strict: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readJson(appTree, 'my-lib/package.json')).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"default": "./dist/index.esm.js",
|
||||||
|
"import": "./dist/index.esm.js",
|
||||||
|
"types": "./dist/index.esm.d.ts",
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json",
|
||||||
|
},
|
||||||
|
"main": "./dist/index.esm.js",
|
||||||
|
"module": "./dist/index.esm.js",
|
||||||
|
"name": "@proj/my-lib",
|
||||||
|
"nx": {
|
||||||
|
"projectType": "library",
|
||||||
|
"sourceRoot": "my-lib/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"executor": "@nx/rollup:rollup",
|
||||||
|
"options": {
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "my-lib/README.md",
|
||||||
|
"input": ".",
|
||||||
|
"output": ".",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"entryFile": "my-lib/src/index.ts",
|
||||||
|
"external": [
|
||||||
|
"react/jsx-runtime",
|
||||||
|
"react-native",
|
||||||
|
"react",
|
||||||
|
"react-dom",
|
||||||
|
],
|
||||||
|
"outputPath": "dist/my-lib",
|
||||||
|
"project": "my-lib/package.json",
|
||||||
|
"rollupConfig": "@nx/react/plugins/bundle-rollup",
|
||||||
|
"tsConfig": "my-lib/tsconfig.lib.json",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{options.outputPath}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "~18.3.1",
|
||||||
|
"react-native": "0.76.3",
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"types": "./dist/index.esm.d.ts",
|
||||||
|
"version": "0.0.1",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -40,7 +40,6 @@ import {
|
|||||||
addProjectToTsSolutionWorkspace,
|
addProjectToTsSolutionWorkspace,
|
||||||
updateTsconfigFiles,
|
updateTsconfigFiles,
|
||||||
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
} from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
import { getImportPath } from '@nx/js/src/utils/get-import-path';
|
|
||||||
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields';
|
||||||
|
|
||||||
export async function expoLibraryGenerator(
|
export async function expoLibraryGenerator(
|
||||||
@ -72,6 +71,10 @@ export async function expoLibraryGeneratorInternal(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.isUsingTsSolutionConfig) {
|
||||||
|
addProjectToTsSolutionWorkspace(host, options.projectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
const initTask = await init(host, { ...options, skipFormat: true });
|
const initTask = await init(host, { ...options, skipFormat: true });
|
||||||
tasks.push(initTask);
|
tasks.push(initTask);
|
||||||
if (!options.skipPackageJson) {
|
if (!options.skipPackageJson) {
|
||||||
@ -88,7 +91,7 @@ export async function expoLibraryGeneratorInternal(
|
|||||||
|
|
||||||
const lintTask = await addLinting(host, {
|
const lintTask = await addLinting(host, {
|
||||||
...options,
|
...options,
|
||||||
projectName: options.name,
|
projectName: options.projectName,
|
||||||
tsConfigPaths: [
|
tsConfigPaths: [
|
||||||
joinPathFragments(options.projectRoot, 'tsconfig.lib.json'),
|
joinPathFragments(options.projectRoot, 'tsconfig.lib.json'),
|
||||||
],
|
],
|
||||||
@ -98,7 +101,7 @@ export async function expoLibraryGeneratorInternal(
|
|||||||
const jestTask = await addJest(
|
const jestTask = await addJest(
|
||||||
host,
|
host,
|
||||||
options.unitTestRunner,
|
options.unitTestRunner,
|
||||||
options.name,
|
options.projectName,
|
||||||
options.projectRoot,
|
options.projectRoot,
|
||||||
options.js,
|
options.js,
|
||||||
options.skipPackageJson,
|
options.skipPackageJson,
|
||||||
@ -134,10 +137,6 @@ export async function expoLibraryGeneratorInternal(
|
|||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
|
||||||
addProjectToTsSolutionWorkspace(host, options.projectRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortPackageJsonFields(host, options.projectRoot);
|
sortPackageJsonFields(host, options.projectRoot);
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
if (!options.skipFormat) {
|
||||||
@ -169,23 +168,35 @@ async function addProject(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (options.isUsingTsSolutionConfig) {
|
if (options.isUsingTsSolutionConfig) {
|
||||||
const packageName = getImportPath(host, options.name);
|
|
||||||
const sourceEntry = !options.buildable
|
const sourceEntry = !options.buildable
|
||||||
? options.js
|
? options.js
|
||||||
? './src/index.js'
|
? './src/index.js'
|
||||||
: './src/index.ts'
|
: './src/index.ts'
|
||||||
: undefined;
|
: undefined;
|
||||||
writeJson(host, joinPathFragments(options.projectRoot, 'package.json'), {
|
writeJson(host, joinPathFragments(options.projectRoot, 'package.json'), {
|
||||||
name: packageName,
|
name: options.projectName,
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
main: sourceEntry,
|
main: sourceEntry,
|
||||||
types: sourceEntry,
|
types: sourceEntry,
|
||||||
nx: {
|
// For buildable libraries, the entries are configured by the bundler (i.e. Rollup).
|
||||||
name: packageName === options.name ? undefined : options.name,
|
exports: options.buildable
|
||||||
projectType: 'library',
|
? undefined
|
||||||
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
|
: {
|
||||||
tags: options.parsedTags?.length ? options.parsedTags : undefined,
|
'./package.json': './package.json',
|
||||||
|
'.': options.js
|
||||||
|
? './src/index.js'
|
||||||
|
: {
|
||||||
|
types: './src/index.ts',
|
||||||
|
import: './src/index.ts',
|
||||||
|
default: './src/index.ts',
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
nx: options.parsedTags?.length
|
||||||
|
? {
|
||||||
|
tags: options.parsedTags,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
addProjectConfiguration(host, options.name, project);
|
addProjectConfiguration(host, options.name, project);
|
||||||
@ -201,7 +212,7 @@ async function addProject(
|
|||||||
);
|
);
|
||||||
const rollupConfigTask = await configurationGenerator(host, {
|
const rollupConfigTask = await configurationGenerator(host, {
|
||||||
...options,
|
...options,
|
||||||
project: options.name,
|
project: options.projectName,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -229,7 +240,7 @@ async function addProject(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
updateProjectConfiguration(host, options.name, project);
|
updateProjectConfiguration(host, options.projectName, project);
|
||||||
|
|
||||||
return rollupConfigTask;
|
return rollupConfigTask;
|
||||||
}
|
}
|
||||||
@ -271,7 +282,11 @@ function createFiles(host: Tree, options: NormalizedSchema) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!options.publishable && !options.buildable) {
|
if (
|
||||||
|
!options.publishable &&
|
||||||
|
!options.buildable &&
|
||||||
|
!options.isUsingTsSolutionConfig
|
||||||
|
) {
|
||||||
host.delete(`${options.projectRoot}/package.json`);
|
host.delete(`${options.projectRoot}/package.json`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,11 @@ export function deleteFiles(tree: Tree, options: NormalizedOptions): void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.buildable && !options.publishable) {
|
if (
|
||||||
|
!options.buildable &&
|
||||||
|
!options.publishable &&
|
||||||
|
!options.isUsingTsSolutionsConfig
|
||||||
|
) {
|
||||||
tree.delete(joinPathFragments(options.projectRoot, 'package.json'));
|
tree.delete(joinPathFragments(options.projectRoot, 'package.json'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,7 @@ export async function normalizeOptions(
|
|||||||
? options.tags.split(',').map((s) => s.trim())
|
? options.tags.split(',').map((s) => s.trim())
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
|
const isUsingTsSolutionsConfig = isUsingTsSolutionSetup(tree);
|
||||||
const normalized: NormalizedOptions = {
|
const normalized: NormalizedOptions = {
|
||||||
...options,
|
...options,
|
||||||
strict: options.strict ?? true,
|
strict: options.strict ?? true,
|
||||||
@ -49,7 +50,7 @@ export async function normalizeOptions(
|
|||||||
linter: options.linter ?? Linter.EsLint,
|
linter: options.linter ?? Linter.EsLint,
|
||||||
parsedTags,
|
parsedTags,
|
||||||
prefix: getNpmScope(tree), // we could also allow customizing this
|
prefix: getNpmScope(tree), // we could also allow customizing this
|
||||||
projectName: isUsingTsSolutionSetup(tree)
|
projectName: isUsingTsSolutionsConfig
|
||||||
? getImportPath(tree, projectName)
|
? getImportPath(tree, projectName)
|
||||||
: projectName,
|
: projectName,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
@ -58,13 +59,14 @@ export async function normalizeOptions(
|
|||||||
target: options.target ?? 'es6',
|
target: options.target ?? 'es6',
|
||||||
testEnvironment: options.testEnvironment ?? 'node',
|
testEnvironment: options.testEnvironment ?? 'node',
|
||||||
unitTestRunner: options.unitTestRunner ?? 'jest',
|
unitTestRunner: options.unitTestRunner ?? 'jest',
|
||||||
|
isUsingTsSolutionsConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toJsLibraryGeneratorOptions(
|
export function toJsLibraryGeneratorOptions(
|
||||||
options: LibraryGeneratorOptions
|
options: NormalizedOptions
|
||||||
): JsLibraryGeneratorSchema {
|
): JsLibraryGeneratorSchema {
|
||||||
return {
|
return {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
@ -80,8 +82,8 @@ export function toJsLibraryGeneratorOptions(
|
|||||||
tags: options.tags,
|
tags: options.tags,
|
||||||
testEnvironment: options.testEnvironment,
|
testEnvironment: options.testEnvironment,
|
||||||
unitTestRunner: options.unitTestRunner,
|
unitTestRunner: options.unitTestRunner,
|
||||||
config: options.standaloneConfig ? 'project' : 'workspace',
|
|
||||||
setParserOptionsProject: options.setParserOptionsProject,
|
setParserOptionsProject: options.setParserOptionsProject,
|
||||||
addPlugin: options.addPlugin,
|
addPlugin: options.addPlugin,
|
||||||
|
useProjectJson: !options.isUsingTsSolutionsConfig,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -379,6 +379,41 @@ describe('lib', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
|
expect(readJson(tree, 'mylib/package.json')).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"dependencies": {},
|
||||||
|
"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": {
|
||||||
|
"targets": {
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint",
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "mylib/jest.config.ts",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/test-output/jest/coverage",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"types": "./src/index.ts",
|
||||||
|
"version": "0.0.1",
|
||||||
|
}
|
||||||
|
`);
|
||||||
expect(readJson(tree, 'mylib/tsconfig.json')).toMatchInlineSnapshot(`
|
expect(readJson(tree, 'mylib/tsconfig.json')).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"extends": "../tsconfig.base.json",
|
"extends": "../tsconfig.base.json",
|
||||||
|
|||||||
@ -28,11 +28,11 @@ export interface LibraryGeneratorOptions {
|
|||||||
| 'es2021';
|
| 'es2021';
|
||||||
testEnvironment?: 'jsdom' | 'node';
|
testEnvironment?: 'jsdom' | 'node';
|
||||||
unitTestRunner?: UnitTestRunner;
|
unitTestRunner?: UnitTestRunner;
|
||||||
standaloneConfig?: boolean;
|
|
||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
skipPackageJson?: boolean;
|
skipPackageJson?: boolean;
|
||||||
simpleName?: boolean;
|
simpleName?: boolean;
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
isUsingTsSolutionsConfig?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NormalizedOptions extends LibraryGeneratorOptions {
|
export interface NormalizedOptions extends LibraryGeneratorOptions {
|
||||||
|
|||||||
@ -118,12 +118,6 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"standaloneConfig": {
|
|
||||||
"description": "Split the project configuration into <projectRoot>/project.json rather than including it inside workspace.json",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true,
|
|
||||||
"x-deprecated": "Nx only supports standaloneConfig"
|
|
||||||
},
|
|
||||||
"setParserOptionsProject": {
|
"setParserOptionsProject": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint \"parserOptions.project\" option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint \"parserOptions.project\" option. We do not do this by default for lint performance reasons.",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user