* Add copilot instructions and skills for build and tests. * Add dev-server skill. * Auth Util changes to fix Entra login while running from copilot. * Fix lint issue.
8.7 KiB
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:
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:
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 viaupdateUserContext(). Not a React store; components read it directly.configContext(src/ConfigContext.ts) – Module-level singleton for environment/endpoint configuration. Updated viaupdateConfigContext().- Zustand stores (
src/hooks/use*.ts) – Used for UI state that React components need to subscribe to reactively. Key stores:useDatabases– Database/collection tree stateuseTabs– Open tab managementuseQueryCopilot– Copilot query assistant stateuseNotificationConsole– Console notificationsuseSidePanel– Side panel visibilityuseSelectedNode– 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:
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:
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: Onlyconsole.errorandconsole.warnare allowed (notconsole.log)@typescript-eslint/no-explicit-any: Error — avoidanytypesprefer-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.tsnext toFoo.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/reactfor 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) overdata-*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.