Skip to content

Commit

Permalink
feat(core): rename lock file pruning function to createLockFile
Browse files Browse the repository at this point in the history
  • Loading branch information
meeroslav authored and FrozenPandaz committed Dec 12, 2022
1 parent dd490c1 commit 8b8a953
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 125 deletions.
67 changes: 46 additions & 21 deletions docs/generated/devkit/index.md
Expand Up @@ -143,6 +143,8 @@ It only uses language primitives and immutable objects
- [applySharedFunction](../../devkit/index#applysharedfunction)
- [convertNxExecutor](../../devkit/index#convertnxexecutor)
- [convertNxGenerator](../../devkit/index#convertnxgenerator)
- [createLockFile](../../devkit/index#createlockfile)
- [createPackageJson](../../devkit/index#createpackagejson)
- [createProjectGraphAsync](../../devkit/index#createprojectgraphasync)
- [defaultTasksRunner](../../devkit/index#defaulttasksrunner)
- [detectPackageManager](../../devkit/index#detectpackagemanager)
Expand Down Expand Up @@ -171,7 +173,6 @@ It only uses language primitives and immutable objects
- [offsetFromRoot](../../devkit/index#offsetfromroot)
- [parseJson](../../devkit/index#parsejson)
- [parseTargetString](../../devkit/index#parsetargetstring)
- [pruneLockFile](../../devkit/index#prunelockfile)
- [readAllWorkspaceConfiguration](../../devkit/index#readallworkspaceconfiguration)
- [readCachedProjectGraph](../../devkit/index#readcachedprojectgraph)
- [readJson](../../devkit/index#readjson)
Expand Down Expand Up @@ -1064,6 +1065,50 @@ Convert an Nx Generator into an Angular Devkit Schematic.

---

### createLockFile

**createLockFile**(`packageJson`, `packageManager?`): `string`

Create lock file based on the root level lock file and (pruned) package.json

#### Parameters

| Name | Type |
| :--------------- | :---------------------------------------------------- |
| `packageJson` | `PackageJson` |
| `packageManager` | [`PackageManager`](../../devkit/index#packagemanager) |

#### Returns

`string`

---

### createPackageJson

**createPackageJson**(`projectName`, `graph`, `options?`): `PackageJson`

Creates a package.json in the output directory for support to install dependencies within containers.

If a package.json exists in the project, it will reuse that.
If isProduction flag is set, it wil remove devDependencies and optional peerDependencies

#### Parameters

| Name | Type |
| :---------------------- | :-------------------------------------------------------- |
| `projectName` | `string` |
| `graph` | [`ProjectGraph`](../../devkit/index#projectgraph)<`any`\> |
| `options` | `Object` |
| `options.isProduction?` | `boolean` |
| `options.root?` | `string` |

#### Returns

`PackageJson`

---

### createProjectGraphAsync

**createProjectGraphAsync**(`opts?`): `Promise`<[`ProjectGraph`](../../devkit/index#projectgraph)\>
Expand Down Expand Up @@ -1725,26 +1770,6 @@ parseTargetString('proj:test:production'); // returns { project: "proj", target:

---

### pruneLockFile

**pruneLockFile**(`projectName`, `isProduction?`, `packageManager?`): `Promise`<`string`\>

Prune lock file based on the given project's dependencies and overrides in local package.json

#### Parameters

| Name | Type | Default value | Description |
| :--------------- | :---------------------------------------------------- | :------------ | :----------------------------------------------------------------- |
| `projectName` | `string` | `undefined` | Project to prune against |
| `isProduction` | `boolean` | `true` | Whether to include optional and dev dependencies |
| `packageManager` | [`PackageManager`](../../devkit/index#packagemanager) | `undefined` | Package manager to use (automatically detected based on lock file) |

#### Returns

`Promise`<`string`\>

---

### readAllWorkspaceConfiguration

**readAllWorkspaceConfiguration**(): [`ProjectsConfigurations`](../../devkit/index#projectsconfigurations) & [`NxJsonConfiguration`](../../devkit/index#nxjsonconfiguration)
Expand Down
2 changes: 1 addition & 1 deletion docs/generated/packages/devkit.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/devkit/index.ts
Expand Up @@ -366,4 +366,5 @@ export { cacheDir } from 'nx/src/utils/cache-directory';
/**
* @category Package Manager
*/
export { pruneLockFile } from 'nx/src/lock-file/lock-file';
export { createLockFile } from 'nx/src/lock-file/lock-file';
export { createPackageJson } from 'nx/src/utils/create-package-json';
24 changes: 9 additions & 15 deletions packages/next/src/executors/build/lib/create-package-json.ts
@@ -1,11 +1,11 @@
import type { ExecutorContext } from '@nrwl/devkit';
import { writeJsonFile } from '@nrwl/devkit';
import { writeFileSync } from 'fs';
import {
getLockFileName,
pruneLockFileFromPackageJson,
} from 'nx/src/lock-file/lock-file';
import { createPackageJson as generatePackageJson } from 'nx/src/utils/create-package-json';
writeJsonFile,
createPackageJson as generatePackageJson,
createLockFile,
} from '@nrwl/devkit';
import { writeFileSync } from 'fs';
import { getLockFileName } from 'nx/src/lock-file/lock-file';
import type { NextBuildBuilderOptions } from '../../../utils/types';

export async function createPackageJson(
Expand All @@ -17,14 +17,11 @@ export async function createPackageJson(
context.projectGraph,
{
root: context.root,
// By default we remove devDependencies since this is a production build.
isProduction: options.includeDevDependenciesInPackageJson,
}
);

// By default we remove devDependencies since this is a production build.
if (!options.includeDevDependenciesInPackageJson) {
delete packageJson.devDependencies;
}

if (!packageJson.scripts) {
packageJson.scripts = {};
}
Expand All @@ -39,10 +36,7 @@ export async function createPackageJson(
writeJsonFile(`${options.outputPath}/package.json`, packageJson);

// generate lock file
const prunedLockFile = pruneLockFileFromPackageJson(
packageJson,
!options.includeDevDependenciesInPackageJson
);
const prunedLockFile = createLockFile(packageJson);
const lockFileName = getLockFileName();
writeFileSync(`${options.outputPath}/${lockFileName}`, prunedLockFile, {
encoding: 'utf-8',
Expand Down
36 changes: 3 additions & 33 deletions packages/nx/src/lock-file/lock-file.ts
Expand Up @@ -28,8 +28,6 @@ import {
ProjectGraphExternalNode,
} from '../config/project-graph';
import { existsSync } from 'fs';
import { createProjectGraphAsync } from '../project-graph/project-graph';
import { createPackageJson } from '../utils/create-package-json';
import { normalizePackageJson } from './utils/pruning';
import { PackageJson } from '../utils/package-json';

Expand Down Expand Up @@ -182,47 +180,19 @@ export function getLockFileName(
}

/**
* Prune lock file based on the given project's dependencies and overrides in local package.json
*
* @param projectName Project to prune against
* @param isProduction Whether to include optional and dev dependencies
* @param packageManager Package manager to use (automatically detected based on lock file)
* @returns
*/
export async function pruneLockFile(
projectName: string,
isProduction = true,
packageManager: PackageManager = detectPackageManager(workspaceRoot)
): Promise<string> {
const projectGraph = await createProjectGraphAsync();

if (!projectGraph.nodes[projectName]) {
throw Error(`Project "${projectName}" was not found.`);
}

const packageJson = createPackageJson(projectName, projectGraph, {});
return pruneLockFileFromPackageJson(
packageJson,
isProduction,
packageManager
);
}

/**
* Prune lock file based on the package.json
* Create lock file based on the root level lock file and (pruned) package.json
*
* @param packageJson
* @param isProduction
* @param packageManager
* @returns
*/
export function pruneLockFileFromPackageJson(
export function createLockFile(
packageJson: PackageJson,
isProduction = true,
packageManager: PackageManager = detectPackageManager(workspaceRoot)
): string {
const lockFileData = parseLockFile(packageManager);
const normalizedPackageJson = normalizePackageJson(packageJson, isProduction);
const normalizedPackageJson = normalizePackageJson(packageJson);

if (packageManager === 'yarn') {
const prunedData = pruneYarnLockFile(lockFileData, normalizedPackageJson);
Expand Down
61 changes: 19 additions & 42 deletions packages/nx/src/lock-file/utils/pruning.ts
Expand Up @@ -13,55 +13,32 @@ export type PackageJsonDeps = Pick<

/**
* Strip off non-pruning related fields from package.json
* Remove devDependencies if production target
* Remove optional peerDependencies if production target
*
* @param packageJson
* @param isProduction
* @param projectName
* @returns
*/
export function normalizePackageJson(
packageJson: PackageJson,
isProduction: boolean
packageJson: PackageJson
): PackageJsonDeps {
const normalized: PackageJsonDeps = {
name: packageJson.name,
version: packageJson.version || '0.0.0',
...(packageJson.license && { license: packageJson.license }),
};
if (packageJson.dependencies) {
normalized.dependencies = packageJson.dependencies;
}
if (packageJson.devDependencies && !isProduction) {
normalized.devDependencies = packageJson.devDependencies;
}
if (packageJson.peerDependencies) {
if (isProduction) {
const normalizedPeedDeps = filterOptionalPeerDependencies(packageJson);
if (normalizedPeedDeps) {
normalized.peerDependencies = normalizedPeedDeps;
}
} else {
normalized.peerDependencies = packageJson.peerDependencies;
if (packageJson.peerDependenciesMeta) {
normalized.peerDependenciesMeta = packageJson.peerDependenciesMeta;
}
}
}

return normalized;
}
const {
name,
version,
license,
dependencies,
devDependencies,
peerDependencies,
peerDependenciesMeta,
} = packageJson;

function filterOptionalPeerDependencies(
packageJson: PackageJson
): Record<string, string> {
let peerDependencies;
Object.keys(packageJson.peerDependencies).forEach((key) => {
if (!packageJson.peerDependenciesMeta?.[key]?.optional) {
peerDependencies = peerDependencies || {};
peerDependencies[key] = packageJson.peerDependencies[key];
}
});
return peerDependencies;
return {
name,
version,
license,
dependencies,
devDependencies,
peerDependencies,
peerDependenciesMeta,
};
}
35 changes: 32 additions & 3 deletions packages/nx/src/utils/create-package-json.ts
Expand Up @@ -9,13 +9,15 @@ import { workspaceRoot } from './workspace-root';
* Creates a package.json in the output directory for support to install dependencies within containers.
*
* If a package.json exists in the project, it will reuse that.
* If isProduction flag is set, it wil remove devDependencies and optional peerDependencies
*/
export function createPackageJson(
projectName: string,
graph: ProjectGraph,
options: {
root?: string;
}
isProduction?: boolean;
} = {}
): PackageJson {
const npmDeps = findAllNpmDeps(projectName, graph);
// default package.json if one does not exist
Expand All @@ -40,8 +42,11 @@ export function createPackageJson(
!packageJson.dependencies?.[packageName] &&
!packageJson.peerDependencies?.[packageName]
) {
packageJson.devDependencies = packageJson.devDependencies || {};
packageJson.devDependencies[packageName] = version;
// don't store dev dependencies for production
if (!options.isProduction) {
packageJson.devDependencies = packageJson.devDependencies || {};
packageJson.devDependencies[packageName] = version;
}
} else {
if (!packageJson.peerDependencies?.[packageName]) {
packageJson.dependencies = packageJson.dependencies || {};
Expand All @@ -54,12 +59,23 @@ export function createPackageJson(
packageJson.dependencies[packageName] = version;
}
});
if (options.isProduction && packageJson.peerDependencies) {
const mandatoryPeedDeps = filterOptionalPeerDependencies(packageJson);
if (mandatoryPeedDeps) {
packageJson.peerDependencies = mandatoryPeedDeps;
} else {
delete packageJson.peerDependencies;
}
}

packageJson.devDependencies &&= sortObjectByKeys(packageJson.devDependencies);
packageJson.dependencies &&= sortObjectByKeys(packageJson.dependencies);
packageJson.peerDependencies &&= sortObjectByKeys(
packageJson.peerDependencies
);
packageJson.peerDependenciesMeta &&= sortObjectByKeys(
packageJson.peerDependenciesMeta
);

return packageJson;
}
Expand Down Expand Up @@ -143,3 +159,16 @@ function recursivelyCollectPeerDependencies(
return list;
}
}

function filterOptionalPeerDependencies(
packageJson: PackageJson
): Record<string, string> {
let peerDependencies;
Object.keys(packageJson.peerDependencies).forEach((key) => {
if (!packageJson.peerDependenciesMeta?.[key]?.optional) {
peerDependencies = peerDependencies || {};
peerDependencies[key] = packageJson.peerDependencies[key];
}
});
return peerDependencies;
}

0 comments on commit 8b8a953

Please sign in to comment.