Skip to main content

@Resolver

The @Resolver() decorator maps a URL path to a controller class. When a user navigates to the specified URL, the framework instantiates the controller and runs its lifecycle methods.

Package: io-oidis-commons

import { Resolver, ResolverType, ResolverScope } from "@io-oidis-commons/.../Primitives/Decorators.js";

Syntax​

@Resolver("/path")
export class MyController extends BasePageController<MyPage> { ... }

@Resolver("/path", { type: ResolverType.BACKEND_ONLY, scope: ResolverScope.DEV, priority: 10 })
export class MyController extends BasePageController<MyPage> { ... }

Parameters​

ParameterTypeDefaultDescription
pathstringrequiredURL path to match (e.g., "/main", "/settings")
options.typeResolverTypeUNIVERSALWhich side handles the request
options.scopeResolverScopeALL_PROFILESWhen the resolver is active
options.prioritynumber0Resolution order (higher = checked first)

ResolverType​

ValueDescription
UNIVERSALWorks on both frontend and backend (default)
BACKEND_ONLYServer-side only (API controllers, server-rendered pages)
FRONTEND_ONLYBrowser-side only

ResolverScope​

ValueDescription
ALL_PROFILESActive in all environments (default)
PRODOnly in production builds
DEVDevelopment mode only — the class exists but is never matched in production routing

DEV scope is particularly useful for:

  • Test pages and debug panels
  • Runtime test viewers (*TestPanelViewer)
  • Development utilities that should never appear in production

Registration​

@Resolver registers the mapping in globalThis.oidisResolvers at class load time. No manual registration is needed — resolvers are auto-detected.

Access Control​

Page-Level: accessValidator()​

Override in your PageController to restrict the entire page:

@Resolver("/admin")
export class AdminPageController extends BasePageController<AdminPage> {

protected async accessValidator() : Promise<boolean> {
const auth = AuthManagerConnector.getClient();
return await auth.IsAdmin();
}
}

The accessValidator() method:

  • Defined in BaseHttpResolver (commons), defaults to true
  • Called in Process() before resolver()
  • On false → calls Return403Forbidden() → reloadToNotAuthorized()
  • AsyncBasePageController (services) wraps this in canResolve() chaining: environment check → accessValidator() → redirect

Tab-Level: AccessValidator()​

Override in your PanelController to restrict individual tabs:

export class UsersPanelController extends BasePanelController<UsersPanel> {

public async AccessValidator() : Promise<boolean> {
const auth = AuthManagerConnector.getClient();
return await auth.HasPermission("admin.users");
}
}

The AccessValidator() method (note: capital A):

  • Defined in BasePanelController (gui), defaults to true
  • Called per-tab in BasePageLayoutController.processRequestPath() during tab URL matching
  • On false → reloadToNotAuthorized()

Custom Redirect​

Override reloadToNotAuthorized() to customize where unauthorized users go:

protected reloadToNotAuthorized() : void {
// Default: redirects to /ServerError/Http/NotAuthorized
// Override for custom behavior:
window.location.href = "/login";
}

Usage on PanelControllers​

While @Resolver is most commonly used on PageControllers, it can also be applied to PanelControllers for direct URL-to-panel routing:

@Resolver("/main/settings")
export class SettingsPanelController extends BasePanelController<SettingsPanel> { ... }

Examples​

// Standard page
@Resolver("/main")
export class MainPageController extends BasePageController<MainPage> { ... }

// Admin-only page
@Resolver("/admin")
export class AdminPageController extends BasePageController<AdminPage> {
protected async accessValidator() : Promise<boolean> {
return await AuthManagerConnector.getClient().IsAdmin();
}
}

// Dev-only test page
@Resolver("/tests", { scope: ResolverScope.DEV })
export class TestPageController extends BasePageController<TestPage> { ... }

// Backend-only resolver
@Resolver("/api/webhooks", { type: ResolverType.BACKEND_ONLY })
export class WebhookController extends BaseHttpResolver { ... }

// High-priority resolver (checked before others)
@Resolver("/", { priority: 100 })
export class RootController extends BasePageController<LandingPage> { ... }

See also: Routing | @Extern | @Route