feat(dev-server): load the authz catalog at boot
Adds loadAppAuthzCatalog(appDir) to @wrnexus/dev-server: discovers app/authz/*.ts declarations via buildRouter, imports and merges them into an AuthzCatalog, returning an empty catalog when the app has no declarations. A declaration with no default export is skipped with a warning; a genuine conflict between two declarations throws WRN-AUTHZ-CONFLICT naming both source files. Declared the missing @wrnexus/authz workspace dependency in dev-server's package.json.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { buildRouter } from "@wrnexus/router";
|
||||
import {
|
||||
emptyCatalog,
|
||||
mergeCatalogs,
|
||||
type AuthzCatalog,
|
||||
type AuthzModule,
|
||||
type CatalogSource,
|
||||
} from "@wrnexus/authz";
|
||||
|
||||
/**
|
||||
* Load and merge every `app/authz/*.ts` declaration. Conflicts throw so a
|
||||
* misconfigured catalog fails the boot rather than silently changing who can
|
||||
* do what. An app with no `app/authz/` directory gets an empty catalog rather
|
||||
* than an error, since not every app uses permissions.
|
||||
*/
|
||||
export async function loadAppAuthzCatalog(appDir: string): Promise<AuthzCatalog> {
|
||||
const router = buildRouter(appDir);
|
||||
if (!router.authz.length) return emptyCatalog();
|
||||
const sources: CatalogSource[] = [];
|
||||
for (const entry of router.authz) {
|
||||
// buildRouter already skips *.gen.ts, so only real declarations arrive here.
|
||||
const imported = (await import(pathToFileURL(entry.file).href)) as { default?: AuthzModule };
|
||||
if (!imported.default) {
|
||||
console.warn(`[wrnexus] authz declaration ${entry.file} has no default export; skipping.`);
|
||||
continue;
|
||||
}
|
||||
sources.push({ source: entry.file, module: imported.default });
|
||||
}
|
||||
return mergeCatalogs(sources);
|
||||
}
|
||||
Reference in New Issue
Block a user