@stll/oxlint-config 1.2.5 → 1.3.0

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.
@@ -298,7 +298,9 @@ network_run() (
298
298
  trap 'exit 143' TERM
299
299
  # Output goes to a file, never a pipe: package scripts may leave processes that keep
300
300
  # inherited descriptors open, and a pipe reader would wait for them past the command.
301
- timeout --signal=TERM --kill-after=5s "$seconds"s "$@" > "$network_log" 2>&1 || status=$?
301
+ # Input is never the terminal: timeout runs the command outside the foreground process
302
+ # group, where apt restoring terminal settings on a terminal stdin stops it for good.
303
+ timeout --signal=TERM --kill-after=5s "$seconds"s "$@" < /dev/null > "$network_log" 2>&1 || status=$?
302
304
  release_log_holders "$network_log"
303
305
  cat -- "$network_log" || fail 'Cannot capture network command output'
304
306
  [[ "$status" != 0 ]] || return 0
@@ -530,16 +532,32 @@ const parseEnvFile = (input) => {
530
532
  if (envFile.startsWith("/") || /^[A-Za-z]:/.test(envFile) || envFile.includes("\\") || /\p{Cc}/u.test(envFile) || envFile.split("/").some((part) => part === "" || part === "." || part === "..")) throw new Error("cloud.envFile must be a canonical repository-relative path");
531
533
  return envFile;
532
534
  };
535
+ const cloudPrepareScript = /^[a-z0-9][a-z0-9:._-]*$/;
536
+ const parsePrepare = (input) => {
537
+ if (input === void 0) return void 0;
538
+ if (typeof input !== "object" || input === null || Array.isArray(input)) throw new Error("cloud.prepare must be an object");
539
+ for (const key of Object.keys(input)) if (key !== "script" && key !== "seconds") throw new Error(`unsupported cloud.prepare key: ${key}`);
540
+ const script = "script" in input ? input.script : void 0;
541
+ if (typeof script !== "string" || !cloudPrepareScript.test(script)) throw new Error("cloud.prepare.script must name a package script");
542
+ const seconds = "seconds" in input ? input.seconds : void 0;
543
+ if (typeof seconds !== "number" || !Number.isInteger(seconds) || seconds < 1 || seconds > 900) throw new Error(`cloud.prepare.seconds must be an integer from 1 to 900`);
544
+ return {
545
+ script,
546
+ seconds
547
+ };
548
+ };
533
549
  /** Parse an explicit declaration without assuming services for undeclared repositories. */
534
550
  const parseCloudSetup = (input) => {
535
551
  if (input === void 0) return void 0;
536
552
  if (typeof input !== "object" || input === null || Array.isArray(input)) throw new Error("cloud must be an object");
537
- for (const key of Object.keys(input)) if (key !== "services" && key !== "install" && key !== "envFile" && key !== "rust" && key !== "tools") throw new Error(`unsupported cloud key: ${key}`);
553
+ for (const key of Object.keys(input)) if (key !== "services" && key !== "install" && key !== "envFile" && key !== "rust" && key !== "tools" && key !== "prepare") throw new Error(`unsupported cloud key: ${key}`);
538
554
  const rust = parseRust("rust" in input ? input.rust : void 0);
539
555
  const tools = parseTools("tools" in input ? input.tools : void 0);
556
+ const prepare = parsePrepare("prepare" in input ? input.prepare : void 0);
540
557
  const extensions = {
541
558
  ...rust === void 0 ? {} : { rust },
542
- ...tools === void 0 ? {} : { tools }
559
+ ...tools === void 0 ? {} : { tools },
560
+ ...prepare === void 0 ? {} : { prepare }
543
561
  };
544
562
  const selected = "services" in input ? input.services : [];
545
563
  if (!Array.isArray(selected)) throw new Error("cloud.services must be an array when provided");
@@ -594,7 +612,9 @@ service_process_matches() {
594
612
  owner="$(stat -c '%u' "/proc/$pid" 2>/dev/null)" || return 2
595
613
  [[ "$owner" =~ ^[0-9]+$ ]] || return 2
596
614
  [[ "$owner" == "$SERVICE_UID" ]] || return 1
597
- actual="$(readlink -f "/proc/$pid/exe" 2>/dev/null)" || return 2
615
+ # Read the executable link as its verified owner: container root may lack the ptrace
616
+ # capability that reading another user's /proc/<pid>/exe requires.
617
+ actual="$(service_run readlink -f "/proc/$pid/exe" 2>/dev/null)" || return 2
598
618
  expected="$(readlink -f "$executable")" || return 2
599
619
  [[ -n "$actual" && -n "$expected" && "$actual" != *' (deleted)' ]] || return 2
600
620
  [[ "$actual" == "$expected" ]]
@@ -1169,12 +1189,15 @@ process.stdout.write([...hosts].sort().join(","));
1169
1189
 
1170
1190
  @ENV_FUNCTIONS@
1171
1191
 
1192
+ @PREPARE_FUNCTION@
1193
+
1172
1194
  if [[ "$MODE" == install ]]; then
1173
1195
  step runtimes install_runtimes
1174
1196
  step services install_services
1175
1197
  step tools install_tools
1176
1198
  step shell install_shell_environment
1177
1199
  step dependencies dependency_install
1200
+ @PREPARE_STEP@
1178
1201
  exit 0
1179
1202
  fi
1180
1203
  step runtime-check runtime_ready
@@ -1215,6 +1238,24 @@ write_environment() {
1215
1238
  }
1216
1239
  `;
1217
1240
  const shellQuote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
1241
+ const renderPrepare = (prepare, files) => {
1242
+ if (prepare === void 0) return "";
1243
+ const manifest = files["package.json"];
1244
+ if (manifest === void 0) throw new Error("cloud.prepare requires a tracked root package.json");
1245
+ const parsed = JSON.parse(manifest);
1246
+ const scripts = typeof parsed === "object" && parsed !== null && "scripts" in parsed ? parsed.scripts : void 0;
1247
+ if (typeof scripts !== "object" || scripts === null || !Object.hasOwn(scripts, prepare.script) || typeof Reflect.get(scripts, prepare.script) !== "string") throw new Error(`cloud.prepare.script ${prepare.script} is not a root package script`);
1248
+ return [
1249
+ "prepare_sources() {",
1250
+ " local leader status=0",
1251
+ ` timeout --kill-after=10 ${prepare.seconds} runuser -u "$OUTPUT_USER" -- env HOME="$OUTPUT_HOME" PATH="$PATH" "$BUN_DIR/bun" run ${shellQuote(prepare.script)} </dev/null &`,
1252
+ " leader=$!",
1253
+ " wait \"$leader\" || status=$?",
1254
+ " kill -KILL -- \"-$leader\" 2>/dev/null || true",
1255
+ " return \"$status\"",
1256
+ "}"
1257
+ ].join("\n");
1258
+ };
1218
1259
  const generateCloudSetup = ({ policy, cloud, nodeVersion, files = {}, rustExceptions = [] }) => {
1219
1260
  const selected = parseCloudSetup(cloud);
1220
1261
  if (selected === void 0) throw new Error("cloud declaration is required");
@@ -1251,6 +1292,8 @@ const generateCloudSetup = ({ policy, cloud, nodeVersion, files = {}, rustExcept
1251
1292
  ["@ENV_FUNCTIONS@", selected.envFile === void 0 ? "" : environmentFunctions],
1252
1293
  ["@ENV_VALIDATE@", selected.envFile === void 0 ? "" : "DATABASE_URL=''\nREDIS_URL=''\nvalidate_environment"],
1253
1294
  ["@ENV_WRITE@", selected.envFile === void 0 ? "" : "write_environment"],
1295
+ ["@PREPARE_FUNCTION@", renderPrepare(selected.prepare, files)],
1296
+ ["@PREPARE_STEP@", selected.prepare === void 0 ? "" : " step prepare prepare_sources"],
1254
1297
  ["@SERVICE_INSTALL@", renderCloudServiceInstall({
1255
1298
  services,
1256
1299
  postgres: policy.postgres,