@mutmutco/cli 4.5.158 → 4.5.160

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.
@@ -190,6 +190,54 @@ var init_error_codes = __esm({
190
190
  }
191
191
  });
192
192
 
193
+ // src/gh-read-route.ts
194
+ function isViewerFreeGhRead(args) {
195
+ if (args.some((a) => VIEWER.test(a))) return false;
196
+ const [group, verb] = args;
197
+ if (group === "api") return isReadOnlyApi(args.slice(1));
198
+ return Boolean(group && verb && READ_VERBS.get(group)?.has(verb));
199
+ }
200
+ function isReadOnlyApi(rest) {
201
+ let path2;
202
+ for (let i = 0; i < rest.length; i++) {
203
+ const a = rest[i];
204
+ if (a === "-X" || a === "--method") {
205
+ if ((rest[i + 1] ?? "").toUpperCase() !== "GET") return false;
206
+ i++;
207
+ } else if (/^--method=/.test(a)) {
208
+ if (a.slice(9).toUpperCase() !== "GET") return false;
209
+ } else if (a === "-f" || a === "-F" || a === "--field" || a === "--raw-field") {
210
+ const field = rest[i + 1] ?? "";
211
+ if (path2 !== "graphql" || !/^query=\s*(query\b|\{)/.test(field) || /projectV2|projectsV2/.test(field)) return false;
212
+ i++;
213
+ } else if (a === "--input" || a.startsWith("--input=")) {
214
+ return false;
215
+ } else if (a === "-H" || a === "--header" || a === "-q" || a === "--jq" || a === "-t" || a === "--template" || a === "--hostname" || a === "--cache") {
216
+ i++;
217
+ } else if (!a.startsWith("-") && path2 === void 0) {
218
+ path2 = a.replace(/^\//, "");
219
+ }
220
+ }
221
+ if (!path2) return false;
222
+ if (path2 === "graphql") return rest.some((a) => /^query=\s*(query\b|\{)/.test(a));
223
+ return !/^(user|users\/[^/]+\/|notifications|search\/|orgs\/[^/]+\/projectsV2|graphql)/.test(path2);
224
+ }
225
+ var READ_VERBS, VIEWER;
226
+ var init_gh_read_route = __esm({
227
+ "src/gh-read-route.ts"() {
228
+ "use strict";
229
+ READ_VERBS = /* @__PURE__ */ new Map([
230
+ ["pr", /* @__PURE__ */ new Set(["view", "list", "checks", "diff"])],
231
+ ["issue", /* @__PURE__ */ new Set(["view", "list"])],
232
+ ["run", /* @__PURE__ */ new Set(["view", "list", "watch"])],
233
+ ["label", /* @__PURE__ */ new Set(["list"])],
234
+ ["release", /* @__PURE__ */ new Set(["view", "list"])],
235
+ ["repo", /* @__PURE__ */ new Set(["view"])]
236
+ ]);
237
+ VIEWER = /@me\b|viewer|project/i;
238
+ }
239
+ });
240
+
193
241
  // src/github-quota.ts
194
242
  var init_github_quota = __esm({
195
243
  "src/github-quota.ts"() {
@@ -237,6 +285,12 @@ var init_stdin_inject = __esm({
237
285
  });
238
286
 
239
287
  // src/cli-shared.ts
288
+ async function ghReadAppEnv(file, args) {
289
+ if (!ghReadTokenProvider || !/(^|[\\/])gh(\.exe)?$/i.test(file) || process.env.MMI_ACTOR?.trim() === "personal") return void 0;
290
+ if (!isViewerFreeGhRead(args)) return void 0;
291
+ const token = await ghReadTokenProvider().catch(() => void 0);
292
+ return token ? { ...process.env, GH_TOKEN: token } : void 0;
293
+ }
240
294
  function killProcessTree(pid) {
241
295
  try {
242
296
  if (process.platform === "win32") {
@@ -271,7 +325,7 @@ function execFileHard(file, args, options) {
271
325
  timer.unref?.();
272
326
  });
273
327
  }
274
- var import_node_child_process3, import_node_util2, rawExecFileP, DEFAULT_EXEC_TIMEOUT_MS, execFileP, ExecDeadlineError;
328
+ var import_node_child_process3, import_node_util2, rawExecFileP, DEFAULT_EXEC_TIMEOUT_MS, execFileP, ghReadTokenProvider, ExecDeadlineError;
275
329
  var init_cli_shared = __esm({
276
330
  "src/cli-shared.ts"() {
277
331
  "use strict";
@@ -282,16 +336,27 @@ var init_cli_shared = __esm({
282
336
  init_clean_exit();
283
337
  init_error_codes();
284
338
  init_github_client();
339
+ init_gh_read_route();
285
340
  init_hub_auth();
286
341
  init_house_map();
287
342
  init_stdin_inject();
288
343
  rawExecFileP = (0, import_node_util2.promisify)(import_node_child_process3.execFile);
289
344
  DEFAULT_EXEC_TIMEOUT_MS = 1e4;
290
- execFileP = (file, args, options = {}) => (
291
- // encoding 'utf8' guarantees string stdout/stderr at runtime; the cast pins the type because
292
- // promisify(execFile)'s overloads widen to string|Buffer when options is spread in.
293
- rawExecFileP(file, args, { encoding: "utf8", windowsHide: true, timeout: DEFAULT_EXEC_TIMEOUT_MS, killSignal: "SIGTERM", ...options })
294
- );
345
+ execFileP = async (file, args, options = {}) => {
346
+ const run = (env) => (
347
+ // encoding 'utf8' guarantees string stdout/stderr at runtime; the cast pins the type because
348
+ // promisify(execFile)'s overloads widen to string|Buffer when options is spread in.
349
+ rawExecFileP(file, args, { encoding: "utf8", windowsHide: true, timeout: DEFAULT_EXEC_TIMEOUT_MS, killSignal: "SIGTERM", ...options, ...env ? { env } : {} })
350
+ );
351
+ const appEnv = options.env ? void 0 : await ghReadAppEnv(file, args);
352
+ if (!appEnv) return run();
353
+ try {
354
+ return await run(appEnv);
355
+ } catch (e) {
356
+ if (/Resource not accessible by integration/i.test(String(e.stderr ?? ""))) return run();
357
+ throw e;
358
+ }
359
+ };
295
360
  ExecDeadlineError = class extends Error {
296
361
  constructor(step, timeoutMs, elapsedMs, killed) {
297
362
  super(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.158",
3
+ "version": "4.5.160",
4
4
  "description": "MMI Future CLI — the org dev toolbox and shared cross-IDE engine for every registry-declared MMI coding surface.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",