Add star-map Angular app, ETL pipeline, and caveman plugin

Angular 3D star map (galaxy/system/body views, Three.js rendering,
navigation store) plus the NASA ETL tooling that builds the star,
exoplanet and solar-system datasets, Playwright e2e suite, and the
cs:caveman Claude Code plugin (command, agent, skill).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@
This commit is contained in:
2026-08-03 16:50:10 +02:00
parent 1e1b58b0e9
commit d7e8ea1d4d
99 changed files with 5513 additions and 1 deletions
View File
@@ -0,0 +1,37 @@
import { TestBed } from '@angular/core/testing';
import { describe, beforeEach, expect, it } from 'vitest';
import { NavigationStore } from './navigation.store';
describe('NavigationStore', () => {
let store: NavigationStore;
beforeEach(() => {
TestBed.configureTestingModule({});
store = TestBed.inject(NavigationStore);
});
it('starts at the galaxy view with nothing selected', () => {
expect(store.viewLevel()).toBe('galaxy');
expect(store.selectedStarId()).toBeNull();
expect(store.selectedBodyId()).toBeNull();
});
it('selectStar updates selectedStarId', () => {
store.selectStar(42);
expect(store.selectedStarId()).toBe(42);
});
it('selectBody updates selectedBodyId', () => {
store.selectBody('mars');
expect(store.selectedBodyId()).toBe('mars');
});
it('setViewLevel switches between galaxy and system', () => {
store.setViewLevel('system');
expect(store.viewLevel()).toBe('system');
});
});
+27
View File
@@ -0,0 +1,27 @@
import { Injectable, signal } from '@angular/core';
export type ViewLevel = 'galaxy' | 'system';
/**
* App-wide navigation state: which zoom level is active and what's currently selected.
* Scene components read these signals to drive rendering; UI (search, picking) writes to
* them to trigger navigation.
*/
@Injectable({ providedIn: 'root' })
export class NavigationStore {
readonly viewLevel = signal<ViewLevel>('galaxy');
readonly selectedStarId = signal<number | null>(null);
readonly selectedBodyId = signal<string | null>(null);
selectStar(starId: number | null): void {
this.selectedStarId.set(starId);
}
selectBody(bodyId: string | null): void {
this.selectedBodyId.set(bodyId);
}
setViewLevel(viewLevel: ViewLevel): void {
this.viewLevel.set(viewLevel);
}
}