@razerspine/runtime
v1.0.2
Published
Lightweight frontend runtime with DI container, router, reactive store, view bindings, and platform services.
Downloads
48
Maintainers
Readme
@razerspine/runtime
Lightweight frontend runtime engine for building modern SPA / Hybrid applications without heavy frameworks.
The runtime provides a minimal but powerful foundation including:
- Dependency Injection
- SPA Router
- Reactive View Engine
- Component Lifecycle
- Template Bindings
- Platform Services
- HTTP Utilities
Zero runtime dependencies.
Table of Contents
- Features
- Installation
- Quick Start
- Application Bootstrap
- Runtime Architecture
- Dependency Injection
- Reactive View Engine
- Component Lifecycle
- SPA Router
- Route Guards
- Programmatic Navigation
- Supported Data Attributes
- ThemeService
- TranslationService
- ApiService
- ConsoleLogger
- Exports
- Requirements
- License
Features
- Reactive View Engine — lightweight DOM binding system
- Dependency Injection — strict-mode DI container
- SPA Router — client-side navigation engine
- Route Guards — navigation protection and redirects
- Component Lifecycle — deterministic initialization and cleanup
- Template Bindings — declarative DOM updates
- Reactive State — Proxy-based store
- HTTP Utilities — structured Fetch wrapper
- Theme Management — light/dark mode with persistence
- Internationalization — DOM-based i18n system
- Logging Utilities
- Zero Dependencies
Installation
npm install @razerspine/runtimeQuick Start
Create a minimal SPA with Router.
import {
bootstrapApplication,
provideRouter
} from '@razerspine/runtime';
import {HomePage} from './views/home';
bootstrapApplication({
providers: [
provideRouter([
{path: '/', component: HomePage, title: 'Home'}
])
]
});Bootstrap will:
- Initialize the DI container
- Register the Router
- Mount the first page
Application Bootstrap
Applications start with: bootstrapApplication()
Example:
bootstrapApplication({
rootId: 'app-root',
providers: [
provideRouter([
{path: '/', component: HomePage}
])
]
});Bootstrap responsibilities:
- Initialize DI container
- Register providers
- Resolve routes
- Wait for DOM readiness
- Start the Router
This makes application startup deterministic and safe.
Runtime Architecture
Version 1.0.0 introduces a modular runtime architecture. The codebase is organized into clearly separated modules.
src/
├── core
├── router
├── reactivity
├── view
├── http
├── platform
└── utilsModule Overview
core
Dependency Injection container.
- Responsibilities: service registration, dependency resolution, injection helper.
router
SPA navigation engine.
- Features: route matching, async navigation, route guards, safe component rendering.
reactivity
Proxy-based reactive store via createStore().
- Features: deep observation, nested proxy caching, stable references, manual cleanup.
view
Component system and DOM rendering engine.
- Contains:
BaseComponent, bindings engine, bootstrap system. - Bindings are implemented using processor-based architecture.
bindings/
└── engine/
└── processors/Processors: bind, class, for, model, show.
http
HTTP utilities. Includes ApiService and ApiError.
platform
Platform-level services. Includes ThemeService and TranslationService.
utils
Shared runtime utilities (DOM helpers, console logging).
Dependency Injection
The runtime includes a strict-mode DI container. Services must be registered during bootstrap.
Injecting Services
import {inject, Router} from '@razerspine/runtime';
export class HomePage {
private router = inject(Router);
navigate() {
this.router.navigate('/dashboard');
}
}Providing Services
bootstrapApplication({
providers: [
{provide: ApiService},
{provide: ConsoleLogger}
]
});Factory Providers
bootstrapApplication({
providers: [
{
provide: ApiService,
useFactory: () => new ApiService('/api')
}
]
});Strict DI Mode: Services are not auto-instantiated. If a service is injected but not registered, the runtime will throw:
Service "MyService" is not registered in the DI container.
Reactive View Engine
Reactive components are built using BaseComponent. State changes automatically update the DOM.
Example Component
import {BaseComponent} from '@razerspine/runtime';
interface HomeState {
title: string
count: number
}
export class HomePage extends BaseComponent<HomeState> {
constructor(container: HTMLElement) {
super(container, {
title: 'Runtime Demo',
count: 0
});
}
protected render() {
this.container.innerHTML = `
<h1 data-bind="title"></h1>
<button data-click="increment">+</button>
<span data-bind="count"></span>
`;
}
increment() {
this.setState({
count: this.state.count + 1
});
}
}Component Lifecycle
Lifecycle execution order:
render() → initEventListeners() → update() → onInit()
Lifecycle orchestration is handled by mount(). Router automatically calls mount() for page components.
Async Lifecycle
Lifecycle hooks support async operations.
protected async onInit() {
const users = await api.get('/users');
this.setState({ users });
}Supported signatures:
render(): void | Promise<void>onInit(): void | Promise<void>
The Router waits for full initialization before completing navigation.
SPA Router
Router manages client-side navigation, browser history, component lifecycle, and route guards.
Route Configuration
import {Route} from '@razerspine/runtime';
const routes: Route[] = [
{
path: '/',
component: HomePage,
title: 'Home'
}
];Route Guards
Routes can define canActivate guards.
Guard results:
true— allow navigationfalse— block navigationstring— redirect (e.g.,'/login')Promise— async guard
Example:
const authGuard = () => {
const token = localStorage.getItem('token');
return token ? true : '/login';
};
// Usage in routes:
{
path: '/dashboard',
component: DashboardPage,
canActivate: [authGuard]
}Programmatic Navigation
import {inject, Router} from '@razerspine/runtime';
export class LoginPage {
private router = inject(Router);
onLoginSuccess() {
this.router.navigate('/dashboard');
}
}Supported Data Attributes
| Attribute | Description | Example |
|------------|------------------------|-------------------------------------|
| data-bind | Updates textContent | span(data-bind="user.name") |
| data-model | Two-way binding | input(data-model="email") |
| data-click | Event delegation | button(data-click="submit") |
| data-show | Conditional visibility | div(data-show="!isError") |
| data-class | Toggle CSS classes | div(data-class="active:isActive") |
| data-for | List rendering | ul(data-for="item:items") |
ThemeService
Manages light/dark theme state.
const theme = new ThemeService();
theme.init();
theme.setTheme('dark');TranslationService
DOM-based i18n system.
const locales = {
en: {greeting: {hello: 'Hello'}},
uk: {greeting: {hello: 'Привіт'}}
};
const i18n = new TranslationService(locales);
i18n.init();ApiService
Fetch wrapper with query params, timeout, automatic JSON handling, structured errors, and Bearer token support.
const api = new ApiService('[https://api.example.com](https://api.example.com)');
api.setToken('jwt');
const users = await api.get('/users');ConsoleLogger
Styled console logs.
const logger = new ConsoleLogger();
logger.success('Application started');Exports
import {
BaseComponent,
Router,
bootstrapApplication,
provideRouter,
inject,
ApiService,
ApiError,
ThemeService,
TranslationService,
ConsoleLogger
} from '@razerspine/runtime';Requirements
- Node.js:
^20.10.0or higher (LTS recommended) - TypeScript:
^5.0.0 - Browsers: Modern evergreen browsers (Chrome, Firefox, Safari, Edge)
License
ISC License
