@bash0816/claude-code 2.1.156 → 2.1.159-1

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,19 +1,17 @@
1
- # @bash0816/cluade-code
1
+ # @bash0816/claude-code
2
2
 
3
3
  Termux-native Claude Code wrapper package.
4
4
 
5
5
  Termux 向け Claude Code native wrapper package です。
6
6
 
7
- Legacy compatibility package:
7
+ This package is the current Termux wrapper package line.
8
8
 
9
- 互換維持用の legacy package:
10
-
11
- - canonical package: `@bash0816/claude-code`
9
+ この package は現行の Termux wrapper package 系です。
12
10
 
13
11
  ## Install / インストール
14
12
 
15
13
  ```sh
16
- npm install -g @bash0816/cluade-code@latest
14
+ npm install -g @bash0816/claude-code@latest
17
15
  ```
18
16
 
19
17
  If an older audited launcher from this repository already exists at `$PREFIX/bin/claude`, migrate through the updated launcher.
@@ -29,19 +27,23 @@ If npm reports `EEXIST` before package scripts run, use a one-time forced migrat
29
27
  package script 実行前に npm が `EEXIST` を返す場合は、初回だけ forced migration を使います。
30
28
 
31
29
  ```sh
32
- npm install -g --force @bash0816/cluade-code@latest
30
+ npm install -g --force @bash0816/claude-code@latest
33
31
  ```
34
32
 
35
33
  After npm owns the `claude` bin link, normal `npm install -g` updates work.
36
34
 
37
35
  npm が `claude` bin link を管理する状態になれば、通常の `npm install -g` 更新が使えます。
38
36
 
39
- Specific audited version:
37
+ Specific audited versions:
40
38
 
41
39
  監査済みの固定 version:
42
40
 
41
+ Current quick examples:
42
+
43
+ 現在の quick example:
44
+
43
45
  ```sh
44
- npm install -g @bash0816/cluade-code@2.1.123
46
+ npm install -g @bash0816/claude-code@2.1.157
45
47
  ```
46
48
 
47
49
  ## Update / 更新
@@ -50,17 +52,9 @@ npm install -g @bash0816/cluade-code@2.1.123
50
52
  claude update
51
53
  ```
52
54
 
53
- `claude update` checks the GitHub release manifest and installs the latest audited package version.
54
-
55
- `claude update` は GitHub release manifest を確認し、最新の監査済み package version を install します。
56
-
57
- For the final legacy bridge release, `claude update` migrates this typo package to the canonical package.
58
-
59
- 最終 legacy bridge release では、`claude update` がこの typo package から canonical package へ移行します。
60
-
61
- This final bridge package is frozen at package version `2.1.123` and launches audited native `2.1.150` by default from the synced metadata set.
55
+ `claude update` installs the latest audited package version.
62
56
 
63
- この最終 bridge package package version `2.1.123` で凍結し、同期済み metadata 集合から既定では監査済み native `2.1.150` を起動します。
57
+ `claude update` は最新の監査済み package version install します。
64
58
 
65
59
  ```sh
66
60
  npm install -g @bash0816/claude-code@<latest_audited_version>
@@ -74,10 +68,10 @@ Normal launch also checks the same manifest with a short timeout and prints a no
74
68
 
75
69
  - Only audited versions in `config/claude-native-audited-versions.json` can run.
76
70
  - `config/claude-native-audited-versions.json` にある監査済み version だけを実行できます。
