# Copilot Instructions for Cosmos Explorer

## Build, Test, and Lint

**To build the project, use the `/build` skill.** It handles dependency checks (`npm install`) and all build variants. See `.github/skills/build/SKILL.md` for full details.

Quick reference:

```bash
npm install              # Install dependencies (runs patch-package and i18n key generation automatically)
npm run build            # Full build: format check → lint → compile → strict compile → webpack prod → copy
npm run build:ci         # CI build: same as above but uses webpack dev mode (faster)
npm start                # Dev server with hot reload at https://localhost:1234 (see /dev-server skill)

npm run compile          # TypeScript check only (no emit)
npm run compile:strict   # TypeScript strict mode check (subset of files in tsconfig.strict.json)
npm run lint             # ESLint across all .ts/.tsx files
npm run format           # Prettier format (write)
npm run format:check     # Prettier format (check only)
```

### Testing

**To run unit tests, use the `/run-unit-tests` skill.** It handles dependency checks and all test variants. See `.github/skills/run-unit-tests/SKILL.md` for full details.

Quick reference:

```bash
npm test                 # Run all unit tests with Jest (includes coverage)
npm run test:file -- path/to/file.test.ts   # Run a single test file (no coverage)
npm run test:debug       # Run tests serially for debugging (--runInBand)

# E2E tests (requires .env config and running dev server)
npm run test:e2e         # Playwright E2E tests
npx playwright test test/sql/document.spec.ts  # Run a single E2E spec
```

Unit tests live adjacent to source files (`*.test.ts` / `*.test.tsx` in `src/`). E2E tests are in `test/` organized by API type (sql, mongo, cassandra, gremlin, tables).

### Dev Server

**To start the local dev server and connect a browser, use the `/dev-server` skill.** It handles dependency checks, server startup, readiness polling, and Playwright browser navigation. See `.github/skills/dev-server/SKILL.md` for full details.

The dev server runs at `https://localhost:1234` with a `/_ready` health-check endpoint. Entry points include `hostedExplorer.html` (standalone), `explorer.html` (portal iframe), and `index.html` (emulator).

## Architecture

### Platform Modes

The app runs in four hosting contexts, determined by `ConfigContext.platform`:
- **Portal** – Embedded as an iframe inside Azure Portal
- **Hosted** – Standalone at cosmos.azure.com, supports AAD, connection string, and resource token auth
- **Emulator** – Connects to local Cosmos DB Emulator via master key
- **Fabric** – Embedded in Microsoft Fabric, communicates via postMessage RPC

Platform-specific code lives in `src/Platform/{Emulator,Hosted,Fabric}/`. The active platform is set during initialization in `src/hooks/useKnockoutExplorer.ts`, which orchestrates bootstrapping for all modes.

### Global State (Module Singletons + Zustand)

State is **not** managed by React Context or Redux for most application concerns. Instead:

- **`userContext`** (`src/UserContext.ts`) – Module-level singleton holding current account info, auth tokens, API type, and feature flags. Updated via `updateUserContext()`. Not a React store; components read it directly.
- **`configContext`** (`src/ConfigContext.ts`) – Module-level singleton for environment/endpoint configuration. Updated via `updateConfigContext()`.
- **Zustand stores** (`src/hooks/use*.ts`) – Used for UI state that React components need to subscribe to reactively. Key stores:
  - `useDatabases` – Database/collection tree state
  - `useTabs` – Open tab management
  - `useQueryCopilot` – Copilot query assistant state
  - `useNotificationConsole` – Console notifications
  - `useSidePanel` – Side panel visibility
  - `useSelectedNode` – Currently selected tree node

### Data Access Layer

`src/Common/dataAccess/` contains all Cosmos DB CRUD operations (createCollection, readDatabases, queryDocuments, etc.). These functions call either the Cosmos SDK (`@azure/cosmos`) directly or go through proxy endpoints depending on the API type and auth method.

ARM (Azure Resource Manager) clients are auto-generated in `src/Utils/arm/generatedClients/` — regenerate with `npm run generateARMClients`.

### Multi-API Support

