@s2j/global-npm 2.1.0 → 2.1.2

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # 📦 Global npm Package Setup
2
2
 
3
3
  Node.js の **グローバル npm パッケージ管理** を `package.json` で一元化する CLI です。
4
- macOS / Windows 11で同じ `global-npm` フローを使えます。
4
+ macOS、Windows 11で同じ `global-npm` フローを使えます。
5
5
 
6
6
  GitHub: [stein2nd/global-npm-setup](https://github.com/stein2nd/global-npm-setup)
7
7
 
@@ -11,7 +11,7 @@ GitHub: [stein2nd/global-npm-setup](https://github.com/stein2nd/global-npm-setup
11
11
  global-npm check # グローバルパッケージの更新確認 (ncu)
12
12
  global-npm update # package.json のバージョン範囲を更新 (ncu -u)
13
13
  global-npm install # dependencies を列挙して npm install -g を実行
14
- global-npm sync # upstream + user-deps → 物理的なアーカイブを再生成
14
+ global-npm sync # upstream + user-deps → 実効 package.json を再生成
15
15
  global-npm add # user-deps.json にパッケージを追記
16
16
  ```
17
17
 
@@ -29,16 +29,16 @@ global-npm install
29
29
  |--------|------|------|
30
30
  | Upstream 正本 | `@s2j/global-npm` 同梱 `package.json` | 公式 `dependencies` 一覧 |
31
31
  | ユーザー overlay | `$SETUP_DIR/user-deps.json` | 追加分、ピン留め |
32
- | 物理的なアーカイブ | `$SETUP_DIR/package.json` | ncu / install が読む実効マニフェスト |
32
+ | 実効 package.json | `$SETUP_DIR/package.json` | ncu、install が読む実効マニフェスト |
33
33
 
34
34
  **setup ディレクトリ (`$SETUP_DIR`) のデフォルト**
35
35
 
36
36
  | OS | パス |
37
37
  |----|------|
38
- | macOS / Linux | `~/.config/global-npm` |
38
+ | macOS、Linux | `~/.config/global-npm` |
39
39
  | Windows 11 | `%APPDATA%\global-npm` |
40
40
 
41
- `GLOBAL_NPM_SETUP_DIR` 環境変数で上書きできます。詳細は [docs/layout.md](./docs/layout.md)。
41
+ `GLOBAL_NPM_SETUP_DIR` 環境変数で上書きできます。詳細は [docs/layout.md](./docs/layout.md) をご覧ください。
42
42
 
43
43
  ## セットアップ
44
44
 
@@ -78,14 +78,15 @@ Node.js v18以上 (LTS 推奨) が未導入の場合は、先にインストー
78
78
 
79
79
  ```sh
80
80
  npm install -g @s2j/global-npm # CLI 本体の導入 (これは一度だけ)
81
+ global-npm check # 同梱 ncu で動作 (PATH に ncu 不要)
81
82
  global-npm add @s2j/docs-linter@^1.0.16 # 任意: ユーザー追加分
82
- global-npm install # 物理的なアーカイブ化 dependencies を global install
83
+ global-npm install # 実効 package.json の dependencies を global install
83
84
  ```
84
85
 
85
- 初回の `global-npm install` で `~/.config/global-npm/` (Windows 11では `%APPDATA%\global-npm\`) に物理的なアーカイブ化 `package.json` が生成されます。
86
+ 初回の `global-npm install` で `~/.config/global-npm/` (Windows 11では `%APPDATA%\global-npm\`) に実効 `package.json` が生成されます。
86
87
  `global-npm install` は、`@s2j/global-npm` 自身 (自己参照) も含め、`dependencies` のキーを列挙して `npm install -g` します。
87
88
 
88
- ### 開発 — リポジトリ clone
89
+ ### 開発: リポジトリ clone
89
90
 
90
91
  ```sh
91
92
  git clone https://github.com/stein2nd/global-npm-setup.git
@@ -110,6 +111,15 @@ global-npm sync --dry-run
110
111
  * upstream 管理パッケージのうち未 update 分は、次回 `check` 時の sync で新 range に追従する。
111
112
  * upstream パッケージをピン留めする場合は、`user-deps.json` の `dependencies` に同名で range を書く。
112
113
 
114
+ ## 使い方
115
+
116
+ 下記については、[使い方](./docs/usage.md) をご覧ください。
117
+
118
+ * 各コマンドの役割
119
+ * 定番フロー (`check` → `update` → `install`)
120
+ * 毎回 `sync` を実行する必要があるか
121
+ * upstream 管理分と追加分の衝突が起こった場合
122
+
113
123
  ## 日常の更新サイクル
114
124
 
115
125
  ```mermaid
@@ -121,8 +131,8 @@ flowchart LR
121
131
  ```
122
132
 
123
133
  * **check:** sync 後に ncu で更新候補を表示。ncu 自体は range を書き換えない。
124
- * **update:** 物理的なアーカイブ化 `dependencies` / `devDependencies` の range を更新。
125
- * **install:** 物理的なアーカイブ化 **dependencies** のみ global install。
134
+ * **update:** 実効 package.json の `dependencies`、`devDependencies` の range を更新。
135
+ * **install:** 実効 package.json の **dependencies** のみ global install。
126
136
 
127
137
  ## 開発用 scripts
128
138
 
@@ -139,8 +149,8 @@ npm run ncu:update
139
149
 
140
150
  | v1 | v2 |
141
151
  |----|-----|
142
- | `~/bin/global-npm` (Zsh) | 廃止 — `npm install -g @s2j/global-npm` |
143
- | `install-global.zsh` | 廃止 — `global-npm install` |
152
+ | `~/bin/global-npm` (Zsh) | 廃止: `npm install -g @s2j/global-npm` |
153
+ | `install-global.zsh` | 廃止: `global-npm install` |
144
154
  | `ncu:install` (jq 列挙) | `global-npm install` (Node 列挙) |
145
155
 
146
156
  ### v2.0.x → v2.1
@@ -148,16 +158,16 @@ npm run ncu:update
148
158
  | v2.0.x | v2.1 |
149
159
  |--------|------|
150
160
  | setup = package root | setup = `~/.config/global-npm`。Windows は `%APPDATA%\global-npm` |
151
- | 同梱 `package.json` を直接 ncu | 物理的なアーカイブを ncu |
152
- | 3サブコマンド | 5サブコマンド (`sync` / `add` 追加) |
161
+ | 同梱 `package.json` を直接 ncu | 実効 package.json を ncu |
162
+ | 3サブコマンド | 5サブコマンド (`sync`、`add` 追加) |
153
163
 
154
164
  移行手順は、下記のとおりです。
155
165
 
156
166
  1. `npm update -g @s2j/global-npm` で v2.1に上げる。
157
167
  2. 追加分を `global-npm add …` で登録する。
158
- 3. `global-npm sync` で 物理的なアーカイブを生成する。
168
+ 3. `global-npm sync` で 実効 package.json を生成する。
159
169
  4. `global-npm install` で global 環境を同期する。
160
170
 
161
171
  ## ライセンス
162
172
 
163
- GPL-3.0-or-later — 詳細は [LICENSE](./LICENSE) を参照してください。
173
+ GPL-3.0-or-later: 詳細は [LICENSE](./LICENSE) をご覧ください。
@@ -6,6 +6,7 @@ const path = require('path');
6
6
  const { toGlobalInstallSpec } = require('../lib/install-spec.cjs');
7
7
  const { ensureSetupDir, readDependencies, readUserDeps, writeJson } = require('../lib/pkg-io.cjs');
8
8
  const { resolveSetupContext } = require('../lib/paths.cjs');
9
+ const { resolveNcuInvocation } = require('../lib/resolve-ncu.cjs');
9
10
  const { parseAddSpec, resolveDefaultRange } = require('../lib/resolve-range.cjs');
10
11
  const { formatReport, syncManifest } = require('../lib/sync-manifest.cjs');
11
12
 
@@ -25,10 +26,10 @@ function usage() {
25
26
  process.exit(1);
26
27
  }
27
28
 
28
- function run(command, args) {
29
+ function run(command, args, { useShell = shell } = {}) {
29
30
  const result = spawnSync(command, args, {
30
31
  stdio: 'inherit',
31
- shell,
32
+ shell: useShell,
32
33
  });
33
34
 
34
35
  if (result.error) {
@@ -39,6 +40,11 @@ function run(command, args) {
39
40
  process.exit(result.status ?? 1);
40
41
  }
41
42
 
43
+ function runNcu(args) {
44
+ const { command, prefixArgs, useShell } = resolveNcuInvocation(packageRoot);
45
+ run(command, [...prefixArgs, ...args], { useShell });
46
+ }
47
+
42
48
  function prepare() {
43
49
  ensureSetupDir(ctx);
44
50
  return syncManifest(ctx);
@@ -102,19 +108,19 @@ const restArgs = process.argv.slice(3);
102
108
  switch (subcommand) {
103
109
  case 'check':
104
110
  prepare();
105
- run('ncu', ['-g', '--format', 'time', '--packageFile', pkgPath]);
111
+ runNcu(['-g', '--format', 'time', '--packageFile', pkgPath]);
106
112
  break;
107
113
 
108
114
  case 'update':
109
115
  prepare();
110
- run('ncu', ['-g', '--format', 'time', '-u', '--packageFile', pkgPath]);
116
+ runNcu(['-g', '--format', 'time', '-u', '--packageFile', pkgPath]);
111
117
  break;
112
118
 
113
119
  case 'install': {
114
120
  prepare();
115
121
  const dependencies = readDependencies(pkgPath);
116
122
  const specs = Object.entries(dependencies).map(([name, versionRange]) =>
117
- toGlobalInstallSpec(name, versionRange),
123
+ toGlobalInstallSpec(name, versionRange, { pinVersion: true }),
118
124
  );
119
125
 
120
126
  if (specs.length === 0) {
@@ -1,13 +1,48 @@
1
1
  'use strict';
2
2
 
3
- function toGlobalInstallSpec(name, versionRange) {
3
+ const { spawnSync } = require('child_process');
4
+
5
+ const shell = process.platform === 'win32';
6
+
7
+ function resolvePinnedVersion(name, versionRange, { spawn = spawnSync } = {}) {
8
+ const trimmed = typeof versionRange === 'string' ? versionRange.trim() : '';
9
+ if (!trimmed) {
10
+ return undefined;
11
+ }
12
+
13
+ const result = spawn('npm', ['view', `${name}@${trimmed}`, 'version', '--json'], {
14
+ encoding: 'utf8',
15
+ shell,
16
+ });
17
+
18
+ if (result.status !== 0) {
19
+ return trimmed;
20
+ }
21
+
22
+ try {
23
+ const parsed = JSON.parse(result.stdout.trim());
24
+ if (typeof parsed === 'string' && parsed) {
25
+ return parsed;
26
+ }
27
+ } catch {
28
+ // fall through to range fallback
29
+ }
30
+
31
+ return trimmed;
32
+ }
33
+
34
+ function toGlobalInstallSpec(name, versionRange, { pinVersion = false, spawn = spawnSync } = {}) {
4
35
  if (typeof versionRange === 'string' && versionRange.trim() !== '') {
5
- return `${name}@${versionRange}`;
36
+ const target = pinVersion
37
+ ? resolvePinnedVersion(name, versionRange, { spawn })
38
+ : versionRange.trim();
39
+ return `${name}@${target}`;
6
40
  }
7
41
 
8
42
  return name;
9
43
  }
10
44
 
11
45
  module.exports = {
46
+ resolvePinnedVersion,
12
47
  toGlobalInstallSpec,
13
48
  };
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ const { existsSync } = require('fs');
4
+ const path = require('path');
5
+
6
+ function bundledNcuCliPath(packageRoot) {
7
+ const nestedCli = path.join(
8
+ packageRoot,
9
+ 'node_modules',
10
+ 'npm-check-updates',
11
+ 'build',
12
+ 'cli.js',
13
+ );
14
+ if (existsSync(nestedCli)) {
15
+ return nestedCli;
16
+ }
17
+
18
+ try {
19
+ const pkgJson = require.resolve('npm-check-updates/package.json', {
20
+ paths: [packageRoot],
21
+ });
22
+ const cliJs = path.join(path.dirname(pkgJson), 'build', 'cli.js');
23
+ if (existsSync(cliJs)) {
24
+ return cliJs;
25
+ }
26
+ } catch {
27
+ // fall through to .bin / PATH
28
+ }
29
+
30
+ return undefined;
31
+ }
32
+
33
+ function resolveNcuInvocation(packageRoot) {
34
+ const cliJs = bundledNcuCliPath(packageRoot);
35
+ if (cliJs) {
36
+ return {
37
+ command: process.execPath,
38
+ prefixArgs: [cliJs],
39
+ useShell: false,
40
+ };
41
+ }
42
+
43
+ const binName = process.platform === 'win32' ? 'ncu.cmd' : 'ncu';
44
+ const localBin = path.join(packageRoot, 'node_modules', '.bin', binName);
45
+ if (existsSync(localBin)) {
46
+ return {
47
+ command: localBin,
48
+ prefixArgs: [],
49
+ useShell: process.platform === 'win32',
50
+ };
51
+ }
52
+
53
+ return {
54
+ command: 'ncu',
55
+ prefixArgs: [],
56
+ useShell: process.platform === 'win32',
57
+ };
58
+ }
59
+
60
+ module.exports = {
61
+ resolveNcuInvocation,
62
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@s2j/global-npm",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "Manage globally installed npm packages via package.json with ncu.",
5
5
  "author": "Koutarou ISHIKAWA <stein2nd@gmail.com>",
6
6
  "type": "commonjs",
@@ -56,7 +56,7 @@
56
56
  "typescript": "^5.9.3"
57
57
  },
58
58
  "dependencies": {
59
- "@s2j/global-npm": "^2.0.2",
59
+ "@s2j/global-npm": "^2.1.1",
60
60
  "corepack": "^0.35.0",
61
61
  "editorconfig-cli": "^1.0.0",
62
62
  "envinfo": "^7.21.0",