Skip to content

Commit

Permalink
feat(provider): add npm2 provider to update package.json, package-loc…
Browse files Browse the repository at this point in the history
…k.json, and npm-shrinkwrap.json

closes #804
  • Loading branch information
davidlday authored and Lee-W committed Aug 26, 2023
1 parent bc11094 commit f50e71e
Show file tree
Hide file tree
Showing 5 changed files with 434 additions and 180 deletions.
82 changes: 82 additions & 0 deletions commitizen/providers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import json
import jsonpath_ng # type: ignore
import re
from abc import ABC, abstractmethod
from pathlib import Path
Expand Down Expand Up @@ -166,6 +167,87 @@ class NpmProvider(JsonProvider):
filename = "package.json"


class Npm2Provider(VersionProvider):
"""
npm package.json and package-lock.json version management
"""

indent: ClassVar[int] = 2
package_filename = "package.json"
package_expression = "$.version"
lock_filename = "package-lock.json"
lock_expressions = ["$.version", "$.packages.''.version"]
shrinkwrap_filename = "npm-shrinkwrap.json"
shrinkwrap_expressions = ["$.version", "$.packages.''.version"]

@property
def package_file(self) -> Path:
return Path() / self.package_filename

@property
def lock_file(self) -> Path:
return Path() / self.lock_filename

@property
def shrinkwrap_file(self) -> Path:
return Path() / self.shrinkwrap_filename

def get_version(self) -> str:
"""
Get the current version from package.json
"""
package_document = json.loads(self.package_file.read_text())
return self.get_package_version(package_document)

def set_version(self, version: str):
package_document = self.set_package_version(
json.loads(self.package_file.read_text()), version
)
self.package_file.write_text(
json.dumps(package_document, indent=self.indent) + "\n"
)
if self.lock_file.exists():
lock_document = self.set_lock_version(
json.loads(self.lock_file.read_text()), version
)
self.lock_file.write_text(
json.dumps(lock_document, indent=self.indent) + "\n"
)
if self.shrinkwrap_file.exists():
shrinkwrap_document = self.set_lock_version(
json.loads(self.shrinkwrap_file.read_text()), version
)
self.shrinkwrap_file.write_text(
json.dumps(shrinkwrap_document, indent=self.indent) + "\n"
)

def get_package_version(self, document: dict[str, Any]) -> str:
expr = jsonpath_ng.parse(self.package_expression)
versions = expr.find(document)
if len(versions) == 0:
raise ValueError("No version found")
elif len(versions) > 1:
raise ValueError("Multiple versions found")
return versions[0].value # type: ignore

def set_package_version(self, document: dict[str, Any], version: str):
expr = jsonpath_ng.parse(self.package_expression)
document = expr.update(document, version)
return document

def set_lock_version(self, document: dict[str, Any], version: str):
for expression in self.lock_expressions:
expr = jsonpath_ng.parse(expression)
document = expr.update(document, version)
return document

def set_shrinkwrap_version(self, document: dict[str, Any], version: str):
for expression in self.shrinkwrap_expressions:
expr = jsonpath_ng.parse(expression)
document = expr.update(document, version)
return document


class ComposerProvider(JsonProvider):
"""
Composer version management
Expand Down
19 changes: 10 additions & 9 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,16 @@ But you can use any `commitizen.provider` entrypoint as value for `version_provi

Commitizen provides some version providers for some well known formats:

| name | description |
| ------------ | --------------------------------------------------------------------- |
| `commitizen` | Default version provider: Fetch and set version in commitizen config. |
| `scm` | Fetch the version from git and does not need to set it back |
| `pep621` | Get and set version from `pyproject.toml` `project.version` field |
| `poetry` | Get and set version from `pyproject.toml` `tool.poetry.version` field |
| `cargo` | Get and set version from `Cargo.toml` `project.version` field |
| `npm` | Get and set version from `package.json` `project.version` field |
| `composer` | Get and set version from `composer.json` `project.version` field |
| name | description |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `commitizen` | Default version provider: Fetch and set version in commitizen config. |
| `scm` | Fetch the version from git and does not need to set it back |
| `pep621` | Get and set version from `pyproject.toml` `project.version` field |
| `poetry` | Get and set version from `pyproject.toml` `tool.poetry.version` field |
| `cargo` | Get and set version from `Cargo.toml` `project.version` field |
| `npm` | Get and set version from `package.json` `project.version` field |
| `npm2` | Get and set version from `package.json` `$.version` field, `package-lock.json` `$.version,$.packages.''.version` fields if the file exists, and `npm-shrinkwrap.json` `$.version,$.packages.''.version` fields if the file exists |
| `composer` | Get and set version from `composer.json` `project.version` field |

!!! note
The `scm` provider is meant to be used with `setuptools-scm` or any packager `*-scm` plugin.
Expand Down
Loading

0 comments on commit f50e71e

Please sign in to comment.