feat(authz): generate Permission and Role union types

Emits sorted TS unions from the merged catalog so a typo in
can(ctx, "post:wrtie") is a compile-time error. Uses JSON.stringify
for string-literal escaping (not manual backslash/quote replace) so
role names containing raw newlines still produce valid TypeScript;
role names are not regex-validated like permission ids, so this
matters for the raw mergeCatalogs path.
This commit is contained in:
2026-08-04 21:19:04 +05:30
parent 91e5c6e0c5
commit 726b8a7d24
4 changed files with 61 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
import type { AuthzCatalog } from "./types.ts";
function union(values: string[]): string {
if (!values.length) return "never";
// JSON.stringify escapes backslashes, quotes, and control characters
// (including raw newlines, which the registry does not reject in role
// names and which would otherwise break out of the string literal).
return values
.slice()
.sort()
.map((value) => JSON.stringify(value))
.join(" | ");
}
/**
* Emit compile-time unions for the registered permissions and roles, so a
* typo in can(ctx, "post:wrtie") is a type error rather than a silent false.
*/
export function generatePermissionTypes(catalog: AuthzCatalog): string {
return `// Generated by \`wrnexus authz generate\`. DO NOT EDIT.
export type Permission = ${union([...catalog.permissions.keys()])};
export type Role = ${union([...catalog.roles.keys()])};
`;
}
+1
View File
@@ -167,3 +167,4 @@ export type {
SubjectAssignments,
} from "./types.ts";
export type { AuthorizeDecisionOptions } from "./advanced.ts";
export { generatePermissionTypes } from "./codegen.ts";