Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .cursor/rules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Cursor rules (contentstack-cli-content-type)

Rules are `.mdc` files under `.cursor/rules/`. For each rule here, **`alwaysApply` is `false`**: Cursor applies it when files matching **`globs`** are in context (open or relevant to the task).

| Rule file | Globs | Purpose | Related skill |
|-----------|--------|---------|----------------|
| [dev-workflow.mdc](dev-workflow.mdc) | `src/**/*.ts`, `tests/**/*.ts`, `package.json`, `jest.config.js` | Run `npm test` / ESLint / `test:coverage` before PR; oclif docs when commands change | [AGENTS.md](../../AGENTS.md), [.cursor/skills/testing/SKILL.md](../skills/testing/SKILL.md) |
| [content-type-plugin.mdc](content-type-plugin.mdc) | `src/commands/**`, `src/core/**`, `src/utils/**`, `src/types/**`, `src/config/**` | OCLIF commands, `ContentTypeCommand`, utils/types/config, Management SDK + axios client, no secret logging, `oclif readme` when commands change | [.cursor/skills/contentstack-cli-content-type/SKILL.md](../skills/contentstack-cli-content-type/SKILL.md) |
| [testing.mdc](testing.mdc) | `tests/**/*.ts`, `jest.config.js` | Jest + ts-jest, mock boundaries, `npm test` / posttest ESLint | [.cursor/skills/testing/SKILL.md](../skills/testing/SKILL.md) |
| [review.mdc](review.mdc) | `compare.ts`, `diagram.ts`, `src/core/contentstack/**`, `package.json` | Security and PR review highlights for high-risk paths and dependency changes | [.cursor/skills/review/SKILL.md](../skills/review/SKILL.md) |
| [typescript-build.mdc](typescript-build.mdc) | `tsconfig.json` | `strict`, `rootDir`/`outDir`, `tsc -b` / prepack alignment | [.cursor/skills/contentstack-cli-content-type/SKILL.md](../skills/contentstack-cli-content-type/SKILL.md) |
| [eslint-config.mdc](eslint-config.mdc) | `.eslintrc` | oclif-typescript style, posttest eslint expectations | — |
| [oclif-docs.mdc](oclif-docs.mdc) | `README.md`, `oclif.manifest.json` | Regenerate command docs/manifest via `oclif readme` / `oclif manifest` after command changes | [.cursor/skills/contentstack-cli-content-type/SKILL.md](../skills/contentstack-cli-content-type/SKILL.md) |

See also [.cursor/skills/README.md](../skills/README.md) for the full skill index.
22 changes: 22 additions & 0 deletions .cursor/rules/content-type-plugin.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
description: OCLIF content-type plugin — commands, core, utils, types, config (ContentTypeCommand, SDK, CMA client)
globs:
- src/commands/**/*.ts
- src/core/**/*.ts
- src/utils/**/*.ts
- src/types/**/*.ts
- src/config/**/*.ts
alwaysApply: false
---

# content-type plugin

- Commands live under `src/commands/content-type/` and extend **`ContentTypeCommand`** from `src/core/command.ts`. Parse flags, call **`setup(flags)`** (await where the command awaits it), then delegate to **`src/core/content-type/`** and **`src/utils/index.ts`**.
- **utils**: Management SDK helpers (`getStack`, `getContentTypes`, pagination via `src/config/index.ts`); keep **`handleErrorMsg`** / `process.exit` patterns consistent with existing code.
- **types / config**: Shared types and query limits affect commands and core—align changes with consumers under `src/core` and `src/commands`.
- Build **`managementSDKClient`** when using stack/content-type fetches; use **`ContentstackClient`** from `src/core/contentstack/client.ts` for audit logs and references REST paths.
- **Never log** tokens, `authtoken`, `authorization` headers, or raw management credentials.
- User-facing errors for REST failures should follow **`ContentstackError`** / `buildError` patterns in `client.ts`.
- After changing command IDs, flags, or descriptions, regenerate docs with **`oclif readme`** (see `package.json` `prepack` / `version`).

