# js-kompo-utils - Architecture

## Two Responsibilities

The system splits app initialization into two classes with distinct roles:

**`KompoJsConfigBuilder`** — Declares *what* the app needs. Knows nothing about how initialization works. Stores components, feature flags, plugins, callbacks. Pure data, no side effects.

**`KompoJsInitializer`** — Executes *how* the app boots. Reads the config and runs a fixed sequence of steps. This is the only place where `require()`, `Vue.component()`, and `window` mutation happen.

The builder can be shared, extended, and modified across apps. The initializer is the part that would change if you migrated to a different framework or build system.

## Why this separation

A typical Laravel `app.js` mixes concerns: imports, global assignments, component registration, library boot, and Vue mounting — all in one imperative file. If one line fails, everything after it breaks.

This system separates *configuration* from *execution*:

- The consumer declares intent: "I want jQuery, these components, this bootstrap"
- The initializer handles the mechanics: load order, global assignment, Vue setup

This means a consuming app doesn't need to know that Vue must be on `window` before `vue-kompo` loads, or that Google Maps needs a style set before import. The initializer encapsulates that knowledge.

## Initialization sequence

```
1. bootstrapExecution    — Run the app's Laravel bootstrap (axios, lodash, CSRF)
2. requireFilesToImport  — Execute file import callbacks (animations, scripts)
3. bootJqueryIfRequired  — Expose jQuery on window
4. bootVue               — Load Vue, vue-kompo, register plugins and components
5. decorateWindow        — Apply window utils and run decorators
6. bootCkEditorIfRequired
7. bootMapsIfRequired
8. instanceApp           — Mount Vue on the DOM
```

Every step supports `addBeforeStepCallback` / `addAfterStepCallback` for app-specific logic at any point in the sequence.

## defaultConfig

`app.js` exports a `defaultConfig` — a pre-built `KompoJsConfigBuilder` with sensible defaults for kompo apps: all package components, jQuery, CKEditor, Maps, QR reader, window utilities, animations.

A consuming app imports this and layers its own config on top:

```javascript
const config = defaultConfig
    .bootstrap(() => require('./bootstrap'))
    .excludeComponent('VlApexChart')
    .addWindowDecorator(myDecorator);
```

This avoids repeating 30+ lines of component registration across every app while keeping full control.

## Error resilience

Steps are categorized as **essential** or **non-essential**:

- **Essential** (`bootstrapExecution`, `bootVue`, `instanceApp`): If these fail, the app can't function. Errors propagate normally — you want these to break the build or show a clear error.
- **Non-essential** (everything else): Wrapped in try/catch. A failed CKEditor init or animation import logs a warning but doesn't prevent the app from rendering.

This prevents the scenario where a runtime error in a non-critical feature (like tutorials) kills the entire view.

## Replacing the initializer

`KompoJsInitializer` is the only class coupled to Vue 2, webpack `require()`, and the specific boot sequence. If you migrate to Vue 3, Vite, or a different framework:

1. Create a new initializer class (e.g., `KompoVue3Initializer`)
2. It reads the same `KompoJsConfigBuilder` config
3. Implements its own step sequence

The config builder stays the same — apps only change which initializer they instantiate.
