Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- Added `rsconnect deploy nodejs` command for deploying Node.js API applications
- Added `rsconnect deploy nodejs` command for deploying Node.js applications
(Express, Fastify, etc.) to Posit Connect. Supports JavaScript and TypeScript
entry points with auto-detection from package.json. Requires Posit Connect with
Node.js runtime enabled.
Expand Down
8 changes: 4 additions & 4 deletions rsconnect/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,7 @@ def make_nodejs_manifest(
env_management_node: Optional[bool] = None,
) -> tuple[ManifestData, list[str]]:
"""
Makes a manifest for a Node.js API application.
Makes a manifest for a Node.js application.

:param directory: the directory containing the files to deploy.
:param entry_point: the main entry point file (e.g., "app.js").
Expand All @@ -1386,7 +1386,7 @@ def make_nodejs_manifest(
manifest: ManifestData = {
"version": 1,
"metadata": {
"appmode": AppModes.NODE_API.name(),
"appmode": AppModes.NODE_JS.name(),
"entrypoint": entry_point,
},
"node": {
Expand Down Expand Up @@ -1427,7 +1427,7 @@ def make_nodejs_bundle(
env_management_node: Optional[bool] = None,
) -> typing.IO[bytes]:
"""
Create a Node.js API bundle, given a directory path.
Create a Node.js application bundle, given a directory path.

:param directory: the directory containing the files to deploy.
:param entry_point: the main entry point file (e.g., "app.js").
Expand Down Expand Up @@ -2148,7 +2148,7 @@ def write_nodejs_manifest_json(
env_management_node: Optional[bool] = None,
) -> None:
"""
Creates and writes a manifest.json file for a Node.js API application.
Creates and writes a manifest.json file for a Node.js application.

:param directory: the root directory of the Node.js application.
:param entry_point: the entry point file (e.g., "app.js").
Expand Down
10 changes: 5 additions & 5 deletions rsconnect/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2130,9 +2130,9 @@ def deploy_app(
# noinspection SpellCheckingInspection
@deploy.command(
name="nodejs",
short_help="Deploy a Node.js API to Posit Connect.",
short_help="Deploy a Node.js application to Posit Connect.",
help=(
"Deploy a Node.js API application to Posit Connect. "
"Deploy a Node.js application to Posit Connect. "
'The "directory" argument must refer to an existing directory that contains '
"a package.json file and a JavaScript or TypeScript entry point."
),
Expand Down Expand Up @@ -2222,7 +2222,7 @@ def deploy_nodejs(
extra_files_list = validate_extra_files(directory, extra_files)
node_environment = NodeEnvironment.create(directory, node_executable=node)

app_mode = AppModes.NODE_API
app_mode = AppModes.NODE_JS

server_version = None

Expand Down Expand Up @@ -2907,9 +2907,9 @@ def manifest_writer(
# noinspection SpellCheckingInspection
@write_manifest.command(
name="nodejs",
short_help="Create a manifest.json file for a Node.js API.",
short_help="Create a manifest.json file for a Node.js application.",
help=(
"Create a manifest.json file for a Node.js API for later deployment. "
"Create a manifest.json file for a Node.js application for later deployment. "
"All files are created in the same directory as the application code."
),
)
Expand Down
14 changes: 11 additions & 3 deletions rsconnect/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class AppModes:
JUPYTER_VOILA = AppMode(16, "jupyter-voila", "Jupyter Voila Application")
PYTHON_GRADIO = AppMode(17, "python-gradio", "Gradio Application")
PYTHON_PANEL = AppMode(18, "python-panel", "Panel Application")
NODE_API = AppMode(20, "nodejs-api", "Node.js API")
NODE_JS = AppMode(20, "nodejs", "Node.js application")

_modes = [
UNKNOWN,
Expand All @@ -121,7 +121,7 @@ class AppModes:
JUPYTER_VOILA,
PYTHON_GRADIO,
PYTHON_PANEL,
NODE_API,
NODE_JS,
]

Modes = Literal[
Expand All @@ -144,7 +144,7 @@ class AppModes:
"jupyter-voila",
"python-gradio",
"python-panel",
"nodejs-api",
"nodejs",
]

_cloud_to_connect_modes = {
Expand All @@ -168,9 +168,17 @@ def get_by_ordinal(cls, ordinal: int, return_unknown: bool = False) -> AppMode:
return_unknown,
)

# Aliases for app mode names that have been renamed in Connect. Local
# AppStore metadata may still contain the old name from a prior deploy;
# this lets resolve() succeed instead of raising on re-deploys.
_name_aliases = {
"nodejs-api": "nodejs",
}

@classmethod
def get_by_name(cls, name: str, return_unknown: bool = False) -> AppMode:
"""Get an AppMode by name"""
name = cls._name_aliases.get(name, name)
return cls._find_by(lambda mode: mode.name() == name, "named %s" % name, return_unknown)

@classmethod
Expand Down
6 changes: 3 additions & 3 deletions tests/test_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3048,7 +3048,7 @@ def test_manifest_structure(self):
manifest, files = make_nodejs_manifest(_NODE_EXPRESS_DIR, "app.js", env, [], [])

assert manifest["version"] == 1
assert manifest["metadata"]["appmode"] == "nodejs-api"
assert manifest["metadata"]["appmode"] == "nodejs"
assert manifest["metadata"]["entrypoint"] == "app.js"
assert manifest["node"]["version"] == "22.22.1"
assert manifest["node"]["package_manager"]["name"] == "npm"
Expand Down Expand Up @@ -3120,7 +3120,7 @@ def test_bundle_manifest_content(self):

with tarfile.open(mode="r:gz", fileobj=bundle_file) as tar:
manifest = json.loads(tar.extractfile("manifest.json").read().decode("utf-8"))
assert manifest["metadata"]["appmode"] == "nodejs-api"
assert manifest["metadata"]["appmode"] == "nodejs"
assert manifest["metadata"]["entrypoint"] == "app.js"
assert manifest["node"]["version"] == "22.22.1"

Expand Down Expand Up @@ -3190,7 +3190,7 @@ def test_ts_manifest_structure(self):
env = _make_node_env(node_version="24.14.0")
manifest, files = make_nodejs_manifest(_NODE_TS_EXPRESS_DIR, "app.ts", env, [], [])

assert manifest["metadata"]["appmode"] == "nodejs-api"
assert manifest["metadata"]["appmode"] == "nodejs"
assert manifest["metadata"]["entrypoint"] == "app.ts"
assert manifest["node"]["version"] == "24.14.0"

Expand Down
4 changes: 2 additions & 2 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,7 @@ def test_help(self):
runner = CliRunner()
result = runner.invoke(cli, ["deploy", "nodejs", "--help"])
assert result.exit_code == 0
assert "Node.js API" in result.output
assert "Node.js application" in result.output
assert "--entrypoint" in result.output
assert "--node" in result.output
assert "--exclude" in result.output
Expand Down Expand Up @@ -1128,7 +1128,7 @@ def test_help(self):
runner = CliRunner()
result = runner.invoke(cli, ["write-manifest", "nodejs", "--help"])
assert result.exit_code == 0
assert "Node.js API" in result.output
assert "Node.js application" in result.output
assert "--entrypoint" in result.output
assert "--node" in result.output
assert "--overwrite" in result.output
Expand Down
Loading