@neoimpulse/cap-js-bootstrap
v1.0.9
Published
SICP-compliant CAP bootstrap package by Neoimpulse
Readme
Bootstrap - SICP-konform
Dieses Bootstrap-Modul folgt strikten SICP-Prinzipien (Structure and Interpretation of Computer Programs) und ist als npm-Paket vorbereitet.
Installation (Consumer-Projekt)
npm install @neoimpulse/cap-js-bootstrapVerwendung
# Aus dem Consumer-Projekt
npx cap-js-bootstrap --verboseAlternativ direkt:
node node_modules/@neoimpulse/cap-js-bootstrap/dist/index.js --verboseKonfiguration
Das Bootstrap liest seine Konfiguration aus der bootstrap-Sektion der package.json im jeweiligen Projektverzeichnis.
CLI-Parameter ueberschreiben die Werte aus der Konfiguration.
CLI-Parameter
--help: Hilfe anzeigen und beenden--debug: Debug-Modus fuer Services aktivieren--with-bindings-update: Bindings/Default-Env aktualisieren--no-bindings: Bindings-Update deaktivieren (ueberschreibtwithBindingsUpdate)--parallel: Services parallel starten (schneller, ggf. Limits beachten)--verbose: Ausfuehrliche Ausgabe--profile <name>: CDS-Profil fuer Binding/Start (z. B.hybrid,pg)--runtime <js|ts>: Runtime-Auswahl (js ->cds, ts ->cds-ts)
package.json: bootstrap-Konfiguration
Beispiel:
{
"bootstrap": {
"debug": false,
"withBindingsUpdate": false,
"parallel": false,
"verboseOutput": true,
"profile": "pg",
"runtime": "ts",
"approuterPath": "recollection",
"basePath": "./",
"services": [
{
"path": "recollection",
"name": "recollection-srv",
"port": 4004,
"addPoolConfiguration": false,
"boundServices": ["uaa-service", "destination-service", "connectivity-service"]
}
]
}
}Bedeutung der Felder
debug: Aktiviert Debug-Ausgabe fuer gestartete Services (kann per--debugueberschrieben werden)withBindingsUpdate: Fuehrtcds bind/default-envaus (per--with-bindings-updateoder--no-bindings)parallel: Startet Services parallel (per--parallel)verboseOutput: Aktiviert detaillierte Logs (per--verbose)profile: CDS-Profil fuer Bindings und Service-Start (per--profile)runtime: Runtime-Auswahl fuer Service-Start (ts->cds-ts,js->cds)basePath: Basisverzeichnis fuer Service-Pfade (relativ zum Projekt-Root)approuterPath: Pfad zum Approuter relativ zubasePathservices: Liste der zu startenden Servicespath: Relativer Pfad des Services (wird mitbasePathkombiniert)name: Service-Name fuerdefault-env/Bindingsport: HTTP-Port des ServicesboundServices: Liste externer Services, die gebunden werdenaddPoolConfiguration: Wenntrue, fuegt DB-Pool-Config in.cdsrc-private.jsonhinzu
Entwicklung
npm install
npm run build
node dist/index.js --verboseArchitektur
Vier-Schichten-Architektur Visualisierung
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 4: I/O & Orchestration (handlers/) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ index.ts (Main) │
│ ├── checkCfLogin() [cloud-foundry.ts] │
│ ├── downloadCredentials() [binding-orchestration.ts] │
│ ├── loadServicesSequentially() [service-operations.ts] │
│ ├── loadServicesParallel() [service-operations.ts] │
│ ├── loadApprouter() [service-operations.ts] │
│ └── createShutdownHandler() [shutdown.ts] │
│ │
│ binding-orchestration.ts │
│ ├── bindServices() │
│ │ ├── checkFileExists() [file-operations.ts] │
│ │ ├── downloadDefaultEnv() [cloud-foundry.ts] │
│ │ ├── bindServiceToCds() [cloud-foundry.ts] │
│ │ └── addPoolConfiguration() [configuration.ts] │
│ └── downloadCredentials() │
│ │
│ service-operations.ts │
│ ├── loadService() │
│ │ ├── spawnProcess() [process-operations.ts] │
│ │ └── waitForProcessOutput() [process-operations.ts] │
│ ├── loadServicesSequentially() │
│ ├── loadServicesParallel() │
│ └── loadApprouter() │
│ │
│ cloud-foundry.ts │
│ ├── checkCfLogin() │
│ ├── downloadDefaultEnv() │
│ └── bindServiceToCds() │
│ │
│ configuration.ts │
│ └── addPoolConfiguration() │
│ ├── readJsonFile() [file-operations.ts] │
│ └── writeJsonFile() [file-operations.ts] │
│ │
│ file-operations.ts │
│ ├── checkFileExists() │
│ ├── readJsonFile() │
│ └── writeJsonFile() │
│ │
│ process-operations.ts │
│ ├── spawnProcess() │
│ ├── waitForProcessOutput() │
│ ├── waitForProcessClose() │
│ └── terminateProcess() │
│ │
│ logging.ts │
│ ├── createLogger() │
│ ├── logMessage() │
│ └── logError() │
│ │
│ shutdown.ts │
│ └── createShutdownHandler() │
│ │
│ help.ts │
│ ├── showHelp() │
│ ├── showParallelHints() │
│ └── showTroubleshootingHints() │
│ │
└─────────────────────────────────────────────────────────────────────┘
↓ ruft auf
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 3: Domain Operations (domain/) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ validation.ts │
│ ├── validatePattern() → Pure Function │
│ ├── findMatchingPattern() → Pure Function │
│ └── hasRejectPattern() → Pure Function │
│ │
│ transformation.ts │
│ ├── formatLogLine() → Pure Function │
│ ├── formatLogChunk() → Pure Function │
│ ├── buildServiceTask() → Pure Function │
│ ├── mergeConfigWithPath() → Pure Function │
│ ├── buildPoolConfig() → Pure Function │
│ ├── parseUserArgs() → Pure Function │
│ └── extractProfileArg() → Pure Function │
│ │
│ calculation.ts │
│ ├── calculateDebugPort() → Pure Function │
│ ├── calculateStartupTime() → Pure Function │
│ └── shouldLoadSequentially() → Pure Function │
│ │
└─────────────────────────────────────────────────────────────────────┘
↓ ruft auf
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 2: Generic Utilities (lib/) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ result-helpers.ts │
│ ├── chain() → Pure Function │
│ ├── pipeline() → Pure Function │
│ ├── success() → Pure Function │
│ └── failure() → Pure Function │
│ │
│ array-utils.ts │
│ ├── mapArray() → Pure Function │
│ ├── filterArray() → Pure Function │
│ └── reduceArray() → Pure Function │
│ │
│ string-utils.ts │
│ ├── splitLines() → Pure Function │
│ ├── joinLines() → Pure Function │
│ └── addPrefix() → Pure Function │
│ │
└─────────────────────────────────────────────────────────────────────┘
↓ ruft auf
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 1: Language Primitives │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Array.map() Array.filter() Array.reduce() │
│ String.split() String.join() Object.keys() │
│ Promise.all() Promise.resolve() │
│ │
└─────────────────────────────────────────────────────────────────────┘Datenfluss
Beispiel: Service starten
User
↓
main() [Layer 4]
↓ ruft
loadServicesParallel() [Layer 4]
↓ ruft
loadService() [Layer 4]
├→ calculateDebugPort() [Layer 3] → Pure
├→ spawnProcess() [Layer 4] → I/O
├→ waitForProcessOutput() [Layer 4] → I/O
│ ├→ hasRejectPattern() [Layer 3] → Pure
│ └→ findMatchingPattern() [Layer 3] → Pure
│ └→ validatePattern() [Layer 3] → Pure
└→ createLogger() [Layer 4] → I/O
└→ formatLogChunk() [Layer 3] → Pure
└→ splitLines() [Layer 2] → PureBeispiel: Config aktualisieren
User
↓
main() [Layer 4]
↓ ruft
downloadCredentials() [Layer 4]
↓ ruft
bindServices() [Layer 4]
↓ ruft
addPoolConfiguration() [Layer 4]
├→ readJsonFile() [Layer 4] → I/O
├→ buildPoolConfig() [Layer 3] → Pure
└→ writeJsonFile() [Layer 4] → I/ODependency Graph
graph TD
A[index.ts] --> B[binding-orchestration.ts]
A --> C[service-operations.ts]
A --> D[shutdown.ts]
A --> E[help.ts]
B --> F[cloud-foundry.ts]
B --> G[configuration.ts]
B --> H[file-operations.ts]
C --> I[process-operations.ts]
C --> J[logging.ts]
F --> I
F --> J
G --> H
I --> K[validation.ts]
J --> L[transformation.ts]
K --> M[result-helpers.ts]
L --> M
L --> N[string-utils.ts]
style A fill:#f9f,stroke:#333
style K fill:#9f9,stroke:#333
style L fill:#9f9,stroke:#333
style M fill:#99f,stroke:#333
style N fill:#99f,stroke:#333Legende:
- 🟪 Layer 4 (I/O & Orchestration)
- 🟩 Layer 3 (Domain Operations - Pure)
- 🟦 Layer 2 (Generic Utilities - Pure)
Verifizierung
✅ Keine Schicht wird übersprungen
- Layer 4 ruft NUR Layer 3 und andere Layer 4 auf
- Layer 3 ruft NUR Layer 2 auf
- Layer 2 ruft NUR Layer 1 (Language Primitives) auf
- Keine Aufrufe nach oben
✅ Pure Functions in Layer 2 & 3
- Alle Funktionen in
lib/sind pure - Alle Funktionen in
domain/sind pure - Keine Seiteneffekte außer in Layer 4
✅ I/O nur in Layer 4
handlers/enthält alle I/O-Operationen- Klare Benennung:
load*,write*,read*,spawn*,log*
Ordnerstruktur (Source)
src/
├── types.ts # Plain Data Types
├── index.ts # Main Entry Point (Layer 4)
│
├── lib/ # Layer 2: Generic Utilities
│ ├── result-helpers.ts # Result type operations
│ ├── array-utils.ts # Array operations
│ └── string-utils.ts # String operations
│
├── domain/ # Layer 3: Business Logic
│ ├── validation.ts # Validation functions
│ ├── transformation.ts # Data transformations
│ └── calculation.ts # Calculations
│
└── handlers/ # Layer 4: I/O & Orchestration
├── file-operations.ts # File I/O
├── process-operations.ts # Process spawning
├── logging.ts # Logging
├── cloud-foundry.ts # CF operations
├── service-operations.ts # Service management
├── configuration.ts # Config management
├── binding-orchestration.ts # Service binding
├── shutdown.ts # Shutdown handler
└── help.ts # Help messages