create-node-lib 2.16.7 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [2.17.0](https://github.com/lirantal/create-node-lib/compare/v2.16.7...v2.17.0) (2026-05-03)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * chmod executable files ([034b771](https://github.com/lirantal/create-node-lib/commit/034b77199ae06936272e8b6afc8a61e98132e9bc))
7
+
8
+
9
+ ### Features
10
+
11
+ * devcontainer updates ([d5618de](https://github.com/lirantal/create-node-lib/commit/d5618def17a07c13b438795d96e5e26bdffab770))
12
+
1
13
  ## [2.16.7](https://github.com/lirantal/create-node-lib/compare/v2.16.6...v2.16.7) (2026-05-01)
2
14
 
3
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-node-lib",
3
- "version": "2.16.7",
3
+ "version": "2.17.0",
4
4
  "description": "Scaffolding out a Node.js library module",
5
5
  "bin": "./bin/cli.js",
6
6
  "engines": {
@@ -10,15 +10,44 @@
10
10
  "shellautocompletion": true
11
11
  }
12
12
  },
13
- // forwardPorts: VS Code / Cursor Ports UI, auto-forward, portsAttributes (spec “forwarding”).
14
- "forwardPorts": [
15
- 5959
16
- ],
17
- // appPort: Docker publish (127.0.0.1:port:port) for @devcontainers/cli — e.g. .devcontainer/start.sh.
18
- // Editors still apply appPort when they create the container; keep this list aligned with forwardPorts.
19
- "appPort": [
20
- 5959
21
- ],
13
+ // Ask the editor to forward these container ports (no Docker appPort).
14
+ "forwardPorts": [8787, 3005, 3001, 3000],
15
+
16
+ "portsAttributes": {
17
+ "8787": {
18
+ "label": "Hono Dev Server",
19
+ "onAutoForward": "notify"
20
+ },
21
+ "3005": {
22
+ "label": "Nuxt Dev Server",
23
+ "onAutoForward": "notify"
24
+ },
25
+ "3001": {
26
+ "label": "Nuxt Preview Server",
27
+ "onAutoForward": "silent"
28
+ },
29
+ "3000": {
30
+ "label": "Published dev server",
31
+ "protocol": "http",
32
+ "onAutoForward": "notify",
33
+ "requireLocalPort": false
34
+ },
35
+ // only enable when running Caddy http proxy in the container
36
+ // "80": {
37
+ // "label": "Caddy HTTP",
38
+ // "onAutoForward": "notify"
39
+ // },
40
+ // "443": {
41
+ // "label": "Caddy HTTPS",
42
+ // "onAutoForward": "notify"
43
+ // }
44
+ },
45
+
46
+ "otherPortsAttributes": {
47
+ "onAutoForward": "notify",
48
+ "requireLocalPort": false
49
+ },
50
+
22
51
  "mounts": [
23
52
  "source=${localEnv:HOME}/.gitconfig,target=/home/node/.gitconfig,type=bind,consistency=cached",
24
53
  // mount host user home directories for agents:
@@ -26,21 +55,22 @@
26
55
  // "source=${localEnv:HOME}/.gemini,target=/home/node/.claude,type=bind,consistency=cached",
27
56
  // "source=${localEnv:HOME}/.codex,target=/home/node/.codex,type=bind,consistency=cached"
28
57
  ],
29
- // Initialize access to 1Password CLI in the container
30
- // "initializeCommand": "echo OP_SERVICE_ACCOUNT_TOKEN=$(op read 'op://Private/1Password op CLI Service Account for DevContainers/password') > .env.development",
31
- // "runArgs": [
32
- // "--env-file",
33
- // "${localWorkspaceFolder}/.env.development"
34
- // ],
58
+
59
+ // Initialize optional host-side secrets before container create/start.
60
+ "initializeCommand": "bash .devcontainer/initialize.sh",
61
+ // After up, discover the published host binding, e.g.:
62
+ // docker port <container-name-or-id> 3000/tcp
63
+ "runArgs": [
64
+ // publish container port 3000 with dynamic host port (CLI / start.sh)
65
+ "-p",
66
+ "127.0.0.1::3000",
67
+ // pass the development environment file to the container
68
+ "--env-file",
69
+ "${localWorkspaceFolder}/.env.development"
70
+ ],
35
71
  // --
36
- "postCreateCommand": {
37
- "pnpm-install": "[ -f package.json ] && pnpm install || true",
38
- "post-create": "bash .devcontainer/post-create.sh"
39
- },
40
- "postStartCommand": {
41
- // "rm-env-file": "if [ -n './.env.development' ]; then rm -f './.env.development'; fi;",
42
- "start-dev": "[ -f package.json ] && pnpm run dev || true"
43
- },
72
+ "postCreateCommand": "bash .devcontainer/post-create.sh",
73
+ "postStartCommand": "bash .devcontainer/post-start.sh",
44
74
  "remoteUser": "node",
45
75
  "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
46
76
  "containerEnv": {
@@ -1,25 +1,46 @@
1
1
  #!/bin/bash
2
2
  set -e
3
3
 
4
- # Local git prefs only apply inside a repository; skip when there is no .git (avoids postCreate failure).
5
- if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
6
- git config --local commit.gpgsign false
7
- git config --local core.pager 'less -R'
8
- fi
9
-
10
- # install apm (the Agent Package Manager: https://github.com/microsoft/apm)
11
- curl -sSL https://aka.ms/apm-unix | sh
12
-
13
- # Install OpenCode CLI
14
- # curl -fsSL https://opencode.ai/install | bash
15
-
16
- # Install Snyk CLI
17
- # curl --compressed https://static.snyk.io/cli/latest/snyk-linux-arm64 -o snyk
18
- # chmod +x ./snyk
19
- # sudo mv -f ./snyk /usr/local/bin/snyk
20
-
21
- # Install 1Password CLI (op) - arm64 Linux binary
22
- # OP_VERSION="2.32.1"
23
- # curl -fsSL "https://cache.agilebits.com/dist/1P/op2/pkg/v${OP_VERSION}/op_linux_arm64_v${OP_VERSION}.zip" -o /tmp/op.zip
24
- # python3 -c "import zipfile; zipfile.ZipFile('/tmp/op.zip').extract('op', '/tmp')"
25
- # sudo mv /tmp/op /usr/local/bin/op && chmod +x /usr/local/bin/op && rm /tmp/op.zip
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+
6
+ main() {
7
+ configure_local_git
8
+ install_apm
9
+ # install_opencode_cli
10
+ install_1password_cli
11
+ run_deps_install
12
+ }
13
+
14
+ configure_local_git() {
15
+ # Local git prefs only apply inside a repository; skip when there is no .git (avoids postCreate failure).
16
+ if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
17
+ git config --local commit.gpgsign false
18
+ git config --local core.pager 'less -R'
19
+ fi
20
+ }
21
+
22
+ install_apm() {
23
+ # Agent Package Manager: https://github.com/microsoft/apm
24
+ curl -sSL https://aka.ms/apm-unix | sh
25
+ }
26
+
27
+ install_opencode_cli() {
28
+ curl -fsSL https://opencode.ai/install | bash
29
+ }
30
+
31
+ # Optional: Snyk CLI
32
+ # curl --compressed https://static.snyk.io/cli/latest/snyk-linux-arm64 -o snyk
33
+ # chmod +x ./snyk && sudo mv -f ./snyk /usr/local/bin/snyk
34
+
35
+ install_1password_cli() {
36
+ local op_version="2.32.1"
37
+ curl -fsSL "https://cache.agilebits.com/dist/1P/op2/pkg/v${op_version}/op_linux_arm64_v${op_version}.zip" -o /tmp/op.zip
38
+ python3 -c "import zipfile; zipfile.ZipFile('/tmp/op.zip').extract('op', '/tmp')"
39
+ sudo mv /tmp/op /usr/local/bin/op && chmod +x /usr/local/bin/op && rm /tmp/op.zip
40
+ }
41
+
42
+ run_deps_install() {
43
+ bash "${SCRIPT_DIR}/utils/deps-install.sh"
44
+ }
45
+
46
+ main "$@"
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bash
2
+ # post-start: runs after each container start (postStartCommand in devcontainer.json).
3
+ # Naming matches post-create.sh; extend with more steps as needed (e.g. source scripts from .devcontainer/utils/).
4
+
5
+ main() {
6
+ remove_ephemeral_env_file_if_present
7
+ }
8
+
9
+ # When initializeCommand + runArgs inject secrets via .env.development, remove the file
10
+ # after start so it is not left on disk and tooling that assumes absence does not break.
11
+ remove_ephemeral_env_file_if_present() {
12
+ local env_file=".env.development"
13
+ if [[ -f "$env_file" ]]; then
14
+ rm -f "$env_file"
15
+ fi
16
+ }
17
+
18
+ main "$@"
@@ -4,16 +4,16 @@
4
4
  # @summary Start the Dev Container for this workspace and attach an interactive shell.
5
5
  #
6
6
  # Uses @devcontainers/cli to run `devcontainer up` then `devcontainer exec bash`.
7
- # Host port publishing for this script comes from **appPort** @devcontainers/cli maps it
8
- # to `docker -p`. It does **not** map **forwardPorts** to Docker (editors use forwardPorts
9
- # for Ports UI / tunneling; they still apply **appPort** when creating the container).
7
+ # Host port publishing comes from **runArgs** in devcontainer.json (e.g. `-p` and
8
+ # `127.0.0.1::<containerPort>` for dynamic host binding). After `devcontainer up`, this
9
+ # script reads that container port from runArgs and prints the mapped URL via `docker port`.
10
10
  #
11
11
  # @usage
12
12
  # .devcontainer/start.sh [options]
13
13
  #
14
14
  # @options
15
15
  # --recreate Remove the existing dev container for this workspace before `up`, so
16
- # changes to appPort (or other create-time settings) take effect.
16
+ # changes to runArgs (or other create-time settings) take effect.
17
17
  # --help, -h Print usage and exit.
18
18
  #
19
19
  # @example
@@ -38,15 +38,25 @@ Then open an interactive bash session inside the container.
38
38
 
39
39
  Options:
40
40
  --recreate Remove the existing dev container for this workspace before starting,
41
- so Docker picks up new settings (e.g. appPort / port mappings).
41
+ so Docker picks up new settings (e.g. runArgs / port mappings).
42
42
  --help, -h Show this help and exit.
43
43
 
44
44
  Notes:
45
- For devcontainer up from the terminal, Docker publish uses appPort. Keep appPort and
46
- forwardPorts lists in sync if you use both this script and VS Code / Cursor.
45
+ Port publishing uses runArgs (Docker -p ...::<containerPort>). The script greps that
46
+ container port from devcontainer.json for the post-up URL hint.
47
47
  EOF
48
48
  }
49
49
 
50
+ # Container-side TCP port published via runArgs, e.g. "127.0.0.1::3000" (Docker -p host::ctr).
51
+ # Requires GNU grep (-P); same as the containerId parse below.
52
+ publish_container_port_from_devcontainer_json() {
53
+ local f="$SCRIPT_DIR/devcontainer.json"
54
+ if [ ! -r "$f" ]; then
55
+ return 1
56
+ fi
57
+ sed 's|//.*||' "$f" | grep -oP '"[0-9.]+\:\:\K[0-9]+(?=")' | head -n1
58
+ }
59
+
50
60
  RECREATE=false
51
61
  while [ $# -gt 0 ]; do
52
62
  case "$1" in
@@ -71,10 +81,35 @@ echo "Starting devcontainer for: $WORKSPACE_FOLDER"
71
81
  UP_ARGS=(--workspace-folder "$WORKSPACE_FOLDER")
72
82
  if [ "$RECREATE" = true ]; then
73
83
  UP_ARGS+=(--remove-existing-container)
74
- echo "Removing existing dev container so create-time settings (e.g. appPort) apply."
84
+ echo "Removing existing dev container so create-time settings (e.g. runArgs) apply."
85
+ fi
86
+
87
+ UP_OUTPUT="$(npx --yes "@devcontainers/cli@${CLI_VERSION}" up "${UP_ARGS[@]}")"
88
+ echo "$UP_OUTPUT"
89
+
90
+ CONTAINER_ID="$(echo "$UP_OUTPUT" | grep -oP '"containerId"\s*:\s*"\K[^"]+')" || true
91
+ if [ -z "$CONTAINER_ID" ]; then
92
+ CONTAINER_ID="$(docker ps --filter "label=devcontainer.local_folder=$WORKSPACE_FOLDER" --format '{{.ID}}' | head -n1)"
75
93
  fi
76
94
 
77
- npx --yes "@devcontainers/cli@${CLI_VERSION}" up "${UP_ARGS[@]}"
95
+ CONTAINER_PORT="$(publish_container_port_from_devcontainer_json || true)"
96
+ if [ -n "$CONTAINER_ID" ]; then
97
+ if [ -n "$CONTAINER_PORT" ]; then
98
+ HOST_BINDING="$(docker port "$CONTAINER_ID" "${CONTAINER_PORT}/tcp" 2>/dev/null | head -n1)" || true
99
+ if [ -n "$HOST_BINDING" ]; then
100
+ echo ""
101
+ echo "Dev server available at: http://${HOST_BINDING}"
102
+ echo ""
103
+ else
104
+ echo "Warning: container is running but port ${CONTAINER_PORT}/tcp is not mapped." >&2
105
+ fi
106
+ else
107
+ echo "Warning: could not find a runArgs publish port (expected a quoted string like \"127.0.0.1::<port>\")." >&2
108
+ echo " Skipping docker port URL hint." >&2
109
+ fi
110
+ else
111
+ echo "Warning: could not resolve container ID; skipping port lookup." >&2
112
+ fi
78
113
 
79
114
  echo "Dropping into container shell..."
80
115
  # Resolve TERM to something the container's terminfo knows about.
@@ -83,4 +118,4 @@ echo "Dropping into container shell..."
83
118
  if ! infocmp "${TERM:-xterm-256color}" &>/dev/null 2>&1; then
84
119
  TERM=xterm-256color
85
120
  fi
86
- TERM="${TERM:-xterm-256color}" npx --yes @devcontainers/cli@${CLI_VERSION} exec --workspace-folder "$WORKSPACE_FOLDER" -- env TERM="${TERM:-xterm-256color}" COLORTERM=truecolor bash
121
+ TERM="${TERM:-xterm-256color}" npx --yes @devcontainers/cli@${CLI_VERSION} exec --workspace-folder "$WORKSPACE_FOLDER" -- env TERM="${TERM:-xterm-256color}" COLORTERM=truecolor bash
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env bash
2
+ # Install workspace JS dependencies when package.json exists (non-fatal on failure).
3
+
4
+ main() {
5
+ [[ -f package.json ]] || return 0
6
+ local pm
7
+ pm=$(detect_package_manager)
8
+ install_dependencies "$pm" || true
9
+ }
10
+
11
+ detect_package_manager() {
12
+ local pm
13
+ if pm=$(detect_package_manager_from_lockfiles); then
14
+ echo "$pm"
15
+ return
16
+ fi
17
+ if pm=$(detect_package_manager_from_repo_markers); then
18
+ echo "$pm"
19
+ return
20
+ fi
21
+ if pm=$(detect_package_manager_from_package_json); then
22
+ echo "$pm"
23
+ return
24
+ fi
25
+ echo npm
26
+ }
27
+
28
+ detect_package_manager_from_lockfiles() {
29
+ if [[ -f pnpm-lock.yaml ]]; then
30
+ echo pnpm
31
+ return 0
32
+ fi
33
+ if [[ -f bun.lockb || -f bun.lock ]]; then
34
+ echo bun
35
+ return 0
36
+ fi
37
+ if [[ -f yarn.lock ]]; then
38
+ echo yarn
39
+ return 0
40
+ fi
41
+ if [[ -f package-lock.json ]]; then
42
+ echo npm
43
+ return 0
44
+ fi
45
+ return 1
46
+ }
47
+
48
+ detect_package_manager_from_repo_markers() {
49
+ if [[ -f pnpm-workspace.yaml ]]; then
50
+ echo pnpm
51
+ return 0
52
+ fi
53
+ if [[ -f bunfig.toml ]]; then
54
+ echo bun
55
+ return 0
56
+ fi
57
+ if [[ -f .yarnrc.yml ]]; then
58
+ echo yarn
59
+ return 0
60
+ fi
61
+ return 1
62
+ }
63
+
64
+ detect_package_manager_from_package_json() {
65
+ [[ -f package.json ]] || return 1
66
+ node -e "
67
+ const p = require('./package.json');
68
+ const spec = p.packageManager;
69
+ if (!spec || typeof spec !== 'string') process.exit(1);
70
+ const name = spec.split('@')[0].trim();
71
+ if (!['pnpm', 'npm', 'yarn', 'bun'].includes(name)) process.exit(1);
72
+ console.log(name);
73
+ " 2>/dev/null || return 1
74
+ }
75
+
76
+ install_dependencies() {
77
+ local pm="$1"
78
+ case "$pm" in
79
+ pnpm) pnpm install ;;
80
+ npm) npm install ;;
81
+ yarn) yarn install ;;
82
+ bun) bun install ;;
83
+ *) npm install ;;
84
+ esac
85
+ }
86
+
87
+ main "$@"