core/producers/tool.sqlfluff.producer.ts
core/producers/tool.sqlfluff.producer.ts is a file in GovLab Quality. 80 lines of code and 23 definitions.
import type { CatalogProduct, CatalogRule, KnobEntry } from "#types/catalog.types";
import { commandOutput, commandVersion } from "#core/adapters/invocation.adapter";
import { INTEGER_TYPE } from "#configuration/constants/knob.constants";
import { byRuleId } from "#core/comparators/rule.comparator";
import { defineProducer } from "#core/registries/producer.registry";
import { intAt } from "#core/parsers/knob.parser";
import { isThreshold } from "#core/predicates/knob.predicate";
import { remoteText } from "#core/adapters/remote.adapter";
import { tallyBy } from "#core/aggregators/catalog.aggregator";
const TOOL = "sqlfluff";
const DOCS = "https://docs.sqlfluff.com/en/stable/reference/rules.html";
const DEFAULTS = "https://raw.githubusercontent.com/sqlfluff/sqlfluff/main/src/sqlfluff/core/default_config.cfg";
const RULE_HEADER_PREFIX = "[sqlfluff:rules:";
const orNull = function orNull(value: string | null): string | null {
return value === null || value === "" ? null : value;
};
const isRuleLine = function isRuleLine(line: string, code: string): boolean {
return line !== "" && !line.startsWith(" ") && line.includes(": [") && code !== "";
};
const bracketed = function bracketed(line: string): string | null {
const open = line.indexOf("[");
const close = line.indexOf("]");
return orNull(open !== -1 && close > open ? line.slice(open + 1, close) : null);
};
const ruleOf = function ruleOf(line: string, version: string): CatalogRule[] {
const code = line.slice(0, line.indexOf(":")).trim();
if (!isRuleLine(line, code)) {
return [];
}
const close = line.indexOf("]");
const dotted = bracketed(line);
return [
{
canonical: null,
category: dotted === null ? null : (dotted.split(".")[0] ?? null),
description: orNull(close === -1 ? null : line.slice(close + 1).trim()),
ecosystem: "sql",
name: dotted ?? code,
ruleId: code,
tool: TOOL,
toolVersion: version,
url: DOCS,
},
];
};
const produce = async function produce(): Promise<CatalogProduct[]> {
const version = commandVersion(TOOL, ["version"]);
const lines = commandOutput(TOOL, ["rules"])
.split("\n")
.map((line) => (line.endsWith("\r") ? line.slice(0, -1) : line));
const rules = lines.flatMap((line) => ruleOf(line, version)).toSorted(byRuleId);
return [
{
rules,
source: TOOL,
summary: { byCategory: tallyBy(rules, "category"), tool: TOOL, toolVersion: version, total: rules.length },
},
];
};
const knobs = async function knobs(): Promise<KnobEntry[]> {
const entries: KnobEntry[] = [];
let rule: string | null = null;
for (const raw of ((await remoteText(DEFAULTS)) ?? "").split("\n")) {
const line = raw.trim();
if (line.startsWith("[")) {
rule = line.startsWith(RULE_HEADER_PREFIX)
? line.slice(RULE_HEADER_PREFIX.length, line.indexOf("]"))
: null;
continue;
}
const eq = line.indexOf("=");
const value = rule !== null && eq !== -1 ? intAt(line.slice(eq + 1), 0) : null;
if (rule !== null && value !== null) {
const knob = line.slice(0, eq).trim();
entries.push([TOOL, rule, { default: value, knob, threshold: isThreshold(knob), type: INTEGER_TYPE }]);
}
}
return entries;
};
defineProducer({ knobs, name: TOOL, produce, refresh: "manual" });