Full detail: `.cursor/skills/contentstack-cli-content-type/SKILL.md` and `references/` there.
18 changes: 18 additions & 0 deletions .cursor/rules/dev-workflow.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
description: Local validation before PR — tests, ESLint, coverage, oclif docs
globs:
- src/**/*.ts
- tests/**/*.ts
- package.json
- jest.config.js
alwaysApply: true
---

# Development workflow

- Run **`npm test`** before opening a PR; fix failures before review.
- **`npm run posttest`** runs ESLint on `.ts` files (see [package.json](package.json)); keep lint clean when shipping changes.
- When changing behavior in **`src/core/`** or **`src/utils/`**, run **`npm run test:coverage`** and ensure coverage does not drop below [jest.config.js](jest.config.js) thresholds.
- After changing command IDs, flags, or descriptions, regenerate CLI docs with **`npm run prepack`** or the **`version`** script so `README.md` and `oclif.manifest.json` stay aligned.

Full context: [AGENTS.md](../../AGENTS.md) at the repository root.
12 changes: 12 additions & 0 deletions .cursor/rules/eslint-config.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
description: ESLint configuration and style expectations for contentstack-cli-content-type
globs:
- .eslintrc
alwaysApply: false
---

# ESLint

- Config extends **oclif-typescript** and **`@typescript-eslint/recommended`** (see [`.eslintrc`](.eslintrc)).
- Notable conventions: **single quotes**, **`eqeqeq`** smart, **`@typescript-eslint/no-unused-vars`** (args none), **`no-var`**. New rule overrides should not break **`npm run posttest`** / **`eslint . --ext .ts --config .eslintrc`**.
- Prefer fixing lint in **`src/`** and **`tests/`** rather than disabling rules project-wide without team agreement.
15 changes: 15 additions & 0 deletions .cursor/rules/oclif-docs.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
description: Oclif-generated README command docs and CLI manifest for contentstack-cli-content-type
globs:
- README.md
- oclif.manifest.json
alwaysApply: false
---

# Oclif docs and manifest

- **README.md** command sections and **oclif.manifest.json** are generated by **`oclif readme`** and **`oclif manifest`** (see [`package.json`](package.json) `prepack`, `version`).
- Prefer changing **`src/commands/**/*.ts`** (descriptions, flags, examples), then run **`npm run prepack`** or the relevant **`oclif`** script so README and manifest stay consistent—avoid hand-editing generated command blocks unless you will regenerate immediately after.
- If you only need doc tweaks without a full prepack, follow the same workflow the team uses for releases so CI and published packages stay aligned.

Full workflow: `.cursor/skills/contentstack-cli-content-type/SKILL.md`.
18 changes: 18 additions & 0 deletions .cursor/rules/review.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
description: PR and security review context for contentstack-cli-content-type (compare, diagram, client, dependencies)
globs:
- src/core/content-type/compare.ts
- src/core/content-type/diagram.ts
- src/core/contentstack/**/*.ts
- package.json
alwaysApply: false
---

# Review

- **Never log** tokens, `authtoken`, `authorization` headers, or raw management credentials. Stack API keys in user-facing errors should follow existing patterns in `client.ts` / `ContentstackError`.
- **Compare** (`compare.ts`): temp HTML, browser open, and diff pipeline—review for accidental data exposure and path handling.
- **Diagram** (`diagram.ts`): Graphviz / file output paths and large-model behavior when changing layout or IO.
- **Dependencies** (`package.json`): version bumps on axios, diff2html, git-diff, node-graphviz, tmp, cli-ux—check changelog and security advisories.

Full checklist: `.cursor/skills/review/SKILL.md` and `references/checklist.md`.
16 changes: 16 additions & 0 deletions .cursor/rules/testing.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
description: Jest tests and config for contentstack-cli-content-type
globs:
- tests/**/*.ts
- jest.config.js
alwaysApply: false
---

# Testing

- Use **Jest** with **ts-jest** per `jest.config.js`. Tests live under **`tests/`** (and may match `*.test.ts` at repo root per config).
- **Mock HTTP and SDK boundaries** — mock `ContentstackClient`, axios, or fake `managementSDKClient` chains. **No live Contentstack API** calls in unit tests.
- Run **`npm test`**; **`npm run test:coverage`** for coverage against [jest.config.js](jest.config.js) thresholds; **`posttest`** runs ESLint on `.ts` files — keep both green when shipping changes.
- Add or update tests for behavioral changes in `src/core/` and `src/utils/` when practical.

