@mesh-tech/mesh-cli 0.20.0 → 0.20.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.
Files changed (49) hide show
  1. package/README.md +13 -8
  2. package/dist/bin/mesh.js +272 -52
  3. package/dist/bin/mesh.js.map +4 -4
  4. package/dist/build-info.json +2 -2
  5. package/dist/src/commands/app-check.d.ts +1 -1
  6. package/dist/src/commands/app-check.d.ts.map +1 -1
  7. package/dist/src/commands/app-check.js +13 -0
  8. package/dist/src/commands/app-check.js.map +1 -1
  9. package/dist/src/commands/create-app.d.ts +14 -0
  10. package/dist/src/commands/create-app.d.ts.map +1 -1
  11. package/dist/src/commands/create-app.js +25 -2
  12. package/dist/src/commands/create-app.js.map +1 -1
  13. package/dist/src/commands/init/wizard.d.ts +21 -4
  14. package/dist/src/commands/init/wizard.d.ts.map +1 -1
  15. package/dist/src/commands/init/wizard.js +51 -10
  16. package/dist/src/commands/init/wizard.js.map +1 -1
  17. package/dist/src/commands/local/hub-local.d.ts +35 -0
  18. package/dist/src/commands/local/hub-local.d.ts.map +1 -1
  19. package/dist/src/commands/local/hub-local.js +61 -1
  20. package/dist/src/commands/local/hub-local.js.map +1 -1
  21. package/dist/src/commands/local/index.d.ts.map +1 -1
  22. package/dist/src/commands/local/index.js +15 -1
  23. package/dist/src/commands/local/index.js.map +1 -1
  24. package/dist/src/commands/local/seed-hub-catalog.d.ts +33 -0
  25. package/dist/src/commands/local/seed-hub-catalog.d.ts.map +1 -0
  26. package/dist/src/commands/local/seed-hub-catalog.js +90 -0
  27. package/dist/src/commands/local/seed-hub-catalog.js.map +1 -0
  28. package/dist/src/commands/login.d.ts +12 -0
  29. package/dist/src/commands/login.d.ts.map +1 -1
  30. package/dist/src/commands/login.js +52 -7
  31. package/dist/src/commands/login.js.map +1 -1
  32. package/dist/src/commands/registry.d.ts +22 -3
  33. package/dist/src/commands/registry.d.ts.map +1 -1
  34. package/dist/src/commands/registry.js +36 -4
  35. package/dist/src/commands/registry.js.map +1 -1
  36. package/dist/src/commands/temporal.js +20 -6
  37. package/dist/src/commands/temporal.js.map +2 -2
  38. package/dist/src/utils/aws-auth.d.ts +19 -0
  39. package/dist/src/utils/aws-auth.d.ts.map +1 -1
  40. package/dist/src/utils/aws-auth.js +30 -9
  41. package/dist/src/utils/aws-auth.js.map +1 -1
  42. package/dist/src/utils/registry-identity.d.ts +35 -0
  43. package/dist/src/utils/registry-identity.d.ts.map +1 -1
  44. package/dist/src/utils/registry-identity.js +47 -1
  45. package/dist/src/utils/registry-identity.js.map +1 -1
  46. package/package.json +2 -2
  47. package/skills/core/SKILL.md +2 -2
  48. package/templates/api-auth/index.ts.hbs +3 -1
  49. package/templates/api-role-gating/index.ts.hbs +3 -1
