@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 +26 -16
- package/bin/global-npm.cjs +11 -5
- package/lib/install-spec.cjs +37 -2
- package/lib/resolve-ncu.cjs +62 -0
- package/package.json +2 -2
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
|
|
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
|
-
|
|
|
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
|
|
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 #
|
|
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\`)
|
|
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
|
-
###
|
|
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:**
|
|
125
|
-
* **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) |
|
|
143
|
-
| `install-global.zsh` |
|
|
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 |
|
|
152
|
-
| 3サブコマンド | 5サブコマンド (`sync
|
|
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
|
|
173
|
+
GPL-3.0-or-later: 詳細は [LICENSE](./LICENSE) をご覧ください。
|
package/bin/global-npm.cjs
CHANGED
|
@@ -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
|
-
|
|
111
|
+
runNcu(['-g', '--format', 'time', '--packageFile', pkgPath]);
|
|
106
112
|
break;
|
|
107
113
|
|
|
108
114
|
case 'update':
|
|
109
115
|
prepare();
|
|
110
|
-
|
|
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) {
|
package/lib/install-spec.cjs
CHANGED
|
@@ -1,13 +1,48 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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",
|