build: enable additional oxlint rules

This commit is contained in:
Peter Steinberger 2026-05-11 03:56:18 +01:00
parent 35bebf732f
commit 30e54b839b
No known key found for this signature in database
12 changed files with 61 additions and 31 deletions

View file

@ -36,8 +36,12 @@
"eslint/no-new-wrappers": "error",
"eslint/no-else-return": "error",
"eslint/no-case-declarations": "error",
"eslint/default-case-last": "error",
"eslint/default-param-last": "error",
"eslint/prefer-exponentiation-operator": "error",
"eslint/prefer-numeric-literals": "error",
"eslint/prefer-rest-params": "error",
"eslint/prefer-spread": "error",
"eslint/radix": "error",
"eslint/unicode-bom": "error",
"eslint/yoda": "error",
@ -49,7 +53,12 @@
"oxc/no-accumulating-spread": "error",
"oxc/no-async-endpoint-handlers": "error",
"oxc/no-map-spread": "error",
"promise/no-callback-in-promise": "error",
"promise/no-multiple-resolved": "error",
"promise/no-promise-in-callback": "error",
"promise/no-return-in-finally": "error",
"promise/no-new-statics": "error",
"promise/valid-params": "error",
"typescript/adjacent-overload-signatures": "error",
"typescript/ban-tslint-comment": "error",
"typescript/consistent-return": "error",
@ -66,24 +75,35 @@
"typescript/no-unnecessary-type-parameters": "error",
"typescript/no-unsafe-type-assertion": "off",
"typescript/no-useless-default-assignment": "error",
"typescript/no-useless-empty-export": "error",
"typescript/no-wrapper-object-types": "error",
"typescript/switch-exhaustiveness-check": [
"error",
{ "considerDefaultExhaustiveForUnions": true }
],
"typescript/prefer-as-const": "error",
"typescript/prefer-namespace-keyword": "error",
"typescript/prefer-return-this-type": "error",
"typescript/prefer-find": "error",
"typescript/prefer-function-type": "error",
"typescript/prefer-includes": "error",
"typescript/prefer-reduce-type-parameter": "error",
"typescript/prefer-ts-expect-error": "error",
"typescript/require-array-sort-compare": "error",
"typescript/restrict-template-expressions": "error",
"typescript/triple-slash-reference": "error",
"unicorn/consistent-date-clone": "error",
"unicorn/consistent-empty-array-spread": "error",
"unicorn/consistent-function-scoping": "off",
"unicorn/no-console-spaces": "error",
"unicorn/no-empty-file": "error",
"unicorn/no-invalid-fetch-options": "error",
"unicorn/no-invalid-remove-event-listener": "error",
"unicorn/no-length-as-slice-end": "error",
"unicorn/no-instanceof-array": "error",
"unicorn/no-negation-in-equality-check": "error",
"unicorn/no-new-buffer": "error",
"unicorn/no-thenable": "error",
"unicorn/no-typeof-undefined": "error",
"unicorn/no-unnecessary-array-flat-depth": "error",
"unicorn/no-unnecessary-array-splice-count": "error",
@ -102,6 +122,7 @@
"unicorn/prefer-prototype-methods": "error",
"unicorn/prefer-regexp-test": "error",
"unicorn/prefer-set-size": "error",
"unicorn/prefer-string-starts-ends-with": "error",
"unicorn/prefer-string-slice": "error",
"unicorn/require-array-join-separator": "error",
"unicorn/require-number-to-fixed-digits-argument": "error",

View file

@ -6,6 +6,7 @@ Docs: https://docs.openclaw.ai
### Changes
- Build: enable additional low-churn oxlint rules for promise, TypeScript, and runtime footgun checks.
- Build: enable stricter Vitest lint rules for focused, disabled, conditional, hook, matcher, and expectation hazards.
- Build: pin explicit oxfmt defaults in the shared formatter config to keep formatting behavior stable across upgrades.
- TypeScript: enable stricter compiler checks for implicit returns, side-effect imports, overrides, and unused production code.

