mirror of
https://github.com/qlik-oss/nebula.js.git
synced 2025-12-19 17:58:43 -05:00
chore: add copilot instructions (#1872)
This commit is contained in:
185
.github/copilot-instructions.md
vendored
Normal file
185
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
# Nebula.js Development Guide for AI Agents
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Nebula.js is a framework for building and embedding Qlik visualizations. It's a **Lerna monorepo** managing multiple packages under `@nebula.js` npm scope. The core architecture separates visualization authoring (`supernova`) from rendering (`nucleus`) with `stardust` as the public API facade.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Package Structure
|
||||||
|
|
||||||
|
- **`apis/stardust/`** - Public API that exposes `nucleus` and `supernova` APIs. Entry point for consumers.
|
||||||
|
- **`apis/nucleus/`** - React-based mashup runtime that renders visualizations in web apps
|
||||||
|
- **`apis/supernova/`** - Hooks-based API for building custom visualizations (the "component" layer)
|
||||||
|
- **`apis/locale/`** - Translation strings and locale generation (private)
|
||||||
|
- **`apis/theme/`** - Theme access and consumption (private)
|
||||||
|
- **`apis/conversion/`** - Conversion utilities for hyperCube extensions (private)
|
||||||
|
- **`apis/enigma-mocker/`** - Mock enigma app for rendering without Qlik engine
|
||||||
|
- **`apis/snapshooter/`** - Chart rendering as images
|
||||||
|
- **`apis/test-utils/`** - Testing utilities
|
||||||
|
- **`commands/`** - CLI tools (`build`, `serve`, `create`, `sense`) for visualization development
|
||||||
|
- **`packages/ui/`** - Shared UI components (private)
|
||||||
|
|
||||||
|
### Visualization Component Pattern (Supernova)
|
||||||
|
|
||||||
|
Visualizations are defined as "supernovas" with this structure:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default function supernova(galaxy) {
|
||||||
|
return {
|
||||||
|
qae: {
|
||||||
|
properties: {}, // QIX object properties schema
|
||||||
|
data: {} // Data definition (dimensions, measures)
|
||||||
|
},
|
||||||
|
component() {
|
||||||
|
// Hooks-based component using @nebula.js/stardust hooks
|
||||||
|
const element = useElement();
|
||||||
|
const layout = useLayout();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Render logic here
|
||||||
|
}, [layout]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Key hooks from `@nebula.js/stardust`:
|
||||||
|
- `useElement()` - Get the DOM element
|
||||||
|
- `useLayout()` - Get QIX layout object
|
||||||
|
- `useModel()` - Access QIX model
|
||||||
|
- `useStaleLayout()` - Layout that doesn't trigger re-renders
|
||||||
|
- `useSelections()` - Handle user selections
|
||||||
|
- `useConstraints()` - Interaction constraints (edit, select, active, passive)
|
||||||
|
- `useEffect()`, `useState()`, etc. - React-like hooks
|
||||||
|
|
||||||
|
See [apis/supernova/src/hooks.js](apis/supernova/src/hooks.js) for complete hook implementations.
|
||||||
|
|
||||||
|
### Nucleus Rendering Flow
|
||||||
|
|
||||||
|
Nucleus (React-based) orchestrates visualization rendering:
|
||||||
|
1. `Supernova.jsx` component mounts the visualization element
|
||||||
|
2. Calls supernova lifecycle: `created()` → `mounted()` → `render()` → `willUnmount()`
|
||||||
|
3. Passes context (constraints, interactions, theme, appLayout) to component
|
||||||
|
4. Uses `RenderDebouncer` to batch updates
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Setup & Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn install # Install all dependencies
|
||||||
|
yarn run locale:generate # Generate translation files (required before build)
|
||||||
|
yarn run build # Build all packages (production UMD + ESM)
|
||||||
|
yarn run build:dev # Build with source maps for development
|
||||||
|
yarn run build:watch # Watch mode for active development
|
||||||
|
```
|
||||||
|
|
||||||
|
**Critical**: Always run `locale:generate` before building if locale files changed.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn test:unit # Jest unit tests for all packages
|
||||||
|
yarn test:component # Playwright component tests
|
||||||
|
yarn test:integration # Playwright integration tests
|
||||||
|
yarn test:rendering # Visual regression tests (Playwright)
|
||||||
|
yarn test:mashup # Full mashup integration tests
|
||||||
|
```
|
||||||
|
|
||||||
|
Unit tests use `jest` with `jest-environment-jsdom`. See [jest.config.js](jest.config.js) for coverage and test patterns.
|
||||||
|
|
||||||
|
### CLI Commands for Visualizations
|
||||||
|
|
||||||
|
When developing a supernova visualization:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nebula create <name> # Scaffold new visualization
|
||||||
|
nebula serve # Start dev server with hot reload
|
||||||
|
nebula build # Build visualization for distribution
|
||||||
|
nebula sense # Build as Qlik Sense extension
|
||||||
|
```
|
||||||
|
|
||||||
|
**Dev Server** (`nebula serve`):
|
||||||
|
- Builds visualization to `/dist` automatically
|
||||||
|
- Connects to Qlik Associative Engine (default: localhost:9076)
|
||||||
|
- Supports fixtures for testing without engine connection
|
||||||
|
- See [commands/serve/README.md](commands/serve/README.md) for options
|
||||||
|
|
||||||
|
### Rollup Build Configuration
|
||||||
|
|
||||||
|
All packages use shared [rollup.config.js](rollup.config.js):
|
||||||
|
- **UMD format** for browsers (default export via `unpkg`/`jsdelivr`)
|
||||||
|
- **ESM format** for bundlers (exposed via `module` field)
|
||||||
|
- Creates `.dev.js` variants with source maps in development mode
|
||||||
|
- Validates `main`, `module`, `unpkg`, `jsdelivr` targets in package.json match naming convention
|
||||||
|
|
||||||
|
### Lerna Versioning
|
||||||
|
|
||||||
|
This project uses Lerna for version management with **conventional commits**:
|
||||||
|
- Use commit types: `feat:`, `fix:`, `chore:`, `docs:`, etc.
|
||||||
|
- `lerna version` reads commits to determine semver bump
|
||||||
|
- All packages are versioned together (see [lerna.json](lerna.json))
|
||||||
|
|
||||||
|
## Code Conventions
|
||||||
|
|
||||||
|
### ESLint Configuration
|
||||||
|
|
||||||
|
- Uses **Airbnb style** with Prettier formatting
|
||||||
|
- Flat config format ([eslint.config.mjs](eslint.config.mjs))
|
||||||
|
- Jest environment globals enabled for test files
|
||||||
|
- Custom rules: `max-len: 0`, `no-plusplus: 0`, React prop-types disabled
|
||||||
|
|
||||||
|
### File Naming
|
||||||
|
|
||||||
|
- Test files: `*.spec.js`, `*.test.js`, `*.spec.jsx`, `*.test.jsx`
|
||||||
|
- Stories (Storybook): `**/__stories__/**`
|
||||||
|
- Built artifacts: `dist/`, `lib/` (git-ignored)
|
||||||
|
|
||||||
|
### Private Packages
|
||||||
|
|
||||||
|
Packages like `locale`, `theme`, `conversion`, and `ui` are marked private/internal - they're consumed by stardust but not published as standalone packages.
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Picasso.js Integration
|
||||||
|
|
||||||
|
Many visualizations use Picasso.js for rendering. Standard pattern:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import picassojs from 'picasso.js';
|
||||||
|
import picassoQ from 'picasso-plugin-q';
|
||||||
|
|
||||||
|
const picasso = picassojs();
|
||||||
|
picasso.use(picassoQ);
|
||||||
|
|
||||||
|
// In component:
|
||||||
|
const instance = picasso.chart({
|
||||||
|
element,
|
||||||
|
data: [{ type: 'q', key: 'qHyperCube', data: layout.qHyperCube }],
|
||||||
|
settings: definition({ layout })
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
See [commands/create/templates/sn/picasso/common/src/index.js](commands/create/templates/sn/picasso/common/src/index.js).
|
||||||
|
|
||||||
|
### Handling Selections
|
||||||
|
|
||||||
|
Use `pic-selections` helper for Picasso-based charts to connect brush selections to QIX selections API. Example in templates.
|
||||||
|
|
||||||
|
### Extension Points (`ext`)
|
||||||
|
|
||||||
|
Qlik Sense extensions can define `ext` object for Sense-specific customizations (support.export, etc.). Pass `galaxy.anything.sense` to detect Sense environment.
|
||||||
|
|
||||||
|
## Key Files to Reference
|
||||||
|
|
||||||
|
- [apis/supernova/src/creator.js](apis/supernova/src/creator.js) - Component lifecycle implementation
|
||||||
|
- [apis/nucleus/src/components/Supernova.jsx](apis/nucleus/src/components/Supernova.jsx) - React wrapper for visualizations
|
||||||
|
- [apis/supernova/src/hooks.js](apis/supernova/src/hooks.js) - All available hooks
|
||||||
|
- [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) - Contribution guidelines and git workflow
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
- **Build issues**: Check locale generation ran, verify package.json targets match rollup config expectations
|
||||||
|
- **Hook errors**: "Invalid stardust hook call" means hooks called outside component function
|
||||||
|
- **Visualization not updating**: Check if using `useStaleLayout()` vs `useLayout()` correctly - stale doesn't trigger re-renders
|
||||||
Reference in New Issue
Block a user