Arkveil
SDK

Typed codes & attributes

Generate compile-time typed action codes and user/context attribute shapes for the Arkveil SDK.

The SDK models action codes and user/context attributes as generic parameters plus three empty registry interfaces:

interface ArkveilCodeRegistry {}
interface ArkveilUserRegistry {}
interface ArkveilContextRegistry {}

Until augmented, these fall back to string and Record<string, any>. Augmenting them via TypeScript declaration merging gives you compile-time checked action codes and attribute shapes everywhere in your app, without passing generics manually at every call site.

This augmentation file is generated by the Arkveil CLI — a separate tool from the arkveil-js SDK packages.

Generate the file

arkveil generate typescript -o src/arkveil.generated.ts

See the CLI's generate command reference for all options, including generating only a subset (--include codes,user,context) or piping to stdout.

Generated shape

export type ArkveilCodes =
  | "content-service.article-delete"
  | "user-service.user-create";

export interface ArkveilUserAttributes {
  id?: string;
  role: "admin" | "editor" | "viewer";
}

export interface ArkveilContextAttributes {
  ipAddress?: string;
  region?: "EU" | "US";
}

declare module "arkveil" {
  interface ArkveilCodeRegistry {
    codes: ArkveilCodes;
  }
  interface ArkveilUserRegistry {
    attributes: ArkveilUserAttributes;
  }
  interface ArkveilContextRegistry {
    attributes: ArkveilContextAttributes;
  }
}
  • ArkveilCodes comes from your workspace's action tree.
  • ArkveilUserAttributes and ArkveilContextAttributes come from the JSON Schemas configured for user and context attributes in your workspace (arkveil schemas set user|context).

Using it

Import the generated file once, anywhere loaded globally (its side effect is what performs the declaration merge):

import "./arkveil.generated";

After that, every SDK entry point — checkPermission, @arkveil/node's permissionPoint, @arkveil/nest's @PermissionPoint — is typed against your workspace's real action codes and attribute shapes, and passing an unknown code or an invalid attribute value becomes a compile error.

Alternatively, skip global augmentation and pass the generated types as explicit generics:

import { Arkveil } from "arkveil";
import type {
  ArkveilCodes,
  ArkveilUserAttributes,
  ArkveilContextAttributes,
} from "./arkveil.generated";

const arkveil = new Arkveil<ArkveilCodes, ArkveilUserAttributes, ArkveilContextAttributes>({
  serviceUrl: "https://api.arkveil.com",
  apiKey: "your-api-key",
});

In NestJS, use createPermissionPoint<ArkveilCodes>() to build a decorator bound to an explicit code union instead of relying on global augmentation — see NestJS SDK: Typed permission points.

Verifying types compile-time

Because unknown codes and invalid attribute values become type errors, you can assert they're rejected with @ts-expect-error in your own test suite:

// @ts-expect-error unknown action code
arkveil.checkPermission({ actionCode: "not-a-real-code", user, context });

// @ts-expect-error role must be "admin" | "editor" | "viewer"
const badUser: ArkveilUserAttributes = { role: "superuser" };

On this page