77
- - This legacy package is frozen at `2.1.123` and exists only as a migration bridge to `@bash0816/claude-code`.
78
- - この legacy package は `2.1.123` で凍結しており、`@bash0816/claude-code` への migration bridge としてのみ存在します。
79
- - The metadata file remains the source of truth for the audited version set.
80
- - 監査済み version 集合の source of truth は引き続き metadata file です。
71
+ - `2.1.150-1`, `2.1.150-2`, `2.1.150-3`, `2.1.153-1`, `2.1.153-2`, `2.1.153-3`, `2.1.153-4`, `2.1.118`, `2.1.119`, `2.1.121`, `2.1.122`, `2.1.123`, `2.1.126`, `2.1.128`, `2.1.136`, `2.1.137`, `2.1.138`, `2.1.139`, `2.1.140`, `2.1.141`, `2.1.142`, `2.1.143`, `2.1.144`, `2.1.150`, `2.1.153`, `2.1.157` are included in the package metadata.
72
+ - `2.1.150-1`、`2.1.150-2`、`2.1.150-3`、`2.1.153-1`、`2.1.153-2`、`2.1.153-3`、`2.1.153-4`、`2.1.118`、`2.1.119`、`2.1.121`、`2.1.122`、`2.1.123`、`2.1.126`、`2.1.128`、`2.1.136`、`2.1.137`、`2.1.138`、`2.1.139`、`2.1.140`、`2.1.141`、`2.1.142`、`2.1.143`、`2.1.144`、`2.1.150`、`2.1.153`、`2.1.157` package metadata に含めています。
73
+ - The metadata file is the source of truth for the currently audited set.
74
+ - 現在の監査済み version 集合の source of truth metadata file です。
81
75
  - Native artifacts are cached under `${HOME}/.claude-termux-native-package`.
82
76
  - native artifact は `${HOME}/.claude-termux-native-package` に cache します。
83
77
  - If native preparation fails, the command exits with an error.
package/bin/claude CHANGED
@@ -14,8 +14,7 @@ done
14
14
  PACKAGE_DIR=$(CDPATH= cd -- "$(dirname -- "${SELF}")/.." && pwd)
15
15
  CONFIG_FILE="${PACKAGE_DIR}/config/claude-native-audited-versions.json"
16
16
  PACKAGE_VERSION=$(node -e 'const fs=require("fs"); const path=require("path"); const p=JSON.parse(fs.readFileSync(path.join(process.argv[1],"package.json"),"utf8")); process.stdout.write(p.version)' "${PACKAGE_DIR}")
17
- DEFAULT_NATIVE_VERSION=$(node -e 'const fs=require("fs"); const path=require("path"); const p=JSON.parse(fs.readFileSync(path.join(process.argv[1],"config","claude-termux-release-manifest.json"),"utf8")); process.stdout.write(String(p.default_native_version || p.latest_audited_version || ""))' "${PACKAGE_DIR}")
18
- CLAUDE_VERSION="${CLAUDE_TERMUX_CLAUDE_VERSION:-${DEFAULT_NATIVE_VERSION:-${PACKAGE_VERSION}}}"
17
+ CLAUDE_VERSION="${CLAUDE_TERMUX_CLAUDE_VERSION:-${PACKAGE_VERSION}}"
19
18
  UPDATE_HELPER="${PACKAGE_DIR}/lib/check-updates.js"
20
19
 
21
20
  if [ "${1:-}" = "update" ]; then
@@ -58,5 +57,6 @@ WORKDIR="${CACHE_DIR}/launcher-workdir" \
58
57
  ENTRY_JS_OFFSET="${ENTRY_JS_OFFSET}" \
59
58
  ENTRY_END_OFFSET="${ENTRY_END_OFFSET}" \
60
59
  CURRENT_CLAUDE_VERSION="${CLAUDE_VERSION}" \
60
+ CLAUDE_TERMUX_PACKAGE_DIR="${PACKAGE_DIR}" \
61
61
  CLAUDE_NATIVE_UPDATE_CHECK=0 \
62
62
  exec sh "${PACKAGE_DIR}/lib/termux-run-claude-native.sh" "$@"
@@ -175,18 +175,11 @@
175
175
  "entry_end_offset": 237958345,
176
176
  "status": "termux_verified"
177
177
  },
