Format authored monorepo code with pinned language formatters

This commit is contained in:
Timothy J. Aveni
2026-09-15 15:23:24 -07:00
parent a174faea5c
commit 00fc2b9ff1
69 changed files with 5135 additions and 3306 deletions
+51 -59
View File
@@ -1,24 +1,11 @@
import { lstat, readFile } from "node:fs/promises";
import path from "node:path";
import {
parseQuixosLockDocument,
type QuixosLockDiagnostic,
type QuixosLockParseResult,
} from "./parser.js";
import type {
LockedResource,
QuixosLockDocument,
QuixosRepositoryLock,
} from "./types.js";
import { parseQuixosLockDocument, type QuixosLockDiagnostic, type QuixosLockParseResult } from "./parser.js";
import type { LockedResource, QuixosLockDocument, QuixosRepositoryLock } from "./types.js";
export type QuixosLockSourceReader = (relativePath: string) => Promise<string>;
const diagnostic = (
code: string,
message: string,
fileName: string,
path?: string,
): QuixosLockDiagnostic => ({
const diagnostic = (code: string, message: string, fileName: string, path?: string): QuixosLockDiagnostic => ({
phase: "resolution",
code,
message,
@@ -38,11 +25,9 @@ export const resolveQuixosLock = async (
if (root.document.kind !== "root") {
return {
ok: false,
diagnostics: [diagnostic(
"expected-root-lock",
"The entrypoint must be a root Quixos lock, not a fragment",
rootFileName,
)],
diagnostics: [
diagnostic("expected-root-lock", "The entrypoint must be a root Quixos lock, not a fragment", rootFileName),
],
};
}
@@ -54,15 +39,16 @@ export const resolveQuixosLock = async (
const addResources = (document: QuixosLockDocument, fileName: string) => {
for (const resource of document.resources) {
const duplicate = resources.find((entry) =>
entry.kind === resource.kind && entry.binding === resource.binding);
const duplicate = resources.find((entry) => entry.kind === resource.kind && entry.binding === resource.binding);
if (duplicate) {
diagnostics.push(diagnostic(
"duplicate-resource-binding",
`Duplicate ${resource.kind} binding ${resource.binding} across imported lock files`,
fileName,
`${resource.kind}.${resource.binding}`,
));
diagnostics.push(
diagnostic(
"duplicate-resource-binding",
`Duplicate ${resource.kind} binding ${resource.binding} across imported lock files`,
fileName,
`${resource.kind}.${resource.binding}`,
),
);
} else {
resources.push(resource);
}
@@ -71,11 +57,9 @@ export const resolveQuixosLock = async (
const visit = async (importPath: string) => {
if (active.includes(importPath)) {
diagnostics.push(diagnostic(
"import-cycle",
`Lock import cycle: ${[...active, importPath].join(" -> ")}`,
importPath,
));
diagnostics.push(
diagnostic("import-cycle", `Lock import cycle: ${[...active, importPath].join(" -> ")}`, importPath),
);
return;
}
if (visited.has(importPath)) return;
@@ -84,11 +68,13 @@ export const resolveQuixosLock = async (
try {
source = await readSource(importPath);
} catch (cause) {
diagnostics.push(diagnostic(
"import-read-failed",
`Could not read lock import ${importPath}: ${cause instanceof Error ? cause.message : String(cause)}`,
importPath,
));
diagnostics.push(
diagnostic(
"import-read-failed",
`Could not read lock import ${importPath}: ${cause instanceof Error ? cause.message : String(cause)}`,
importPath,
),
);
active.pop();
return;
}
@@ -99,11 +85,13 @@ export const resolveQuixosLock = async (
return;
}
if (parsed.document.kind !== "fragment") {
diagnostics.push(diagnostic(
"imported-root-lock",
`Imported file ${importPath} must begin with "quixos-lock fragment"`,
importPath,
));
diagnostics.push(
diagnostic(
"imported-root-lock",
`Imported file ${importPath} must begin with "quixos-lock fragment"`,
importPath,
),
);
active.pop();
return;
}
@@ -131,20 +119,24 @@ export const loadQuixosLock = async (fileName: string): Promise<QuixosLockParseR
const repositoryRoot = path.dirname(absoluteRoot);
const rootName = path.basename(absoluteRoot);
const rootSource = await readFile(absoluteRoot, "utf8");
return await resolveQuixosLock(rootSource, async (relativePath) => {
let absoluteImport = repositoryRoot;
const segments = relativePath.split("/");
for (const [index, segment] of segments.entries()) {
absoluteImport = path.join(absoluteImport, segment);
const metadata = await lstat(absoluteImport);
if (metadata.isSymbolicLink()) {
throw new Error("imports must not traverse symbolic links");
return await resolveQuixosLock(
rootSource,
async (relativePath) => {
let absoluteImport = repositoryRoot;
const segments = relativePath.split("/");
for (const [index, segment] of segments.entries()) {
absoluteImport = path.join(absoluteImport, segment);
const metadata = await lstat(absoluteImport);
if (metadata.isSymbolicLink()) {
throw new Error("imports must not traverse symbolic links");
}
const final = index === segments.length - 1;
if ((!final && !metadata.isDirectory()) || (final && !metadata.isFile())) {
throw new Error("imports must be ordinary files beneath ordinary directories");
}
}
const final = index === segments.length - 1;
if ((!final && !metadata.isDirectory()) || (final && !metadata.isFile())) {
throw new Error("imports must be ordinary files beneath ordinary directories");
}
}
return await readFile(absoluteImport, "utf8");
}, rootName);
return await readFile(absoluteImport, "utf8");
},
rootName,
);
};
+60 -113
View File
@@ -13,13 +13,7 @@ import {
type QuixosSourceBlockContext,
type SourceBlockContext,
} from "./generated/QuixosLockParser.js";
import type {
GitSource,
LockedResource,
QuixosLockDocument,
QuixosRepositoryLock,
QuixosSource,
} from "./types.js";
import type { GitSource, LockedResource, QuixosLockDocument, QuixosRepositoryLock, QuixosSource } from "./types.js";
export type QuixosLockDiagnostic = {
phase: "syntax" | "validation" | "resolution";
@@ -66,8 +60,7 @@ class SyntaxErrorListener extends BaseErrorListener {
}
}
const stringValue = (context: { getText(): string }): string =>
JSON.parse(context.getText()) as string;
const stringValue = (context: { getText(): string }): string => JSON.parse(context.getText()) as string;
const lowerSource = (context: SourceBlockContext): GitSource => ({
resolver: "git",
@@ -103,15 +96,16 @@ const issue = (
path?: string,
line = 1,
column = 0,
) => diagnostics.push({
phase: "validation",
code,
message,
fileName,
line,
column,
path,
});
) =>
diagnostics.push({
phase: "validation",
code,
message,
fileName,
line,
column,
path,
});
const validateImport = (
importPath: string,
@@ -123,11 +117,11 @@ const validateImport = (
) => {
const path = `imports[${index}]`;
if (
!importPath
|| importPath.startsWith("/")
|| importPath.includes("\\")
|| importPath.split("/").some((segment) => !segment || segment === "." || segment === "..")
|| /^[A-Za-z][A-Za-z0-9+.-]*:/.test(importPath)
!importPath ||
importPath.startsWith("/") ||
importPath.includes("\\") ||
importPath.split("/").some((segment) => !segment || segment === "." || segment === "..") ||
/^[A-Za-z][A-Za-z0-9+.-]*:/.test(importPath)
) {
issue(
diagnostics,
@@ -141,12 +135,7 @@ const validateImport = (
}
};
const validateSource = (
source: GitSource,
path: string,
fileName: string,
diagnostics: QuixosLockDiagnostic[],
) => {
const validateSource = (source: GitSource, path: string, fileName: string, diagnostics: QuixosLockDiagnostic[]) => {
if (!/^([0-9a-f]{40}|[0-9a-f]{64})$/.test(source.commit)) {
issue(
diagnostics,
@@ -198,25 +187,22 @@ const validateSource = (
}
};
const validateQuixosSource = (
source: QuixosSource,
fileName: string,
diagnostics: QuixosLockDiagnostic[],
) => {
const validateQuixosSource = (source: QuixosSource, fileName: string, diagnostics: QuixosLockDiagnostic[]) => {
validateSource(source, "quixos", fileName, diagnostics);
if (!source.policy) return;
const forbiddenRefCharacters = new Set("~^:?*[\\");
const invalidRef = !source.ref
|| [...source.ref].some((character) => {
const invalidRef =
!source.ref ||
[...source.ref].some((character) => {
const code = character.charCodeAt(0);
return code <= 0x20 || code === 0x7f || forbiddenRefCharacters.has(character);
})
|| source.ref.startsWith("/")
|| source.ref.endsWith("/")
|| source.ref.endsWith(".")
|| source.ref.includes("..")
|| source.ref.includes("@{")
|| source.ref.includes("//");
}) ||
source.ref.startsWith("/") ||
source.ref.endsWith("/") ||
source.ref.endsWith(".") ||
source.ref.includes("..") ||
source.ref.includes("@{") ||
source.ref.includes("//");
if (invalidRef) {
issue(
diagnostics,
@@ -247,10 +233,7 @@ const validateQuixosSource = (
}
};
export const parseQuixosLockDocument = (
source: string,
fileName = "<memory>",
): QuixosLockDocumentParseResult => {
export const parseQuixosLockDocument = (source: string, fileName = "<memory>"): QuixosLockDocumentParseResult => {
const diagnostics: QuixosLockDiagnostic[] = [];
const listener = new SyntaxErrorListener(fileName, diagnostics);
const lexer = new QuixosLockLexer(CharStream.fromString(source));
@@ -299,26 +282,13 @@ export const parseQuixosLockDocument = (
const imports = tree.importEntry().map((context, index) => {
const importPath = stringValue(context.stringLiteral());
validateImport(
importPath,
index,
fileName,
diagnostics,
context.start?.line ?? 1,
context.start?.column ?? 0,
);
validateImport(importPath, index, fileName, diagnostics, context.start?.line ?? 1, context.start?.column ?? 0);
return importPath;
});
const repeatedImports = new Set<string>();
imports.forEach((importPath, index) => {
if (repeatedImports.has(importPath)) {
issue(
diagnostics,
fileName,
"duplicate-import",
`Duplicate lock import ${importPath}`,
`imports[${index}]`,
);
issue(diagnostics, fileName, "duplicate-import", `Duplicate lock import ${importPath}`, `imports[${index}]`);
}
repeatedImports.add(importPath);
});
@@ -355,36 +325,38 @@ export const parseQuixosLockDocument = (
};
};
export const parseQuixosLock = (
source: string,
fileName = "<memory>",
): QuixosLockParseResult => {
export const parseQuixosLock = (source: string, fileName = "<memory>"): QuixosLockParseResult => {
const parsed = parseQuixosLockDocument(source, fileName);
if (!parsed.ok) return parsed;
if (parsed.document.kind === "fragment") {
return {
ok: false,
diagnostics: [{
phase: "validation",
code: "expected-root-lock",
message: "Expected a root Quixos lock, found a lock fragment",
fileName,
line: 1,
column: 0,
}],
diagnostics: [
{
phase: "validation",
code: "expected-root-lock",
message: "Expected a root Quixos lock, found a lock fragment",
fileName,
line: 1,
column: 0,
},
],
};
}
if (parsed.document.imports.length) {
return {
ok: false,
diagnostics: [{
phase: "resolution",
code: "imports-require-file-resolution",
message: "This lock has imports and must be loaded from its repository rather than parsed as an isolated string",
fileName,
line: 1,
column: 0,
}],
diagnostics: [
{
phase: "resolution",
code: "imports-require-file-resolution",
message:
"This lock has imports and must be loaded from its repository rather than parsed as an isolated string",
fileName,
line: 1,
column: 0,
},
],
};
}
return {
@@ -407,44 +379,23 @@ const sourceLines = (source: GitSource, indentation: string): string[] => [
const quixosSourceLines = (source: QuixosSource, indentation: string): string[] => [
`${indentation}repository ${quoted(source.repository)};`,
...(source.policy
? [
`${indentation}policy ${source.policy};`,
`${indentation}ref ${quoted(source.ref)};`,
]
: []),
...(source.policy ? [`${indentation}policy ${source.policy};`, `${indentation}ref ${quoted(source.ref)};`] : []),
`${indentation}commit ${quoted(source.commit.toLowerCase())};`,
];
export const formatQuixosLock = (lock: QuixosRepositoryLock): string => {
const lines = [
"quixos-lock version 1 {",
" quixos source {",
...quixosSourceLines(lock.quixos, " "),
" }",
];
const lines = ["quixos-lock version 1 {", " quixos source {", ...quixosSourceLines(lock.quixos, " "), " }"];
for (const resource of lock.resources) {
lines.push(
"",
` ${resource.kind} ${resource.binding} source {`,
...sourceLines(resource.source, " "),
" }",
);
lines.push("", ` ${resource.kind} ${resource.binding} source {`, ...sourceLines(resource.source, " "), " }");
}
lines.push("}", "");
return lines.join("\n");
};
export const formatQuixosLockDocument = (document: QuixosLockDocument): string => {
const lines = [
`quixos-lock${document.kind === "fragment" ? " fragment" : ""} version 1 {`,
];
const lines = [`quixos-lock${document.kind === "fragment" ? " fragment" : ""} version 1 {`];
if (document.kind === "root") {
lines.push(
" quixos source {",
...quixosSourceLines(document.quixos, " "),
" }",
);
lines.push(" quixos source {", ...quixosSourceLines(document.quixos, " "), " }");
}
for (const importPath of document.imports) {
if (lines.length > 1) lines.push("");
@@ -452,11 +403,7 @@ export const formatQuixosLockDocument = (document: QuixosLockDocument): string =
}
for (const resource of document.resources) {
if (lines.length > 1) lines.push("");
lines.push(
` ${resource.kind} ${resource.binding} source {`,
...sourceLines(resource.source, " "),
" }",
);
lines.push(` ${resource.kind} ${resource.binding} source {`, ...sourceLines(resource.source, " "), " }");
}
lines.push("}", "");
return lines.join("\n");
+13 -12
View File
@@ -9,13 +9,17 @@ export type QuixosSourcePolicy = "pinned" | "track-release" | "track-development
// Resource repositories only need the exact Quixos commit they were authored
// against. A workspace root additionally declares how a runtime may advance
// that exact baseline.
export type QuixosSource = GitSource & ({
policy: QuixosSourcePolicy;
ref: string;
} | {
policy?: undefined;
ref?: undefined;
});
export type QuixosSource = GitSource &
(
| {
policy: QuixosSourcePolicy;
ref: string;
}
| {
policy?: undefined;
ref?: undefined;
}
);
export type LockedResourceKind = "interface" | "package";
@@ -40,9 +44,7 @@ export type QuixosLockFragmentDocument = {
resources: LockedResource[];
};
export type QuixosLockDocument =
| QuixosLockRootDocument
| QuixosLockFragmentDocument;
export type QuixosLockDocument = QuixosLockRootDocument | QuixosLockFragmentDocument;
export type QuixosRepositoryLock = {
formatVersion: 1;
@@ -60,8 +62,7 @@ export type NixGitInput = {
export const RETENTION_TAG_PREFIX = "refs/tags/quixos-reachability/";
export const retentionTagForCommit = (commit: string): string =>
`${RETENTION_TAG_PREFIX}${commit.toLowerCase()}`;
export const retentionTagForCommit = (commit: string): string => `${RETENTION_TAG_PREFIX}${commit.toLowerCase()}`;
export const nixGitInput = (source: GitSource): NixGitInput => ({
type: "git",