Full detail: `.cursor/skills/testing/SKILL.md`; `references/conventions.md` and `references/jest-mocking.md`.
14 changes: 14 additions & 0 deletions .cursor/rules/typescript-build.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
description: TypeScript compiler options and build layout for contentstack-cli-content-type
globs:
- tsconfig.json
alwaysApply: false
---

# TypeScript build

- Preserve [`tsconfig.json`](tsconfig.json) intent: **`strict: true`**, **`rootDir: src`**, **`outDir: lib`**, **`module: commonjs`**, **`target: es2017`**.
- Changes to **`include`**, **`compilerOptions.paths`**, or **`rootDir`/`outDir`** affect the whole package and published `lib/` output—validate with **`tsc -b`** (as in `prepack`).
- Source of truth for app code is **`src/`**; compiled JS lives under **`lib/`** (do not treat `lib/` as hand-edited).

See `.cursor/skills/contentstack-cli-content-type/SKILL.md` for release/prepack workflow.
11 changes: 11 additions & 0 deletions .cursor/skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Project skills (contentstack-cli-content-type)

Cursor loads **project skills** from `.cursor/skills/<skill-name>/SKILL.md`. Each folder below is one skill; open `SKILL.md` for instructions and follow links into `references/` for detail.

| Skill folder | Purpose | When to load |
|--------------|---------|----------------|
| [contentstack-cli-content-type](contentstack-cli-content-type/SKILL.md) | Plugin architecture, `ContentTypeCommand`, CMA client, commands, build/readme workflow | Editing `src/commands`, `src/core`, `src/utils`, auth, compare/diagram behavior, oclif |
| [testing](testing/SKILL.md) | Jest, `tests/`, mocking, `npm test` / `test:coverage` / ESLint posttest; see `references/conventions.md` | Adding or changing tests, Jest config, mocks |
| [review](review/SKILL.md) | PR review checklist and risk areas | Reviewing PRs, dependency bumps, security-sensitive edits |

Use the skill whose **description** frontmatter best matches the task; combine **testing** with **contentstack-cli-content-type** when implementing features that need tests.
69 changes: 69 additions & 0 deletions .cursor/skills/contentstack-cli-content-type/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: contentstack-cli-content-type
description: >-
Develops and maintains the contentstack-cli-content-type csdx plugin (content-type list,
details, audit, compare, compare-remote, diagram). Use when editing this repository,
ContentTypeCommand setup and flags, CMA/Management SDK usage, axios audit/references calls,
diff/compare HTML output, Graphviz diagrams, or oclif readme/manifest workflows.
---

# contentstack-cli-content-type

## Repository role

npm package `contentstack-cli-content-type`: a **Contentstack CLI** (`csdx`) plugin that reads Content Type metadata from a stack—list, field details, audit log lines, version or cross-stack comparison, and stack content-model diagrams.

## Code layout

| Area | Path |
|------|------|
| Command classes (oclif) | `src/commands/content-type/*.ts` |
| Shared base | `src/core/command.ts` — `ContentTypeCommand` extends `@contentstack/cli-command` `Command` |
| Core output / logic | `src/core/content-type/*.ts` |
| HTTP client (axios CMA) | `src/core/contentstack/client.ts`, `src/core/contentstack/error.ts` |
| Stack / CT fetch helpers | `src/utils/index.ts` (uses Management SDK from `@contentstack/cli-utilities`) |
| Types | `src/types/index.ts` |
| Config (pagination limits) | `src/config/index.ts` |

Commands **parse flags**, call **`setup(flags)`** (see below), build **`managementSDKClient`**, then call utils + core builders. See [references/architecture.md](references/architecture.md) and [references/commands.md](references/commands.md).

## Authentication and stack identity