178
- "2.1.154": {
179
- "wrapper_spec": "@anthropic-ai/claude-code@2.1.154",
180
- "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.154",
181
- "entry_js_offset": 222957396,
182
- "entry_end_offset": 238482842,
183
- "status": "termux_verified"
184
- },
185
- "2.1.156": {
186
- "wrapper_spec": "@anthropic-ai/claude-code@2.1.156",
187
- "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.156",
188
- "entry_js_offset": 222957812,
189
- "entry_end_offset": 238483519,
178
+ "2.1.157": {
179
+ "wrapper_spec": "@anthropic-ai/claude-code@2.1.157",
180
+ "native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.157",
181
+ "entry_js_offset": 223210916,
182
+ "entry_end_offset": 238725072,
190
183
  "status": "termux_verified"
191
184
  }
192
185
  }
@@ -1,13 +1,8 @@
1
1
  {
2
2
  "manifest_version": 1,
3
3
  "package_name": "@bash0816/claude-code",
4
- "canonical_package_name": "@bash0816/claude-code",
5
- "canonical_manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json",
6
- "canonical_repository_url": "https://github.com/bash0816/ClaudeCode-Termux",
7
- "bridge_package_version": "2.1.156",
8
- "default_native_version": "2.1.156",
9
- "latest_audited_version": "2.1.156",
10
- "latest_candidate_version": "2.1.156",
11
- "previous_stable_version": "2.1.154",
4
+ "latest_audited_version": "2.1.157",
5
+ "latest_candidate_version": "2.1.157",
6
+ "previous_stable_version": "2.1.153-4",
12
7
  "manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json"
13
8
  }
@@ -19,19 +19,10 @@ const timeoutMs = Number(process.env.CLAUDE_TERMUX_UPDATE_TIMEOUT_MS || '1200');
19
19
  const ttlMs = Number(process.env.CLAUDE_TERMUX_UPDATE_CACHE_TTL_MS || String(24 * 60 * 60 * 1000));
20
20
  const skipCheck = process.env.CLAUDE_TERMUX_SKIP_UPDATE_CHECK === '1';
21
21
  const manifestUrl = process.env.CLAUDE_TERMUX_MANIFEST_URL || localManifest.manifest_url;
22
- const canonicalManifestUrl = process.env.CLAUDE_TERMUX_CANONICAL_MANIFEST_URL || localManifest.canonical_manifest_url || '';
23
- const canonicalPackageName = process.env.CLAUDE_TERMUX_CANONICAL_PACKAGE_NAME || localManifest.canonical_package_name || '';
24
- const canonicalRepositoryUrl = process.env.CLAUDE_TERMUX_CANONICAL_REPOSITORY_URL || localManifest.canonical_repository_url || '';
25
22
 
