From bfedfafe63967e00a6dec74f67b46c283850ec58 Mon Sep 17 00:00:00 2001 From: raj pandey Date: Sun, 19 Apr 2026 05:50:17 +0530 Subject: [PATCH] update: align plugin monorepo docs with AGENTS.md + top-level skills --- .cursor/commands/code-review.md | 156 ------ .cursor/commands/execute-tests.md | 252 ---------- .cursor/rules/README.md | 100 +--- .cursor/rules/contentstack-plugin.mdc | 475 ------------------ .cursor/rules/dev-workflow.md | 206 -------- .cursor/rules/oclif-commands.mdc | 352 ------------- .cursor/rules/testing.mdc | 323 ------------ .cursor/rules/typescript.mdc | 246 --------- .cursor/skills/SKILL.md | 32 -- .cursor/skills/code-review/SKILL.md | 77 --- .cursor/skills/contentstack-cli/SKILL.md | 178 ------- .cursor/skills/framework/SKILL.md | 142 ------ .cursor/skills/testing/SKILL.md | 200 -------- .talismanrc | 34 +- AGENTS.md | 45 ++ skills/README.md | 3 + .../code-review/SKILL.md | 150 ++++-- .../contentstack-cli/SKILL.md | 7 +- skills/dev-workflow/SKILL.md | 50 ++ .../framework/SKILL.md | 7 +- .../testing/SKILL.md | 221 +++++++- 21 files changed, 451 insertions(+), 2805 deletions(-) delete mode 100644 .cursor/commands/code-review.md delete mode 100644 .cursor/commands/execute-tests.md delete mode 100644 .cursor/rules/contentstack-plugin.mdc delete mode 100644 .cursor/rules/dev-workflow.md delete mode 100644 .cursor/rules/oclif-commands.mdc delete mode 100644 .cursor/rules/testing.mdc delete mode 100644 .cursor/rules/typescript.mdc delete mode 100644 .cursor/skills/SKILL.md delete mode 100644 .cursor/skills/code-review/SKILL.md delete mode 100644 .cursor/skills/contentstack-cli/SKILL.md delete mode 100644 .cursor/skills/framework/SKILL.md delete mode 100644 .cursor/skills/testing/SKILL.md create mode 100644 AGENTS.md create mode 100644 skills/README.md rename .cursor/skills/code-review/references/code-review-checklist.md => skills/code-review/SKILL.md (71%) rename .cursor/skills/contentstack-cli/references/contentstack-patterns.md => skills/contentstack-cli/SKILL.md (97%) create mode 100644 skills/dev-workflow/SKILL.md rename .cursor/skills/framework/references/framework-patterns.md => skills/framework/SKILL.md (97%) rename .cursor/skills/testing/references/testing-patterns.md => skills/testing/SKILL.md (53%) diff --git a/.cursor/commands/code-review.md b/.cursor/commands/code-review.md deleted file mode 100644 index 669fec77..00000000 --- a/.cursor/commands/code-review.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -name: code-review -description: Automated PR review using comprehensive checklist tailored for modularized Contentstack CLI ---- - -# Code Review Command - -## Usage Patterns - -### Scope-Based Reviews -- `/code-review` - Review all current changes with full checklist -- `/code-review --scope typescript` - Focus on TypeScript configuration and patterns -- `/code-review --scope testing` - Focus on Mocha/Chai test patterns -- `/code-review --scope oclif` - Focus on command structure and OCLIF patterns -- `/code-review --scope packages` - Focus on package structure and organization - -### Severity Filtering -- `/code-review --severity critical` - Show only critical issues (security, breaking changes) -- `/code-review --severity high` - Show high and critical issues -- `/code-review --severity all` - Show all issues including suggestions - -### Package-Aware Reviews -- `/code-review --package contentstack-import` - Review changes in import package -- `/code-review --package contentstack-export` - Review changes in export package -- `/code-review --package-type plugin` - Review all plugin packages (all 12 packages are plugins) -- `/code-review --package-scope cm` - Review CM (content management) related packages - -### File Type Focus -- `/code-review --files commands` - Review command files only -- `/code-review --files tests` - Review test files only -- `/code-review --files utils` - Review utility files - -## Comprehensive Review Checklist - -### Monorepo Structure Compliance -- **Package organization**: 12 plugin packages under `packages/contentstack-*` -- **pnpm workspace**: Correct `pnpm-workspace.yaml` configuration -- **Build artifacts**: No `lib/` directories committed to version control -- **Dependencies**: Proper use of shared utilities (`@contentstack/cli-command`, `@contentstack/cli-utilities`) -- **Scripts**: Consistent build, test, and lint scripts across packages - -### Package-Specific Structure -- **All packages are plugins**: Each has `oclif.commands` configuration pointing to `./lib/commands` -- **Plugin topics**: All commands under `cm:` topic (content management) -- **Base commands**: Each plugin defines its own `BaseCommand` extending `@contentstack/cli-command` Command -- **Inter-plugin dependencies**: Some plugins depend on others (e.g., import depends on audit) -- **Dependency versions**: Using consistent versions across plugins - -### TypeScript Standards -- **Configuration compliance**: Follows package TypeScript config (`strict: false`, `target: es2017`) -- **Naming conventions**: kebab-case files, PascalCase classes, camelCase functions -- **Import patterns**: ES modules with proper default/named exports -- **Type safety**: No unnecessary `any` types in production code - -### OCLIF Command Patterns -- **Base class usage**: Extends plugin-specific `BaseCommand` or `@contentstack/cli-command` Command -- **Command structure**: Proper `static id`, `static description`, `static examples`, `static flags` -- **Topic organization**: Uses `cm:stacks:*` structure (`cm:stacks:import`, `cm:stacks:export`, `cm:stacks:audit`) -- **Error handling**: Uses `handleAndLogError` from utilities with context -- **Flag validation**: Early validation and user-friendly error messages -- **Service delegation**: Commands are thin, services handle business logic - -### Testing Excellence (Mocha/Chai Stack) -- **Framework compliance**: Uses Mocha + Chai (not Jest) -- **File patterns**: Follows `*.test.ts` naming convention -- **Directory structure**: Proper placement in `test/unit/` -- **Test organization**: Arrange-Act-Assert pattern consistently used -- **Isolation**: Proper setup/teardown with beforeEach/afterEach -- **No real API calls**: All external dependencies properly mocked - -### Error Handling Standards -- **Consistent patterns**: Use `handleAndLogError` from utilities -- **User-friendly messages**: Clear error descriptions for end users -- **Logging**: Proper use of `log.debug` for diagnostic information -- **Status messages**: Use `cliux` for user feedback (success, error, info) - -### Build and Compilation -- **TypeScript compilation**: Clean compilation with no errors -- **OCLIF manifest**: Generated for command discovery -- **README generation**: Commands documented in package README -- **Source maps**: Properly configured for debugging -- **No build artifacts in commit**: `.gitignore` excludes `lib/` directories - -### Testing Coverage -- **Test structure**: Tests in `test/unit/` with descriptive names -- **Command testing**: Uses @oclif/test for command validation -- **Error scenarios**: Tests for both success and failure paths -- **Mocking**: All dependencies properly mocked - -### Package.json Compliance -- **Correct metadata**: name, description, version, author -- **Script definitions**: build, compile, test, lint scripts present -- **Dependencies**: Correct versions of shared packages -- **Main/types**: Properly configured for library packages -- **OCLIF config**: Present for plugin packages - -### Security and Best Practices -- **No secrets**: No API keys or tokens in code or tests -- **Input validation**: Proper validation of user inputs and flags -- **Process management**: Appropriate use of error codes -- **File operations**: Safe handling of file system operations - -### Code Quality -- **Naming consistency**: Follow established conventions -- **Comments**: Only for non-obvious logic (no "narration" comments) -- **Error messages**: Clear, actionable messages for users -- **Module organization**: Proper separation of concerns - -## Review Execution - -### Automated Checks -1. **Lint compliance**: ESLint checks for code style -2. **TypeScript compiler**: Successful compilation to `lib/` directories -3. **Test execution**: All tests pass successfully -4. **Build verification**: Build scripts complete without errors - -### Manual Review Focus Areas -1. **Command usability**: Clear help text and realistic examples -2. **Error handling**: Appropriate error messages and recovery options -3. **Test quality**: Comprehensive test coverage for critical paths -4. **Monorepo consistency**: Consistent patterns across all packages -5. **Flag design**: Intuitive flag names and combinations - -### Common Issues to Flag -- **Inconsistent TypeScript settings**: Mixed strict mode without reason -- **Real API calls in tests**: Unmocked external dependencies -- **Missing error handling**: Commands that fail silently -- **Poor test organization**: Tests without clear Arrange-Act-Assert -- **Build artifacts committed**: `lib/` directories in version control -- **Unclear error messages**: Non-actionable error descriptions -- **Inconsistent flag naming**: Similar flags with different names -- **Missing command examples**: Examples not showing actual usage - -## Repository-Specific Checklist - -### For Modularized CLI -- [ ] Command properly extends `@contentstack/cli-command` Command -- [ ] Flags defined with proper types from `@contentstack/cli-utilities` -- [ ] Error handling uses `handleAndLogError` utility -- [ ] User feedback uses `cliux` utilities -- [ ] Tests use Mocha + Chai pattern with mocked dependencies -- [ ] Package.json has correct scripts (build, compile, test, lint) -- [ ] TypeScript compiles with no errors -- [ ] Tests pass: `pnpm test` -- [ ] No `.only` or `.skip` in test files -- [ ] Build succeeds: `pnpm run build` -- [ ] OCLIF manifest generated successfully - -### Before Merge -- [ ] All review items addressed -- [ ] No build artifacts in commit -- [ ] Tests added for new functionality -- [ ] Documentation updated if needed -- [ ] No console.log() statements (use log.debug instead) -- [ ] Error messages are user-friendly -- [ ] No secrets or credentials in code diff --git a/.cursor/commands/execute-tests.md b/.cursor/commands/execute-tests.md deleted file mode 100644 index a27de0cd..00000000 --- a/.cursor/commands/execute-tests.md +++ /dev/null @@ -1,252 +0,0 @@ ---- -name: execute-tests -description: Run tests by scope, file, or module with intelligent filtering for this pnpm monorepo ---- - -# Execute Tests Command - -## Usage Patterns - -### Monorepo-Wide Testing -- `/execute-tests` - Run all tests across all packages -- `/execute-tests --coverage` - Run all tests with coverage reporting -- `/execute-tests --parallel` - Run package tests in parallel using pnpm - -### Package-Specific Testing -- `/execute-tests contentstack-import` - Run tests for import package -- `/execute-tests contentstack-export` - Run tests for export package -- `/execute-tests contentstack-audit` - Run tests for audit package -- `/execute-tests contentstack-clone` - Run tests for clone package -- `/execute-tests packages/contentstack-import/` - Run tests using path - -### Scope-Based Testing -- `/execute-tests unit` - Run unit tests only (`test/unit/**/*.test.ts`) -- `/execute-tests commands` - Run command tests (`test/unit/commands/**/*.test.ts`) -- `/execute-tests services` - Run service layer tests - -### File Pattern Testing -- `/execute-tests *.test.ts` - Run all TypeScript tests -- `/execute-tests test/unit/commands/` - Run tests for specific directory - -### Watch and Development -- `/execute-tests --watch` - Run tests in watch mode with file monitoring -- `/execute-tests --debug` - Run tests with debug output enabled -- `/execute-tests --bail` - Stop on first test failure - -## Intelligent Filtering - -### Repository-Aware Detection -- **Test patterns**: All use `*.test.ts` naming convention -- **Directory structures**: Standard `test/unit/` layout -- **Test locations**: `packages/*/test/unit/**/*.test.ts` -- **Build exclusion**: Ignores `lib/` directories (compiled artifacts) - -### Package Structure -The monorepo contains 12 CLI plugin packages: -- `contentstack-audit` - Stack audit and fix operations -- `contentstack-bootstrap` - Seed/bootstrap stacks -- `contentstack-branches` - Git-based branch management -- `contentstack-bulk-publish` - Bulk publish operations -- `contentstack-clone` - Clone/duplicate stacks -- `contentstack-export` - Export stack content -- `contentstack-export-to-csv` - Export to CSV format -- `contentstack-import` - Import content to stacks -- `contentstack-import-setup` - Import setup and validation -- `contentstack-migration` - Content migration workflows -- `contentstack-seed` - Seed stacks with data -- `contentstack-variants` - Manage content variants - -### Monorepo Integration -- **pnpm workspace support**: Uses `pnpm -r --filter` for package targeting -- **Dependency awareness**: Understands package interdependencies -- **Parallel execution**: Leverages pnpm's parallel capabilities -- **Selective testing**: Can target specific packages or file patterns - -### Framework Detection -- **Mocha configuration**: Respects `.mocharc.json` files per package -- **TypeScript compilation**: Handles test TypeScript setup -- **Test setup**: Detects test helper initialization files -- **Test timeout**: 30 seconds standard (configurable per package) - -## Execution Examples - -### Common Workflows -```bash -# Run all tests with coverage -/execute-tests --coverage - -# Test specific package during development -/execute-tests contentstack-import --watch - -# Run only command tests across all packages -/execute-tests commands - -# Run unit tests with detailed output -/execute-tests --debug - -# Test until first failure (quick feedback) -/execute-tests --bail -``` - -### Package-Specific Commands Generated -```bash -# For contentstack-import package -cd packages/contentstack-import && pnpm test - -# For all packages with parallel execution -pnpm -r run test - -# For specific test file -cd packages/contentstack-import && npx mocha "test/unit/commands/import.test.ts" - -# With coverage -pnpm -r run test:coverage -``` - -## Configuration Awareness - -### Mocha Integration -- Respects individual package `.mocharc.json` configurations -- Handles TypeScript compilation via ts-node/register -- Supports test helpers and initialization files -- Manages timeout settings per package (default 30 seconds) - -### Test Configuration -```json -// .mocharc.json -{ - "require": [ - "test/helpers/init.js", - "ts-node/register", - "source-map-support/register" - ], - "recursive": true, - "timeout": 30000, - "spec": "test/**/*.test.ts" -} -``` - -### pnpm Workspace Features -- Leverages workspace dependency resolution -- Supports filtered execution by package patterns -- Enables parallel test execution across packages -- Respects package-specific scripts and configurations - -## Test Structure - -### Standard Test Organization -``` -packages/*/ -├── test/ -│ └── unit/ -│ ├── commands/ # Command-specific tests -│ ├── services/ # Service/business logic tests -│ └── utils/ # Utility function tests -└── src/ - ├── commands/ # CLI commands - ├── services/ # Business logic - └── utils/ # Utilities -``` - -### Test File Naming -- **Pattern**: `*.test.ts` across all packages -- **Location**: `test/unit/` directories -- **Organization**: Mirrors `src/` structure for easy navigation - -## Performance Optimization - -### Parallel Testing -```bash -# Run tests in parallel for faster feedback -pnpm -r --filter './packages/*' run test - -# Watch mode during development -/execute-tests --watch -``` - -### Selective Testing -- Run only affected packages' tests during development -- Use `--bail` to stop on first failure for quick iteration -- Target specific test files for focused debugging - -## Troubleshooting - -### Common Issues - -**Tests not found** -- Check that files follow `*.test.ts` pattern -- Verify files are in `test/unit/` directory -- Ensure `.mocharc.json` has correct spec pattern - -**TypeScript compilation errors** -- Verify `tsconfig.json` in package root -- Check that `ts-node/register` is in `.mocharc.json` requires -- Run `pnpm compile` to check TypeScript errors - -**Watch mode not detecting changes** -- Verify `--watch` flag is supported in your Mocha version -- Check that file paths are correct -- Ensure no excessive `.gitignore` patterns - -**Port conflicts** -- Tests should not use hard-coded ports -- Use dynamic port allocation or test isolation -- Check for process cleanup in `afterEach` hooks - -## Best Practices - -### Test Execution -- Run tests before committing: `pnpm test` -- Use `--bail` during development for quick feedback -- Run full suite before opening PR -- Check coverage for critical paths - -### Test Organization -- Keep tests close to source code structure -- Use descriptive test names -- Group related tests with `describe` blocks -- Clean up resources in `afterEach` - -### Debugging -- Use `--debug` flag for detailed output -- Add `log.debug()` statements in tests -- Run individual test files for isolation -- Use `--bail` to stop at first failure - -## Integration with CI/CD - -### GitHub Actions -- Runs `pnpm test` on pull requests -- Enforces test passage before merge -- May include coverage reporting -- Runs linting and build verification - -### Local Development -```bash -# Before committing -pnpm test -pnpm run lint -pnpm run build - -# Or use watch mode for faster iteration -pnpm test --watch -``` - -## Coverage Reporting - -### Coverage Commands -```bash -# Run tests with coverage -/execute-tests --coverage - -# Coverage output location -coverage/ -├── index.html # HTML report -├── coverage-summary.json # JSON summary -└── lcov.info # LCOV format -``` - -### Coverage Goals -- **Team aspiration**: 80% minimum coverage -- **Focus on**: Critical business logic and error paths -- **Not critical**: Utility functions and edge cases diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md index cbb51b61..f5c1f870 100644 --- a/.cursor/rules/README.md +++ b/.cursor/rules/README.md @@ -1,99 +1,5 @@ -# Cursor Rules +# Cursor (optional) -Context-aware rules that load automatically based on the files you're editing, optimized for this CLI plugins monorepo. +**Cursor** users: start at **[AGENTS.md](../../AGENTS.md)**. All conventions live in **`skills/*/SKILL.md`**. -## Rule Files - -| File | Scope | Always Applied | Purpose | -|------|-------|----------------|---------| -| `dev-workflow.md` | `**/*.ts`, `**/*.js`, `**/*.json` | Yes | Monorepo TDD workflow, pnpm workspace patterns (12 plugin packages) | -| `typescript.mdc` | `**/*.ts`, `**/*.tsx` | No | TypeScript configurations and naming conventions | -| `testing.mdc` | `**/test/**/*.ts`, `**/test/**/*.js`, `**/__tests__/**/*.ts`, `**/*.spec.ts`, `**/*.test.ts` | Yes | Mocha, Chai test patterns and test structure | -| `oclif-commands.mdc` | `**/commands/**/*.ts`, `**/base-command.ts` | No | OCLIF command patterns and CLI validation | -| `contentstack-plugin.mdc` | `packages/contentstack-*/src/**/*.ts`, `packages/contentstack-*/src/**/*.js` | No | CLI plugin package patterns, commands, services, and inter-plugin dependencies | - -## Commands - -| File | Trigger | Purpose | -|------|---------|---------| -| `execute-tests.md` | `/execute-tests` | Run tests by scope, package, or module with monorepo awareness | -| `code-review.md` | `/code-review` | Automated PR review with CLI-specific checklist | - -## Loading Behaviour - -### File Type Mapping -- **TypeScript files** → `typescript.mdc` + `dev-workflow.md` -- **Command files** (`packages/*/src/commands/**/*.ts`) → `oclif-commands.mdc` + `typescript.mdc` + `dev-workflow.md` -- **Base command files** (`packages/*/src/base-command.ts`, `packages/*/*base-command.ts`) → `oclif-commands.mdc` + `typescript.mdc` + `dev-workflow.md` -- **Plugin package files** (`packages/contentstack-*/src/**/*.ts`) → `contentstack-plugin.mdc` + `typescript.mdc` + `dev-workflow.md` -- **Test files** (`packages/*/test/**/*.{ts,js}`) → `testing.mdc` + `dev-workflow.md` -- **Utility files** (`packages/*/src/utils/**/*.ts`) → `typescript.mdc` + `dev-workflow.md` - -### Package-Specific Loading -- **Plugin packages** (with `oclif.commands`) → Full command and utility rules -- **Library packages** → TypeScript and utility rules only - -## Repository-Specific Features - -### Monorepo Structure - -This is a **CLI plugins** monorepo with 12 plugin packages under `packages/`: -- `contentstack-audit` - Stack audit and fix operations -- `contentstack-bootstrap` - Seed/bootstrap stacks with content -- `contentstack-branches` - Git-based branch management for stacks -- `contentstack-bulk-publish` - Bulk publish operations for entries/assets -- `contentstack-clone` - Clone/duplicate stacks -- `contentstack-export` - Export stack content to filesystem -- `contentstack-export-to-csv` - Export stack data to CSV format -- `contentstack-import` - Import content into stacks -- `contentstack-import-setup` - Setup and validation for imports -- `contentstack-migration` - Content migration workflows -- `contentstack-seed` - Seed stacks with generated data -- `contentstack-variants` - Manage content variants - -All plugins depend on: -- `@contentstack/cli-command` - Base Command class -- `@contentstack/cli-utilities` - Shared utilities and helpers -- Optionally on each other (e.g., `contentstack-import` depends on `@contentstack/cli-audit`) - -### Build Configuration -- **pnpm workspaces** configuration (all 12 plugins under `packages/`) -- **Shared dependencies**: Each plugin depends on `@contentstack/cli-command` and `@contentstack/cli-utilities` -- **Inter-plugin dependencies**: Some plugins depend on others (e.g., import → audit) -- **Build process**: TypeScript compilation → `lib/` directories -- **OCLIF manifest** generation per plugin for command discovery - -### Actual Patterns Detected -- **Testing**: Mocha + Chai (consistent across all plugins) -- **TypeScript**: Strict mode for type safety -- **Commands**: Extend `@contentstack/cli-command` Command class with plugin-specific base-commands -- **Topics**: All commands under `cm:` topic (content management) -- **Services/Modules**: Domain-specific business logic organized by concern -- **Build artifacts**: `lib/` directories (excluded from rules) - -## Performance Benefits - -- **Lightweight loading** - Only relevant rules activate based on file patterns -- **Precise glob patterns** - Avoid loading rules for build artifacts -- **Context-aware** - Rules load based on actual file structure - -## Design Principles - -### Validated Against Codebase -- Rules reflect **actual patterns** found in repository -- Glob patterns match **real file structure** -- Examples use **actual dependencies** and APIs - -### Lightweight and Focused -- Each rule has **single responsibility** -- Package-specific variations acknowledged -- `alwaysApply: true` only for truly universal patterns - -## Quick Reference - -For detailed patterns: -- **Testing**: See `testing.mdc` for Mocha/Chai test structure -- **Commands**: See `oclif-commands.mdc` for command development -- **Plugins**: See `contentstack-plugin.mdc` for plugin architecture and patterns -- **Development**: See `dev-workflow.md` for TDD and monorepo workflow -- **TypeScript**: See `typescript.mdc` for type safety patterns +This folder only points contributors to **`AGENTS.md`** so editor-specific config does not duplicate the canonical docs. diff --git a/.cursor/rules/contentstack-plugin.mdc b/.cursor/rules/contentstack-plugin.mdc deleted file mode 100644 index e653d2c5..00000000 --- a/.cursor/rules/contentstack-plugin.mdc +++ /dev/null @@ -1,475 +0,0 @@ ---- -description: "Contentstack CLI plugin package patterns — commands, services, base-commands, and inter-plugin dependencies" -globs: ["packages/contentstack-*/src/**/*.ts", "packages/contentstack-*/src/**/*.js"] -alwaysApply: false ---- - -# Contentstack CLI Plugin Standards - -## Overview - -The **cli-plugins** monorepo contains 12 OCLIF plugin packages under `packages/`: -- `contentstack-audit`, `contentstack-bootstrap`, `contentstack-branches`, `contentstack-bulk-publish`, `contentstack-clone`, `contentstack-export`, `contentstack-export-to-csv`, `contentstack-import`, `contentstack-import-setup`, `contentstack-migration`, `contentstack-seed`, `contentstack-variants` - -Each plugin is a self-contained OCLIF package that: -- **Defines commands** — via `oclif.commands` in `package.json` pointing to `./lib/commands` -- **Depends on shared libraries** — `@contentstack/cli-command` (Base Command class), `@contentstack/cli-utilities` (shared utils and services) -- **May depend on other plugins** — e.g., `contentstack-import` depends on `@contentstack/cli-audit` for audit operations -- **Implements business logic** — in services, modules, and utility classes -- **Has a local base-command** — extending `@contentstack/cli-command` Command class with plugin-specific initialization and flags - -## Architecture - -### Package Structure - -``` -packages/contentstack-import/ -├── src/ -│ ├── commands/ -│ │ └── cm/ -│ │ └── stacks/ -│ │ └── import.ts -│ ├── services/ -│ │ ├── import-service.ts -│ │ └── validation-service.ts -│ ├── modules/ -│ │ ├── entries.ts -│ │ ├── assets.ts -│ │ └── ... -│ ├── base-command.ts (or import-base-command.ts) -│ ├── types/ -│ ├── interfaces/ -│ ├── messages/ -│ └── utils/ -├── test/ -│ └── unit/ -│ ├── commands/ -│ ├── services/ -│ └── ... -├── package.json -├── tsconfig.json -└── .mocharc.json -``` - -### Package Configuration - -Each plugin's `package.json` declares its commands and declares itself as an OCLIF plugin: - -```json -{ - "name": "@contentstack/cli-cm-import", - "oclif": { - "commands": "./lib/commands", - "topics": { - "stacks": { - "description": "Manage stacks" - } - } - }, - "dependencies": { - "@contentstack/cli-command": "~1.8.0", - "@contentstack/cli-utilities": "~1.18.0", - "@contentstack/cli-audit": "~1.19.0" - } -} -``` - -## Base Command Pattern - -### Plugin-Specific Base Command - -Each plugin defines its own `BaseCommand` (or specialized variant like `AuditBaseCommand`): - -```typescript -// ✅ GOOD - packages/contentstack-audit/src/base-command.ts -import { Command } from '@contentstack/cli-command'; -import { Flags, FlagInput } from '@contentstack/cli-utilities'; - -export abstract class BaseCommand extends Command { - protected sharedConfig = { - basePath: process.cwd(), - }; - - static baseFlags: FlagInput = { - config: Flags.string({ - char: 'c', - description: 'Path to config file', - }), - 'data-dir': Flags.string({ - char: 'd', - description: 'Data directory path', - }), - }; - - public async init(): Promise { - await super.init(); - const { args, flags } = await this.parse({ - flags: this.ctor.flags, - args: this.ctor.args, - strict: this.ctor.strict !== false, - }); - this.args = args; - this.flags = flags; - } -} -``` - -### Specialized Base Commands - -Some plugins define specialized versions for specific concerns: - -```typescript -// ✅ GOOD - packages/contentstack-audit/src/audit-base-command.ts -// Extends BaseCommand with audit-specific logic -import { BaseCommand } from './base-command'; - -export abstract class AuditBaseCommand extends BaseCommand { - // Audit-specific initialization and helpers - protected async runAudit(): Promise { - // Common audit logic - } -} - -// Usage in commands -export default class AuditFixCommand extends AuditBaseCommand { - async run(): Promise { - await this.runAudit(); - } -} -``` - -## Command Structure - -### CM Topic Commands - -Commands are organized under the `cm` topic with subtopics for domains: - -```typescript -// ✅ GOOD - packages/contentstack-import/src/commands/cm/stacks/import.ts -import { Flags, FlagInput, cliux } from '@contentstack/cli-utilities'; -import { BaseCommand } from '../../../base-command'; - -export default class ImportCommand extends BaseCommand { - static id = 'cm:stacks:import'; - static description = 'Import content into a stack'; - static examples = [ - '$ csdx cm:stacks:import -k -d ', - '$ csdx cm:stacks:import -k -d --content-types entry,asset', - ]; - - static flags: FlagInput = { - 'stack-api-key': Flags.string({ - char: 'k', - description: 'Stack API key', - required: true, - }), - 'data-dir': Flags.string({ - char: 'd', - description: 'Directory with import data', - required: true, - }), - 'content-types': Flags.string({ - description: 'Content types to import (comma-separated)', - default: 'all', - }), - }; - - async run(): Promise { - try { - const { flags } = this; - cliux.loaderV2('Starting import...'); - - // Delegate to service - const importService = new ImportService(flags); - await importService.import(); - - cliux.success('Import completed'); - } catch (error) { - handleAndLogError(error, { - module: 'import', - command: this.id, - }); - } - } -} -``` - -## Service and Module Patterns - -### Service Layer - -Services encapsulate business logic and are used by commands: - -```typescript -// ✅ GOOD - packages/contentstack-import/src/services/import-service.ts -import { cliux, log } from '@contentstack/cli-utilities'; - -export class ImportService { - constructor(private flags: any) {} - - async import(): Promise { - // Orchestrate import workflow - await this.validateInput(); - await this.loadData(); - await this.importContent(); - } - - private async validateInput(): Promise { - log.debug('Validating input', { module: 'import-service' }); - // Validation logic - } - - private async loadData(): Promise { - // Load data from directory - } - - private async importContent(): Promise { - // Import content logic - } -} -``` - -### Module Pattern - -Some plugins use modules for domain-specific operations: - -```typescript -// ✅ GOOD - packages/contentstack-import/src/modules/entries.ts -import isEmpty from 'lodash/isEmpty'; -import { log } from '@contentstack/cli-utilities'; - -export class Entries { - constructor(private client: any, private basePath: string) {} - - async import(entries: any[]): Promise { - if (isEmpty(entries)) { - log.debug('No entries to import'); - return; - } - - for (const entry of entries) { - await this.importEntry(entry); - } - } - - private async importEntry(entry: any): Promise { - // Import individual entry - } -} -``` - -## Shared Dependencies - -All plugins depend on core libraries: - -```json -{ - "dependencies": { - "@contentstack/cli-command": "~1.8.0", - "@contentstack/cli-utilities": "~1.18.0" - } -} -``` - -### Common Utilities Used - -```typescript -// ✅ GOOD - Import and use shared utilities -import { - cliux, // CLI UI helpers (loaders, tables, success/error) - ux, // OCLIF ux utilities - log, // Structured logging - handleAndLogError, // Error handling with context - configHandler, // CLI configuration management - sanitizePath, // Path sanitization - managementSDKClient, // Contentstack API client factory -} from '@contentstack/cli-utilities'; - -import { Command, Interfaces } from '@contentstack/cli-command'; -``` - -## Inter-Plugin Dependencies - -Plugins can depend on other plugins to share functionality: - -```json -{ - "dependencies": { - "@contentstack/cli-audit": "~1.19.0" - } -} -``` - -### Using Shared Plugin Code - -```typescript -// ✅ GOOD - Import from other plugin packages -import { AuditService } from '@contentstack/cli-audit'; - -export class ImportService { - async import(): Promise { - // Do import - await new AuditService().runAudit(); - } -} -``` - -## Error Handling - -Error handling follows a consistent pattern across plugins: - -```typescript -// ✅ GOOD - Comprehensive error handling -import { handleAndLogError, CLIError } from '@contentstack/cli-utilities'; - -async run(): Promise { - try { - // Business logic - const result = await this.importService.import(); - return result; - } catch (error) { - // Log error with module/command context - handleAndLogError(error, { - module: 'import', - command: this.id, - dataDir: this.flags['data-dir'], - }); - this.exit(1); - } -} -``` - -## Build Process - -Each plugin builds independently but follows the same pattern: - -```bash -# In package.json scripts -"build": "pnpm compile && oclif manifest" -``` - -### Build Steps - -1. **compile** — TypeScript → JavaScript in `lib/` -2. **oclif manifest** — Generate `oclif.manifest.json` for command discovery - -### Build Artifacts - -- `lib/` — Compiled commands, services, modules -- `oclif.manifest.json` — Command registry for this plugin -- `README.md` — Generated command documentation (optional) - -## Configuration and Messaging - -### Messages - -Plugins store user-facing strings in centralized message files: - -```typescript -// ✅ GOOD - packages/contentstack-import/src/messages/index.ts -export const importMsg = { - IMPORT_START: 'Starting import...', - IMPORT_SUCCESS: 'Import completed successfully', - VALIDATION_ERROR: 'Validation failed: {{reason}}', -}; -``` - -### Configuration - -Plugin-specific defaults are stored in config files: - -```typescript -// ✅ GOOD - packages/contentstack-import/src/config/index.ts -export default { - batchSize: 50, - retryAttempts: 3, - timeout: 30000, - logLevel: 'info', -}; -``` - -## Testing Patterns - -### Command Testing - -Test commands using `@oclif/test`: - -```typescript -// ✅ GOOD - packages/contentstack-import/test/unit/commands/import.test.ts -import { test } from '@oclif/test'; -import { expect } from 'chai'; - -describe('ImportCommand', () => { - test - .stdout() - .command(['cm:stacks:import', '--help']) - .it('shows help message', (ctx) => { - expect(ctx.stdout).to.contain('Import content'); - }); - - test - .command(['cm:stacks:import', '-k', 'test-key', '-d', '/tmp/data']) - .it('runs import command'); -}); -``` - -### Service Testing - -Test services with unit tests: - -```typescript -// ✅ GOOD - packages/contentstack-import/test/unit/services/import-service.test.ts -import { expect } from 'chai'; -import { ImportService } from '../../../src/services/import-service'; - -describe('ImportService', () => { - let service: ImportService; - - beforeEach(() => { - service = new ImportService({ - 'stack-api-key': 'test-key', - 'data-dir': '/tmp/data', - }); - }); - - it('should validate input before import', async () => { - // Test validation logic - }); - - it('should handle import errors', async () => { - // Test error handling - }); -}); -``` - -## Best Practices - -### Command Design -- Keep commands thin — delegate to services -- Validate flags early and fail fast -- Provide clear error messages with actionable guidance -- Include command examples in static `examples` - -### Service Design -- Keep services focused on a single domain -- Make services testable by accepting dependencies via constructor -- Use modules for complex domain operations -- Document service public API clearly - -### Error Handling -- Always provide context in error logs (module, command, relevant state) -- Use structured error types (CLIError) for user-facing errors -- Include remediation guidance in error messages -- Log all errors, even those caught and handled - -### Testing -- Test commands with @oclif/test -- Test services with unit tests and mocks -- Cover both happy path and error cases -- Use fixtures for test data, not live APIs - -### Dependencies -- Always use `@contentstack/cli-utilities` for CLI concerns -- Use `@contentstack/cli-command` as base for commands -- Depend on other plugins only if truly needed (watch for circular deps) -- Pin dependency versions to minor (`~` semver) for stability diff --git a/.cursor/rules/dev-workflow.md b/.cursor/rules/dev-workflow.md deleted file mode 100644 index 4bfe9136..00000000 --- a/.cursor/rules/dev-workflow.md +++ /dev/null @@ -1,206 +0,0 @@ ---- -description: "Core development workflow and TDD patterns - always applied" -globs: ["**/*.ts", "**/*.js", "**/*.json"] -alwaysApply: true ---- - -# Development Workflow - -## Monorepo Structure - -### Package Organization -This **CLI plugins** monorepo has 12 packages under `packages/`: - -1. **contentstack-audit** - Stack audit and fix operations -2. **contentstack-bootstrap** - Seed/bootstrap stacks -3. **contentstack-branches** - Git-based branch management -4. **contentstack-bulk-publish** - Bulk publish operations -5. **contentstack-clone** - Clone/duplicate stacks -6. **contentstack-export** - Export stack content -7. **contentstack-export-to-csv** - Export to CSV format -8. **contentstack-import** - Import content to stacks -9. **contentstack-import-setup** - Import setup and validation -10. **contentstack-migration** - Content migration workflows -11. **contentstack-seed** - Seed stacks with data -12. **contentstack-variants** - Manage content variants - -All plugins depend on `@contentstack/cli-command` and `@contentstack/cli-utilities`. Some plugins also depend on each other. - -### pnpm Workspace Configuration -```json -{ - "workspaces": ["packages/*"] -} -``` - -### Development Commands -```bash -# Install dependencies for all packages -pnpm install - -# Run command across all packages -pnpm -r run - -# Run command in specific package -pnpm -r --filter '@contentstack/cli-cm-import' test - -# Work on specific package -cd packages/contentstack-import -pnpm test -``` - -## TDD Workflow - MANDATORY - -1. **RED** → Write ONE failing test in `test/unit/**/*.test.ts` -2. **GREEN** → Write minimal code in `src/` to pass -3. **REFACTOR** → Improve code quality while keeping tests green - -### Test-First Examples -```typescript -// ✅ GOOD - Write test first -describe('ConfigService', () => { - it('should load configuration', async () => { - // Arrange - Set up mocks - const mockConfig = { region: 'us', alias: 'default' }; - - // Act - Call the method - const result = await configService.load(); - - // Assert - Verify behavior - expect(result).to.deep.equal(mockConfig); - }); -}); -``` - -## Critical Rules - -### Testing Standards -- **NO implementation before tests** - Test-driven development only -- **Mock all external dependencies** - No real API calls in tests -- **Use Mocha + Chai** - Standard testing stack -- **Coverage aspiration**: 80% minimum - -### Code Quality -- **TypeScript configuration**: Varies by package -- **NO test.skip or .only in commits** - Clean test suites only -- **Proper error handling** - Clear error messages - -### Build Process -```bash -# Standard build process for each package -pnpm run build # tsc compilation + oclif manifest -pnpm run test # Run test suite -pnpm run lint # ESLint checks -``` - -## Package-Specific Patterns - -### Plugin Packages (auth, config) -- Have `oclif.commands` in `package.json` -- Commands in `src/commands/cm/**/*.ts` -- Built commands in `lib/commands/` -- Extend `@oclif/core` Command class -- Script: `build`: compiles TypeScript, generates OCLIF manifest and README - -### Library Packages (command, utilities, dev-dependencies) -- No OCLIF commands configuration -- Pure TypeScript/JavaScript libraries -- Consumed by other packages -- `main` points to `lib/index.js` - -### Main CLI Package (contentstack) -- Entry point through `bin/run.js` -- Aggregates plugin commands -- Package dependencies reference plugin packages - -## Script Conventions - -### Build Scripts -```json -{ - "build": "pnpm compile && oclif manifest && oclif readme", - "compile": "tsc -b tsconfig.json", - "prepack": "pnpm compile && oclif manifest && oclif readme", - "test": "mocha \"test/unit/**/*.test.ts\"", - "lint": "eslint src/**/*.ts" -} -``` - -### Key Build Steps -1. **compile** - TypeScript compilation to `lib/` -2. **oclif manifest** - Generate command manifest for discovery -3. **oclif readme** - Generate command documentation - -## Quick Reference - -For detailed patterns, see: -- `@testing` - Mocha, Chai test patterns -- `@oclif-commands` - Command structure and validation -- `@dev-workflow` (this document) - Monorepo workflow and TDD - -## Development Checklist - -### Before Starting Work -- [ ] Identify target package in `packages/` -- [ ] Check existing tests in `test/unit/` -- [ ] Understand command structure if working on commands -- [ ] Set up proper TypeScript configuration - -### During Development -- [ ] Write failing test first -- [ ] Implement minimal code to pass -- [ ] Mock external dependencies -- [ ] Follow naming conventions (kebab-case files, PascalCase classes) - -### Before Committing -- [ ] All tests pass: `pnpm test` -- [ ] No `.only` or `.skip` in test files -- [ ] Build succeeds: `pnpm run build` -- [ ] TypeScript compilation clean -- [ ] Proper error handling implemented - -## Common Patterns - -### Service/Class Architecture -```typescript -// ✅ GOOD - Separate concerns -export default class ConfigCommand extends Command { - static description = 'Manage CLI configuration'; - - async run(): Promise { - try { - const service = new ConfigService(); - await service.execute(); - this.log('Configuration updated successfully'); - } catch (error) { - this.error('Configuration update failed'); - } - } -} -``` - -### Error Handling -```typescript -// ✅ GOOD - Clear error messages -try { - await this.performAction(); -} catch (error) { - if (error instanceof ValidationError) { - this.error(`Invalid input: ${error.message}`); - } else { - this.error('Operation failed'); - } -} -``` - -## CI/CD Integration - -### GitHub Actions -- Uses workflow files in `.github/workflows/` -- Runs linting, tests, and builds on pull requests -- Enforces code quality standards - -### Pre-commit Hooks -- Husky integration for pre-commit checks -- Prevents commits with linting errors -- Located in `.husky/` diff --git a/.cursor/rules/oclif-commands.mdc b/.cursor/rules/oclif-commands.mdc deleted file mode 100644 index 7ca9bc25..00000000 --- a/.cursor/rules/oclif-commands.mdc +++ /dev/null @@ -1,352 +0,0 @@ ---- -description: 'OCLIF command development patterns and CLI best practices' -globs: ['**/commands/**/*.ts', '**/base-command.ts'] -alwaysApply: false ---- - -# OCLIF Command Standards - -## Command Structure - -### Standard Command Pattern -```typescript -// ✅ GOOD - Standard command structure -import { Command } from '@contentstack/cli-command'; -import { cliux, flags, FlagInput, handleAndLogError } from '@contentstack/cli-utilities'; - -export default class ConfigSetCommand extends Command { - static description = 'Set CLI configuration values'; - - static flags: FlagInput = { - region: flags.string({ - char: 'r', - description: 'Set region (us/eu)', - }), - alias: flags.string({ - char: 'a', - description: 'Configuration alias', - }), - }; - - static examples = [ - 'csdx config:set --region eu', - 'csdx config:set --region us --alias default', - ]; - - async run(): Promise { - try { - const { flags: configFlags } = await this.parse(ConfigSetCommand); - // Command logic here - } catch (error) { - handleAndLogError(error, { module: 'config-set' }); - } - } -} -``` - -## Base Classes - -### Command Base Class -```typescript -// ✅ GOOD - Extend Command from @contentstack/cli-command -import { Command } from '@contentstack/cli-command'; - -export default class MyCommand extends Command { - async run(): Promise { - // Command implementation - } -} -``` - -### Custom Base Classes -```typescript -// ✅ GOOD - Create custom base classes for shared functionality -export abstract class BaseCommand extends Command { - protected contextDetails = { - command: this.id || 'unknown', - }; - - async init(): Promise { - await super.init(); - log.debug('Command initialized', this.contextDetails); - } -} -``` - -## OCLIF Configuration - -### Package.json Setup -```json -{ - "oclif": { - "commands": "./lib/commands", - "bin": "csdx", - "topicSeparator": ":" - } -} -``` - -### Command Topics -- All commands use `cm` topic: `cm:config:set`, `cm:auth:login` -- Built commands live in `lib/commands` (compiled from `src/commands`) -- Commands use nested directories: `src/commands/config/set.ts` → `cm:config:set` - -### Command Naming -- **Topic hierarchy**: `config/remove/proxy.ts` → `cm:config:remove:proxy` -- **Descriptive names**: Use verb-noun pattern (`set`, `remove`, `show`) -- **Grouping**: Related commands share parent topics - -## Flag Management - -### Flag Definition Patterns -```typescript -// ✅ GOOD - Define flags clearly -static flags: FlagInput = { - 'stack-api-key': flags.string({ - char: 'k', - description: 'Stack API key', - required: false, - }), - region: flags.string({ - char: 'r', - description: 'Set region', - options: ['us', 'eu'], - }), - verbose: flags.boolean({ - char: 'v', - description: 'Show verbose output', - default: false, - }), -}; -``` - -### Flag Parsing -```typescript -// ✅ GOOD - Parse and validate flags -async run(): Promise { - const { flags: parsedFlags } = await this.parse(MyCommand); - - // Validate flag combinations - if (!parsedFlags['stack-api-key'] && !parsedFlags.alias) { - this.error('Either --stack-api-key or --alias is required'); - } - - // Use parsed flags - const region = parsedFlags.region || 'us'; -} -``` - -## Error Handling - -### Standard Error Pattern -```typescript -// ✅ GOOD - Use handleAndLogError from utilities -try { - await this.executeCommand(); -} catch (error) { - handleAndLogError(error, { module: 'my-command' }); -} -``` - -### User-Friendly Messages -```typescript -// ✅ GOOD - Clear user feedback -import { cliux } from '@contentstack/cli-utilities'; - -// Success message -cliux.success('Configuration updated successfully', { color: 'green' }); - -// Error message -cliux.error('Invalid region specified', { color: 'red' }); - -// Info message -cliux.print('Setting region to eu', { color: 'blue' }); -``` - -## Validation Patterns - -### Early Validation -```typescript -// ✅ GOOD - Validate flags early -async run(): Promise { - const { flags } = await this.parse(MyCommand); - - // Validate required flags - if (!flags.region) { - this.error('--region is required'); - } - - // Validate flag values - if (!['us', 'eu'].includes(flags.region)) { - this.error('Region must be "us" or "eu"'); - } - - // Proceed with validated input -} -``` - -## Progress and Logging - -### User Feedback -```typescript -// ✅ GOOD - Provide user feedback -import { log, cliux } from '@contentstack/cli-utilities'; - -// Regular logging -this.log('Starting configuration update...'); - -// Debug logging -log.debug('Detailed operation information', { context: 'data' }); - -// Status messages -cliux.print('Processing...', { color: 'blue' }); -``` - -### Progress Indication -```typescript -// ✅ GOOD - Show progress for long operations -cliux.print('Processing items...', { color: 'blue' }); -let count = 0; -for (const item of items) { - await this.processItem(item); - count++; - cliux.print(`Processed ${count}/${items.length} items`, { color: 'blue' }); -} -``` - -## Command Delegation - -### Service Layer Separation -```typescript -// ✅ GOOD - Commands orchestrate, services implement -async run(): Promise { - try { - const { flags } = await this.parse(MyCommand); - const config = this.buildConfig(flags); - const service = new ConfigService(config); - - await service.execute(); - cliux.success('Operation completed successfully'); - } catch (error) { - this.handleError(error); - } -} -``` - -## Testing Commands - -### OCLIF Test Support -```typescript -// ✅ GOOD - Use @oclif/test for command testing -import { test } from '@oclif/test'; - -describe('cm:config:set', () => { - test - .stdout() - .command(['cm:config:set', '--help']) - .it('shows help', ctx => { - expect(ctx.stdout).to.contain('Set CLI configuration'); - }); - - test - .stdout() - .command(['cm:config:set', '--region', 'eu']) - .it('sets region to eu', ctx => { - expect(ctx.stdout).to.contain('success'); - }); -}); -``` - -## Log Integration - -### Debug Logging -```typescript -// ✅ GOOD - Use structured debug logging -import { log } from '@contentstack/cli-utilities'; - -log.debug('Command started', { - command: this.id, - flags: this.flags, - timestamp: new Date().toISOString(), -}); - -log.debug('Processing complete', { - itemsProcessed: count, - module: 'my-command', -}); -``` - -### Error Context -```typescript -// ✅ GOOD - Include context in error handling -try { - await operation(); -} catch (error) { - handleAndLogError(error, { - module: 'config-set', - command: 'cm:config:set', - flags: { region: 'eu' }, - }); -} -``` - -## Multi-Topic Commands - -### Nested Command Structure -```typescript -// File: src/commands/config/show.ts -export default class ShowConfigCommand extends Command { - static description = 'Show current configuration'; - static examples = ['csdx config:show']; - async run(): Promise { } -} - -// File: src/commands/config/set.ts -export default class SetConfigCommand extends Command { - static description = 'Set configuration values'; - static examples = ['csdx config:set --region eu']; - async run(): Promise { } -} - -// Generated commands: -// - cm:config:show -// - cm:config:set -``` - -## Best Practices - -### Command Organization -```typescript -// ✅ GOOD - Well-organized command -export default class MyCommand extends Command { - static description = 'Clear, concise description'; - - static flags: FlagInput = { - // Define all flags - }; - - static examples = [ - 'csdx my:command', - 'csdx my:command --flag value', - ]; - - async run(): Promise { - try { - const { flags } = await this.parse(MyCommand); - await this.execute(flags); - } catch (error) { - handleAndLogError(error, { module: 'my-command' }); - } - } - - private async execute(flags: Flags): Promise { - // Implementation - } -} -``` - -### Clear Help Text -- Write description as action-oriented statement -- Provide multiple examples for common use cases -- Document each flag with clear description -- Show output format or examples of results diff --git a/.cursor/rules/testing.mdc b/.cursor/rules/testing.mdc deleted file mode 100644 index daf6de10..00000000 --- a/.cursor/rules/testing.mdc +++ /dev/null @@ -1,323 +0,0 @@ ---- -description: 'Testing patterns and TDD workflow' -globs: ['**/test/**/*.ts', '**/test/**/*.js', '**/__tests__/**/*.ts', '**/*.spec.ts', '**/*.test.ts'] -alwaysApply: true ---- - -# Testing Standards - -## Framework Stack - -### Primary Testing Tools -- **Mocha** - Test runner (used across all packages) -- **Chai** - Assertion library -- **@oclif/test** - Command testing support (for plugin packages) - -### Test Setup -- TypeScript compilation via ts-node/register -- Source map support for stack traces -- Global test timeout: 30 seconds (configurable per package) - -## Test File Patterns - -### Naming Conventions -- **Primary**: `*.test.ts` (standard pattern across all packages) -- **Location**: `test/unit/**/*.test.ts` (most packages) - -### Directory Structure -``` -packages/*/ -├── test/ -│ └── unit/ -│ ├── commands/ # Command-specific tests -│ ├── services/ # Service/business logic tests -│ └── utils/ # Utility function tests -└── src/ # Source code - ├── commands/ # CLI commands - ├── services/ # Business logic - └── utils/ # Utilities -``` - -## Mocha Configuration - -### Standard Setup (.mocharc.json) -```json -{ - "require": [ - "test/helpers/init.js", - "ts-node/register", - "source-map-support/register" - ], - "recursive": true, - "timeout": 30000, - "spec": "test/**/*.test.ts" -} -``` - -### TypeScript Compilation -```json -// package.json scripts -{ - "test": "mocha \"test/unit/**/*.test.ts\"", - "test:coverage": "nyc mocha \"test/unit/**/*.test.ts\"" -} -``` - -## Test Structure - -### Standard Test Pattern -```typescript -// ✅ GOOD - Comprehensive test structure -describe('ConfigService', () => { - let service: ConfigService; - - beforeEach(() => { - service = new ConfigService(); - }); - - describe('loadConfig()', () => { - it('should load configuration successfully', async () => { - // Arrange - const expectedConfig = { region: 'us' }; - - // Act - const result = await service.loadConfig(); - - // Assert - expect(result).to.deep.equal(expectedConfig); - }); - - it('should handle missing configuration', async () => { - // Arrange & Act & Assert - await expect(service.loadConfig()).to.be.rejectedWith('Config not found'); - }); - }); -}); -``` - -### Async/Await Pattern -```typescript -// ✅ GOOD - Use async/await in tests -it('should process data asynchronously', async () => { - const result = await service.processAsync(); - expect(result).to.exist; -}); - -// ✅ GOOD - Explicit Promise handling -it('should return a promise', () => { - return service.asyncMethod().then(result => { - expect(result).to.be.true; - }); -}); -``` - -## Mocking Patterns - -### Class Mocking -```typescript -// ✅ GOOD - Mock class dependencies -class MockConfigService { - async loadConfig() { - return { region: 'us' }; - } -} - -it('should use mocked service', async () => { - const mockService = new MockConfigService(); - const result = await mockService.loadConfig(); - expect(result.region).to.equal('us'); -}); -``` - -### Function Stubs -```typescript -// ✅ GOOD - Stub module functions if needed -beforeEach(() => { - // Stub file system operations - // Stub network calls -}); - -afterEach(() => { - // Restore original implementations -}); -``` - -## Command Testing - -### OCLIF Test Pattern -```typescript -// ✅ GOOD - Test commands with @oclif/test -import { test } from '@oclif/test'; - -describe('cm:config:region', () => { - test - .stdout() - .command(['cm:config:region', '--help']) - .it('shows help message', ctx => { - expect(ctx.stdout).to.contain('Display region'); - }); - - test - .stdout() - .command(['cm:config:region']) - .it('shows current region', ctx => { - expect(ctx.stdout).to.contain('us'); - }); -}); -``` - -### Command Flag Testing -```typescript -// ✅ GOOD - Test command flags and arguments -describe('cm:config:set', () => { - test - .command(['cm:config:set', '--help']) - .it('shows usage information'); - - test - .command(['cm:config:set', '--region', 'eu']) - .it('sets region to eu'); -}); -``` - -## Error Testing - -### Error Handling -```typescript -// ✅ GOOD - Test error scenarios -it('should throw ValidationError on invalid input', async () => { - const invalidInput = ''; - await expect(service.validate(invalidInput)) - .to.be.rejectedWith('Invalid input'); -}); - -it('should handle network errors gracefully', async () => { - // Mock network failure - const result = await service.fetchWithRetry(); - expect(result).to.be.null; -}); -``` - -### Error Types -```typescript -// ✅ GOOD - Test specific error types -it('should throw appropriate error', async () => { - try { - await service.failingOperation(); - } catch (error) { - expect(error).to.be.instanceof(ValidationError); - expect(error.code).to.equal('INVALID_CONFIG'); - } -}); -``` - -## Test Data Management - -### Mock Data Organization -```typescript -// ✅ GOOD - Organize test data -const mockData = { - validConfig: { - region: 'us', - timeout: 30000, - }, - invalidConfig: { - region: '', - }, - users: [ - { email: 'user1@example.com', name: 'User 1' }, - { email: 'user2@example.com', name: 'User 2' }, - ], -}; -``` - -### Test Helpers -```typescript -// ✅ GOOD - Create reusable test utilities -export function createMockConfig(overrides?: Partial): Config { - return { - region: 'us', - timeout: 30000, - ...overrides, - }; -} - -export function createMockService( - config: Config = createMockConfig() -): ConfigService { - return new ConfigService(config); -} -``` - -## Coverage - -### Coverage Goals -- **Team aspiration**: 80% minimum coverage -- **Current enforcement**: Applied consistently across packages -- **Focus areas**: Critical business logic and error paths - -### Coverage Reporting -```bash -# Run tests with coverage -pnpm test:coverage - -# Coverage reports generated in: -# - coverage/index.html (HTML report) -# - coverage/coverage-summary.json (JSON report) -``` - -## Critical Testing Rules - -- **No real external calls** - Mock all dependencies -- **Test both success and failure paths** - Cover error scenarios completely -- **One assertion per test** - Focus each test on single behavior -- **Use descriptive test names** - Test name should explain what's tested -- **Arrange-Act-Assert** - Follow AAA pattern consistently -- **Test command validation** - Verify flag validation and error messages -- **Clean up after tests** - Restore any mocked state - -## Best Practices - -### Test Organization -```typescript -// ✅ GOOD - Organize related tests -describe('AuthCommand', () => { - describe('login', () => { - it('should authenticate user'); - it('should save token'); - }); - - describe('logout', () => { - it('should clear token'); - it('should reset config'); - }); -}); -``` - -### Async Test Patterns -```typescript -// ✅ GOOD - Handle async operations properly -it('should complete async operation', async () => { - const promise = service.asyncMethod(); - expect(promise).to.be.instanceof(Promise); - - const result = await promise; - expect(result).to.equal('success'); -}); -``` - -### Isolation -```typescript -// ✅ GOOD - Ensure test isolation -describe('ConfigService', () => { - let service: ConfigService; - - beforeEach(() => { - service = new ConfigService(); - }); - - afterEach(() => { - // Clean up resources - }); -}); -``` diff --git a/.cursor/rules/typescript.mdc b/.cursor/rules/typescript.mdc deleted file mode 100644 index ea4d82a2..00000000 --- a/.cursor/rules/typescript.mdc +++ /dev/null @@ -1,246 +0,0 @@ ---- -description: 'TypeScript strict mode standards and naming conventions' -globs: ['**/*.ts', '**/*.tsx'] -alwaysApply: false ---- - -# TypeScript Standards - -## Configuration - -### Standard Configuration (All Packages) -```json -{ - "compilerOptions": { - "declaration": true, - "importHelpers": true, - "module": "commonjs", - "outDir": "lib", - "rootDir": "src", - "strict": false, // Relaxed for compatibility - "target": "es2017", - "sourceMap": false, - "allowJs": true, // Mixed JS/TS support - "skipLibCheck": true, - "esModuleInterop": true - }, - "include": ["src/**/*"] -} -``` - -### Root Configuration -```json -// tsconfig.json - Baseline configuration -{ - "compilerOptions": { - "strict": false, - "module": "commonjs", - "target": "es2017", - "declaration": true, - "outDir": "lib", - "rootDir": "src" - } -} -``` - -## Naming Conventions (Actual Usage) - -### Files -- **Primary pattern**: `kebab-case.ts` (e.g., `base-command.ts`, `config-handler.ts`) -- **Single-word modules**: `index.ts`, `types.ts` -- **Commands**: Follow OCLIF topic structure (`cm/auth/login.ts`, `cm/config/region.ts`) - -### Classes -```typescript -// ✅ GOOD - PascalCase for classes -export default class ConfigCommand extends Command { } -export class AuthService { } -export class ValidationError extends Error { } -``` - -### Functions and Methods -```typescript -// ✅ GOOD - camelCase for functions -export async function loadConfig(): Promise { } -async validateInput(input: string): Promise { } -createCommandContext(): CommandContext { } -``` - -### Constants -```typescript -// ✅ GOOD - SCREAMING_SNAKE_CASE for constants -const DEFAULT_REGION = 'us'; -const MAX_RETRIES = 3; -const API_BASE_URL = 'https://api.contentstack.io'; -``` - -### Interfaces and Types -```typescript -// ✅ GOOD - PascalCase for types -export interface CommandConfig { - region: string; - alias?: string; -} - -export type CommandResult = { - success: boolean; - message?: string; -}; -``` - -## Import/Export Patterns - -### ES Modules (Preferred) -```typescript -// ✅ GOOD - ES import/export syntax -import { Command } from '@oclif/core'; -import type { CommandConfig } from '../types'; -import { loadConfig } from '../utils'; - -export default class ConfigCommand extends Command { } -export { CommandConfig }; -``` - -### Default Exports -```typescript -// ✅ GOOD - Default export for commands and main classes -export default class ConfigCommand extends Command { } -``` - -### Named Exports -```typescript -// ✅ GOOD - Named exports for utilities and types -export async function delay(ms: number): Promise { } -export interface CommandOptions { } -export type ActionResult = 'success' | 'failure'; -``` - -## Type Definitions - -### Local Types -```typescript -// ✅ GOOD - Define types close to usage -export interface AuthOptions { - email: string; - password: string; - token?: string; -} - -export type ConfigResult = { - success: boolean; - config?: Record; -}; -``` - -### Type Organization -```typescript -// ✅ GOOD - Organize types in dedicated files -// src/types/index.ts -export interface CommandConfig { } -export interface AuthConfig { } -export type ConfigValue = string | number | boolean; -``` - -## Null Safety - -### Function Return Types -```typescript -// ✅ GOOD - Explicit return types -export async function getConfig(): Promise { - return await this.loadFromFile(); -} - -export function createDefaults(): CommandConfig { - return { - region: 'us', - timeout: 30000, - }; -} -``` - -### Null/Undefined Handling -```typescript -// ✅ GOOD - Handle null/undefined explicitly -function processConfig(config: CommandConfig | null): void { - if (!config) { - throw new Error('Configuration is required'); - } - // Process config safely -} -``` - -## Error Handling Types - -### Custom Error Classes -```typescript -// ✅ GOOD - Typed error classes -export class ValidationError extends Error { - constructor( - message: string, - public readonly code?: string - ) { - super(message); - this.name = 'ValidationError'; - } -} -``` - -### Error Union Types -```typescript -// ✅ GOOD - Model expected errors -type AuthResult = { - success: true; - data: T; -} | { - success: false; - error: string; -}; -``` - -## Strict Mode Adoption - -### Current Status -- Most packages use `strict: false` for compatibility -- Gradual migration path available -- Team working toward stricter TypeScript - -### Gradual Adoption -```typescript -// ✅ ACCEPTABLE - Comments for known issues -// TODO: Fix type issues in legacy code -const legacyData = unknownData as unknown; -``` - -## Package-Specific Patterns - -### Command Packages (auth, config) -- Extend `@oclif/core` Command -- Define command flags with `static flags` -- Use @oclif/core flag utilities -- Define command-specific types - -### Library Packages (command, utilities) -- No OCLIF dependencies -- Pure TypeScript interfaces -- Consumed by command packages -- Focus on type safety for exports - -### Main Package (contentstack) -- Aggregates command plugins -- May have common types -- Shared interfaces for plugin integration - -## Export Patterns - -### Package Exports (lib/index.js) -```typescript -// ✅ GOOD - Barrel exports for libraries -export { Command } from './command'; -export { loadConfig } from './config'; -export type { CommandConfig, AuthOptions } from './types'; -``` - -### Entry Points -- Libraries export from `lib/index.js` -- Commands export directly as default classes -- Type definitions included via `types` field in package.json diff --git a/.cursor/skills/SKILL.md b/.cursor/skills/SKILL.md deleted file mode 100644 index db406d53..00000000 --- a/.cursor/skills/SKILL.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: contentstack-cli-skills -description: Collection of project-specific skills for Contentstack CLI plugins monorepo development. Use when working with CLI commands, testing, framework utilities, or reviewing code changes. ---- - -# Contentstack CLI Skills - -Project-specific skills for the pnpm monorepo containing 12 CLI plugin packages. - -## Skills Overview - -| Skill | Purpose | Trigger | -|-------|---------|---------| -| **testing** | Testing patterns, TDD workflow, and test automation for CLI development | When writing tests or debugging test failures | -| **framework** | Core utilities, configuration, logging, and framework patterns | When working with utilities, config, or error handling | -| **contentstack-cli** | CLI commands, OCLIF patterns, authentication and configuration workflows | When implementing commands or integrating APIs | -| **code-review** | PR review guidelines and monorepo-aware checks | When reviewing code or pull requests | - -## Quick Links - -- **[Testing Skill](./testing/SKILL.md)** — TDD patterns, test structure, mocking strategies -- **[Framework Skill](./framework/SKILL.md)** — Utilities, configuration, logging, error handling -- **[Contentstack CLI Skill](./contentstack-cli/SKILL.md)** — Command development, API integration, auth/config patterns -- **[Code Review Skill](./code-review/SKILL.md)** — Review checklist with monorepo awareness - -## Repository Context - -- **Monorepo**: 12 pnpm workspace packages under `packages/` (all CLI plugins for content management) -- **Tech Stack**: TypeScript, OCLIF v4, Mocha+Chai, pnpm workspaces -- **Packages**: `@contentstack/cli-cm-*` scope (import, export, audit, bootstrap, branches, bulk-publish, clone, export-to-csv, import-setup, migration, seed, variants) -- **Dependencies**: All plugins depend on `@contentstack/cli-command` and `@contentstack/cli-utilities` -- **Build**: TypeScript → `lib/` directories, OCLIF manifest generation per plugin diff --git a/.cursor/skills/code-review/SKILL.md b/.cursor/skills/code-review/SKILL.md deleted file mode 100644 index bc647259..00000000 --- a/.cursor/skills/code-review/SKILL.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -name: code-review -description: Automated PR review checklist covering security, performance, architecture, and code quality. Use when reviewing pull requests, examining code changes, or performing code quality assessments. ---- - -# Code Review Skill - -## Quick Reference - -For comprehensive review guidelines, see: -- **[Code Review Checklist](./references/code-review-checklist.md)** - Complete PR review guidelines with severity levels and checklists - -## Review Process - -### Severity Levels -- 🔴 **Critical**: Must fix before merge (security, correctness, breaking changes) -- 🟡 **Important**: Should fix (performance, maintainability, best practices) -- 🟢 **Suggestion**: Consider improving (style, optimization, readability) - -### Quick Review Categories - -1. **Security** - No hardcoded secrets, input validation, secure error handling -2. **Correctness** - Logic validation, error scenarios, data integrity -3. **Architecture** - Code organization, design patterns, modularity -4. **Performance** - Efficiency, resource management, concurrency -5. **Testing** - Test coverage, quality tests, TDD compliance -6. **Conventions** - TypeScript standards, code style, documentation -7. **Monorepo** - Cross-package imports, workspace dependencies, manifest validity - -## Quick Checklist Template - -```markdown -## Security Review -- [ ] No hardcoded secrets or tokens -- [ ] Input validation present -- [ ] Error handling secure (no sensitive data in logs) - -## Correctness Review -- [ ] Logic correctly implemented -- [ ] Edge cases handled -- [ ] Error scenarios covered -- [ ] Async/await chains correct - -## Architecture Review -- [ ] Proper code organization -- [ ] Design patterns followed -- [ ] Good modularity -- [ ] No circular dependencies - -## Performance Review -- [ ] Efficient implementation -- [ ] No unnecessary API calls -- [ ] Memory leaks avoided -- [ ] Concurrency handled correctly - -## Testing Review -- [ ] Adequate test coverage (80%+) -- [ ] Quality tests (not just passing) -- [ ] TDD compliance -- [ ] Both success and failure paths tested - -## Code Conventions -- [ ] TypeScript strict mode -- [ ] Consistent naming conventions -- [ ] No unused imports or variables -- [ ] Documentation adequate - -## Monorepo Checks -- [ ] Cross-package imports use published names -- [ ] Workspace dependencies declared correctly -- [ ] OCLIF manifest updated if commands changed -- [ ] No breaking changes to exported APIs -``` - -## Usage - -Use the comprehensive checklist guide for detailed review guidelines, common issues, severity assessment, and best practices for code quality in the Contentstack CLI monorepo. diff --git a/.cursor/skills/contentstack-cli/SKILL.md b/.cursor/skills/contentstack-cli/SKILL.md deleted file mode 100644 index df669104..00000000 --- a/.cursor/skills/contentstack-cli/SKILL.md +++ /dev/null @@ -1,178 +0,0 @@ ---- -name: contentstack-cli -description: Contentstack CLI development patterns, OCLIF commands, API integration, and authentication/configuration workflows. Use when working with Contentstack CLI plugins, OCLIF commands, CLI commands, or Contentstack API integration. ---- - -# Contentstack CLI Development - -## Quick Reference - -For comprehensive patterns, see: -- **[Contentstack Patterns](./references/contentstack-patterns.md)** - Complete CLI commands, API integration, and configuration patterns -- **[Framework Patterns](../framework/references/framework-patterns.md)** - Utilities, configuration, and error handling - -## Key Patterns Summary - -### OCLIF Command Structure -- Extend plugin-specific `BaseCommand` or `Command` from `@contentstack/cli-command` -- Validate flags early: `if (!flags['stack-api-key']) this.error('Stack API key is required')` -- Delegate to services/modules: commands handle CLI, services handle business logic -- Show progress: `cliux.success('✅ Operation completed')` -- Include command examples: `static examples = ['$ csdx cm:stacks:import -k -d ./data', '$ csdx cm:stacks:export -k ']` - -### Command Topics -- CM topic commands: `cm:stacks:import`, `cm:stacks:export`, `cm:stacks:audit`, `cm:stacks:clone`, etc. -- File pattern: `src/commands/cm/stacks/import.ts` → command `cm:stacks:import` -- Plugin structure: Each package defines commands in `oclif.commands` pointing to `./lib/commands` - -### Flag Patterns -```typescript -static flags: FlagInput = { - username: flags.string({ - char: 'u', - description: 'Email address', - required: false - }), - oauth: flags.boolean({ - description: 'Enable SSO', - default: false, - exclusive: ['username', 'password'] - }) -}; -``` - -### Logging and Error Handling -- Use structured logging: `log.debug('Message', { context: 'data' })` -- Include contextDetails: `handleAndLogError(error, { ...this.contextDetails, module: 'auth-login' })` -- User feedback: `cliux.success()`, `cliux.error()`, `throw new CLIError()` - -### I18N Messages -- Store user-facing strings in `messages/*.json` files -- Load with `messageHandler` from utilities -- Example: `messages/en.json` for English strings - -## Command Base Class Pattern - -Each plugin defines its own `BaseCommand` extending `@contentstack/cli-command`: - -```typescript -export abstract class BaseCommand extends Command { - protected sharedConfig = { basePath: process.cwd() }; - - static baseFlags: FlagInput = { - config: Flags.string({ - char: 'c', - description: 'Path to config file', - }), - 'data-dir': Flags.string({ - char: 'd', - description: 'Data directory path', - }), - }; - - async init(): Promise { - await super.init(); - const { args, flags } = await this.parse({ - flags: this.ctor.flags, - args: this.ctor.args, - }); - this.args = args; - this.flags = flags; - } -} -``` - -Specialized base commands extend this for domain-specific concerns (e.g., `AuditBaseCommand` for audit operations). - -## Plugin Development Patterns - -### Import Plugin Example -```typescript -// packages/contentstack-import/src/commands/cm/stacks/import.ts -export default class ImportCommand extends BaseCommand { - static id = 'cm:stacks:import'; - static description = 'Import content into a stack'; - - static flags: FlagInput = { - 'stack-api-key': Flags.string({ - char: 'k', - description: 'Stack API key', - required: true, - }), - 'data-dir': Flags.string({ - char: 'd', - description: 'Directory with import data', - required: true, - }), - }; - - async run(): Promise { - const { flags } = this; - const importService = new ImportService(flags); - await importService.import(); - cliux.success('✅ Import completed'); - } -} -``` - -### Service Layer Pattern -Services encapsulate business logic separate from CLI concerns: - -```typescript -export class ImportService { - async import(): Promise { - await this.validateInput(); - await this.loadData(); - await this.importContent(); - } -} -``` - -### Module Pattern -Complex domains split work across modules: - -```typescript -export class Entries { - async import(entries: any[]): Promise { - for (const entry of entries) { - await this.importEntry(entry); - } - } -} -``` - -## API Integration - -### Management SDK Client -```typescript -import { managementSDKClient } from '@contentstack/cli-utilities'; - -const client = await managementSDKClient({ - host: this.cmaHost, - skipTokenValidity: true -}); - -const stack = client.stack({ api_key: stackApiKey }); -const entries = await stack.entry().query().find(); -``` - -### Error Handling for API Calls -```typescript -try { - const result = await this.client.stack().entry().fetch(); -} catch (error) { - if (error.status === 401) { - throw new CLIError('Authentication failed. Please login again.'); - } else if (error.status === 404) { - throw new CLIError('Entry not found.'); - } - handleAndLogError(error, { - module: 'entry-fetch', - entryId: entryUid - }); -} -``` - -## Usage - -Reference the comprehensive patterns guide above for detailed implementations, examples, and best practices for CLI command development, authentication flows, configuration management, and API integration. diff --git a/.cursor/skills/framework/SKILL.md b/.cursor/skills/framework/SKILL.md deleted file mode 100644 index 80be284d..00000000 --- a/.cursor/skills/framework/SKILL.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -name: framework -description: Core utilities, configuration, logging, and framework patterns for CLI development. Use when working with utilities, configuration management, error handling, or core framework components. ---- - -# Framework Patterns - -## Quick Reference - -For comprehensive framework guidance, see: -- **[Framework Patterns](./references/framework-patterns.md)** - Complete utilities, configuration, logging, and framework patterns - -## Core Utilities from @contentstack/cli-utilities - -### Configuration Management -```typescript -import { configHandler } from '@contentstack/cli-utilities'; - -// Get config values -const region = configHandler.get('region'); -const email = configHandler.get('email'); -const authToken = configHandler.get('authenticationMethod'); - -// Set config values -configHandler.set('region', 'us'); -``` - -### Logging Framework -```typescript -import { log } from '@contentstack/cli-utilities'; - -// Use structured logging -log.debug('Debug message', { context: 'data' }); -log.info('Information message', { userId: '123' }); -log.warn('Warning message'); -log.error('Error message', { errorCode: 'ERR_001' }); -``` - -### Error Handling -```typescript -import { handleAndLogError, CLIError } from '@contentstack/cli-utilities'; - -try { - await operation(); -} catch (error) { - handleAndLogError(error, { - module: 'my-command', - command: 'cm:auth:login' - }); -} - -// Or throw CLI errors -throw new CLIError('User-friendly error message'); -``` - -### CLI UX / User Output -```typescript -import { cliux } from '@contentstack/cli-utilities'; - -// Success message -cliux.success('Operation completed successfully'); - -// Error message -cliux.error('Something went wrong'); - -// Print message with color -cliux.print('Processing...', { color: 'blue' }); - -// Prompt user for input -const response = await cliux.prompt('Enter region:'); - -// Show table -cliux.table([ - { name: 'Alice', region: 'us' }, - { name: 'Bob', region: 'eu' } -]); -``` - -### HTTP Client -```typescript -import { httpClient } from '@contentstack/cli-utilities'; - -// Make HTTP requests with built-in error handling -const response = await httpClient.request({ - url: 'https://api.contentstack.io/v3/stacks', - method: 'GET', - headers: { 'Authorization': `Bearer ${token}` } -}); -``` - -## Command Base Class - -```typescript -import { Command } from '@contentstack/cli-command'; - -export default class MyCommand extends Command { - static description = 'My command description'; - - static flags = { - region: flags.string({ - char: 'r', - description: 'Set region' - }) - }; - - async run(): Promise { - const { flags } = await this.parse(MyCommand); - // Command logic here - } -} -``` - -## Error Handling Patterns - -### With Context -```typescript -try { - const result = await this.client.stack().entry().fetch(); -} catch (error) { - handleAndLogError(error, { - module: 'auth-service', - command: 'cm:auth:login', - userId: this.contextDetails.userId, - email: this.contextDetails.email - }); -} -``` - -### Custom Errors -```typescript -if (response.status === 401) { - throw new CLIError('Authentication failed. Please login again.'); -} - -if (response.status === 429) { - throw new CLIError('Rate limited. Please try again later.'); -} -``` - -## Usage - -Reference the comprehensive patterns guide above for detailed implementations of configuration, logging, error handling, utilities, and dependency injection patterns. diff --git a/.cursor/skills/testing/SKILL.md b/.cursor/skills/testing/SKILL.md deleted file mode 100644 index d5359192..00000000 --- a/.cursor/skills/testing/SKILL.md +++ /dev/null @@ -1,200 +0,0 @@ ---- -name: testing -description: Testing patterns, TDD workflow, and test automation for CLI development. Use when writing tests, implementing TDD, setting up test coverage, or debugging test failures. ---- - -# Testing Patterns - -## Quick Reference - -For comprehensive testing guidance, see: -- **[Testing Patterns](./references/testing-patterns.md)** - Complete testing best practices and TDD workflow -- See also `.cursor/rules/testing.mdc` for workspace-wide testing standards - -## TDD Workflow Summary - -**Simple RED-GREEN-REFACTOR:** -1. **RED** → Write failing test -2. **GREEN** → Make it pass with minimal code -3. **REFACTOR** → Improve code quality while keeping tests green - -## Key Testing Rules - -- **80% minimum coverage** (lines, branches, functions) -- **Class-based mocking** (no external libraries; extend and override methods) -- **Never make real API calls** in tests -- **Mock at service boundaries**, not implementation details -- **Test both success and failure paths** -- **Use descriptive test names**: "should [behavior] when [condition]" - -## Quick Test Template - -```typescript -describe('[ServiceName]', () => { - let service: [ServiceName]; - - beforeEach(() => { - service = new [ServiceName](); - }); - - afterEach(() => { - // Clean up any resources - }); - - it('should [expected behavior] when [condition]', async () => { - // Arrange - const input = { /* test data */ }; - - // Act - const result = await service.method(input); - - // Assert - expect(result).to.deep.equal(expectedOutput); - }); - - it('should throw error when [error condition]', async () => { - // Arrange & Act & Assert - await expect(service.failingMethod()) - .to.be.rejectedWith('Expected error message'); - }); -}); -``` - -## Common Mock Patterns - -### Class-Based Mocking -```typescript -// Mock a service by extending it -class MockContentstackClient extends ContentstackClient { - async fetch() { - return mockData; - } -} - -it('should use mocked client', async () => { - const mockClient = new MockContentstackClient(config); - const result = await mockClient.fetch(); - expect(result).to.deep.equal(mockData); -}); -``` - -### Constructor Injection -```typescript -class RateLimiter { - async execute(operation: () => Promise): Promise { - return operation(); - } -} - -class MyService { - constructor(private rateLimiter: RateLimiter) {} - - async doWork() { - return this.rateLimiter.execute(() => this.performWork()); - } -} - -it('should rate limit operations', () => { - const mockLimiter = { execute: () => Promise.resolve('result') }; - const service = new MyService(mockLimiter as any); - // test service behavior -}); -``` - -## Running Tests - -### Run all tests in workspace -```bash -pnpm test -``` - -### Run tests for specific package -```bash -pnpm --filter @contentstack/cli-auth test -pnpm --filter @contentstack/cli-config test -``` - -### Run tests with coverage -```bash -pnpm test:coverage -``` - -### Run tests in watch mode -```bash -pnpm test:watch -``` - -### Run specific test file -```bash -pnpm test -- test/unit/commands/auth/login.test.ts -``` - -## Test Organization - -### File Structure -- Mirror source structure: `test/unit/commands/auth/`, `test/unit/services/`, `test/unit/utils/` -- Use consistent naming: `[module-name].test.ts` -- Integration tests: `test/integration/` - -### Test Data Management -```typescript -// Create mock data factories in test/fixtures/ -const mockAuthToken = { token: 'abc123', expiresAt: Date.now() + 3600000 }; -const mockConfig = { region: 'us', email: 'test@example.com' }; -``` - -## Error Testing - -### Rate Limit Handling -```typescript -it('should handle rate limit errors', async () => { - const error = new Error('Rate limited'); - (error as any).status = 429; - - class MockClient { - fetch() { throw error; } - } - - try { - await new MockClient().fetch(); - expect.fail('Should have thrown'); - } catch (err: any) { - expect(err.status).to.equal(429); - } -}); -``` - -### Validation Error Testing -```typescript -it('should throw validation error for invalid input', () => { - expect(() => service.validateRegion('')) - .to.throw('Region is required'); -}); -``` - -## Coverage and Quality - -### Coverage Requirements -```json -"nyc": { - "check-coverage": true, - "lines": 80, - "functions": 80, - "branches": 80, - "statements": 80 -} -``` - -### Quality Checklist -- [ ] All public methods tested -- [ ] Error paths covered (success + failure) -- [ ] Edge cases included -- [ ] No real API calls -- [ ] Descriptive test names -- [ ] Minimal test setup -- [ ] Tests run < 5s per test file -- [ ] 80%+ coverage achieved - -## Usage - -Reference the comprehensive patterns guide above for detailed test structures, mocking strategies, error testing patterns, and coverage requirements. diff --git a/.talismanrc b/.talismanrc index 45de773a..b122a8c1 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,22 +1,14 @@ fileignoreconfig: -- filename: pnpm-lock.yaml - checksum: e4c0b8eff5a2fbb954e207e1b341b6fa9e7c838695ccf829158f7203df91e56a -- filename: .cursor/skills/contentstack-cli/SKILL.md - checksum: 45f0d0c81086eaee850311e0caae198cf6dd2a7bc73bd1340b320b15047c6dae -- filename: .cursor/skills/code-review/SKILL.md - checksum: 29d812ac5c2ed4c55490f8d31e15eb592851601a6a141354cb458b1b9f1daa7a -- filename: .cursor/skills/testing/references/testing-patterns.md - checksum: 0a6cb66f27eda46b40508517063a2f43fea1b4b8df878e7ddff404ab7fc126f8 -- filename: .cursor/skills/code-review/references/code-review-checklist.md - checksum: bdf7453f08d7209deaee411f47a1132ee872b28f0eb082563dfe20aa56eab057 -- filename: .cursor/skills/contentstack-cli/references/contentstack-patterns.md - checksum: 9888d481b6a1ae8c7102d9efed0fdbae2b7592f582a62c8bff6deccf03fdf341 -- filename: .cursor/rules/dev-workflow.md - checksum: 3c3a483b44901bb440b4ce311a40d6e8c11decf9795f6d2d1d3a3787aa9981c3 -- filename: .cursor/commands/code-review.md - checksum: a2737c43d58de842cf48c06b0471648a7c38b5fa8854d7c30f3d9258cd8b48f9 -- filename: .cursor/rules/contentstack-plugin.mdc - checksum: 4d41211088c2302a533559bb1e7e80fe69e6980f23c9a2e90b8ea9d03ba3f040 -- filename: .cursor/rules/oclif-commands.mdc - checksum: 8e269309cbfc9687e4a889c4a7983f145e77066d515dae53968d7553ae726b41 -version: "1.0" \ No newline at end of file + - filename: pnpm-lock.yaml + checksum: ad974018ebd0f3c362e59fc802735c0197bc1472605d8ef3121a9ce160da5b54 + - filename: skills/testing/SKILL.md + checksum: 78719d06b5fb82b53e8b61e5569496e50cb87f6be358d24e30c68d5c0695da18 + - filename: skills/framework/SKILL.md + checksum: 3c29a941b64d0cd8b7a893d4bd8121d7eedbeec41579803e61ef9698cd3b222f + - filename: skills/contentstack-cli/SKILL.md + checksum: 3ff07b7bb8a80cd9eeb3c3ef8410bd705e430fcb99998df11d8c9f30e2dd8f4d + - filename: skills/code-review/SKILL.md + checksum: a8b6da36c93bb0019e9a1cb8ece84279f2e4dc9a4daa5bb774e4b6ee0bad269a + - filename: skills/dev-workflow/SKILL.md + checksum: 0181865f509fb5bf4ae0bea827581674617b552f7c03dd18ab9a077cf7d9d8a2 +version: "1.0" diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..c1c1995d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,45 @@ +# Contentstack CLI plugins – Agent guide + +**Universal entry point** for contributors and AI agents. Detailed conventions live in **`skills/*/SKILL.md`**. + +## What this repo is + +| Field | Detail | +| --- | --- | +| **Name:** | Contentstack CLI plugins (pnpm monorepo; root package name `csdx`) | +| **Purpose:** | OCLIF plugins that extend the Contentstack CLI (import/export, clone, migration, seed, audit, variants, etc.). | +| **Out of scope (if any):** | The **core** CLI aggregation lives in the separate `cli` monorepo; this repo ships plugin packages only. | + +## Tech stack (at a glance) + +| Area | Details | +| --- | --- | +| **Language** | TypeScript / JavaScript, Node **>= 18** (`engines` in root `package.json`) | +| **Build** | pnpm workspaces (`packages/*`); per package: `tsc`, OCLIF manifest/readme where applicable → `lib/` | +| **Tests** | Mocha + Chai; layouts under `packages/*/test/` (see [skills/testing/SKILL.md](skills/testing/SKILL.md)) | +| **Lint / coverage** | ESLint in packages that define `lint` scripts; nyc where configured | +| **Other** | OCLIF v4, Husky | + +## Commands (quick reference) + +| Command type | Command | +| --- | --- | +| **Build** | `pnpm build` | +| **Test** | `pnpm test` | +| **Lint** | `pnpm run lint` in a package that defines `lint` (no root aggregate lint script) | + +CI: [.github/workflows/unit-test.yml](.github/workflows/unit-test.yml) and other workflows under [.github/workflows/](.github/workflows/). + +## Where the documentation lives: skills + +| Skill | Path | What it covers | +| --- | --- | --- | +| Development workflow | [skills/dev-workflow/SKILL.md](skills/dev-workflow/SKILL.md) | pnpm commands, CI, TDD expectations, PR checklist | +| Contentstack CLI | [skills/contentstack-cli/SKILL.md](skills/contentstack-cli/SKILL.md) | Plugin commands, OCLIF, Contentstack APIs | +| Framework | [skills/framework/SKILL.md](skills/framework/SKILL.md) | Utilities, config, logging, errors | +| Testing | [skills/testing/SKILL.md](skills/testing/SKILL.md) | Mocha/Chai, coverage, mocks | +| Code review | [skills/code-review/SKILL.md](skills/code-review/SKILL.md) | PR review for this monorepo | + +## Using Cursor (optional) + +If you use **Cursor**, [.cursor/rules/README.md](.cursor/rules/README.md) only points to **`AGENTS.md`**—same docs as everyone else. diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 00000000..3257d9d5 --- /dev/null +++ b/skills/README.md @@ -0,0 +1,3 @@ +# Skills – Contentstack CLI plugins + +Source of truth for detailed guidance. Read [AGENTS.md](../AGENTS.md) for the skill index, then open the `SKILL.md` that matches your task. Each folder contains `SKILL.md` with YAML frontmatter (`name`, `description`). diff --git a/.cursor/skills/code-review/references/code-review-checklist.md b/skills/code-review/SKILL.md similarity index 71% rename from .cursor/skills/code-review/references/code-review-checklist.md rename to skills/code-review/SKILL.md index 682cc86a..3b926964 100644 --- a/.cursor/skills/code-review/references/code-review-checklist.md +++ b/skills/code-review/SKILL.md @@ -1,8 +1,58 @@ -# Code Review Checklist +--- +name: code-review +description: Automated PR review checklist covering security, performance, architecture, and code quality. Use when reviewing pull requests, examining code changes, or performing code quality assessments. +--- -Automated PR review guidelines covering security, performance, architecture, and code quality for the Contentstack CLI monorepo. +# Code Review Skill -## Review Process +Use the **Quick checklist template** for a short paste into a PR description. Everything from **Review process** through **Approval criteria** is the full deep checklist. + +## Quick checklist template + +```markdown +## Security Review +- [ ] No hardcoded secrets or tokens +- [ ] Input validation present +- [ ] Error handling secure (no sensitive data in logs) + +## Correctness Review +- [ ] Logic correctly implemented +- [ ] Edge cases handled +- [ ] Error scenarios covered +- [ ] Async/await chains correct + +## Architecture Review +- [ ] Proper code organization +- [ ] Design patterns followed +- [ ] Good modularity +- [ ] No circular dependencies + +## Performance Review +- [ ] Efficient implementation +- [ ] No unnecessary API calls +- [ ] Memory leaks avoided +- [ ] Concurrency handled correctly + +## Testing Review +- [ ] Adequate test coverage (80%+) +- [ ] Quality tests (not just passing) +- [ ] TDD compliance +- [ ] Both success and failure paths tested + +## Code Conventions +- [ ] TypeScript strict mode +- [ ] Consistent naming conventions +- [ ] No unused imports or variables +- [ ] Documentation adequate + +## Monorepo Checks +- [ ] Cross-package imports use published names +- [ ] Workspace dependencies declared correctly +- [ ] OCLIF manifest updated if commands changed +- [ ] No breaking changes to exported APIs +``` + +## Review process ### Severity Levels - **🔴 Critical** (must fix before merge): @@ -311,47 +361,7 @@ import { configHandler } from '../../../contentstack-utilities/src'; - [ ] Race conditions in tests - [ ] Hardcoded timeouts -## Review Checklist Template - -```markdown -## Security -- [ ] No hardcoded secrets -- [ ] Input validation present -- [ ] Error handling secure - -## Correctness -- [ ] Logic is correct -- [ ] Edge cases handled -- [ ] Error scenarios covered - -## Architecture -- [ ] Good code organization -- [ ] Design patterns followed -- [ ] Modularity intact - -## Performance -- [ ] Efficient implementation -- [ ] Rate limits respected -- [ ] Memory managed properly - -## Testing -- [ ] Adequate coverage -- [ ] Quality tests -- [ ] Both paths tested - -## Conventions -- [ ] TypeScript standards met -- [ ] Code style consistent -- [ ] Documentation adequate - -## Monorepo -- [ ] Package imports correct -- [ ] Dependencies declared properly -- [ ] Manifest/build updated -- [ ] No breaking changes -``` - -## Approval Criteria +## Approval criteria **APPROVE when:** - ✅ All 🔴 Critical items addressed @@ -371,3 +381,55 @@ import { configHandler } from '../../../contentstack-utilities/src'; - 💬 🟢 Suggestions (non-blocking) - 💬 Questions about implementation - 💬 Appreciation for good patterns + +## Additional PR review notes (former .cursor/commands/code-review.md) + +- **Module organization**: Proper separation of concerns + +## Review Execution + +### Automated Checks +1. **Lint compliance**: ESLint checks for code style +2. **TypeScript compiler**: Successful compilation to `lib/` directories +3. **Test execution**: All tests pass successfully +4. **Build verification**: Build scripts complete without errors + +### Manual Review Focus Areas +1. **Command usability**: Clear help text and realistic examples +2. **Error handling**: Appropriate error messages and recovery options +3. **Test quality**: Comprehensive test coverage for critical paths +4. **Monorepo consistency**: Consistent patterns across all packages +5. **Flag design**: Intuitive flag names and combinations + +### Common Issues to Flag +- **Inconsistent TypeScript settings**: Mixed strict mode without reason +- **Real API calls in tests**: Unmocked external dependencies +- **Missing error handling**: Commands that fail silently +- **Poor test organization**: Tests without clear Arrange-Act-Assert +- **Build artifacts committed**: `lib/` directories in version control +- **Unclear error messages**: Non-actionable error descriptions +- **Inconsistent flag naming**: Similar flags with different names +- **Missing command examples**: Examples not showing actual usage + +## Repository-Specific Checklist + +### For Modularized CLI +- [ ] Command properly extends `@contentstack/cli-command` Command +- [ ] Flags defined with proper types from `@contentstack/cli-utilities` +- [ ] Error handling uses `handleAndLogError` utility +- [ ] User feedback uses `cliux` utilities +- [ ] Tests use Mocha + Chai pattern with mocked dependencies +- [ ] Package.json has correct scripts (build, compile, test, lint) +- [ ] TypeScript compiles with no errors +- [ ] Tests pass: `pnpm test` +- [ ] No `.only` or `.skip` in test files +- [ ] Build succeeds: `pnpm run build` +- [ ] OCLIF manifest generated successfully + +### Before Merge +- [ ] All review items addressed +- [ ] No build artifacts in commit +- [ ] Tests added for new functionality +- [ ] Documentation updated if needed +- [ ] No console.log() statements (use log.debug instead) +- [ ] Error messages are user-friendly diff --git a/.cursor/skills/contentstack-cli/references/contentstack-patterns.md b/skills/contentstack-cli/SKILL.md similarity index 97% rename from .cursor/skills/contentstack-cli/references/contentstack-patterns.md rename to skills/contentstack-cli/SKILL.md index 2ee74721..12d49884 100644 --- a/.cursor/skills/contentstack-cli/references/contentstack-patterns.md +++ b/skills/contentstack-cli/SKILL.md @@ -1,6 +1,9 @@ -# Contentstack CLI Patterns +--- +name: contentstack-cli +description: Contentstack CLI development patterns, OCLIF commands, API integration, and authentication/configuration workflows. Use when working with Contentstack CLI plugins, OCLIF commands, CLI commands, or Contentstack API integration. +--- -Contentstack CLI plugin development patterns, OCLIF commands, API integration, and workflows. +# Contentstack CLI Development ## OCLIF Command Structure diff --git a/skills/dev-workflow/SKILL.md b/skills/dev-workflow/SKILL.md new file mode 100644 index 00000000..72837ba5 --- /dev/null +++ b/skills/dev-workflow/SKILL.md @@ -0,0 +1,50 @@ +--- +name: dev-workflow +description: Branches, CI, pnpm workspace commands, PR expectations, and TDD workflow for the Contentstack CLI plugins monorepo. +--- + +# Development workflow – Contentstack CLI plugins + +## When to use + +- Before you run builds or tests across the workspace +- When wiring CI or interpreting `.github/workflows/` +- When following TDD expectations for a plugin under `packages/` + +## Monorepo layout + +Plugins live under `packages/` (pnpm workspaces: `packages/*`). Current packages include: + +- `contentstack-audit`, `contentstack-bootstrap`, `contentstack-branches`, `contentstack-clone`, `contentstack-export`, `contentstack-export-to-csv`, `contentstack-import`, `contentstack-import-setup`, `contentstack-migration`, `contentstack-seed`, `contentstack-variants` + +Plugins typically depend on `@contentstack/cli-command` and `@contentstack/cli-utilities`. + +## Commands (root) + +| Command | Purpose | +| --- | --- | +| `pnpm install` | Install all workspace dependencies | +| `pnpm build` | `pnpm -r --filter './packages/*' run build` | +| `pnpm test` | `pnpm -r --filter './packages/*' run test` | +| `pnpm prepack` | `pnpm -r --filter './packages/*' run prepack` | + +There is no root `lint` script; run ESLint in a package that defines `lint` (e.g. `cd packages/contentstack-import && pnpm run lint`). Filter example: `pnpm --filter @contentstack/cli-cm-import test` (adjust scope to the package you change). + +## TDD expectations + +1. **RED** — one failing test in the package’s unit test tree +2. **GREEN** — minimal `src/` change to pass +3. **REFACTOR** — keep tests green + +Do not commit `test.only` / `test.skip`. Target **80%** coverage where `nyc` is configured. Mock external APIs; no real API calls in unit tests. + +## CI and hooks + +- Workflows: [`.github/workflows/`](../../../.github/workflows/) — e.g. `unit-test.yml`, `release-v2-beta-plugins.yml`, `sca-scan.yml`, `policy-scan.yml`, `codeql-analysis.yml` +- Husky: [`.husky/`](../../../.husky/) when present + +## PR expectations + +- Tests and build pass for affected packages +- No stray `.only` / `.skip` in tests +- Follow [testing](../testing/SKILL.md) and [code-review](../code-review/SKILL.md) diff --git a/.cursor/skills/framework/references/framework-patterns.md b/skills/framework/SKILL.md similarity index 97% rename from .cursor/skills/framework/references/framework-patterns.md rename to skills/framework/SKILL.md index 8c1d4fc1..08777ef5 100644 --- a/.cursor/skills/framework/references/framework-patterns.md +++ b/skills/framework/SKILL.md @@ -1,3 +1,8 @@ +--- +name: framework +description: Core utilities, configuration, logging, and framework patterns for CLI development. Use when working with utilities, configuration management, error handling, or core framework components. +--- + # Framework Patterns Core utilities, configuration, logging, and framework patterns for Contentstack CLI development. @@ -94,7 +99,7 @@ The utilities provide error handling functions and error classes. import { handleAndLogError } from '@contentstack/cli-utilities'; try { - await risky operation(); + await riskyOperation(); } catch (error) { handleAndLogError(error, { module: 'config-set-region', diff --git a/.cursor/skills/testing/references/testing-patterns.md b/skills/testing/SKILL.md similarity index 53% rename from .cursor/skills/testing/references/testing-patterns.md rename to skills/testing/SKILL.md index fa4d4810..1344fbb8 100644 --- a/.cursor/skills/testing/references/testing-patterns.md +++ b/skills/testing/SKILL.md @@ -1,3 +1,8 @@ +--- +name: testing +description: Testing patterns, TDD workflow, and test automation for CLI development. Use when writing tests, implementing TDD, setting up test coverage, or debugging test failures. +--- + # Testing Patterns Testing best practices and TDD workflow for Contentstack CLI monorepo development. @@ -289,7 +294,9 @@ it('should handle async operation failures', async () => { } ``` -## Monorepo Testing Commands +## Monorepo test execution + +Use **pnpm** from the repo root or `cd packages/`; there is no `/execute-tests` slash command in this repository. ### Run all tests across workspace ```bash @@ -323,6 +330,15 @@ pnpm test -- test/unit/commands/config/set/region.test.ts pnpm test -- --grep "should authenticate user" ``` +### Quick reference + +- **All packages:** `pnpm test` +- **With coverage:** `pnpm test:coverage` or `pnpm -r --filter './packages/*' run test:coverage` (when scripts exist) +- **Single package:** `pnpm --filter test` or `cd packages/ && pnpm test` (e.g. `@contentstack/cli-cm-import` / `contentstack-import` in this repo — adjust to the package you changed) +- **Watch:** `pnpm test --watch` or `pnpm --filter test -- --watch` (depends on package script) +- **Command tests only:** run tests under `packages/*/test/unit/commands/` for the package you are changing +- **Bail on first failure:** `pnpm test -- --bail` if the test runner forwards args + ## Coverage and Quality ### Coverage Enforcement @@ -356,3 +372,206 @@ open coverage/index.html - [ ] 80%+ coverage achieved - [ ] Mocks properly isolated per test - [ ] No test pollution (afterEach cleanup) + +## Intelligent Filtering + +### Repository-Aware Detection +- **Test patterns**: All use `*.test.ts` naming convention +- **Directory structures**: Standard `test/unit/` layout +- **Test locations**: `packages/*/test/unit/**/*.test.ts` +- **Build exclusion**: Ignores `lib/` directories (compiled artifacts) + +### Package Structure +The monorepo contains 12 CLI plugin packages: +- `contentstack-audit` - Stack audit and fix operations +- `contentstack-bootstrap` - Seed/bootstrap stacks +- `contentstack-branches` - Git-based branch management +- `contentstack-bulk-publish` - Bulk publish operations +- `contentstack-clone` - Clone/duplicate stacks +- `contentstack-export` - Export stack content +- `contentstack-export-to-csv` - Export to CSV format +- `contentstack-import` - Import content to stacks +- `contentstack-import-setup` - Import setup and validation +- `contentstack-migration` - Content migration workflows +- `contentstack-seed` - Seed stacks with data +- `contentstack-variants` - Manage content variants + +### Monorepo Integration +- **pnpm workspace support**: Uses `pnpm -r --filter` for package targeting +- **Dependency awareness**: Understands package interdependencies +- **Parallel execution**: Leverages pnpm's parallel capabilities +- **Selective testing**: Can target specific packages or file patterns + +### Framework Detection +- **Mocha configuration**: Respects `.mocharc.json` files per package +- **TypeScript compilation**: Handles test TypeScript setup +- **Test setup**: Detects test helper initialization files +- **Test timeout**: 30 seconds standard (configurable per package) + +## Execution Examples + +### Common Workflows +```bash +# Run all tests with coverage +pnpm test:coverage + +# Test specific package during development (example: contentstack-import) +pnpm --filter @contentstack/cli-cm-import test -- --watch + +# Run only command tests (example: from a package directory) +cd packages/contentstack-import && pnpm test -- "test/unit/commands/**/*.test.ts" + +# Verbose / debug output (depends on package script / mocha) +pnpm test -- --reporter spec + +# Bail on first failure +pnpm test -- --bail +``` + +### Package-Specific Commands Generated +```bash +# For contentstack-import package +cd packages/contentstack-import && pnpm test + +# For all packages with parallel execution +pnpm -r run test + +# For specific test file +cd packages/contentstack-import && npx mocha "test/unit/commands/import.test.ts" + +# With coverage +pnpm -r run test:coverage +``` + +## Configuration Awareness + +### Mocha Integration +- Respects individual package `.mocharc.json` configurations (see **Test Organization** → **Test Configuration** above for an example) +- Handles TypeScript compilation via ts-node/register +- Supports test helpers and initialization files +- Manages timeout settings per package (default 30 seconds) + +### pnpm Workspace Features +- Leverages workspace dependency resolution +- Supports filtered execution by package patterns +- Enables parallel test execution across packages +- Respects package-specific scripts and configurations + +## Test Structure + +### Standard Test Organization +``` +packages/*/ +├── test/ +│ └── unit/ +│ ├── commands/ # Command-specific tests +│ ├── services/ # Service/business logic tests +│ └── utils/ # Utility function tests +└── src/ + ├── commands/ # CLI commands + ├── services/ # Business logic + └── utils/ # Utilities +``` + +### Test File Naming +- **Pattern**: `*.test.ts` across all packages +- **Location**: `test/unit/` directories +- **Organization**: Mirrors `src/` structure for easy navigation + +## Performance Optimization + +### Parallel Testing +```bash +# Run tests in parallel for faster feedback +pnpm -r --filter './packages/*' run test + +# Watch mode during development +pnpm test --watch +``` + +### Selective Testing +- Run only affected packages' tests during development +- Use `--bail` to stop on first failure for quick iteration +- Target specific test files for focused debugging + +## Troubleshooting + +### Common Issues + +**Tests not found** +- Check that files follow `*.test.ts` pattern +- Verify files are in `test/unit/` directory +- Ensure `.mocharc.json` has correct spec pattern + +**TypeScript compilation errors** +- Verify `tsconfig.json` in package root +- Check that `ts-node/register` is in `.mocharc.json` requires +- Run `pnpm compile` to check TypeScript errors + +**Watch mode not detecting changes** +- Verify `--watch` flag is supported in your Mocha version +- Check that file paths are correct +- Ensure no excessive `.gitignore` patterns + +**Port conflicts** +- Tests should not use hard-coded ports +- Use dynamic port allocation or test isolation +- Check for process cleanup in `afterEach` hooks + +## Best Practices + +### Test Execution +- Run tests before committing: `pnpm test` +- Use `--bail` during development for quick feedback +- Run full suite before opening PR +- Check coverage for critical paths + +### Test Organization +- Keep tests close to source code structure +- Use descriptive test names +- Group related tests with `describe` blocks +- Clean up resources in `afterEach` + +### Debugging +- Use `--debug` flag for detailed output +- Add `log.debug()` statements in tests +- Run individual test files for isolation +- Use `--bail` to stop at first failure + +## Integration with CI/CD + +### GitHub Actions +- Runs `pnpm test` on pull requests +- Enforces test passage before merge +- May include coverage reporting +- Runs linting and build verification + +### Local Development +```bash +# Before committing +pnpm test +pnpm run lint +pnpm run build + +# Or use watch mode for faster iteration +pnpm test --watch +``` + +## Coverage Reporting + +### Coverage Commands +```bash +# Run tests with coverage +pnpm test:coverage + +# Typical coverage output layout (package-dependent) +# coverage/ +# ├── index.html +# ├── coverage-summary.json +# └── lcov.info +``` + +### Coverage Goals +- **Team aspiration**: 80% minimum coverage +- **Focus on**: Critical business logic and error paths +- **Not critical**: Utility functions and edge cases