1. `authenticationHandler.getAuthDetails()`; must have **access token** or command exits with `auth:login` message (`exit: 2`).
2. User must pass **either** a **management token alias** (`-a` / `--alias` or `--token-alias`) **or** **stack API key** (`-k` / `--stack-api-key`) or deprecated `--stack` (maps to stack key). If neither: error and `process.exit(1)` (message references “token alias or stack UID”).
3. Token alias: `getToken(alias)` → `apiKey` from token; warns if token type is not `management`.
4. `ContentTypeCommand` constructs **`ContentstackClient(this.cmaHost, authToken)`** for REST calls that use `api_key` in headers.

**Do not log** tokens, `authorization` / `authtoken` headers, or full CLI credentials.

## Two ways to call APIs

- **Axios `ContentstackClient`**: `GET https://{cmaHost}/v3/...` with default headers `authorization` (if Bearer) or `authtoken`, plus per-request `headers: { api_key }`. Used for audit logs and references. Errors → `ContentstackError` via `buildError`.
- **Management SDK** (`managementSDKClient({ host, 'X-CS-CLI': ... })`): stack fetch, content types, global fields, content type by version—see `src/utils/index.ts`.

## Build and CLI metadata

From `package.json`:

- **`prepack`**: `rm -rf lib && tsc -b && oclif manifest && oclif readme` — publishable `lib/`, manifest, and README command docs.
- **`version`**: `oclif readme && git add README.md`.

After changing commands, flags, or descriptions, run the appropriate script so **README** and **oclif.manifest.json** stay in sync.

## Short command names (csdx)

`package.json` → `csdxConfig.shortCommandName`:

| Command id | Short name |
|------------|------------|
| `content-type:audit` | CTAUDIT |
| `content-type:compare` | CTCMP |
| `content-type:compare-remote` | CTCMP-R |
| `content-type:details` | CTDET |
| `content-type:diagram` | CTDIAG |
| `content-type:list` | CTLS |

## Further reading

- [references/architecture.md](references/architecture.md) — command → core mapping, auth flow, CMA shape.
- [references/commands.md](references/commands.md) — flags, UX notes, files to edit per command.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Architecture

## Command → core modules

| Command file | Core / utilities | Notes |
|--------------|------------------|--------|
| `src/commands/content-type/audit.ts` | `core/content-type/audit.ts`, `utils` (`getStack`, `getUsers`, `getContentType`), `client.getContentTypeAuditLogs` | Audit + users for display |
| `src/commands/content-type/compare.ts` | `core/content-type/compare.ts`, `utils` | Same-stack two versions; optional `--left` / `--right` |
| `src/commands/content-type/compare-remote.ts` | `core/content-type/compare.ts` (same `buildOutput`), `utils` | Two stacks; `setup` uses origin stack key only |
| `src/commands/content-type/details.ts` | `core/content-type/details.ts`, `utils`, `client.getContentTypeReferences` | `--path` / `--no-path` |
| `src/commands/content-type/diagram.ts` | `core/content-type/diagram.ts`, `utils` (`getStack`, `getContentTypes`, `getGlobalFields`) | Writes file via Graphviz |
| `src/commands/content-type/list.ts` | `core/content-type/list.ts`, `utils` | `--order title|modified` |

Formatting helpers live under `src/core/content-type/formatting.ts` where imported by core modules.

## Auth flow (high level)

```mermaid
flowchart LR
subgraph setup [ContentTypeCommand.setup]
A[getAuthDetails]
B{accessToken?}
C[error auth:login]
D{alias or stack key?}
E[exit 1 missing stack]
F[getToken or use stack API key]
G[ContentstackClient]
end
A --> B
B -->|no| C
B -->|yes| D
D -->|neither| E
D -->|ok| F
F --> G
```

- **`compare-remote`**: `setup` is called with `{ alias: undefined, stack: flags["origin-stack"] }` so `apiKey` is the **origin** stack API key; remote stack is passed only in `getStack` / `getContentType` calls.

## CMA request shape (ContentstackClient)

- **Base URL**: `https://{cmaHost}/v3/` (`cmaHost` from command context).
- **Default axios headers**: `authorization: <token>` if token string includes `Bearer`, else `authtoken: <token>`.
- **Per-request**: `headers: { api_key: <stack API key> }` for stack-scoped routes.