package/dist/bin/mesh.js CHANGED
@@ -3274,6 +3274,7 @@ __export(login_exports, {
3274
3274
  discoverConfigForContext: () => discoverConfigForContext,
3275
3275
  discoverConfigFromWellKnown: () => discoverConfigFromWellKnown,
3276
3276
  ensureLogin: () => ensureLogin,
3277
+ forceRefreshToken: () => forceRefreshToken,
3277
3278
  getContextConfig: () => getContextConfig,
3278
3279
  getValidToken: () => getValidToken,
3279
3280
  isRemoteEnvironment: () => isRemoteEnvironment,
@@ -3993,22 +3994,43 @@ async function getValidToken(context, opts = {}) {
3993
3994
  if (tokenStillValid(creds.expiresAt, opts.marginMs ?? 0)) {
3994
3995
  return creds.idToken;
3995
3996
  }
3997
+ return remintToken(context, config, creds);
3998
+ }
3999
+ async function remintToken(context, config, creds) {
3996
4000
  if (!creds.refreshToken) return null;
4001
+ let tokens;
4002
+ try {
4003
+ tokens = await refreshTokens(config.issuer, config.clientId, creds.refreshToken);
4004
+ } catch {
4005
+ return null;
4006
+ }
4007
+ let email = creds.email;
4008
+ try {
4009
+ email = decodeJwtPayload(tokens.id_token).email ?? creds.email;
4010
+ } catch {
4011
+ }
3997
4012
  try {
3998
- const tokens = await refreshTokens(config.issuer, config.clientId, creds.refreshToken);
3999
- const idPayload = decodeJwtPayload(tokens.id_token);
4000
4013
  writeCredentials(context, {
4001
4014
  ...creds,
4002
4015
  idToken: tokens.id_token,
4003
4016
  accessToken: tokens.access_token,
4004
4017
  refreshToken: tokens.refresh_token ?? creds.refreshToken,
4005
4018
  expiresAt: new Date(Date.now() + tokens.expires_in * 1e3).toISOString(),
4006
- email: idPayload.email ?? creds.email
4019
+ email
4007
4020
  });
4008
- return tokens.id_token;
4009
- } catch {
4010
- return null;
4021
+ } catch (err) {
4022
+ logWarn(
4023
+ `The refreshed ${context} session could not be cached (${err instanceof Error ? err.message : String(err)}) \u2014 this run continues on the new token, but the next one may need a fresh sign-in.`
4024
+ );
4011
4025
  }
4026
+ return tokens.id_token;
4027
+ }
4028
+ async function forceRefreshToken(context) {
4029
+ const config = getContextConfig(context);
4030
+ if (!config) return null;
4031
+ const creds = readCredentials(context);
4032
+ if (!creds) return null;
4033
+ return remintToken(context, config, creds);
4012
4034
  }
4013
4035
  async function probeCredentials(context, roleArn) {
4014
4036
  const cached = readCredentials(context);
@@ -4376,7 +4398,9 @@ __export(registry_identity_exports, {
4376
4398
  isReservedRegistryContext: () => isReservedRegistryContext,
4377
4399
  logRegistryIdentity: () => logRegistryIdentity,
4378
4400
  readRegistrySession: () => readRegistrySession,
4401
+ refreshRegistrySession: () => refreshRegistrySession,
4379
4402
  registrySessionCandidates: () => registrySessionCandidates,
4403
+ registryTokenRoles: () => registryTokenRoles,
4380
4404
  resolveRegistryIdentity: () => resolveRegistryIdentity
4381
4405
  });
4382
4406
  function isReservedRegistryContext(context) {
@@ -4480,6 +4504,22 @@ async function ensureRegistrySession(opts) {
4480
4504
  expiresAt: creds.expiresAt
4481
4505
  };
4482
4506
  }
4507
+ function registryTokenRoles(idToken) {
4508
+ if (!idToken) return [];
4509
+ try {
4510
+ return projectRoleKeys(decodeJwtPayload(idToken)).sort();
4511
+ } catch {
4512
+ return [];
4513
+ }
4514
+ }
4515
+ async function refreshRegistrySession(context) {
4516
+ const before = registryTokenRoles(readCredentials(context)?.idToken);
4517
+ const idToken = await forceRefreshToken(context);
4518
+ if (!idToken) return { reminted: false, rolesChanged: false };
4519
+ const after = registryTokenRoles(idToken);
4520
+ const same = after.length === before.length && after.every((role, i) => role === before[i]);
4521
+ return { reminted: true, rolesChanged: !same };
4522
+ }
4483
4523
  function clearRegistrySession() {
4484
4524
  clearCredentials(REGISTRY_CREDENTIAL_KEY);
4485
4525
  clearContextConfig(REGISTRY_CREDENTIAL_KEY);
@@ -4508,6 +4548,7 @@ var init_registry_identity = __esm({
4508
4548
  "libs/mesh-cli/src/utils/registry-identity.ts"() {
4509
4549
  "use strict";
4510
4550
  init_login();
4551
+ init_aws_auth();
4511
4552
  init_first_party_contexts();
4512
4553
  init_registry_broker();
4513
4554
  init_errors();
@@ -4985,16 +5026,20 @@ function selectRoleForCaller(idToken, options) {
4985
5026
  const adminRoles = options.adminClaimRoles ?? ["mesh.platform:admin"];
4986
5027
  const claims = decodeJwtPayload2(idToken);
4987
5028
  if (!claims) return options.defaultRole;
5029
+ const claimedRoles = projectRoleKeys(claims);
5030
+ return adminRoles.some((target) => claimedRoles.includes(target)) ? options.adminRole : options.defaultRole;
5031
+ }
5032
+ function projectRoleKeys(claims) {
5033
+ const names = /* @__PURE__ */ new Set();
4988
5034
  for (const [key, value] of Object.entries(claims)) {
4989
5035
  if (!key.startsWith("urn:zitadel:iam:org:project:")) continue;
4990
5036
  if (!key.endsWith(":roles")) continue;
4991
- if (!value || typeof value !== "object") continue;
4992
- const claimedRoles = Object.keys(value);
4993
- for (const target of adminRoles) {
4994
- if (claimedRoles.includes(target)) return options.adminRole;
5037
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
5038
+ for (const name of Object.keys(value)) {
5039
+ if (name) names.add(name);
4995
5040
  }
4996
5041
  }
4997
- return options.defaultRole;
5042
+ return [...names];
4998
5043
  }
4999
5044
  async function resolveAwsCredentials(roleArn, appRoot, stack) {
5000
5045
  const roleName = roleArn.split("/").pop() ?? roleArn;
@@ -10748,6 +10793,11 @@ function scanApp(root, appRel) {
10748
10793
  for (const f of files) hit(code, rel(root, f), why);
10749
10794
  };
10750
10795
  anti("IAC_GRANTS", RE_IAC_GRANT, "per-user role grant baked into IaC \u2014 grants belong in the Hub (Access \u2192 People), not in a config redeploy");
10796
+ anti(
10797
+ "POINTER_PROJECT_OVERRIDE",
10798
+ RE_POINTER_OVERRIDE,
10799
+ "AppAuthzPointer is given a `zitadel:` override \u2014 an app binds its project with AppEnvironment's zitadelAppProjectId so every consumer of env.zitadel agrees; the override is reserved for the Hub"
10800
+ );
10751
10801
  anti(
10752
10802
  "PASSWORD_STORE",
10753
10803
  RE_PASSWORD,
@@ -10857,7 +10907,7 @@ function registerAppCommands(program2) {
10857
10907
  }
10858
10908
  });
10859
10909
  }
10860
- var APP_CHECK_RULES, APP_CHECK_CODES, SRC_EXT, SKIP_DIRS, NON_SERVICE_DIRS, RE_HTML, RE_OIDC, RE_COOKIE, RE_LOGGER, RE_EXPOSURE, RE_POINTER, RE_METADATA, RE_IAC_GRANT, RE_PASSWORD, RE_ALLOWLIST, RE_USERS_TABLE;
10910
+ var APP_CHECK_RULES, APP_CHECK_CODES, SRC_EXT, SKIP_DIRS, NON_SERVICE_DIRS, RE_HTML, RE_OIDC, RE_COOKIE, RE_LOGGER, RE_EXPOSURE, RE_POINTER, RE_METADATA, RE_IAC_GRANT, RE_POINTER_OVERRIDE, RE_PASSWORD, RE_ALLOWLIST, RE_USERS_TABLE;
10861
10911
  var init_app_check = __esm({
10862
10912
  "libs/mesh-cli/src/commands/app-check.ts"() {
10863
10913
  "use strict";
@@ -10929,6 +10979,13 @@ var init_app_check = __esm({
10929
10979
  remediation: "remove the per-user grant map; grant roles from the Hub (App \u2192 Access \u2192 People)",
10930
10980
  scope: "app"
10931
10981
  },
10982
+ POINTER_PROJECT_OVERRIDE: {
10983
+ gate: "H",
10984
+ title: "Pointer publishes the env's project",
10985
+ severity: "advisory",
10986
+ remediation: "drop `zitadel:` from AppAuthzPointer and pass `zitadelAppProjectId: identity.projectId` to AppEnvironment \u2014 the override is the Hub's",
10987
+ scope: "app"
10988
+ },
10932
10989
  PASSWORD_STORE: {
10933
10990
  gate: "H",
10934
10991
  title: "No app-side credentials",
@@ -10976,6 +11033,7 @@ var init_app_check = __esm({
10976
11033
  RE_POINTER = /AppAuthzPointer/;
10977
11034
  RE_METADATA = /compileOpsHubMetadata|ops-hub-metadata|SpiceDBSchema/;
10978
11035
  RE_IAC_GRANT = /userId: *"[0-9]{6,}"/;
11036
+ RE_POINTER_OVERRIDE = /\bzitadel: *\{\s*projectId\b/;
10979
11037
  RE_PASSWORD = /(^|[^a-z])(bcrypt|argon2)|password_hash|passwordHash|hashPassword|temporaryPassword.*(send|mail)|(send|mail).*temporaryPassword/;
10980
11038
  RE_ALLOWLIST = /ADMIN_EMAILS|ALLOWED_EMAILS|allowedEmails|adminEmails/;
10981
11039
  RE_USERS_TABLE = /create table (if not exists )?"?(users|roles|user_roles|permissions)"?/i;
@@ -12214,6 +12272,7 @@ __export(create_app_exports, {
12214
12272
  PLATFORM_MONOREPO_NAME: () => PLATFORM_MONOREPO_NAME,
12215
12273
  bootstrapAppsRepo: () => bootstrapAppsRepo,
12216
12274
  copyTemplate: () => copyTemplate,
12275
+ describeNoAppsHome: () => describeNoAppsHome,
12217
12276
  ensureRegistryAccess: () => ensureRegistryAccess,
12218
12277
  ensureWorkspaceGlobs: () => ensureWorkspaceGlobs,
12219
12278
  generateComposableApp: () => generateComposableApp,
@@ -12403,6 +12462,18 @@ function parsePrimitives(input2) {
12403
12462
  }
12404
12463
  return selected;
12405
12464
  }
12465
+ function describeNoAppsHome(cwd, tenant, baseDir, test) {
12466
+ if (test || isInsidePlatformMonorepo(cwd)) {
12467
+ return {
12468
+ message: `Tenant directory not found: ${baseDir}/${tenant}/`,
12469
+ hint: "Create the tenant directory first, or run from within it."
12470
+ };
12471
+ }
12472
+ return {
12473
+ message: `This directory is not a Mesh apps repo \u2014 no apps/ here${fs23.existsSync(path25.join(cwd, ".git")) ? "" : " and it is not a git repo"}.`,
12474
+ hint: `Run: mesh init (turns this folder into your ${tenant}-mesh-apps repo), or cd into that repo and re-run mesh create-app.`
12475
+ };
12476
+ }
12406
12477
  function resolveAppDir(cwd, tenant, name, test) {
12407
12478
  const baseDir = test ? "tests/tenants" : "tenants";
12408
12479
  const possiblePaths = test ? [path25.join(cwd, baseDir, tenant, "apps")] : [
@@ -12414,8 +12485,9 @@ function resolveAppDir(cwd, tenant, name, test) {
12414
12485
  if (!appsDir) {
12415
12486
  appsDir = path25.join(cwd, baseDir, tenant, "apps");
12416
12487
  if (!fs23.existsSync(path25.join(cwd, baseDir, tenant))) {
12417
- logError(`Tenant directory not found: ${baseDir}/${tenant}/`);
12418
- logInfo("Create the tenant directory first, or run from within it.");
12488
+ const { message, hint } = describeNoAppsHome(cwd, tenant, baseDir, test);
12489
+ logError(message);
12490
+ logInfo(hint);
12419
12491
  process.exit(1);
12420
12492
  }
12421
12493
  if (!fs23.existsSync(appsDir)) {
@@ -16159,6 +16231,7 @@ __export(registry_exports, {
16159
16231
  resolvePublisherRoleArn: () => resolvePublisherRoleArn,
16160
16232
  runRegistryLogin: () => runRegistryLogin,
16161
16233
  runRegistryStatus: () => runRegistryStatus,
16234
+ shouldRemintAfter: () => shouldRemintAfter,
16162
16235
  shouldRepairUserNpmrc: () => shouldRepairUserNpmrc
16163
16236
  });
16164
16237
  import { execFileSync as execFileSync24 } from "child_process";
@@ -16422,6 +16495,9 @@ function describeBrokerFailure(failure) {
16422
16495
  function registrySignInAllowed(opts, hasTty = Boolean(process.stdin.isTTY && process.stdout.isTTY)) {
16423
16496
  return Boolean(opts.device) || hasTty;
16424
16497
  }
16498
+ function shouldRemintAfter(failure) {
16499
+ return failure.kind === "not-authorized";
16500
+ }
16425
16501
  async function tryBrokerLogin(opts) {
16426
16502
  if (opts.broker === false) return { outcome: { kind: "skipped-flag", flag: "--no-broker" } };
16427
16503
  if (opts.ci) return { outcome: { kind: "skipped-flag", flag: "--ci" } };
@@ -16461,6 +16537,13 @@ async function tryBrokerLogin(opts) {
16461
16537
  result = await requestGrant(session.context, identity);
16462
16538
  }
16463
16539
  }
16540
+ if (!result.ok && shouldRemintAfter(result.failure)) {
16541
+ const { rolesChanged } = await refreshRegistrySession(session.context);
16542
+ if (rolesChanged) {
16543
+ logInfo("Your sign-in now carries a role it did not have \u2014 retrying\u2026");
16544
+ result = await requestGrant(session.context, identity);
16545
+ }
16546
+ }
16464
16547
  if (result.ok) return { grant: result.grant };
16465
16548
  const { message, hint, fatal } = describeBrokerFailure(result.failure);
16466
16549
  if (fatal) {
@@ -16810,7 +16893,7 @@ var init_registry = __esm({
16810
16893
  this.name = "RegistryNotAuthorizedError";
16811
16894
  }
16812
16895
  };
16813
- NOT_AUTHORIZED_RERUN = "Once granted, run: mesh registry login (your sign-in is kept; no second browser trip)";
16896
+ NOT_AUTHORIZED_RERUN = "Once granted, run: mesh registry login (it re-mints your sign-in; still refused? mesh registry logout && mesh registry login)";
16814
16897
  CONTEXT_IGNORED_NOTICE = "The registry is global \u2014 the context argument is no longer needed (ignored).";
16815
16898
  }
16816
16899
  });
@@ -16818,6 +16901,7 @@ var init_registry = __esm({
16818
16901
  // libs/mesh-cli/src/commands/init/wizard.ts
16819
16902
  var wizard_exports = {};
16820
16903
  __export(wizard_exports, {
16904
+ INIT_REPO_FIX: () => INIT_REPO_FIX,
16821
16905
  INTERRUPTED_EXIT_CODE: () => INTERRUPTED_EXIT_CODE,
16822
16906
  NO_SESSION_NO_TTY_MESSAGE: () => NO_SESSION_NO_TTY_MESSAGE,
16823
16907
  TENANT_REQUIRED_MESSAGE: () => TENANT_REQUIRED_MESSAGE,
@@ -16826,6 +16910,7 @@ __export(wizard_exports, {
16826
16910
  describeMode: () => describeMode,
16827
16911
  registryStep: () => registryStep,
16828
16912
  renderWizardSummary: () => renderWizardSummary,
16913
+ repoStep: () => repoStep,
16829
16914
  resolveAnswers: () => resolveAnswers,
16830
16915
  runInitWizard: () => runInitWizard,
16831
16916
  runWizardSteps: () => runWizardSteps,
@@ -16835,12 +16920,15 @@ __export(wizard_exports, {
16835
16920
  });
16836
16921
  import * as fs30 from "fs";
16837
16922
  import * as path37 from "path";
16923
+ import { execFileSync as execFileSync25 } from "child_process";
16838
16924
  import chalk4 from "chalk";
16839
16925
  function wizardExitCode(steps) {
16840
16926
  return steps.some((s) => s.status === "fail") ? 1 : 0;
16841
16927
  }
16842
- function wizardNextCommands(mode) {
16843
- return mode === "local" ? ["mesh create-app"] : ["mesh create-app", "mesh deploy up # from the app directory, once it exists"];
16928
+ function wizardNextCommands(mode, steps = []) {
16929
+ const repo = steps.find((s) => s.name === STEP_LABELS.repo);
16930
+ const first = repo && repo.status !== "pass" && repo.fix ? repo.fix : "mesh create-app";
16931
+ return mode === "local" ? [first] : [first, "mesh deploy up # from the app directory, once it exists"];
16844
16932
  }
16845
16933
  function stepBlocks(result) {
16846
16934
  return result.status === "fail" && result.blocking !== false;
@@ -16889,12 +16977,18 @@ function classifyRepo(cwd) {
16889
16977
  if (shouldBootstrapAppsRepo(cwd)) return { kind: "empty-apps-repo", root: cwd };
16890
16978
  const root = resolveTargetRoot(cwd);
16891
16979
  const inRepo = fs30.existsSync(path37.join(root, ".git"));
16892
- if (!inRepo) return { kind: "no-repo", root };
16980
+ if (!inRepo) {
16981
+ const hasContent = fs30.readdirSync(cwd).some((entry) => !entry.startsWith("."));
16982
+ return { kind: hasContent ? "no-repo" : "empty-dir", root: cwd };
16983
+ }
16893
16984
  const hasWorkspace = fs30.existsSync(path37.join(root, "pnpm-workspace.yaml")) || fs30.existsSync(path37.join(root, "pnpm-lock.yaml"));
16894
16985
  const hasApps = fs30.existsSync(path37.join(root, "apps")) || fs30.existsSync(path37.join(root, "tenants"));
16895
16986
  if (hasWorkspace || hasApps) return { kind: "apps-repo", root };
16896
16987
  return { kind: "other-repo", root };
16897
16988
  }
16989
+ function gitInit(dir) {
16990
+ execFileSync25("git", ["init", "-q"], { cwd: dir, stdio: ["ignore", "ignore", "pipe"] });
16991
+ }
16898
16992
  async function runWizardSteps(ctx, steps) {
16899
16993
  const results = [];
16900
16994
  for (const step of steps) {
@@ -16986,7 +17080,7 @@ async function runInitWizard(opts, deps = {}) {
16986
17080
  const written = writeMeshJson(root, { tenant, platform: mode === "local" ? "local" : mode.platform });
16987
17081
  logInfo(`Recorded tenant + mode in ${written}`);
16988
17082
  }
16989
- const outcome = { tenant, mode, steps, next: wizardNextCommands(mode) };
17083
+ const outcome = { tenant, mode, steps, next: wizardNextCommands(mode, steps) };
16990
17084
  const code = wizardExitCode(steps);
16991
17085
  if (opts.json) {
16992
17086
  console.log = origLog;
@@ -17008,7 +17102,7 @@ async function runInitWizard(opts, deps = {}) {
17008
17102
  console.log = origLog;
17009
17103
  }
17010
17104
  }
17011
- var NO_SESSION_NO_TTY_MESSAGE, TENANT_REQUIRED_MESSAGE, INTERRUPTED_EXIT_CODE, STEP_LABELS, registryStep, platformStep, repoStep, skillsStep, WIZARD_STEPS;
17105
+ var NO_SESSION_NO_TTY_MESSAGE, TENANT_REQUIRED_MESSAGE, INTERRUPTED_EXIT_CODE, STEP_LABELS, registryStep, platformStep, INIT_REPO_FIX, repoStep, skillsStep, WIZARD_STEPS;
17012
17106
  var init_wizard = __esm({
17013
17107
  "libs/mesh-cli/src/commands/init/wizard.ts"() {
17014
17108
  "use strict";
@@ -17112,6 +17206,7 @@ var init_wizard = __esm({
17112
17206
  };
17113
17207
  }
17114
17208
  };
17209
+ INIT_REPO_FIX = "git init && mesh init";
17115
17210
  repoStep = {
17116
17211
  name: "repo",
17117
17212
  async run(ctx) {
@@ -17121,11 +17216,34 @@ var init_wizard = __esm({
17121
17216
  switch (kind) {
17122
17217
  case "platform-monorepo":
17123
17218
  return { name, status: "skip", detail: "inside mesh-platform \u2014 apps here link workspace packages; nothing to set up" };
17219
+ case "empty-dir": {
17220
+ const go = ctx.yes || !ctx.interactive ? true : await ctx.prompts.confirm({
17221
+ message: `This folder is not a git repo \u2014 initialize ${root} as your ${ctx.tenant}-mesh-apps repo here?`,
17222
+ default: true
17223
+ });
17224
+ if (!go) {
17225
+ return { name, status: "skip", detail: "folder left as is", fix: `cd <your ${ctx.tenant}-mesh-apps clone> && mesh init` };
17226
+ }
17227
+ try {
17228
+ (ctx.seams?.gitInit ?? gitInit)(root);
17229
+ } catch (err) {
17230
+ const why = err instanceof Error && "stderr" in err && err.stderr ? String(err.stderr).trim() : "";
17231
+ return {
17232
+ name,
17233
+ status: "fail",
17234
+ detail: `git init failed \u2014 is git installed and ${root} writable?${why ? ` (${why})` : ""}`,
17235
+ fix: INIT_REPO_FIX
17236
+ };
17237
+ }
17238
+ const created = bootstrapAppsRepo(root, ctx.tenant);
17239
+ return { name, status: "pass", detail: `initialized a git repo and bootstrapped the apps repo: ${created.join(", ")}` };
17240
+ }
17124
17241
  case "no-repo":
17125
17242
  return {
17126
17243
  name,
17127
17244
  status: "skip",
17128
- detail: `not in a git repo \u2014 clone (or git init) your ${ctx.tenant}-mesh-apps repo and re-run mesh init there`
17245
+ detail: `not in a git repo, and this folder already holds files \u2014 clone (or git init) your ${ctx.tenant}-mesh-apps repo and re-run mesh init there`,
17246
+ fix: INIT_REPO_FIX
17129
17247
  };
17130
17248
  case "other-repo":
17131
17249
  return {
@@ -17464,7 +17582,7 @@ var init_init = __esm({
17464
17582
  });
17465
17583
 
17466
17584
  // libs/mesh-cli/src/commands/install-shim.ts
17467
- import { execFileSync as execFileSync25 } from "child_process";
17585
+ import { execFileSync as execFileSync26 } from "child_process";
17468
17586
  import * as fs32 from "fs";
17469
17587
  import * as os10 from "os";
17470
17588
  import * as path39 from "path";
@@ -17577,7 +17695,7 @@ function registerInstallShimCommand(program2) {
17577
17695
  let status = 0;
17578
17696
  let ok = true;
17579
17697
  try {
17580
- stdout = execFileSync25(target, ["--help"], {
17698
+ stdout = execFileSync26(target, ["--help"], {
17581
17699
  cwd: process.cwd(),
17582
17700
  encoding: "utf8",
17583
17701
  stdio: ["ignore", "pipe", "pipe"]
@@ -17624,7 +17742,7 @@ var init_install_shim = __esm({
17624
17742
  });
17625
17743
 
17626
17744
  // libs/mesh-cli/src/commands/local/hub-local.ts
17627
- import { execFile as execFile3, execFileSync as execFileSync26 } from "child_process";
17745
+ import { execFile as execFile3, execFileSync as execFileSync27 } from "child_process";
17628
17746
  import * as fs33 from "fs";
17629
17747
  import * as os11 from "os";
17630
17748
  import * as path40 from "path";
@@ -17644,7 +17762,7 @@ function npmrcPath() {
17644
17762
  }
17645
17763
  function imageExists(tag) {
17646
17764
  try {
17647
- execFileSync26("docker", ["image", "inspect", tag], { stdio: ["ignore", "pipe", "pipe"] });
17765
+ execFileSync27("docker", ["image", "inspect", tag], { stdio: ["ignore", "pipe", "pipe"] });
17648
17766
  return true;
17649
17767
  } catch {
17650
17768
  return false;
@@ -17654,7 +17772,7 @@ function ensureHubAuthImage() {
17654
17772
  if (imageExists(HUB_AUTH_IMAGE)) return;
17655
17773
  logInfo(`Building ${HUB_AUTH_IMAGE} (Hub auth proxy)\u2026`);
17656
17774
  const hubStackDir = path40.join(findPackageRoot(), "stack", "hub");
17657
- execFileSync26(
17775
+ execFileSync27(
17658
17776
  "docker",
17659
17777
  ["build", "-f", path40.join(hubStackDir, "Dockerfile.auth"), "-t", HUB_AUTH_IMAGE, hubStackDir],
17660
17778
  { stdio: ["ignore", "inherit", "inherit"], env: { ...process.env, DOCKER_BUILDKIT: "1" } }
@@ -17668,7 +17786,7 @@ function hasRegistryAuth() {
17668
17786
  function localHubVersion() {
17669
17787
  const versions = HUB_IMAGES.map((name) => {
17670
17788
  try {
17671
- const out = execFileSync26("docker", ["images", name, "--format", "{{.Tag}}"], {
17789
+ const out = execFileSync27("docker", ["images", name, "--format", "{{.Tag}}"], {
17672
17790
  encoding: "utf-8",
17673
17791
  stdio: ["ignore", "pipe", "pipe"]
17674
17792
  });
@@ -17747,7 +17865,7 @@ async function ensureHubImages() {
17747
17865
  const context = path40.join(cacheDir(), `context-${version}`);
17748
17866
  fs33.rmSync(context, { recursive: true, force: true });
17749
17867
  fs33.mkdirSync(context, { recursive: true });
17750
- execFileSync26("tar", ["-xzf", tarball, "-C", context, "--strip-components", "1"], {
17868
+ execFileSync27("tar", ["-xzf", tarball, "-C", context, "--strip-components", "1"], {
17751
17869
  stdio: ["ignore", "pipe", "pipe"]
17752
17870
  });
17753
17871
  const hubStackDir = path40.join(findPackageRoot(), "stack", "hub");
@@ -17758,7 +17876,7 @@ async function ensureHubImages() {
17758
17876
  const tag = `${name}:${version}`;
17759
17877
  if (imageExists(tag)) continue;
17760
17878
  logInfo(`Building ${tag} from the published tarball\u2026`);
17761
- execFileSync26(
17879
+ execFileSync27(
17762
17880
  "docker",
17763
17881
  [
17764
17882
  "build",
@@ -17776,6 +17894,32 @@ async function ensureHubImages() {
17776
17894
  }
17777
17895
  return version;
17778
17896
  }
17897
+ function tarballNameForImageVersion(version) {
17898
+ if (version.endsWith("-src")) return null;
17899
+ return `mesh-tech-hub-${version.replace(/-r\d+$/, "")}.tgz`;
17900
+ }
17901
+ function readHubCompiledAuthz(version) {
17902
+ const context = path40.join(cacheDir(), `context-${version}`);
17903
+ const file = path40.join(context, HUB_COMPILED_AUTHZ_REL);
17904
+ if (!fs33.existsSync(file)) {
17905
+ const tarball = tarballNameForImageVersion(version);
17906
+ if (!tarball || !fs33.existsSync(path40.join(cacheDir(), tarball))) return null;
17907
+ fs33.mkdirSync(context, { recursive: true });
17908
+ try {
17909
+ execFileSync27(
17910
+ "tar",
17911
+ ["-xzf", path40.join(cacheDir(), tarball), "-C", context, "--strip-components", "1", `package/${HUB_COMPILED_AUTHZ_REL}`],
17912
+ { stdio: ["ignore", "pipe", "pipe"] }
17913
+ );
17914
+ } catch {
17915
+ return null;
17916
+ }
17917
+ if (!fs33.existsSync(file)) return null;
17918
+ }
17919
+ const parsed = JSON.parse(fs33.readFileSync(file, "utf-8"));
17920
+ if (typeof parsed.zed !== "string" || !parsed.metadata || typeof parsed.metadata !== "object") return null;
17921
+ return { zed: parsed.zed, metadata: parsed.metadata };
17922
+ }
17779
17923
  function readWorkspaceCatalog(repoRoot2) {
17780
17924
  const text = fs33.readFileSync(path40.join(repoRoot2, "pnpm-workspace.yaml"), "utf-8");
17781
17925
  const marker = "\ncatalog:\n";
@@ -17790,7 +17934,7 @@ function readWorkspaceCatalog(repoRoot2) {
17790
17934
  return catalog;
17791
17935
  }
17792
17936
  function normalizeHubManifests(contextDir, catalog) {
17793
- const DEP_FIELDS = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"];
17937
+ const DEP_FIELDS = ["dependencies", "optionalDependencies", "peerDependencies"];
17794
17938
  const touched = [];
17795
17939
  for (const entry of fs33.readdirSync(contextDir, { withFileTypes: true })) {
17796
17940
  if (!entry.isDirectory()) continue;
@@ -17798,6 +17942,10 @@ function normalizeHubManifests(contextDir, catalog) {
17798
17942
  if (!fs33.existsSync(manifest)) continue;
17799
17943
  const pkg = JSON.parse(fs33.readFileSync(manifest, "utf-8"));
17800
17944
  let changed = false;
17945
+ if (pkg.devDependencies) {
17946
+ delete pkg.devDependencies;
17947
+ changed = true;
17948
+ }
17801
17949
  for (const field of DEP_FIELDS) {
17802
17950
  const deps = pkg[field];
17803
17951
  if (!deps) continue;
@@ -17852,7 +18000,7 @@ async function buildHubImagesFromSource(repoRoot2) {
17852
18000
  await execFileAsync2("pnpm", ["pack", "--pack-destination", context], { cwd: hubDir, maxBuffer: 64 * 1024 * 1024 });
17853
18001
  const tarball = fs33.readdirSync(context).find((f) => f.endsWith(".tgz"));
17854
18002
  if (!tarball) throw new MeshCliError("pnpm pack produced no tarball for apps/hub");
17855
- execFileSync26("tar", ["-xzf", path40.join(context, tarball), "-C", context, "--strip-components", "1"], {
18003
+ execFileSync27("tar", ["-xzf", path40.join(context, tarball), "-C", context, "--strip-components", "1"], {
17856
18004
  stdio: ["ignore", "pipe", "pipe"]
17857
18005
  });
17858
18006
  const rewritten = normalizeHubManifests(context, readWorkspaceCatalog(repoRoot2));
@@ -17864,7 +18012,7 @@ async function buildHubImagesFromSource(repoRoot2) {
17864
18012
  ]) {
17865
18013
  const tag = `${name}:${version}`;
17866
18014
  logInfo(`Building ${tag} from source\u2026`);
17867
- execFileSync26(
18015
+ execFileSync27(
17868
18016
  "docker",
17869
18017
  ["build", "-f", path40.join(hubStackDir, dockerfile), "-t", tag, "--secret", `id=npmrc,src=${npmrc}`, context],
17870
18018
  { stdio: ["ignore", "inherit", "inherit"], env: { ...process.env, DOCKER_BUILDKIT: "1" } }
@@ -17873,7 +18021,7 @@ async function buildHubImagesFromSource(repoRoot2) {
17873
18021
  }
17874
18022
  return version;
17875
18023
  }
17876
- var execFileAsync2, HUB_PACKAGE, HUB_IMAGES, LOCAL_IMAGE_REV, HUB_AUTH_IMAGE;
18024
+ var execFileAsync2, HUB_PACKAGE, HUB_IMAGES, LOCAL_IMAGE_REV, HUB_AUTH_IMAGE, HUB_COMPILED_AUTHZ_REL;
17877
18025
  var init_hub_local = __esm({
17878
18026
  "libs/mesh-cli/src/commands/local/hub-local.ts"() {
17879
18027
  "use strict";
@@ -17887,6 +18035,66 @@ var init_hub_local = __esm({
17887
18035
  HUB_IMAGES = ["mesh-local-hub-api", "mesh-local-hub-ui"];
17888
18036
  LOCAL_IMAGE_REV = "r2";
17889
18037
  HUB_AUTH_IMAGE = "mesh-local-hub-auth:v7.7.1-r1";
18038
+ HUB_COMPILED_AUTHZ_REL = "api/dist/authz/compiled.json";
18039
+ }
18040
+ });
18041
+
18042
+ // libs/mesh-cli/src/commands/local/seed-hub-catalog.ts
18043
+ function withHubCatalogRefs(pointer, metadataRef) {
18044
+ return {
18045
+ spicedb: { instanceRefs: [] },
18046
+ ...pointer,
18047
+ opsHubMetadataRef: metadataRef,
18048
+ mode: typeof pointer.mode === "string" ? pointer.mode : "policy-engine"
18049
+ };
18050
+ }
18051
+ async function publishHubAuthzCatalog(compiled, awsConfig) {
18052
+ const { SSMClient: SSMClient5, GetParameterCommand: GetParameterCommand2, PutParameterCommand } = await import("@aws-sdk/client-ssm");
18053
+ const ssm = new SSMClient5(awsConfig);
18054
+ await ssm.send(
18055
+ new PutParameterCommand({
18056
+ Name: HUB_OPS_HUB_METADATA_PARAM,
18057
+ Type: "String",
18058
+ // The blob is ~7.5 KB — past the 4 KB standard tier, within Advanced (8 KB),
18059
+ // the tier the platform's Export uses for the same param.
18060
+ Tier: "Advanced",
18061
+ Overwrite: true,
18062
+ Value: JSON.stringify(compiled.metadata),
18063
+ Description: "Hub role catalog \u2014 ops-hub-metadata (local analog of MeshHub's SpiceDBSchema export)"
18064
+ })
18065
+ );
18066
+ let current = {};
18067
+ try {
18068
+ const existing = await ssm.send(new GetParameterCommand2({ Name: HUB_AUTHZ_POINTER_PARAM }));
18069
+ current = JSON.parse(existing.Parameter?.Value ?? "{}");
18070
+ } catch {
18071
+ }
18072
+ await ssm.send(
18073
+ new PutParameterCommand({
18074
+ Name: HUB_AUTHZ_POINTER_PARAM,
18075
+ Type: "String",
18076
+ Overwrite: true,
18077
+ Value: JSON.stringify(withHubCatalogRefs(current, HUB_OPS_HUB_METADATA_PARAM)),
18078
+ Description: "Hub authz pointer (local analog of the platform Pulumi program)"
18079
+ })
18080
+ );
18081
+ return { bundles: catalogBundleNames(compiled.metadata) };
18082
+ }
18083
+ function catalogBundleNames(metadata) {
18084
+ const bundles = metadata.bundles;
18085
+ if (Array.isArray(bundles)) {
18086
+ return bundles.map((b) => b && typeof b === "object" && typeof b.name === "string" ? b.name : null).filter((n) => n !== null);
18087
+ }
18088
+ if (bundles && typeof bundles === "object") return Object.keys(bundles);
18089
+ return [];
18090
+ }
18091
+ var HUB_AUTHZ_POINTER_PARAM, HUB_OPS_HUB_METADATA_PARAM;
18092
+ var init_seed_hub_catalog = __esm({
18093
+ "libs/mesh-cli/src/commands/local/seed-hub-catalog.ts"() {
18094
+ "use strict";
18095
+ init_seed();
18096
+ HUB_AUTHZ_POINTER_PARAM = `/mesh-platform/${LOCAL_TENANT}/${LOCAL_ENV}/apps/hub/stacks/local/authz`;
18097
+ HUB_OPS_HUB_METADATA_PARAM = `${HUB_AUTHZ_POINTER_PARAM}/ops-hub-metadata`;
17890
18098
  }
17891
18099
  });
17892
18100
 
@@ -18063,6 +18271,17 @@ Re-running start from here may recreate shared containers with this checkout's c
18063
18271
  logInfo("Seeding Zitadel (Platform project, Mesh CLI app, Hub auth, test users)\u2026");
18064
18272
  const zitadel = await seedZitadel(LOCAL_AWS_CONFIG);
18065
18273
  hubAuth = zitadel.hubAuth;
18274
+ if (hubVersion) {
18275
+ const compiled = readHubCompiledAuthz(hubVersion);
18276
+ if (compiled) {
18277
+ const { bundles } = await publishHubAuthzCatalog(compiled, LOCAL_AWS_CONFIG);
18278
+ logSuccess(`Hub role catalog seeded: ${bundles.length} role(s) (${bundles.join(", ")})`);
18279
+ } else {
18280
+ logWarn(
18281
+ `Hub v${hubVersion} ships no compiled role catalog (api/dist/authz/compiled.json) \u2014 Users \u2192 Roles will be empty. Hub \u2265 2.1.0 publishes one.`
18282
+ );
18283
+ }
18284
+ }
18066
18285
  try {
18067
18286
  const reconciled = await reconcileRegistryFromZitadel();
18068
18287
  if (reconciled.tenants.length > 0) {
@@ -18230,6 +18449,7 @@ var init_local = __esm({
18230
18449
  init_auth_provision();
18231
18450
  init_seed();
18232
18451
  init_seed_zitadel();
18452
+ init_seed_hub_catalog();
18233
18453
  WAIT_TIMEOUT_MS = 18e4;
18234
18454
  WAIT_POLL_MS = 3e3;
18235
18455
  }
@@ -19424,7 +19644,7 @@ var init_site = __esm({
19424
19644
  });
19425
19645
 
19426
19646
  // libs/mesh-cli/src/commands/stack.ts
19427
- import { execFileSync as execFileSync27 } from "child_process";
19647
+ import { execFileSync as execFileSync28 } from "child_process";
19428
19648
  import * as path42 from "path";
19429
19649
  import * as fs35 from "fs";
19430
19650
  import { parse as parseYaml5 } from "yaml";
@@ -19517,7 +19737,7 @@ function readBaseConfigFromYaml(appRoot, stack) {
19517
19737
  }
19518
19738
  function getGitHubUsername() {
19519
19739
  try {
19520
- const result = execFileSync27("gh", ["api", "user", "--jq", ".login"], {
19740
+ const result = execFileSync28("gh", ["api", "user", "--jq", ".login"], {
19521
19741
  encoding: "utf-8",
19522
19742
  stdio: ["pipe", "pipe", "pipe"]
19523
19743
  });
@@ -19526,7 +19746,7 @@ function getGitHubUsername() {
19526
19746
  } catch {
19527
19747
  }
19528
19748
  try {
19529
- const result = execFileSync27("git", ["config", "user.email"], {
19749
+ const result = execFileSync28("git", ["config", "user.email"], {
19530
19750
  encoding: "utf-8",
19531
19751
  stdio: ["pipe", "pipe", "pipe"]
19532
19752
  });
@@ -19612,7 +19832,7 @@ Specify which to base on: mesh stack init --from <stack>`
19612
19832
  if (!opts.adopt) {
19613
19833
  let existing = [];
19614
19834
  try {
19615
- const raw = execFileSync27("pulumi", ["stack", "ls", "--json"], {
19835
+ const raw = execFileSync28("pulumi", ["stack", "ls", "--json"], {
19616
19836
  cwd: appRoot,
19617
19837
  encoding: "utf-8",
19618
19838
  env: pulumiEnv,
@@ -19636,7 +19856,7 @@ Specify which to base on: mesh stack init --from <stack>`
19636
19856
  logInfo(`Using KMS secrets provider: ${secretsProvider}`);
19637
19857
  }
19638
19858
  try {
19639
- execFileSync27("pulumi", initArgs, {
19859
+ execFileSync28("pulumi", initArgs, {
19640
19860
  cwd: appRoot,
19641
19861
  env: pulumiEnv,
19642
19862
  stdio: "inherit"
@@ -19653,7 +19873,7 @@ Specify which to base on: mesh stack init --from <stack>`
19653
19873
  }
19654
19874
  }
19655
19875
  try {
19656
- execFileSync27("pulumi", ["stack", "select", newStack], {
19876
+ execFileSync28("pulumi", ["stack", "select", newStack], {
19657
19877
  cwd: appRoot,
19658
19878
  env: pulumiEnv,
19659
19879
  stdio: ["pipe", "pipe", "pipe"]
@@ -19663,7 +19883,7 @@ Specify which to base on: mesh stack init --from <stack>`
19663
19883
  if (!configExists) {
19664
19884
  let baseConfig = {};
19665
19885
  try {
19666
- const raw = execFileSync27(
19886
+ const raw = execFileSync28(
19667
19887
  "pulumi",
19668
19888
  ["config", "--json", "--stack", baseStack],
19669
19889
  { cwd: appRoot, env: pulumiEnv, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
@@ -19681,19 +19901,19 @@ Specify which to base on: mesh stack init --from <stack>`
19681
19901
  if (key === "mesh:deploy") continue;
19682
19902
  try {
19683
19903
  if (entry.objectValue !== void 0) {
19684
- execFileSync27(
19904
+ execFileSync28(
19685
19905
  "pulumi",
19686
19906
  ["config", "set", key, JSON.stringify(entry.objectValue)],
19687
19907
  { cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
19688
19908
  );
19689
19909
  } else if (entry.value === "true" || entry.value === "false") {
19690
- execFileSync27(
19910
+ execFileSync28(
19691
19911
  "pulumi",
19692
19912
  ["config", "set", "--type", "bool", key, entry.value],
19693
19913
  { cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
19694
19914
  );
19695
19915
  } else {
19696
- execFileSync27(
19916
+ execFileSync28(
19697
19917
  "pulumi",
19698
19918
  ["config", "set", key, entry.value],
19699
19919
  { cwd: appRoot, env: pulumiEnv, stdio: ["pipe", "pipe", "pipe"] }
@@ -19706,7 +19926,7 @@ Specify which to base on: mesh stack init --from <stack>`
19706
19926
  const baseEnv = readConfigBlockKey(appRoot, baseStack, "mesh:coreEnv") ?? (baseTenant && baseStack.startsWith(`${baseTenant}-`) ? baseStack.slice(baseTenant.length + 1) : baseStack);
19707
19927
  const setCfg = (args) => {
19708
19928
  try {
19709
- execFileSync27("pulumi", ["config", "set", ...args], {
19929
+ execFileSync28("pulumi", ["config", "set", ...args], {
19710
19930
  cwd: appRoot,
19711
19931
  env: pulumiEnv,
19712
19932
  stdio: ["pipe", "pipe", "pipe"]
@@ -19755,7 +19975,7 @@ Specify which to base on: mesh stack init --from <stack>`
19755
19975
  `Configured Pulumi.${newStack}.yaml (personal platform env on core '${baseEnv}'${opts.parentZone ? `, DNS zone ${newStack.startsWith(`${baseTenant}-`) ? newStack.slice(baseTenant.length + 1) : newStack}.${opts.parentZone}` : ""})`
19756
19976
  );
19757
19977
  } else {
19758
- execFileSync27("pulumi", ["config", "set", "--type", "bool", "mesh:deploy", "false"], {
19978
+ execFileSync28("pulumi", ["config", "set", "--type", "bool", "mesh:deploy", "false"], {
19759
19979
  cwd: appRoot,
19760
19980
  env: pulumiEnv,
19761
19981
  stdio: ["pipe", "pipe", "pipe"]
@@ -19785,7 +20005,7 @@ Specify which to base on: mesh stack init --from <stack>`
19785
20005
  const args = ["stack", "rm", name];
19786
20006
  if (opts.yes) args.push("--yes");
19787
20007
  try {
19788
- execFileSync27("pulumi", args, { cwd: appRoot, env: pulumiEnv, stdio: "inherit" });
20008
+ execFileSync28("pulumi", args, { cwd: appRoot, env: pulumiEnv, stdio: "inherit" });
19789
20009
  logSuccess(`Removed stack ${name}`);
19790
20010
  } catch (err) {
19791
20011
  process.exit(err.status ?? 1);
@@ -19997,12 +20217,12 @@ var init_recover_conversation = __esm({
19997
20217
  });
19998
20218
 
19999
20219
  // libs/mesh-cli/src/utils/temporal-codec.ts
20000
- import { execFileSync as execFileSync28 } from "child_process";
20220
+ import { execFileSync as execFileSync29 } from "child_process";
20001
20221
  import { webcrypto as crypto4 } from "node:crypto";
20002
20222
  function resolveTemporalEncodingKeyFromK8s(namespace) {
20003
20223
  const secretName = `${namespace}-temporal-encoding-key`;
20004
20224
  try {
20005
- const b64 = execFileSync28(
20225
+ const b64 = execFileSync29(
20006
20226
  "kubectl",
20007
20227
  [
20008
20228
  "get",
@@ -23342,7 +23562,7 @@ var init_src4 = __esm({
23342
23562
  import * as fs38 from "fs";
23343
23563
  import * as path45 from "path";
23344
23564
  import { createRequire as createRequire2 } from "module";
23345
- import { execFileSync as execFileSync29 } from "child_process";
23565
+ import { execFileSync as execFileSync30 } from "child_process";
23346
23566
  function resolveExtractorPath() {
23347
23567
  try {
23348
23568
  const require2 = createRequire2(import.meta.url);
@@ -23397,7 +23617,7 @@ for (const file of files) {
23397
23617
  process.stdout.write(JSON.stringify(results));
23398
23618
  `;
23399
23619
  try {
23400
- const result = execFileSync29("npx", ["tsx", "--eval", script], {
23620
+ const result = execFileSync30("npx", ["tsx", "--eval", script], {
23401
23621
  encoding: "utf-8",
23402
23622
  stdio: ["pipe", "pipe", "inherit"],
23403
23623
  maxBuffer: 10 * 1024 * 1024
@@ -23439,7 +23659,7 @@ for (const file of files) {
23439
23659
  process.stdout.write(JSON.stringify(results));
23440
23660
  `;
23441
23661
  try {
23442
- const result = execFileSync29("npx", ["tsx", "--eval", script], {
23662
+ const result = execFileSync30("npx", ["tsx", "--eval", script], {
23443
23663
  encoding: "utf-8",
23444
23664
  stdio: ["pipe", "pipe", "inherit"],
23445
23665
  maxBuffer: 10 * 1024 * 1024
@@ -23494,7 +23714,7 @@ for (const file of files) {
23494
23714
  process.stdout.write(JSON.stringify(results));
23495
23715
  `;
23496
23716
  try {
23497
- const result = execFileSync29("npx", ["tsx", "--eval", script], {
23717
+ const result = execFileSync30("npx", ["tsx", "--eval", script], {
23498
23718
  encoding: "utf-8",
23499
23719
  stdio: ["pipe", "pipe", "inherit"],
23500
23720
  maxBuffer: 10 * 1024 * 1024