@stll/oxlint-config 1.2.6 → 1.3.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
@@ -349,6 +349,15 @@ matching package is reused without network access.
349
349
  `wasm-bindgen-cli` requires the matching `wasm-bindgen` crate version in tracked
350
350
  root `Cargo.lock`. Regenerate after updating the lockfile or any tool pin.
351
351
 
352
+ `cloud.prepare` (optional) names one root `package.json` script and a time bound,
353
+ for example `{ "script": "generate:cloud", "seconds": 300 }`. The install phase
354
+ runs it once after dependencies, as the invoking user, with stdin closed. At the
355
+ bound (1 to 900 seconds) the script receives TERM and, 10 seconds later, KILL;
356
+ when it ends, anything still running in its process group is killed. Use it
357
+ for cheap derived sources that tasks need when `install` skips lifecycle scripts;
358
+ it gets no network allowance. Generation fails when the script is not in the
359
+ root `package.json`.
360
+
352
361
  Generation uses the installed policy's Bun, Node, PostgreSQL, and Valkey pins.
353
362
  PostgreSQL uses the PGDG major-version packages; minor updates within the pinned
354
363
  major are accepted for the disposable database. Before adding PGDG, provisioning
@@ -13,7 +13,7 @@ let picomatch = require("picomatch");
13
13
  picomatch = require_rolldown_runtime.__toESM(picomatch, 1);
14
14
  //#endregion
15
15
  //#region src/toolchain-consumer-checks.ts
16
- const consumerRunnerVersion = "1.2.6";
16
+ const consumerRunnerVersion = "1.3.1";
17
17
  const consumerCheckWorkflow = "stella/.github/.github/workflows/package-consumer-compat.yml";
18
18
  const record$7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
