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:
@@ -0,0 +1,33 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { defineAuthz } from "../src/registry.ts";
|
||||
import { mergeCatalogs, emptyCatalog } from "../src/catalog.ts";
|
||||
import { generatePermissionTypes } from "../src/codegen.ts";
|
||||
|
||||
describe("generatePermissionTypes", () => {
|
||||
test("emits sorted Permission and Role unions", () => {
|
||||
const catalog = mergeCatalogs([
|
||||
{
|
||||
source: "t.ts",
|
||||
module: defineAuthz({
|
||||
permissions: { "post:write": {}, "post:read": {} },
|
||||
roles: { editor: ["post:*"], admin: ["*"] },
|
||||
}),
|
||||
},
|
||||
]);
|
||||
const out = generatePermissionTypes(catalog);
|
||||
expect(out).toContain('export type Permission = "post:read" | "post:write";');
|
||||
expect(out).toContain('export type Role = "admin" | "editor";');
|
||||
expect(out).toContain("DO NOT EDIT");
|
||||
});
|
||||
|
||||
test("emits never for an empty catalog so the file still typechecks", () => {
|
||||
const out = generatePermissionTypes(emptyCatalog());
|
||||
expect(out).toContain("export type Permission = never;");
|
||||
expect(out).toContain("export type Role = never;");
|
||||
});
|
||||
|
||||
test("escapes quotes in identifiers", () => {
|
||||
const catalog = mergeCatalogs([{ source: "t.ts", module: { roles: { 'we"ird': [] } } }]);
|
||||
expect(generatePermissionTypes(catalog)).toContain('"we\\"ird"');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user