feat(cli): add wrnexus authz list/generate/init

Introspects the merged authz catalog, emits app/authz/permissions.gen.ts
type unions, and scaffolds the assignment-table migration. init validates
--dialect explicitly (unrecognised values reject rather than silently
falling back to sqlite) and joins authzMigrationSql's up/down statement
lists with terminators instead of interpolating the arrays.

Test scaffolding for dynamically-imported app/authz declarations must
live inside the repo tree (not os.tmpdir()) for the "@wrnexus/*" bare
specifier to resolve via tsconfig paths; .gitignore excludes the scratch
dirs this produces.
This commit is contained in:
2026-08-04 21:34:56 +05:30
parent e5d0654d2a
commit b9098382b3
4 changed files with 325 additions and 0 deletions
+9
View File
@@ -7,6 +7,7 @@
* wrnexus create <app-name> scaffold a new app
* wrnexus eject <name...> copy a Wire UI component into your app
* wrnexus db <migrate|rollback|status|new> database migrations
* wrnexus authz <list|generate|init> authorization catalog tooling
*/
import { join, resolve } from "node:path";
@@ -66,6 +67,7 @@ Usage:
wrnexus eject <name...> Copy a Wire UI component into app/components
wrnexus update [dir] [--latest] Upgrade deps, migrate project files, and verify the app
wrnexus db <cmd> Migrations: migrate | rollback | status | seed | generate | new
wrnexus authz <cmd> Authorization: list | generate | init [--dialect=sqlite|postgres|mysql]
wrnexus test [level] [app-dir] [--watch]
Run unit | component | api | browser | visual | accessibility | performance
wrnexus profiles [app-dir] List config profiles (dev/prod/uat/…) and their env files
@@ -270,6 +272,13 @@ async function main(): Promise<void> {
await runDbCommand(".", sub, dbArgs);
break;
}
case "authz": {
bootstrapProfile(".", "development", rest);
const { runAuthzCommand } = await import("./authz.ts");
const [sub, ...authzArgs] = rest.filter((a) => !a.startsWith("--profile="));
await runAuthzCommand(".", sub, authzArgs);
break;
}
case "profiles": {
const { listProfiles } = await import("./profiles.ts");
await listProfiles(rest.find((a) => !a.startsWith("--")) ?? ".");