xPulse
πŸ‡¬πŸ‡§ EN

@xpulse/app – Component Spec

Status: ACCEPTED Β· Updated March 2026 Parent: GLOBAL_concept-ecosystem.md


Overview

Entry point for every xPart. Bootstraps the entire stack via a resilient service loader and provides the app root as well as environment helpers.

Two responsibilities: bootstrap the stack + provide the app root – nothing more.

@xpulse/app is the only permitted place in the ecosystem that "knows everything". All other packages remain fully decoupled.


Dependencies

Two hard dependencies that are always required:

The standard stack is shipped as dependencies for convenience and auto-discovered by the service loader at runtime: @xpulse/logger, @xpulse/http, @xpulse/router, @xpulse/template, @xpulse/theme, @xpulse/controller.

@xpulse/debug and @xpulse/dev are optional β€” no error if not installed. Feature packages (@xpulse/doc, etc.) are installed explicitly by the app.


API

app.init(env?)

Bootstraps the entire stack via the resilient service loader. Always everything – no selective loading.

import app from '@xpulse/app';
// env from APP_ENV β†’ NODE_ENV β†’ null
await app.init();
// explicit env
await app.init('stage');
await app.init('production');

app.start() / app.stop()

app.start(); // blocking
await app.stop(); // graceful shutdown

Typical index.js

import app from '@xpulse/app';
await app.init();
app.start();
process.on('SIGTERM', () => app.stop());
process.on('SIGINT', () => app.stop());

Environments

Value Description
development Local development
stage Staging environment – RC testing
production Production environment

Additional environments are allowed but undocumented. APP_ENV takes precedence over NODE_ENV.


App Root

The directory where xpulse.json lives – typically process.cwd(). Set on the first app.init() call and immutable thereafter.

All paths in the ecosystem are defined relative to the app root.


Helper Methods

app.root()

Returns the absolute app root path.

app.root()
// β†’ '/var/www/my-app'

app.path(relative)

Resolves a relative path starting from the app root.

app.path('src/templates') // β†’ '/var/www/my-app/src/templates'
app.path('var/cache/template') // β†’ '/var/www/my-app/var/cache/template'
app.path('var/log') // β†’ '/var/www/my-app/var/log'

app.env

The current environment.

app.env // β†’ 'stage' | 'production' | 'development' | null

app.isDev()

app.isDev() // β†’ true when env === 'development'

app.isProd()

app.isProd() // β†’ true when env === 'production'

app.isStage()

app.isStage() // β†’ true when env === 'stage'

Bootstrap Order

app.init() works via a auto-discovery service loader β€” packages declare their dependencies in xpulse.json, the loader resolves the correct init order via topological sort. See service-loader.md.

1. Set app root + config.load() ← xpulse.json + .env
2. debug.bootstrapDebug() ← only when debug.enabled
runs before loader so everything is debuggable
3. Service loader ← auto-discovers all installed @xpulse/* packages
with a service section in their xpulse.json
topological sort by depends[]
resilient: missing or disabled packages are skipped

@xpulse/event does not need an init() β€” zero dependencies, works on import. @xpulse/dev is a separate system β€” hooks in from the outside, loader ignores it.


Graceful Shutdown

1. Stop accepting new requests
2. Complete running requests (timeout: 30s)
3. Flush @xpulse/logger
4. process.exit(0)

Emitted Events

Event Payload When
app:init { env, root } Bootstrap begins
app:ready { env, root, uptime } Entire stack ready
app:stopping { signal } SIGTERM / SIGINT received
app:stopped { uptime, exitCode } Shutdown complete
app:service:ready { service } Service initialised successfully
app:service:skipped { service, reason } Not installed or load: false
app:service:error { service, error } Init threw, loader continues

The complete event reference for all packages is in GLOBAL_adr-010-event-driven.md.


Receipt

@xpulse/app ships a receipt that is automatically executed on npm install.

receipt/up.js creates (only if not already present):

File Contents
src/index.js Minimal runnable app
xpulse.json Minimal configuration (name, type)
.npmrc Registry reference to npm.xpulse.one
.env.example Documented example variables

receipt/down.js: Warning – no automatic deletion.

.env.example Contents

# xPulse App – Environment Variables
# Copy this file to .env and adjust the values
# Server
PORT=3000
# Environment: development | stage | production
APP_ENV=development
# Logging
LOG=true
DEBUG=false

Package Structure

@xpulse/app/
src/
index.js ← default export: app object
bootstrap/
app.js ← app root + config.load()
services.js ← auto-discovery service loader (reads xpulse.json, topo-sort)
receipt/
up.js
down.js
files/
src/
index.js
xpulse.json
.npmrc
.env.example
test/
app.test.js
docs/
index.md
de/ index, guide, api
en/ index, guide, api
Dockerfile
Makefile
README.md
package.json
xpulse.json
en/spec.md 2026-03-30