Skip to content

Using TypeScript

Sentrie has a built-in TypeScript compiler and runtime that allows you to use TypeScript in your policy packs. This enables you to write reusable utility functions, type definitions, and complex logic that can be shared across policies.

TypeScript support in Sentrie allows you to:

  • Import built-in libraries from @sentrie/* modules
  • Create and import your own TypeScript modules from the policy pack
  • Use TypeScript functions in your policies
  • Leverage full TypeScript type checking and IntelliSense support

The use statement allows you to import functions from TypeScript modules:

use { function1, function2 } from @sentrie/module

Note: Built-in @sentrie/* modules do not use quotes. Local TypeScript files use quotes for relative paths.

Built-in libraries are prefixed with @sentrie/:

namespace com/example/auth
policy mypolicy {
use { now } from @sentrie/time
use { sha256 } from @sentrie/hash
fact user!: User
fact passwordInput!: string
rule myrule = default false {
let currentTime = time.now()
let hash = sha256(passwordInput)
yield hash == user.passwordHash
}
export decision of myrule
}

You can import TypeScript files from your policy pack using relative paths. These paths are automatically normalized to @local paths as described below:

namespace com/example/auth
policy mypolicy {
use { calculateAge } from "./utils.ts" as utils
use { validateEmail } from "../helpers/validation.ts"
fact user!: utils.User
rule myrule = default false {
yield utils.calculateAge(user.birthDate) >= 18
and utils.validateEmail(user.email)
}
export decision of myrule
}

Here’s a complete example showing various usage patterns:

namespace com/example/auth
shape User {
passwordHash: string
birthDate: string
email: string
}
policy mypolicy {
use { md5, sha256 } from @sentrie/hash
use { now } from @sentrie/time
use { calculateAge, validateEmail } from "./utils.ts"
fact user!: User
fact passwordInput!: string
fact userAge!: number
rule myrule = default false {
yield
sha256(passwordInput) == user.passwordHash
and
userAge == utils.calculateAge(user.birthDate)
and
utils.validateEmail(user.email)
}
export decision of myrule
}

Relative paths are resolved relative to the current file (.sentrie or .ts):

  • ./file.ts - Same directory as the policy file
  • ../parent.ts - Parent directory
  • ./utils/helper.ts - Subdirectory
import { now } from "./utils/time";
let currentTime = now();
namespace com/example/auth
policy mypolicy {
use { now } from "./utils/time"
}

All relative paths are normalized to @local paths internally, ensuring consistent imports regardless of file location.

The @local prefix indicates paths relative to the pack root. These paths are normalized from relative imports or can be used directly in policies and TypeScript files as described above:

  • @local/user/id evaluates to $PACKROOT/user/id.ts
  • @local/utils/helper evaluates to $PACKROOT/utils/helper.ts
  • @local/something evaluates to $PACKROOT/something.ts

Built-in modules use the @sentrie/* prefix:

  • @sentrie/time - Time and date utilities
  • @sentrie/crypto - Cryptographic functions
  • @sentrie/hash - Hash functions
  • @sentrie/encoding - Encoding/decoding utilities
  • And more…

See the Built-in TypeScript Modules documentation for a complete list.

When importing from a module, you can optionally specify an alias using the as keyword:

use { now, parse } from @sentrie/time as time
use { md5 } from @sentrie/hash as crypto

If no alias is specified, the default alias is the last part of the module path. You can use an explicit alias to organize imports for both built-in and user-defined modules:

  • use { now } from @sentrie/time → default alias is timetime.now()
  • use { now } from @sentrie/time as timeModule → explicit alias → timeModule.now()
  • use { calculateAge } from "./utils.ts" → default alias is utilsutils.calculateAge()
  • use { calculateAge } from "./utils.ts" as helpers → explicit alias → helpers.calculateAge()

You can create your own TypeScript modules in your policy pack. These modules:

  1. Must be in the pack directory - TypeScript files must be within the policy pack root
  2. Can import other modules - Including both built-in and local modules
  3. Use normalized paths - Relative imports are automatically converted to @local paths

Example TypeScript file (user.ts in the pack root):

import { something } from @local/something;
export function User() {
return {
something: something(),
name: "John Doe",
email: "john.doe@example.com",
role: "admin",
status: "active",
};
}

When this file is located at $PACKROOT/user.ts, the import @local/something evaluates to $PACKROOT/something.ts.

The import can also be written as import { something } from "./something.ts".

Sentrie provides a comprehensive set of built-in TypeScript libraries for common operations:

  • JavaScript Globals - JavaScript globals (Math, String, Number, Date, JSON, Array)
  • Collection - List and map manipulation utilities
  • Crypto - Cryptographic functions (SHA-256)
  • Encoding - Base64, Hex, and URL encoding/decoding
  • Hash - MD5, SHA-1, SHA-256, SHA-512, and HMAC
  • JSON - JSON validation utility
  • JWT - JSON Web Token decoding and verification
  • Net - Network and IP address utilities
  • Regex - Regular expression pattern matching
  • Semver - Semantic version comparison and validation
  • Time - Date and time manipulation
  • URL - URL parsing and manipulation
  • UUID - UUID generation (v4, v6, v7)

See the Built-in TypeScript Modules index for detailed documentation on each library.

  1. Use descriptive aliases - When importing multiple items from the same module, use a clear alias
  2. Organize your modules - Keep related TypeScript files in organized directories
  3. Leverage built-in libraries - Use @sentrie/* modules for common operations instead of reimplementing
  4. Type safety - Take advantage of TypeScript’s type checking for better error detection
  5. Module reuse - Create reusable utility modules that can be shared across multiple policies