View file

@ -46,26 +46,27 @@ export class DiscordThreadInitialMessageError extends Error {
export async function readMessagesDiscord(
channelId: string,
query: DiscordMessageQuery = {},
query: DiscordMessageQuery | undefined,
opts: DiscordReactOpts,
): Promise<APIMessage[]> {
const messageQuery = query ?? {};
const rest = resolveDiscordRest(opts);
const limit =
typeof query.limit === "number" && Number.isFinite(query.limit)
? Math.min(Math.max(Math.floor(query.limit), 1), 100)
typeof messageQuery.limit === "number" && Number.isFinite(messageQuery.limit)
? Math.min(Math.max(Math.floor(messageQuery.limit), 1), 100)
: undefined;
const params: Record<string, string | number> = {};
if (limit) {
params.limit = limit;
}
if (query.before) {
params.before = query.before;
if (messageQuery.before) {
params.before = messageQuery.before;
}
if (query.after) {
params.after = query.after;
if (messageQuery.after) {
params.after = messageQuery.after;
}
if (query.around) {
params.around = query.around;
if (messageQuery.around) {
params.around = messageQuery.around;
}
return await listChannelMessages(rest, channelId, params);
}

View file

@ -186,12 +186,13 @@ export const nostrPlugin: ChannelPlugin<ResolvedNostrAccount> = createChatChanne
* @throws Error if account is not running
*/
export async function publishNostrProfile(
accountId: string = DEFAULT_ACCOUNT_ID,
accountId: string | undefined,
profile: NostrProfile,
): Promise<ProfilePublishResult> {
const bus = getActiveNostrBuses().get(accountId);
const resolvedAccountId = accountId ?? DEFAULT_ACCOUNT_ID;
const bus = getActiveNostrBuses().get(resolvedAccountId);
if (!bus) {
throw new Error(`Nostr bus not running for account ${accountId}`);
throw new Error(`Nostr bus not running for account ${resolvedAccountId}`);
}
return bus.publishProfile(profile);
}

View file

@ -216,9 +216,10 @@ function formatInventoryHuman(inventory) {
return lines.join("\n");
}
async function runArchitectureSmellsCheck(argv = process.argv.slice(2), io) {
async function runArchitectureSmellsCheck(argv, io) {
const args = argv ?? process.argv.slice(2);
const streams = io ?? { stdout: process.stdout, stderr: process.stderr };
const json = argv.includes("--json");
const json = args.includes("--json");
const inventory = await collectArchitectureSmells();
if (json) {
@ -231,7 +232,7 @@ async function runArchitectureSmellsCheck(argv = process.argv.slice(2), io) {
return 0;
}
export async function main(argv = process.argv.slice(2), io) {
export async function main(argv, io) {
return await runArchitectureSmellsCheck(argv, io);
}

View file

@ -294,10 +294,11 @@ function formatInventoryHuman(mode, inventory) {
return lines.join("\n");
}
export async function runExtensionPluginSdkBoundaryCheck(argv = process.argv.slice(2), io) {
export async function runExtensionPluginSdkBoundaryCheck(argv, io) {
const args = argv ?? process.argv.slice(2);
const streams = io ?? { stdout: process.stdout, stderr: process.stderr };
const json = argv.includes("--json");
const modeArg = argv.find((arg) => arg.startsWith("--mode="));
const json = args.includes("--json");
const modeArg = args.find((arg) => arg.startsWith("--mode="));
const mode = modeArg?.slice("--mode=".length) ?? "src-outside-plugin-sdk";
if (!MODES.has(mode)) {
throw new Error(`Unknown mode: ${mode}`);
@ -342,7 +343,7 @@ export async function runExtensionPluginSdkBoundaryCheck(argv = process.argv.sli
return 1;
}
export async function main(argv = process.argv.slice(2), io) {
export async function main(argv, io) {
const exitCode = await runExtensionPluginSdkBoundaryCheck(argv, io);
if (!io) {
process.exitCode = exitCode;

View file

@ -199,9 +199,9 @@ function formatEntry(entry) {
return `${entry.file}:${entry.line} [${entry.kind}] ${entry.reason} (${entry.specifier} -> ${entry.resolvedPath})`;
}
export async function runPluginExtensionImportBoundaryCheck(argv = process.argv.slice(2), io) {
export async function runPluginExtensionImportBoundaryCheck(argv, io) {
return await runBaselineInventoryCheck({
argv,
argv: argv ?? process.argv.slice(2),
io,
collectActual: collectPluginExtensionImportBoundaryInventory,
readExpected: readExpectedInventory,
@ -211,7 +211,7 @@ export async function runPluginExtensionImportBoundaryCheck(argv = process.argv.
});
}
export async function main(argv = process.argv.slice(2), io) {
export async function main(argv, io) {
const exitCode = await runPluginExtensionImportBoundaryCheck(argv, io);
if (!io && exitCode !== 0) {
process.exit(exitCode);

View file

@ -81,8 +81,9 @@ export async function collectWebFetchProviderBoundaryViolations() {
return await webFetchProviderViolationsPromise;
}
export async function main(argv = process.argv.slice(2), io) {
const json = argv.includes("--json");
export async function main(argv, io) {
const args = argv ?? process.argv.slice(2);
const json = args.includes("--json");
const violations = await collectWebFetchProviderBoundaryViolations();
const writeStdout = (chunk) => {
if (io?.stdout?.write) {

View file

@ -219,9 +219,9 @@ function formatEntry(entry) {
return `${entry.provider} ${entry.file}:${entry.line} ${entry.reason}`;
}
export async function runWebSearchProviderBoundaryCheck(argv = process.argv.slice(2), io) {
export async function runWebSearchProviderBoundaryCheck(argv, io) {
return await runBaselineInventoryCheck({
argv,
argv: argv ?? process.argv.slice(2),
io,
collectActual: collectWebSearchProviderBoundaryInventory,
readExpected: readExpectedInventory,
@ -231,7 +231,7 @@ export async function runWebSearchProviderBoundaryCheck(argv = process.argv.slic
});
}
export async function main(argv = process.argv.slice(2), io) {
export async function main(argv, io) {
const exitCode = await runWebSearchProviderBoundaryCheck(argv, io);
if (!io && exitCode !== 0) {
process.exit(exitCode);

View file

@ -93,9 +93,10 @@ export function createExtensionImportBoundaryChecker(params) {
return inventory.toSorted(compareEntries);
});
async function main(argv = process.argv.slice(2), io) {
async function main(argv, io) {
const args = argv ?? process.argv.slice(2);
const streams = io ?? { stdout: process.stdout, stderr: process.stderr };
const json = argv.includes("--json");
const json = args.includes("--json");
const inventory = await collectInventory();
if (json) {

View file

@ -1543,7 +1543,8 @@ function hasConservativeVitestWorkerBudget(env) {
return workerBudget !== null && workerBudget <= 1;
}
export function resolveParallelFullSuiteConcurrency(specCount, env = process.env, hostInfo) {
export function resolveParallelFullSuiteConcurrency(specCount, env, hostInfo) {
env ??= process.env;
const override = parsePositiveInt(env.OPENCLAW_TEST_PROJECTS_PARALLEL);
if (override !== null) {
return Math.min(override, specCount);

View file

@ -178,9 +178,10 @@ async function requireRiskAcknowledgement(params: {
export async function runSetupWizard(
opts: OnboardOptions,
runtime: RuntimeEnv = defaultRuntime,
runtime: RuntimeEnv | undefined,
prompter: WizardPrompter,
) {
runtime ??= defaultRuntime;
const onboardHelpers = await import("../commands/onboard-helpers.js");
onboardHelpers.printWizardHeader(runtime);
await prompter.intro("OpenClaw setup");