| Method | HTTP | Path / params |
|--------|------|----------------|
| `getContentTypeAuditLogs` | GET | `/audit-logs` — `params.query.$and`: `module: content_type`, `metadata.uid` |
| `getContentTypeReferences` | GET | `/content_types/{uid}/references` — `include_global_fields: true` |

Errors: response `data.errors` → `ContentstackError`; optional suffix with stack API key when `data.errors.api_key` and context `api_key` are set.

## Compare output pipeline

`core/content-type/compare.ts` builds a unified diff from two JSON snapshots (`git-diff`), parses with **diff2html**, writes a **temporary HTML** file, opens it in the browser (`cli-ux` / `cli.open`). Not a terminal table.

## Diagram pipeline

`core/content-type/diagram.ts` builds a DOT graph, runs **node-graphviz** (`graphviz` binary must be available on the system for SVG rendering). Output path is sanitized where utilities apply.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Commands reference

Primary sources: `README.md` and `src/commands/content-type/*.ts`.

## `content-type:list`

- **Flags**: `--stack-api-key` (`-k`), `--stack` (deprecated → use stack key), `--token-alias` / `--alias` (`-a`), `--order` (`-o`) `title` | `modified` (default `title`).
- **Files**: `src/commands/content-type/list.ts`, `src/core/content-type/list.ts`.
- **Behavior**: Lists Content Types for the stack; table output via core builder.

## `content-type:details`

- **Flags**: stack identity flags as above; `--content-type` (`-c`) required; `--path` / `--no-path` (`-p`) — default shows path column; use `--no-path` on narrow terminals (README).
- **Files**: `src/commands/content-type/details.ts`, `src/core/content-type/details.ts`.
- **Behavior**: Fetches CT + **references** via `ContentstackClient.getContentTypeReferences`.

## `content-type:audit`

- **Flags**: stack identity + `--content-type` (`-c`) required.
- **Files**: `src/commands/content-type/audit.ts`, `src/core/content-type/audit.ts`.
- **Behavior**: Audit logs via `getContentTypeAuditLogs`; README notes **audit log retention** (e.g. 90 days) per Contentstack docs.

## `content-type:compare`

- **Flags**: stack identity + `--content-type` (`-c`); optional `--left` (`-l`) / `--right` (`-r`) **integers** (both required if either set). If omitted, command infers latest version vs previous from discovery fetch.
- **Files**: `src/commands/content-type/compare.ts`, `src/core/content-type/compare.ts`.
- **Behavior**: Side-by-side diff in **HTML** in a browser; not stdout-only. Warns if left === right.

## `content-type:compare-remote`

- **Flags**: `--origin-stack` (`-o`) and `--remote-stack` (`-r`) **required** (stack API keys); `--content-type` (`-c`) required. No token-alias flow for two stacks—setup uses **origin** stack key for session.
- **Files**: `src/commands/content-type/compare-remote.ts`, same `core/content-type/compare.ts` as same-stack compare.
- **Behavior**: Same HTML diff pipeline; compares CT JSON from two stacks. Warns if origin === remote API key.

## `content-type:diagram`

- **Flags**: stack identity; `--output` (`-o`) **required** (full path); `--direction` (`-d`) `portrait` | `landscape` (required in schema, default portrait); `--type` (`-t`) `svg` | `dot` (default svg).
- **Files**: `src/commands/content-type/diagram.ts`, `src/core/content-type/diagram.ts`.
- **Behavior**: Loads all content types + global fields; renders graph. **Graphviz** must be installed for typical SVG generation; DOT export available. README documents `-t dot` for raw DOT language.

## Editing checklist

| Change | Touch first |
|--------|-------------|
| New flag / description | Command file under `src/commands/content-type/`, then `oclif readme` |
| Output format / table | `src/core/content-type/*.ts`, `formatting.ts` |
| REST audit/references | `src/core/contentstack/client.ts`, `error.ts` |
| SDK pagination / fetch | `src/utils/index.ts`, `src/config/index.ts` |
Loading
Loading