Cosmos DB supports multiple APIs: SQL, Mongo, Gremlin, Tables, Cassandra, Postgres, and VCoreMongo. The current API type is determined from `userContext.apiType` (derived from the database account's capabilities). API-specific UI components branch on this value.

### Entry Points

Webpack builds multiple independent entry points (see `webpack.config.js`):
- `src/Main.tsx` → `explorer.html` (Portal iframe)
- `src/Index.tsx` → `index.html` (Emulator)
- `src/HostedExplorer.tsx` → `hostedExplorer.html` (cosmos.azure.com)
- Plus: terminal, cellOutputViewer, galleryViewer, selfServe, connectToGitHub, quickstart

### Knockout → React Migration

The codebase is actively migrating from Knockout.js to React. Legacy Knockout code still exists (observables, bindings), but all new UI must be React. The main `Explorer` class (`src/Explorer/Explorer.tsx`) is a large legacy class that orchestrates much of the app — it is not a React component but interacts with React via hooks and stores.

## Key Conventions

### Ignored Directories

The `src/preview/` folder is a separate project and should not be modified or referenced.

### Localization

All user-facing strings must be defined in `src/Localization/en/Resources.json` and referenced via the type-safe `t()` helper:
```typescript
import { t } from "Localization/t";

// Use dot-notation keys matching the JSON structure
const label = t("common.save");
const title = t("splashScreen.title.default");
```
The `ResourceKey` type (derived from `Resources.json`) ensures compile-time safety — invalid keys will cause a type error. When adding new strings, add the English entry to `Resources.json` first, then reference it with `t()`.

### Imports

TypeScript `baseUrl` is set to `src/`, so imports from `src/` are written without a leading `./src/` prefix:
```typescript
import { userContext } from "UserContext";         // src/UserContext.ts
import { configContext } from "ConfigContext";      // src/ConfigContext.ts
import { readDatabases } from "Common/dataAccess/readDatabases";
```

### React Components

- Use **Fluent UI v9** (`@fluentui/react-components`) for new components. Legacy code uses v8 (`@fluentui/react`), but new code should prefer v9.
- Prefer pure functional components; hooks and class components are both acceptable
- Do **not** use component inheritance for shared behavior
- Do **not** suffix file or component names with "Component"

### ESLint Rules to Note

- `no-console`: Only `console.error` and `console.warn` are allowed (not `console.log`)
- `@typescript-eslint/no-explicit-any`: Error — avoid `any` types
- `prefer-arrow/prefer-arrow-functions`: Arrow functions preferred (standalone declarations allowed)
- `eqeqeq`: Strict equality required
- `@typescript-eslint/switch-exhaustiveness-check`: Switch statements must handle all cases
- Do not use `JSON.stringify(error)` — it prints `'{}'`. The linter catches variable names matching `$err`.

### Testing

Any code change should consider both unit and E2E test coverage:

- **Unit tests** – Write or update unit tests for all logic, utility, and component changes. Place test files adjacent to the source file (`Foo.test.ts` next to `Foo.ts`). Do not decrease existing coverage.
- **E2E tests** – Write or update a Playwright E2E test when a change affects a user-facing workflow (e.g., creating a container, running a query, editing a document). E2E tests live in `test/` organized by API type.

Tooling and conventions:
- Use **Jest** for unit tests with `jest-environment-jsdom`
- Use `@testing-library/react` for new component tests. Enzyme exists in legacy tests but should not be used for new code.
- Use Jest built-in mocking (not sinon.js)
- E2E tests use **Playwright** (configured in `playwright.config.ts`); use accessible attributes (role, title, label) over `data-*` attributes for selectors

### Strict Null Checks

The project is incrementally adopting strict null checks. `tsconfig.strict.json` lists files that compile under `--strictNullChecks`. **New files must be added to `tsconfig.strict.json`** so they compile under strict mode. Use `npm run strict:add` to add eligible files.

### Libraries to Avoid

- **underscore.js** – Use native JS methods instead (legacy usage exists)
- **jQuery** – Being removed; do not add new usage
- **sinon.js** – Deprecated; use Jest mocking
- **TSLint** – Removed; use ESLint only

### Formatting

Prettier with `printWidth: 120` and `endOfLine: auto`. Format is enforced in the build pipeline via `npm run format:check`.