26
23
  function compareVersions(a, b) {
27
- const parse = v => {
28
- const [main, patch] = String(v).split('-');
29
- const parts = main.split('.').map(Number);
30
- parts.push(patch !== undefined ? Number(patch) : 0);
31
- return parts;
32
- };
33
- const aParts = parse(a);
34
- const bParts = parse(b);
24
+ const aParts = String(a).split('.').map(Number);
25
+ const bParts = String(b).split('.').map(Number);
35
26
  const len = Math.max(aParts.length, bParts.length);
36
27
  for (let index = 0; index < len; index += 1) {
37
28
  const diff = (aParts[index] || 0) - (bParts[index] || 0);
@@ -111,64 +102,10 @@ async function resolveManifest(forceRefresh) {
111
102
  }
112
103
  }
113
104
 
114
- async function resolveCanonicalManifest() {
115
- if (!canonicalManifestUrl || !canonicalPackageName || canonicalPackageName === pkg.name) {
116
- return null;
117
- }
118
-
119
- if (skipCheck) {
120
- return {
121
- packageName: canonicalPackageName,
122
- latestVersion: localManifest.latest_audited_version || pkg.version,
123
- repositoryUrl: canonicalRepositoryUrl,
124
- };
125
- }
126
-
127
- try {
128
- const manifest = await fetchManifest(canonicalManifestUrl);
129
- return {
130
- packageName: manifest.package_name || canonicalPackageName,
131
- latestVersion: manifest.latest_audited_version || localManifest.latest_audited_version || pkg.version,
132
- repositoryUrl: canonicalRepositoryUrl,
133
- };
134
- } catch {
135
- return {
136
- packageName: canonicalPackageName,
137
- latestVersion: localManifest.latest_audited_version || pkg.version,
138
- repositoryUrl: canonicalRepositoryUrl,
139
- };
140
- }
141
- }
142
-
143
- async function resolveTarget(forceRefresh) {
144
- const base = await resolveManifest(forceRefresh);
145
- const canonical = await resolveCanonicalManifest();
146
- if (!canonical) {
147
- return {
148
- manifest: base.manifest,
149
- cache: base.cache,
150
- packageName: base.manifest.package_name || pkg.name,
151
- targetVersion: base.manifest.latest_audited_version || localManifest.latest_audited_version || pkg.version,
152
- repositoryUrl: '',
153
- migration: false,
154
- };
155
- }
156
-
157
- return {
158
- manifest: base.manifest,
159
- cache: base.cache,
160
- packageName: canonical.packageName,
161
- targetVersion: canonical.latestVersion,
162
- repositoryUrl: canonical.repositoryUrl,
163
- migration: canonical.packageName !== pkg.name,
164
- };
165
- }
166
-
167
- function updateNoticeCache(cache, packageName, latestVersion) {
105
+ function updateNoticeCache(cache, latestVersion) {
168
106
  const nextCache = {
169
107
  ...cache,
170
108
  last_notice: {
171
- package_name: packageName,
172
109
  current_version: currentVersion,
173
110
  latest_audited_version: latestVersion,
174
111
  notified_at: Date.now(),
@@ -177,10 +114,9 @@ function updateNoticeCache(cache, packageName, latestVersion) {
177
114
  writeCache(nextCache);
178
115
  }
179
116
 
180
- function shouldNotify(cache, packageName, latestVersion) {
117
+ function shouldNotify(cache, latestVersion) {
181
118
  const lastNotice = cache.last_notice;
182
119
  if (!lastNotice) return true;
183
- if (lastNotice.package_name !== packageName) return true;
184
120
  if (lastNotice.current_version !== currentVersion) return true;
185
121
  if (lastNotice.latest_audited_version !== latestVersion) return true;
186
122
  return Date.now() - Number(lastNotice.notified_at || 0) >= ttlMs;
@@ -204,40 +140,26 @@ function installTarget(packageName, targetVersion) {
204
140
  }
205
141
 
206
142
  async function runNotify() {
207
- const target = await resolveTarget(false);
208
- const latest = target.targetVersion;
209
- const packageName = target.packageName;
210
- const migration = target.migration;
211
- if (!migration && compareVersions(currentVersion, latest) >= 0) return 0;
212
- if (!shouldNotify(target.cache, packageName, latest)) return 0;
213
-
214
- if (migration) {
215
- console.error(`Legacy package detected: ${pkg.name}`);
216
- console.error(`Canonical package available: ${packageName}@${latest}`);
217
- if (target.repositoryUrl) {
218
- console.error(`Canonical repository: ${target.repositoryUrl}`);
219
- }
220
- console.error('Run: claude update');
221
- updateNoticeCache(target.cache, packageName, latest);
222
- return 0;
223
- }
143
+ const { manifest, cache } = await resolveManifest(false);
144
+ const latest = manifest.latest_audited_version || localManifest.latest_audited_version || pkg.version;
145
+ if (compareVersions(currentVersion, latest) >= 0) return 0;
146
+ if (!shouldNotify(cache, latest)) return 0;
224
147
 
225
148
  console.error(`Audited update available: ${currentVersion} -> ${latest}`);
226
149
  console.error('Run: claude update');
227
- updateNoticeCache(target.cache, packageName, latest);
150
+ updateNoticeCache(cache, latest);
228
151
  return 0;
229
152
  }
230
153
 
231
154
  async function runUpdate() {
232
- const target = await resolveTarget(true);
233
- if (!target.migration && compareVersions(currentVersion, target.targetVersion) >= 0) {
155
+ const { manifest } = await resolveManifest(true);
156
+ const packageName = manifest.package_name || localManifest.package_name;
157
+ const target = manifest.latest_audited_version || localManifest.latest_audited_version || pkg.version;
158
+ if (compareVersions(currentVersion, target) >= 0) {
234
159
  console.error(`Already on latest audited version: ${currentVersion}`);
235
160
  return 0;
236
161
  }
237
- if (target.migration) {
238
- console.error(`Migrating from legacy package ${pkg.name} to canonical package ${target.packageName}@${target.targetVersion}`);
239
- }
240
- return installTarget(target.packageName, target.targetVersion);
162
+ return installTarget(packageName, target);
241
163
  }
242
164
 
243
165
  async function main() {
@@ -0,0 +1,257 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const EventEmitter = require('events');
5
+
6
+ const OFFICIAL_PACKAGE = '@anthropic-ai/claude-code';
7
+ const BLOCK_MESSAGE = [
8
+ 'Official native self-update is disabled on Termux.',
9
+ 'Run: claude update',
10
+ ].join('\n');
11
+
12
+ function lastPathSegment(value) {
13
+ return String(value || '').replace(/\\/g, '/').split('/').pop();
14
+ }
15
+
16
+ function isNpmCommand(command) {
17
+ const text = String(command || '');
18
+ const leaf = lastPathSegment(text);
19
+ return leaf === 'npm' || leaf === 'npm-cli.js';
20
+ }
21
+
22
+ function isPnpmCommand(command) {
23
+ return lastPathSegment(command) === 'pnpm';
24
+ }
25
+
26
+ function isYarnCommand(command) {
27
+ const leaf = lastPathSegment(command);
28
+ return leaf === 'yarn' || leaf === 'yarnpkg';
29
+ }
30
+
31
+ function isNpxCommand(command) {
32
+ const leaf = lastPathSegment(command);
33
+ return leaf === 'npx' || leaf === 'pnpx';
34
+ }
35
+
36
+ function isEnvCommand(command) {
37
+ return lastPathSegment(command) === 'env';
38
+ }
39
+
40
+ function isCorepackCommand(command) {
41
+ return lastPathSegment(command) === 'corepack';
42
+ }
43
+
44
+ function isShellCommand(command) {
45
+ const leaf = lastPathSegment(command);
46
+ return leaf === 'sh' || leaf === 'bash';
47
+ }
48
+
49
+ function isSupportedOperation(value) {
50
+ return ['install', 'i', 'add', 'update', 'up', 'upgrade'].includes(String(value || ''));
51
+ }
52
+
53
+ function isOfficialTarget(value) {
54
+ return String(value || '') === OFFICIAL_PACKAGE || String(value || '').startsWith(`${OFFICIAL_PACKAGE}@`);
55
+ }
56
+
57
+ function normalizeCommand(command, args) {
58
+ let normalizedCommand = command;
59
+ let normalizedArgs = Array.isArray(args) ? args.slice() : [];
60
+
61
+ if (isEnvCommand(normalizedCommand)) {
62
+ while (normalizedArgs.length > 0 && /^[A-Za-z_][A-Za-z0-9_]*=.*/.test(String(normalizedArgs[0]))) {
63
+ normalizedArgs.shift();
64
+ }
65
+ if (normalizedArgs.length === 0) return { command: normalizedCommand, args: normalizedArgs };
66
+ normalizedCommand = normalizedArgs.shift();
67
+ }
68
+
69
+ if (isCorepackCommand(normalizedCommand)) {
70
+ if (normalizedArgs.length === 0) return { command: normalizedCommand, args: normalizedArgs };
71
+ normalizedCommand = normalizedArgs.shift();
72
+ }
73
+
74
+ return { command: normalizedCommand, args: normalizedArgs };
75
+ }
76
+
77
+ function hasOfficialTarget(args) {
78
+ return args.some(isOfficialTarget);
79
+ }
80
+
81
+ function shouldBlockNpmLike(command, args) {
82
+ if (!(isNpmCommand(command) || isPnpmCommand(command))) return false;
83
+ if (!args.find(isSupportedOperation)) return false;
84
+ return hasOfficialTarget(args);
85
+ }
86
+
87
+ function shouldBlockYarn(command, args) {
88
+ if (!isYarnCommand(command)) return false;
89
+ return String(args[0] || '') === 'global' && String(args[1] || '') === 'add' && hasOfficialTarget(args.slice(2));
90
+ }
91
+
92
+ function shouldBlockNpx(command, args) {
93
+ if (!isNpxCommand(command)) return false;
94
+ for (let index = 0; index < args.length; index += 1) {
95
+ const token = String(args[index] || '');
96
+ if (token === '-p' || token === '--package') {
97
+ if (isOfficialTarget(args[index + 1])) return true;
98
+ index += 1;
99
+ continue;
100
+ }
101
+ if (token.startsWith('--package=')) {
102
+ if (isOfficialTarget(token.slice('--package='.length))) return true;
103
+ continue;
104
+ }
105
+ if (!token.startsWith('-')) {
106
+ return isOfficialTarget(token);
107
+ }
108
+ }
109
+ return false;
110
+ }
111
+
112
+ function shouldBlockCommand(command, args) {
113
+ if (!Array.isArray(args)) return false;
114
+ const normalized = normalizeCommand(command, args);
115
+ return (
116
+ shouldBlockNpmLike(normalized.command, normalized.args) ||
117
+ shouldBlockYarn(normalized.command, normalized.args) ||
118
+ shouldBlockNpx(normalized.command, normalized.args)
119
+ );
120
+ }
121
+
122
+ function normalizeTokensForExec(tokens) {
123
+ if (tokens.length === 0) return tokens;
124
+ const normalized = normalizeCommand(tokens[0], tokens.slice(1));
125
+ return [normalized.command, ...normalized.args].filter(value => value !== undefined);
126
+ }
127
+
128
+ function unwrapShellCommand(command, args) {
129
+ if (!isShellCommand(command) || !Array.isArray(args) || args.length < 2) return null;
130
+ const first = String(args[0] || '');
131
+ const second = String(args[1] || '');
132
+ if ((first === '-c' || first === '-lc') && second) return second;
133
+ if (first === '-l' && String(args[1] || '') === '-c' && String(args[2] || '')) return String(args[2]);
134
+ return null;
135
+ }
136
+
137
+ function tokenizeShellString(command) {
138
+ const text = String(command || '').trim();
139
+ if (!text) return [];
140
+ return text.match(/(?:[^\s'"]+|'[^']*'|"[^"]*")+/g) || [];
141
+ }
142
+
143
+ function unquote(token) {
144
+ if (
145
+ (token.startsWith('"') && token.endsWith('"')) ||
146
+ (token.startsWith("'") && token.endsWith("'"))
147
+ ) {
148
+ return token.slice(1, -1);
149
+ }
150
+ return token;
151
+ }
152
+
153
+ function shouldBlockExecString(command) {
154
+ const tokens = normalizeTokensForExec(tokenizeShellString(command).map(unquote));
155
+ if (tokens.length === 0) return false;
156
+ const shellInner = unwrapShellCommand(tokens[0], tokens.slice(1));
157
+ if (shellInner) return shouldBlockExecString(shellInner);
158
+ return shouldBlockCommand(tokens[0], tokens.slice(1));
159
+ }
160
+
161
+ function createBlockedError(blockedStderr) {
162
+ const error = new Error(BLOCK_MESSAGE);
163
+ error.code = 'CLAUDE_TERMUX_OFFICIAL_UPDATE_BLOCKED';
164
+ error.status = 1;
165
+ error.stdout = Buffer.from('');
166
+ error.stderr = Buffer.from(blockedStderr);
167
+ return error;
168
+ }
169
+
170
+ function createBlockedSpawn(blockedStderr, stderrWriter, options) {
171
+ const child = new EventEmitter();
172
+ child.stdout = null;
173
+ child.stderr = null;
174
+ child.stdin = null;
175
+ child.pid = 0;
176
+ child.killed = false;
177
+ child.kill = () => false;
178
+ process.nextTick(() => {
179
+ if (!(options && options.stdio === 'ignore')) {
180
+ stderrWriter(blockedStderr);
181
+ }
182
+ child.emit('close', 1, null);
183
+ child.emit('exit', 1, null);
184
+ });
185
+ return child;
186
+ }
187
+
188
+ function createBlockedSpawnSync(blockedStderr, stderrWriter) {
189
+ stderrWriter(blockedStderr);
190
+ return {
191
+ pid: 0,
192
+ output: [null, Buffer.from(''), Buffer.from(blockedStderr)],
193
+ stdout: Buffer.from(''),
194
+ stderr: Buffer.from(blockedStderr),
195
+ status: 1,
196
+ signal: null,
197
+ error: createBlockedError(blockedStderr),
198
+ };
199
+ }
200
+
201
+ function createBlockedExecResult(blockedStderr, stderrWriter, callback) {
202
+ const child = createBlockedSpawn(blockedStderr, stderrWriter);
203
+ const error = createBlockedError(blockedStderr);
204
+ process.nextTick(() => {
205
+ if (typeof callback === 'function') {
206
+ callback(error, '', blockedStderr);
207
+ }
208
+ });
209
+ return child;
210
+ }
211
+
212
+ function shouldBlockSpawnArgs(args) {
213
+ if (!Array.isArray(args) || args.length === 0) return false;
214
+ const command = args[0];
215
+ const commandArgs = Array.isArray(args[1]) ? args[1] : [];
216
+ const shellInner = unwrapShellCommand(command, commandArgs);
217
+ if (shellInner) return shouldBlockExecString(shellInner);
218
+ return shouldBlockCommand(command, commandArgs);
219
+ }
220
+
221
+ function createGuardedChildProcess(realChild, stderrWriter = value => process.stderr.write(value)) {
222
+ const blockedStderr = `${BLOCK_MESSAGE}\n`;
223
+ return {
224
+ spawn: (...args) => {
225
+ if (shouldBlockSpawnArgs(args)) return createBlockedSpawn(blockedStderr, stderrWriter, args[2]);
226
+ return realChild.spawn(...args);
227
+ },
228
+ execFile: (...args) => {
229
+ if (shouldBlockSpawnArgs(args)) return createBlockedExecResult(blockedStderr, stderrWriter, args[args.length - 1]);
230
+ return realChild.execFile(...args);
231
+ },
232
+ exec: (...args) => {
233
+ if (shouldBlockExecString(args[0])) return createBlockedExecResult(blockedStderr, stderrWriter, args[args.length - 1]);
234
+ return realChild.exec(...args);
235
+ },
236
+ spawnSync: (...args) => {
237
+ if (shouldBlockSpawnArgs(args)) return createBlockedSpawnSync(blockedStderr, stderrWriter);
238
+ return realChild.spawnSync(...args);
239
+ },
240
+ execFileSync: (...args) => {
241
+ if (shouldBlockSpawnArgs(args)) throw createBlockedError(blockedStderr);
242
+ return realChild.execFileSync(...args);
243
+ },
244
+ execSync: (...args) => {
245
+ if (shouldBlockExecString(args[0])) throw createBlockedError(blockedStderr);
246
+ return realChild.execSync(...args);
247
+ },
248
+ };
249
+ }
250
+
251
+ module.exports = {
252
+ BLOCK_MESSAGE,
253
+ OFFICIAL_PACKAGE,
254
+ createGuardedChildProcess,
255
+ shouldBlockCommand,
256
+ shouldBlockExecString,
257
+ };