Files
WRNexusJS/packages/syntax/src/versioning.ts
T
2026-07-27 12:42:18 +05:30

64 lines
1.8 KiB
TypeScript

import type { WrnDiagnostic } from "./diagnostics.ts";
/** Current stable syntax contract. Bump only when parsers/codegen need migration. */
export const WRN_SYNTAX_VERSION = "0.4" as const;
export type WrnSyntaxFeature =
| "typed-declarations"
| "layouts"
| "server-client-blocks"
| "effects"
| "watch"
| "lifecycle"
| "embedded-api"
| "realtime"
| "runtime-markers";
export const WRN_SYNTAX_FEATURES: Readonly<Record<WrnSyntaxFeature, boolean>> = Object.freeze({
"typed-declarations": true,
layouts: true,
"server-client-blocks": true,
effects: true,
watch: true,
lifecycle: true,
"embedded-api": true,
realtime: true,
"runtime-markers": true,
});
export interface SourceRange {
start: number;
end: number;
}
export function createSourceRange(start: number, end: number): SourceRange {
if (!Number.isInteger(start) || !Number.isInteger(end) || start < 0 || end < start) {
throw new RangeError(`Invalid source range ${start}..${end}`);
}
return { start, end };
}
export function sliceSource(source: string, range: SourceRange): string {
return source.slice(range.start, range.end);
}
export function diagnosticSummary(diagnostics: readonly WrnDiagnostic[]): {
errors: number;
warnings: number;
info: number;
codes: Record<string, number>;
} {
const summary = { errors: 0, warnings: 0, info: 0, codes: {} as Record<string, number> };
for (const diagnostic of diagnostics) {
if (diagnostic.severity === "error") summary.errors++;
else if (diagnostic.severity === "warning") summary.warnings++;
else summary.info++;
summary.codes[diagnostic.code] = (summary.codes[diagnostic.code] ?? 0) + 1;
}
return summary;
}
export function supportsSyntaxFeature(feature: string): feature is WrnSyntaxFeature {
return Object.prototype.hasOwnProperty.call(WRN_SYNTAX_FEATURES, feature);
}