19
19
  const repositoryDirectory = (value) => typeof value === "string" && value !== "" && !value.includes("\\") && !value.includes("${{") && !value.split("").some((character) => {
@@ -10,7 +10,7 @@ import { LineCounter, isAlias, isMap, isNode, isScalar, isSeq, parseAllDocuments
10
10
  import picomatch from "picomatch";
11
11
  //#endregion
12
12
  //#region src/toolchain-consumer-checks.ts
13
- const consumerRunnerVersion = "1.2.6";
13
+ const consumerRunnerVersion = "1.3.1";
14
14
  const consumerCheckWorkflow = "stella/.github/.github/workflows/package-consumer-compat.yml";
15
15
  const record$7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
16
16
  const repositoryDirectory = (value) => typeof value === "string" && value !== "" && !value.includes("\\") && !value.includes("${{") && !value.split("").some((character) => {
@@ -535,16 +535,32 @@ const parseEnvFile = (input) => {
535
535
  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");
536
536
  return envFile;
537
537
  };
538
+ const cloudPrepareScript = /^[a-z0-9][a-z0-9:._-]*$/;
539
+ const parsePrepare = (input) => {
540
+ if (input === void 0) return void 0;
541
+ if (typeof input !== "object" || input === null || Array.isArray(input)) throw new Error("cloud.prepare must be an object");
542
+ for (const key of Object.keys(input)) if (key !== "script" && key !== "seconds") throw new Error(`unsupported cloud.prepare key: ${key}`);
543
+ const script = "script" in input ? input.script : void 0;
544
+ if (typeof script !== "string" || !cloudPrepareScript.test(script)) throw new Error("cloud.prepare.script must name a package script");
545
+ const seconds = "seconds" in input ? input.seconds : void 0;
546
+ 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`);
547
+ return {
548
+ script,
549
+ seconds
550
+ };
551
+ };
538
552
  /** Parse an explicit declaration without assuming services for undeclared repositories. */
539
553
  const parseCloudSetup = (input) => {
540
554
  if (input === void 0) return void 0;
541
555
  if (typeof input !== "object" || input === null || Array.isArray(input)) throw new Error("cloud must be an object");
542
- 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}`);
556
+ 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}`);
543
557
  const rust = parseRust("rust" in input ? input.rust : void 0);
544
558
  const tools = parseTools("tools" in input ? input.tools : void 0);
559
+ const prepare = parsePrepare("prepare" in input ? input.prepare : void 0);
545
560
  const extensions = {
546
561
  ...rust === void 0 ? {} : { rust },
547
- ...tools === void 0 ? {} : { tools }
562
+ ...tools === void 0 ? {} : { tools },
563
+ ...prepare === void 0 ? {} : { prepare }
548
564
  };
549
565
  const selected = "services" in input ? input.services : [];
550
566
  if (!Array.isArray(selected)) throw new Error("cloud.services must be an array when provided");
@@ -599,7 +615,9 @@ service_process_matches() {
599
615
  owner="$(stat -c '%u' "/proc/$pid" 2>/dev/null)" || return 2
600
616
  [[ "$owner" =~ ^[0-9]+$ ]] || return 2
601
617
  [[ "$owner" == "$SERVICE_UID" ]] || return 1
602
- actual="$(readlink -f "/proc/$pid/exe" 2>/dev/null)" || return 2
618
+ # Read the executable link as its verified owner: container root may lack the ptrace
619
+ # capability that reading another user's /proc/<pid>/exe requires.
620
+ actual="$(service_run readlink -f "/proc/$pid/exe" 2>/dev/null)" || return 2
603
621
  expected="$(readlink -f "$executable")" || return 2
604
622
  [[ -n "$actual" && -n "$expected" && "$actual" != *' (deleted)' ]] || return 2
605
623
  [[ "$actual" == "$expected" ]]
@@ -1071,7 +1089,15 @@ OUTPUT_USER="$(getent passwd "$OUTPUT_UID" | cut -d: -f1)"
1071
1089
  OUTPUT_HOME="$(getent passwd "$OUTPUT_UID" | cut -d: -f6)"
1072
1090
  [[ -n "$OUTPUT_USER" && "$OUTPUT_HOME" == /* && -d "$OUTPUT_HOME" ]] || fail 'Invoking user requires an existing home directory'
1073
1091
  root() { "$@"; }
1074
- service_run() { runuser -u stll-cloud -- "$@" 9>&-; }
1092
+ # Service daemons outlive setup, so they inherit no descriptor beyond stdio: a cloud
1093
+ # runner can pass its terminal as extra descriptors and wait until every copy closes.
1094
+ service_run() (
1095
+ for descriptor in "/proc/$BASHPID/fd/"*; do
1096
+ descriptor="$(basename -- "$descriptor")"
1097
+ if [[ "$descriptor" =~ ^[0-9]+$ ]] && (( descriptor > 2 )); then eval "exec $descriptor>&-"; fi
1098
+ done
1099
+ exec runuser -u stll-cloud -- "$@"
1100
+ )
1075
1101
  BUN_VERSION='@BUN@'
1076
1102
  NODE_VERSION='@NODE@'
1077
1103
  NODE_DIR="/opt/stll-cloud/node/$NODE_VERSION"
@@ -1174,12 +1200,15 @@ process.stdout.write([...hosts].sort().join(","));
1174
1200
 
1175
1201
  @ENV_FUNCTIONS@
1176
1202
 
1203
+ @PREPARE_FUNCTION@
1204
+
1177
1205
  if [[ "$MODE" == install ]]; then
1178
1206
  step runtimes install_runtimes
1179
1207
  step services install_services
1180
1208
  step tools install_tools
1181
1209
  step shell install_shell_environment
1182
1210
  step dependencies dependency_install
1211
+ @PREPARE_STEP@
1183
1212
  exit 0
1184
1213
  fi
1185
1214
  step runtime-check runtime_ready
@@ -1220,6 +1249,24 @@ write_environment() {
1220
1249
  }
1221
1250
  `;
1222
1251
  const shellQuote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
1252
+ const renderPrepare = (prepare, files) => {
1253
+ if (prepare === void 0) return "";
1254
+ const manifest = files["package.json"];
1255
+ if (manifest === void 0) throw new Error("cloud.prepare requires a tracked root package.json");
1256
+ const parsed = JSON.parse(manifest);
1257
+ const scripts = typeof parsed === "object" && parsed !== null && "scripts" in parsed ? parsed.scripts : void 0;
1258
+ 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`);
1259
+ return [
1260
+ "prepare_sources() {",
1261
+ " local leader status=0",
1262
+ ` 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 &`,
1263
+ " leader=$!",
1264
+ " wait \"$leader\" || status=$?",
1265
+ " kill -KILL -- \"-$leader\" 2>/dev/null || true",
1266
+ " return \"$status\"",
1267
+ "}"
1268
+ ].join("\n");
1269
+ };
1223
1270
  const generateCloudSetup = ({ policy, cloud, nodeVersion, files = {}, rustExceptions = [] }) => {
1224
1271
  const selected = parseCloudSetup(cloud);
1225
1272
  if (selected === void 0) throw new Error("cloud declaration is required");
@@ -1256,6 +1303,8 @@ const generateCloudSetup = ({ policy, cloud, nodeVersion, files = {}, rustExcept
1256
1303
  ["@ENV_FUNCTIONS@", selected.envFile === void 0 ? "" : environmentFunctions],
1257
1304
  ["@ENV_VALIDATE@", selected.envFile === void 0 ? "" : "DATABASE_URL=''\nREDIS_URL=''\nvalidate_environment"],
1258
1305
  ["@ENV_WRITE@", selected.envFile === void 0 ? "" : "write_environment"],
1306
+ ["@PREPARE_FUNCTION@", renderPrepare(selected.prepare, files)],
1307
+ ["@PREPARE_STEP@", selected.prepare === void 0 ? "" : " step prepare prepare_sources"],
1259
1308
  ["@SERVICE_INSTALL@", renderCloudServiceInstall({
1260
1309
  services,
1261
1310
  postgres: policy.postgres,