Skip to content

Commit

Permalink
fix(js): generate pacakge.json for non-buildable nest and expo libs (#…
Browse files Browse the repository at this point in the history
…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 #
  • Loading branch information
jaysoo authored Feb 5, 2025
1 parent d62b94f commit 8bd0bcd
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 38 deletions.
6 changes: 0 additions & 6 deletions docs/generated/packages/nest/generators/library.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,6 @@
"type": "boolean",
"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": {
"type": "boolean",
"description": "Whether or not to configure the ESLint \"parserOptions.project\" option. We do not do this by default for lint performance reasons.",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "<%= name %>",
"name": "<%= projectName %>",
"version": "0.0.1",
"main": "<%= appMain %>"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import {
} from '@nx/devkit/src/generators/project-name-and-root-utils';
import { Schema } from '../schema';
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 {
name: string;
fileName: string;
projectName: string;
projectRoot: string;
routePath: string;
parsedTags: string[];
Expand Down Expand Up @@ -43,16 +45,20 @@ export async function normalizeOptions(
: [];
const appMain = options.js ? 'src/index.js' : 'src/index.ts';

const isUsingTsSolutionConfig = isUsingTsSolutionSetup(host);
const normalized: NormalizedSchema = {
...options,
fileName: projectName,
routePath: `/${projectNames.projectSimpleName}`,
name: projectName,
projectName: isUsingTsSolutionConfig
? getImportPath(host, projectName)
: projectName,
projectRoot,
parsedTags,
importPath,
appMain,
isUsingTsSolutionConfig: isUsingTsSolutionSetup(host),
isUsingTsSolutionConfig,
};

return normalized;
Expand Down
82 changes: 81 additions & 1 deletion packages/expo/src/generators/library/library.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,30 @@ describe('lib', () => {
]
`);
// 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')))
.toMatchInlineSnapshot(`
[
"name",
"version",
"main",
"types",
"nx",
"exports",
]
`);
expect(readJson(appTree, 'my-lib/tsconfig.json')).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -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",
}
`);
});
});
});
51 changes: 33 additions & 18 deletions packages/expo/src/generators/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import {
addProjectToTsSolutionWorkspace,
updateTsconfigFiles,
} 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';

export async function expoLibraryGenerator(
Expand Down Expand Up @@ -72,6 +71,10 @@ export async function expoLibraryGeneratorInternal(
);
}

if (options.isUsingTsSolutionConfig) {
addProjectToTsSolutionWorkspace(host, options.projectRoot);
}

const initTask = await init(host, { ...options, skipFormat: true });
tasks.push(initTask);
if (!options.skipPackageJson) {
Expand All @@ -88,7 +91,7 @@ export async function expoLibraryGeneratorInternal(

const lintTask = await addLinting(host, {
...options,
projectName: options.name,
projectName: options.projectName,
tsConfigPaths: [
joinPathFragments(options.projectRoot, 'tsconfig.lib.json'),
],
Expand All @@ -98,7 +101,7 @@ export async function expoLibraryGeneratorInternal(
const jestTask = await addJest(
host,
options.unitTestRunner,
options.name,
options.projectName,
options.projectRoot,
options.js,
options.skipPackageJson,
Expand Down Expand Up @@ -134,10 +137,6 @@ export async function expoLibraryGeneratorInternal(
: undefined
);

if (options.isUsingTsSolutionConfig) {
addProjectToTsSolutionWorkspace(host, options.projectRoot);
}

sortPackageJsonFields(host, options.projectRoot);

if (!options.skipFormat) {
Expand Down Expand Up @@ -169,23 +168,35 @@ async function addProject(
};

if (options.isUsingTsSolutionConfig) {
const packageName = getImportPath(host, options.name);
const sourceEntry = !options.buildable
? options.js
? './src/index.js'
: './src/index.ts'
: undefined;
writeJson(host, joinPathFragments(options.projectRoot, 'package.json'), {
name: packageName,
name: options.projectName,
version: '0.0.1',
main: sourceEntry,
types: sourceEntry,
nx: {
name: packageName === options.name ? undefined : options.name,
projectType: 'library',
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
tags: options.parsedTags?.length ? options.parsedTags : undefined,
},
// For buildable libraries, the entries are configured by the bundler (i.e. Rollup).
exports: options.buildable
? 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 {
addProjectConfiguration(host, options.name, project);
Expand All @@ -201,7 +212,7 @@ async function addProject(
);
const rollupConfigTask = await configurationGenerator(host, {
...options,
project: options.name,
project: options.projectName,
skipFormat: true,
});

Expand Down Expand Up @@ -229,7 +240,7 @@ async function addProject(
},
};

updateProjectConfiguration(host, options.name, project);
updateProjectConfiguration(host, options.projectName, project);

return rollupConfigTask;
}
Expand Down Expand Up @@ -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`);
}

Expand Down
6 changes: 5 additions & 1 deletion packages/nest/src/generators/library/lib/delete-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
}
}
8 changes: 5 additions & 3 deletions packages/nest/src/generators/library/lib/normalize-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export async function normalizeOptions(
? options.tags.split(',').map((s) => s.trim())
: [];

const isUsingTsSolutionsConfig = isUsingTsSolutionSetup(tree);
const normalized: NormalizedOptions = {
...options,
strict: options.strict ?? true,
Expand All @@ -49,7 +50,7 @@ export async function normalizeOptions(
linter: options.linter ?? Linter.EsLint,
parsedTags,
prefix: getNpmScope(tree), // we could also allow customizing this
projectName: isUsingTsSolutionSetup(tree)
projectName: isUsingTsSolutionsConfig
? getImportPath(tree, projectName)
: projectName,
projectRoot,
Expand All @@ -58,13 +59,14 @@ export async function normalizeOptions(
target: options.target ?? 'es6',
testEnvironment: options.testEnvironment ?? 'node',
unitTestRunner: options.unitTestRunner ?? 'jest',
isUsingTsSolutionsConfig,
};

return normalized;
}

export function toJsLibraryGeneratorOptions(
options: LibraryGeneratorOptions
options: NormalizedOptions
): JsLibraryGeneratorSchema {
return {
name: options.name,
Expand All @@ -80,8 +82,8 @@ export function toJsLibraryGeneratorOptions(
tags: options.tags,
testEnvironment: options.testEnvironment,
unitTestRunner: options.unitTestRunner,
config: options.standaloneConfig ? 'project' : 'workspace',
setParserOptionsProject: options.setParserOptionsProject,
addPlugin: options.addPlugin,
useProjectJson: !options.isUsingTsSolutionsConfig,
};
}
35 changes: 35 additions & 0 deletions packages/nest/src/generators/library/library.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(`
{
"extends": "../tsconfig.base.json",
Expand Down
2 changes: 1 addition & 1 deletion packages/nest/src/generators/library/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ export interface LibraryGeneratorOptions {
| 'es2021';
testEnvironment?: 'jsdom' | 'node';
unitTestRunner?: UnitTestRunner;
standaloneConfig?: boolean;
setParserOptionsProject?: boolean;
skipPackageJson?: boolean;
simpleName?: boolean;
addPlugin?: boolean;
isUsingTsSolutionsConfig?: boolean;
}

export interface NormalizedOptions extends LibraryGeneratorOptions {
Expand Down
Loading

0 comments on commit 8bd0bcd

Please sign in to comment.