diff --git a/.cursor/commands/code-review.md b/.cursor/commands/code-review.md deleted file mode 100644 index 14dd499df1..0000000000 --- a/.cursor/commands/code-review.md +++ /dev/null @@ -1,154 +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-config` - Review changes in specific package -- `/code-review --package-type plugin` - Review plugin packages only (auth, config) -- `/code-review --package-type library` - Review library packages (command, utilities, dev-dependencies) - -### 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**: Proper placement in `packages/` structure -- **pnpm workspace**: Correct `package.json` workspace 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 -- **Plugin packages** (auth, config): Have `oclif.commands` configuration -- **Library packages** (command, utilities, dev-dependencies): Proper exports in package.json -- **Main package** (contentstack): Aggregates plugins correctly -- **Dependency versions**: Using beta versions appropriately (~version ranges) - -### 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 `@contentstack/cli-command` Command -- **Command structure**: Proper `static description`, `static examples`, `static flags` -- **Topic organization**: Uses `cm` topic structure (`cm:config:set`, `cm:auth:login`) -- **Error handling**: Uses `handleAndLogError` from utilities -- **Flag validation**: Early validation and user-friendly error messages -- **Service delegation**: Commands orchestrate, services implement 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 fb473ecf26..0000000000 --- a/.cursor/commands/execute-tests.md +++ /dev/null @@ -1,246 +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-config` - Run tests for config package -- `/execute-tests contentstack-auth` - Run tests for auth package -- `/execute-tests contentstack-command` - Run tests for command package -- `/execute-tests contentstack-utilities` - Run tests for utilities package -- `/execute-tests packages/contentstack-config/` - 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 6 packages: -- `contentstack` - Main CLI package -- `contentstack-auth` - Authentication plugin -- `contentstack-config` - Configuration plugin -- `contentstack-command` - Base Command class (library) -- `contentstack-utilities` - Utilities library -- `contentstack-dev-dependencies` - Dev dependencies - -### 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-config --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-config package -cd packages/contentstack-config && pnpm test - -# For all packages with parallel execution -pnpm -r --filter './packages/*' run test - -# For specific test file -cd packages/contentstack-config && npx mocha "test/unit/commands/region.test.ts" - -# With coverage -pnpm -r --filter './packages/*' 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 148ead7678..f5c1f87014 100644 --- a/.cursor/rules/README.md +++ b/.cursor/rules/README.md @@ -1,84 +1,5 @@ -# Cursor Rules +# Cursor (optional) -Context-aware rules that load automatically based on the files you're editing, optimized for this modularized Contentstack CLI. +**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 (6 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-core.mdc` | `packages/contentstack/src/**/*.ts`, `packages/contentstack/src/**/*.js` | No | Core package plugin aggregation, hooks, and entry point patterns | - -## 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`) → `oclif-commands.mdc` + `typescript.mdc` + `dev-workflow.md` -- **Core package files** (`packages/contentstack/src/**/*.ts`) → `contentstack-core.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 -- **6 packages** under `packages/`: - - `contentstack` - Main CLI entry point (bin/run.js) - - `contentstack-auth` - Authentication plugin - - `contentstack-config` - Configuration plugin - - `contentstack-command` - Base Command class for plugins - - `contentstack-utilities` - Shared utilities and helpers - - `contentstack-dev-dependencies` - Development dependencies - -### Build Configuration -- **pnpm workspaces** configuration -- **Shared dependencies**: `@contentstack/cli-command`, `@contentstack/cli-utilities` -- **Build process**: TypeScript compilation → `lib/` directories -- **OCLIF manifest** generation for command discovery - -### Actual Patterns Detected -- **Testing**: Mocha + Chai (not Jest or Sinon-heavy) -- **TypeScript**: Mixed strict mode adoption -- **Commands**: Extend `@oclif/core` Command class -- **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 -- **Core Package**: See `contentstack-core.mdc` for plugin aggregation and hook 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-core.mdc b/.cursor/rules/contentstack-core.mdc deleted file mode 100644 index 730daaa5f9..0000000000 --- a/.cursor/rules/contentstack-core.mdc +++ /dev/null @@ -1,358 +0,0 @@ ---- -description: "Contentstack core CLI package patterns — plugin aggregation, hooks, and entry point" -globs: ["packages/contentstack/src/**/*.ts", "packages/contentstack/src/**/*.js"] -alwaysApply: false ---- - -# Contentstack Core Package Standards - -## Overview - -The `@contentstack/cli` core package is the entry point for the entire CLI. Unlike plugin packages (auth, config), it: -- **Aggregates all plugins** — declared in `oclif.plugins` array in `package.json` -- **Implements hooks** — `init` and `prerun` hooks in `src/hooks/` for global behaviors -- **Shares interfaces** — Core types used across all plugins in `src/interfaces/` -- **Provides utilities** — Helper classes like `CsdxContext` in `src/utils/` -- **Has no command files** — Commands are provided by plugin packages - -## Architecture - -### Entry Point - -```typescript -// ✅ GOOD - bin/run.js (CommonJS) -// This is the executable entry point referenced in package.json "bin" -// Standard OCLIF entry point pattern -``` - -### Package Configuration - -The `oclif` configuration in `package.json`: -```json -{ - "oclif": { - "bin": "csdx", - "topicSeparator": ":", - "helpClass": "./lib/help.js", - "plugins": [ - "@oclif/plugin-help", - "@oclif/plugin-not-found", - "@oclif/plugin-plugins", - "@contentstack/cli-config", - "@contentstack/cli-auth" - // ... more plugins - ], - "hooks": { - "init": [ - "./lib/hooks/init/context-init", - "./lib/hooks/init/utils-init" - ], - "prerun": [ - "./lib/hooks/prerun/init-context-for-command", - "./lib/hooks/prerun/command-deprecation-check", - "./lib/hooks/prerun/default-rate-limit-check", - "./lib/hooks/prerun/latest-version-warning" - ] - }, - "topics": { - "auth": { "description": "Perform authentication-related activities" }, - "config": { "description": "Perform configuration related activities" }, - "cm": { "description": "Perform content management activities" } - } - } -} -``` - -## Hook Lifecycle - -### OCLIF Hook Execution Order - -1. **CLI initialization** → Node process starts -2. **`init` hooks** → Set up global context and utilities (executed once) -3. **Command detection** → OCLIF matches command name to plugin -4. **`prerun` hooks** → Validate state, check auth, prepare for command execution (per command) -5. **Command execution** → Plugin command's `run()` method executes - -### Init Hooks - -Init hooks run once during CLI startup. Use them for expensive setup operations. - -```typescript -// ✅ GOOD - src/hooks/init/context-init.ts -// Initialize CLI context that commands depend on -import { CsdxContext } from '../../utils'; -import { configHandler } from '@contentstack/cli-utilities'; - -export default function (opts): void { - // Store command ID for session-based log organization - if (opts.id) { - configHandler.set('currentCommandId', opts.id); - } - // Make context available to all commands via this.config.context - this.config.context = new CsdxContext(opts, this.config); -} -``` - -### Prerun Hooks - -Prerun hooks run before each command. Use them for validation and state checks. - -```typescript -// ✅ GOOD - src/hooks/prerun/auth-guard.ts -// Validate authentication before running protected commands - -import { cliux, isAuthenticated, managementSDKClient } from '@contentstack/cli-utilities'; - -export default async function (opts): Promise { - const { context: { region = null } = {} } = this.config; - - // Validate region is set (required for all non-region commands) - if (opts.Command.id !== 'config:set:region') { - if (!region) { - cliux.error('No region found, please set a region via config:set:region'); - this.exit(); - return; - } - } - - // Example: Validate auth for protected commands - if (isProtectedCommand(opts.Command.id)) { - if (!isAuthenticated()) { - cliux.error('Please log in to execute this command'); - this.exit(); - } - } -} -``` - -### Hook Patterns - -#### Accessing Configuration -```typescript -// ✅ GOOD - Access global config in hooks -export default function (opts): void { - const { config } = this; // OCLIF Config object - const { context, region } = config; // Custom properties set by other hooks -} -``` - -#### Async Hooks -```typescript -// ✅ GOOD - Async hooks for operations requiring I/O -export default async function (opts): Promise { - const client = await managementSDKClient({ host: this.config.region.cma }); - const user = await client.getUser(); - // Hook runs to completion before command starts -} -``` - -#### Early Exit -```typescript -// ✅ GOOD - Exit hook execution when validation fails -export default function (opts): void { - if (!isValid()) { - cliux.error('Validation failed'); - this.exit(); // Stops command from executing - return; - } -} -``` - -## Context Object - -The `CsdxContext` class wraps OCLIF config and adds CLI-specific state. - -```typescript -// ✅ GOOD - Accessing context in commands -import { CLIConfig } from '../interfaces'; - -export default class MyCommand extends Command { - async run(): Promise { - const config: CLIConfig = this.config; - const { context } = config; - - // Available context properties: - // - context.id: unique session identifier - // - context.user: authenticated user info (authtoken, email) - // - context.region: current region configuration - // - context.config: regional configuration - // - context.plugin: current plugin metadata - } -} -``` - -## Shared Interfaces - -Interfaces in `src/interfaces/index.ts` are exported and consumed by all plugins. - -```typescript -// ✅ GOOD - Define shared types -export interface Context { - id: string; - user: { - authtoken: string; - email: string; - }; - region: Region; - plugin: Plugin; - config: any; -} - -export interface CLIConfig extends Config { - context: Context; -} - -export interface Region { - name: string; - cma: string; // Content Management API endpoint - cda: string; // Content Delivery API endpoint -} -``` - -## Utilities - -Core utilities in `src/utils/` provide shared functionality. - -```typescript -// ✅ GOOD - src/utils/context-handler.ts -// Wrapper around context initialization and access -export class CsdxContext { - constructor(opts: any, config: any) { - this.id = opts.id || generateId(); - this.region = config.region; - this.user = extractUserFromToken(); - } -} - -// Export utilities for use in hooks and contexts -export { CsdxContext }; -``` - -## Plugin Registration - -Plugins are registered via `oclif.plugins` in `package.json`. Each plugin package must: - -1. **Provide commands** — via `oclif.commands` in its `package.json` -2. **Be installed** — as a dependency in the core package -3. **Be listed** — in `oclif.plugins` array for auto-discovery - -```json -{ - "dependencies": { - "@contentstack/cli-config": "~1.20.0-beta.1", - "@contentstack/cli-auth": "~1.8.0-beta.1" - }, - "oclif": { - "plugins": [ - "@contentstack/cli-config", - "@contentstack/cli-auth" - ] - } -} -``` - -### Plugin Discovery - -OCLIF automatically discovers commands in: -1. Built-in plugins (`@oclif/plugin-help`, etc.) -2. Core package commands (none in contentstack core) -3. Registered plugins (listed in `oclif.plugins`) - -## Differences from Plugin Packages - -| Aspect | Core Package | Plugin Package | -|--------|--------------|----------------| -| **OCLIF config** | No `commands` field | Has `oclif.commands: "./lib/commands"` | -| **Source structure** | `src/hooks/`, `src/interfaces/`, `src/utils/` | `src/commands/`, `src/services/` | -| **Entry point** | `bin/run.js` | None | -| **Dependencies** | References all plugins | Depends on `@contentstack/cli-command` | -| **Execution role** | Aggregates and initializes | Implements business logic | - -## Build Process - -The core package build includes hook compilation and OCLIF manifest generation. - -```bash -# In package.json scripts -"build": "pnpm compile && oclif manifest && oclif readme" -``` - -### Build Steps - -1. **compile** — TypeScript → JavaScript in `lib/` -2. **oclif manifest** — Generate `oclif.manifest.json` for plugin discovery -3. **oclif readme** — Generate README with available commands - -### Build Artifacts - -- `lib/` — Compiled hooks, utilities, interfaces -- `oclif.manifest.json` — Plugin and command registry -- `bin/run.js` — Executable entry point -- `README.md` — Generated command documentation - -## Testing Hooks - -Hooks cannot be tested with standard command testing. Test hook behavior by: - -1. **Unit test hook functions** — Import and invoke directly -2. **Integration test via CLI** — Run commands that trigger hooks -3. **Mock OCLIF config** — Provide mocked `this.config` object - -```typescript -// ✅ GOOD - Test hook function directly -import contextInit from '../src/hooks/init/context-init'; - -describe('context-init hook', () => { - it('should set context on config', () => { - const mockConfig = { context: null }; - const hookContext = { config: mockConfig }; - const opts = { id: 'test-command' }; - - contextInit.call(hookContext, opts); - - expect(mockConfig.context).to.exist; - }); -}); -``` - -## Error Handling in Hooks - -Hooks should fail fast and provide clear error messages to users. - -```typescript -// ✅ GOOD - Clear error messages with user guidance -export default function (opts): void { - if (!isRegionSet()) { - cliux.error('No region configured'); - cliux.print('Run: csdx config:set:region --region us', { color: 'blue' }); - this.exit(); - } -} -``` - -## Best Practices - -### Hook Organization -- Keep hooks focused on a single concern (validation, initialization, etc.) -- Use descriptive names that indicate when they run (`prerun-`, `init-`) -- Initialize dependencies in `init` hooks, not in `prerun` hooks - -### Performance -- Minimize work in `init` hooks (they run once per CLI session) -- Cache expensive operations in context for reuse -- Avoid repeated API calls across hooks - -### Ordering -- Place hooks that prepare data before hooks that consume it -- Auth validation (`auth-guard`) should run after region validation -- Version warnings can run last (non-critical) - -### Context Usage -- Store computed values in context to avoid recalculation -- Make context available to all commands via `this.config.context` -- Document context properties that plugins should expect - -### Plugin Development -- Ensure plugins depend on `@contentstack/cli-command`, not the core package -- Commands should extend the shared Command base class -- Plugins should not modify or depend on core hooks directly diff --git a/.cursor/rules/dev-workflow.md b/.cursor/rules/dev-workflow.md deleted file mode 100644 index 517867b0ef..0000000000 --- a/.cursor/rules/dev-workflow.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -description: "Core development workflow and TDD patterns - always applied" -globs: ["**/*.ts", "**/*.js", "**/*.json"] -alwaysApply: true ---- - -# Development Workflow - -## Monorepo Structure - -### Package Organization -This modularized CLI has 6 packages under `packages/`: - -1. **contentstack** - Main CLI package - - Entry point: `bin/run.js` - - Aggregates all plugins - -2. **contentstack-auth** - Authentication plugin - - Commands: `cm:auth:*` - - Handles login/logout flows - -3. **contentstack-config** - Configuration plugin - - Commands: `cm:config:*`, `cm:region:*`, etc. - - Manages CLI settings and preferences - -4. **contentstack-command** - Base Command class (library) - - Shared Command base for all plugins - - Utilities and helpers for command development - -5. **contentstack-utilities** - Utilities library - - Shared helpers and utilities - - Used by all packages - -6. **contentstack-dev-dependencies** - Dev dependencies - - Centralized development dependencies - -### pnpm Workspace Configuration -```json -{ - "workspaces": ["packages/*"] -} -``` - -### Development Commands -```bash -# Install dependencies for all packages -pnpm install - -# Run command across all packages -pnpm -r --filter './packages/*' - -# Work on specific package -cd packages/contentstack-config -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 7ca9bc25ab..0000000000 --- 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 daf6de1089..0000000000 --- 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 ea4d82a265..0000000000 --- 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 422807ad04..0000000000 --- a/.cursor/skills/SKILL.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: contentstack-cli-skills -description: Collection of project-specific skills for Contentstack CLI 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 6 CLI 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**: 6 pnpm workspace packages under `packages/` -- **Tech Stack**: TypeScript, OCLIF v4, Mocha+Chai, pnpm workspaces -- **Packages**: `@contentstack/cli` (main), `@contentstack/cli-auth`, `@contentstack/cli-config`, `@contentstack/cli-command`, `@contentstack/cli-utilities`, `@contentstack/cli-dev-dependencies` -- **Build**: TypeScript → `lib/` directories, OCLIF manifest generation diff --git a/.cursor/skills/code-review/SKILL.md b/.cursor/skills/code-review/SKILL.md deleted file mode 100644 index bc647259c0..0000000000 --- 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 f5a29a9a3b..0000000000 --- a/.cursor/skills/contentstack-cli/SKILL.md +++ /dev/null @@ -1,150 +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 `BaseCommand` (package-level) or `Command` from `@contentstack/cli-command` -- Validate flags early: `if (!flags.region) this.error('Region is required')` -- Delegate to services/utils: commands handle CLI, utilities handle logic -- Show progress: `cliux.success('✅ Operation completed')` -- Include command examples: `static examples = ['$ csdx auth:login', '$ csdx auth:login -u email@example.com']` - -### Command Topics -- Auth commands: `auth:login`, `auth:logout`, `auth:whoami`, `auth:tokens:add`, `auth:tokens:remove`, `auth:tokens:index` -- Config commands: `config:get:region`, `config:set:region`, `config:remove:proxy`, etc. -- File pattern: `src/commands/auth/login.ts` → command `cm:auth:login` - -### 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 - -```typescript -export abstract class BaseCommand extends Command { - protected contextDetails!: Context; - - async init(): Promise { - await super.init(); - this.contextDetails = { - command: this.context?.info?.command || 'unknown', - userId: configHandler.get('userUid'), - email: configHandler.get('email') - }; - } - - protected async catch(err: Error & { exitCode?: number }): Promise { - return super.catch(err); - } -} -``` - -## Authentication Patterns - -### Login Command Example -```typescript -async run(): Promise { - const { flags: loginFlags } = await this.parse(LoginCommand); - - if (loginFlags.oauth) { - await oauthHandler.oauth(); - } else { - const username = loginFlags.username || await interactive.askUsername(); - const password = loginFlags.password || await interactive.askPassword(); - await authHandler.login(username, password); - } - - cliux.success('✅ Authenticated successfully'); -} -``` - -### Check Authentication -```typescript -if (!configHandler.get('authenticationMethod')) { - throw new CLIError('Authentication required. Please login first.'); -} -``` - -## Configuration Patterns - -### Config Set/Get/Remove Commands -- Use `configHandler.get()` and `configHandler.set()` -- Support interactive mode when no flags provided -- Display results with `cliux.success()` or `cliux.print()` - -### Region Configuration -```typescript -const selectedRegion = args.region || await interactive.askRegions(); -const regionDetails = regionHandler.setRegion(selectedRegion); -cliux.success(`Region set to ${regionDetails.name}`); -cliux.success(`CMA host: ${regionDetails.cma}`); -``` - -## 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 80be284d90..0000000000 --- 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 d53591924e..0000000000 --- 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/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..d44ff540c9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,45 @@ +# Contentstack CLI – 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 (pnpm monorepo; root package name `csdx`) | +| **Purpose:** | Command-line tool and plugins to manage Contentstack stacks (auth, import/export, bulk operations, and related workflows). | +| **Out of scope (if any):** | Individual plugin packages may scope their own features; see each package under `packages/`. | + +## 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; patterns under `packages/*/test/` (see [skills/testing/SKILL.md](skills/testing/SKILL.md)) | +| **Lint / coverage** | ESLint per package (`src/**/*.ts`); nyc where configured for coverage | +| **Other** | OCLIF v4, Husky | + +## Commands (quick reference) + +| Command type | Command | +| --- | --- | +| **Build** | `pnpm build` | +| **Test** | `pnpm test` | +| **Lint** | `pnpm lint` | + +CI: [.github/workflows/unit-test.yml](.github/workflows/unit-test.yml), [.github/workflows/lint.yml](.github/workflows/lint.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 workspace commands, CI, TDD expectations, PR checklist | +| Contentstack CLI | [skills/contentstack-cli/SKILL.md](skills/contentstack-cli/SKILL.md) | OCLIF commands, plugins, integration patterns | +| 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 0000000000..5aeeb67b20 --- /dev/null +++ b/skills/README.md @@ -0,0 +1,5 @@ +# Skills – Contentstack CLI + +Source of truth for detailed guidance. Read [AGENTS.md](../AGENTS.md) first (skill index and stack summary), then open the skill 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 682cc86a40..f4e045bae4 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,54 @@ 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) + +## 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/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 36bf7d2f42..91ae16cf49 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 development patterns, OCLIF commands, API integration, and configuration 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 0000000000..c62d50695e --- /dev/null +++ b/skills/dev-workflow/SKILL.md @@ -0,0 +1,58 @@ +--- +name: dev-workflow +description: Branches, CI, pnpm workspace commands, PR expectations, and TDD workflow for the Contentstack CLI monorepo. +--- + +# Development workflow – Contentstack CLI + +## 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 package under `packages/` + +## Monorepo layout + +Six packages under `packages/`: + +| Package | Role | +| --- | --- | +| `contentstack` | Main CLI; entry `bin/run.js`; aggregates plugins | +| `contentstack-auth` | Authentication plugin (`cm:auth:*`) | +| `contentstack-config` | Configuration plugin (`cm:config:*`, regions, etc.) | +| `contentstack-command` | Shared base Command and helpers for plugins | +| `contentstack-utilities` | Shared helpers | +| `contentstack-dev-dependencies` | Centralized dev dependencies | + +Workspaces: `packages/*` (see root `package.json`). + +## 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 lint` | `pnpm -r --filter './packages/*' run lint` | +| `pnpm prepack` | `pnpm -r --filter './packages/*' run prepack` | + +Run a command in one package: `pnpm --filter @contentstack/cli-auth test` (adjust package name). + +## TDD expectations + +1. **RED** — one failing test under `test/unit/**/*.test.ts` (or package’s test glob) +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`, `lint.yml`, `release.yml`, `sca-scan.yml`, `policy-scan.yml`, `codeql-analysis.yml` +- Husky: [`.husky/`](../../../.husky/) for pre-commit hooks + +## PR expectations + +- Tests and build pass for affected packages +- No stray `.only` / `.skip` in tests +- Follow patterns in [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 c41223b7a3..d7aac9edfe 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 54% rename from .cursor/skills/testing/references/testing-patterns.md rename to skills/testing/SKILL.md index fa4d481092..c9896a02ce 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 @contentstack/cli-config test` or `cd packages/contentstack-config && pnpm test` +- **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,200 @@ 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 6 packages: +- `contentstack` - Main CLI package +- `contentstack-auth` - Authentication plugin +- `contentstack-config` - Configuration plugin +- `contentstack-command` - Base Command class (library) +- `contentstack-utilities` - Utilities library +- `contentstack-dev-dependencies` - Dev dependencies + +### 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-config) +pnpm --filter @contentstack/cli-config test -- --watch + +# Run only command tests (example: from a package directory) +cd packages/contentstack-config && 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-config package +cd packages/contentstack-config && pnpm test + +# For all packages with parallel execution +pnpm -r --filter './packages/*' run test + +# For specific test file +cd packages/contentstack-config && npx mocha "test/unit/commands/region.test.ts" + +# With coverage +pnpm -r --filter './packages/*' 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