@stll/oxlint-config 1.2.6 → 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.
@@ -532,16 +532,32 @@ const parseEnvFile = (input) => {
532
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");
533
533
  return envFile;
534
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
+ };
535
549
  /** Parse an explicit declaration without assuming services for undeclared repositories. */
536
550
  const parseCloudSetup = (input) => {
537
551
  if (input === void 0) return void 0;
538
552
  if (typeof input !== "object" || input === null || Array.isArray(input)) throw new Error("cloud must be an object");
539
- 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}`);
540
554
  const rust = parseRust("rust" in input ? input.rust : void 0);
541
555
  const tools = parseTools("tools" in input ? input.tools : void 0);
556
+ const prepare = parsePrepare("prepare" in input ? input.prepare : void 0);
542
557
  const extensions = {
543
558
  ...rust === void 0 ? {} : { rust },
544
- ...tools === void 0 ? {} : { tools }
559
+ ...tools === void 0 ? {} : { tools },
560
+ ...prepare === void 0 ? {} : { prepare }
545
561
  };
546
562
  const selected = "services" in input ? input.services : [];
547
563
  if (!Array.isArray(selected)) throw new Error("cloud.services must be an array when provided");
@@ -596,7 +612,9 @@ service_process_matches() {
596
612
  owner="$(stat -c '%u' "/proc/$pid" 2>/dev/null)" || return 2
597
613
  [[ "$owner" =~ ^[0-9]+$ ]] || return 2
598
614
  [[ "$owner" == "$SERVICE_UID" ]] || return 1
599
- 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
600
618
  expected="$(readlink -f "$executable")" || return 2
601
619
  [[ -n "$actual" && -n "$expected" && "$actual" != *' (deleted)' ]] || return 2
602
620
  [[ "$actual" == "$expected" ]]
@@ -1171,12 +1189,15 @@ process.stdout.write([...hosts].sort().join(","));
1171
1189
 
1172
1190
  @ENV_FUNCTIONS@
1173
1191
 
1192
+ @PREPARE_FUNCTION@
1193
+
1174
1194
  if [[ "$MODE" == install ]]; then
1175
1195
  step runtimes install_runtimes
1176
1196
  step services install_services
1177
1197
  step tools install_tools
1178
1198
  step shell install_shell_environment
1179
1199
  step dependencies dependency_install
1200
+ @PREPARE_STEP@
1180
1201
  exit 0
1181
1202
  fi
1182
1203
  step runtime-check runtime_ready
@@ -1217,6 +1238,24 @@ write_environment() {
1217
1238
  }
1218
1239
  `;
1219
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
+ };
1220
1259
  const generateCloudSetup = ({ policy, cloud, nodeVersion, files = {}, rustExceptions = [] }) => {
1221
1260
  const selected = parseCloudSetup(cloud);
1222
1261
  if (selected === void 0) throw new Error("cloud declaration is required");
@@ -1253,6 +1292,8 @@ const generateCloudSetup = ({ policy, cloud, nodeVersion, files = {}, rustExcept
1253
1292
  ["@ENV_FUNCTIONS@", selected.envFile === void 0 ? "" : environmentFunctions],
1254
1293
  ["@ENV_VALIDATE@", selected.envFile === void 0 ? "" : "DATABASE_URL=''\nREDIS_URL=''\nvalidate_environment"],
1255
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"],
1256
1297
  ["@SERVICE_INSTALL@", renderCloudServiceInstall({
1257
1298
  services,
1258
1299
  postgres: policy.postgres,