diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md new file mode 100644 index 0000000..b4b2107 --- /dev/null +++ b/.cursor/rules/README.md @@ -0,0 +1,26 @@ +# Cursor rules — `@contentstack/utils` + +This folder holds project-specific rules for AI assistants working in **contentstack-utils-javascript**. For the full project overview, see **[`AGENTS.md`](../../AGENTS.md)** at the repository root. + +## How rules are picked up + +Each rule is a `.md`/`.mdc` file. Files with YAML frontmatter can set `description`, `globs`, and `alwaysApply`. Cursor uses these to decide when a rule is included in context. + +### Referencing rules in chat + +In Cursor, you can **`@`-mention** a rule file (e.g. type `@` and choose the rule from the list) to force its guidance into the conversation. The file name (without extension) is the usual handle, e.g. **`typescript`**, **`testing`**, **`code-review`**. + +## Rule index + +| File | `alwaysApply` | Globs | When it applies | +|------|----------------|-------|------------------| +| [`dev-workflow.md`](dev-workflow.md) | no | *(none)* | Branching, CI alignment, commits, releases, and day-to-day commands for this repo. | +| [`typescript.mdc`](typescript.mdc) | no | `src/**/*.ts`, `__test__/**/*.ts` | TypeScript version, layout, ESLint/Prettier, strictness, imports. | +| [`typescript-contentstack-utils.mdc`](typescript-contentstack-utils.mdc) | no | `src/**/*.ts` | Delivery-oriented utils only: RTE rendering, GQL helpers, endpoints JSON, Live Preview tags—**not** full CDA/CMA SDK surface. | +| [`testing.mdc`](testing.mdc) | no | `__test__/**/*.ts` | Jest, jsdom, mocks, coverage output paths, no live-test env. | +| [`code-review.mdc`](code-review.mdc) | **yes** | *(global)* | PR checklist: public API docs, compatibility, errors, dependencies, terminology (utils + delivery context). | + +## Related + +- **[`AGENTS.md`](../../AGENTS.md)** — Single entry point (package purpose, stack, commands). +- **[`skills/README.md`](../../skills/README.md)** — Longer-form skill docs for the same themes. diff --git a/.cursor/rules/code-review.mdc b/.cursor/rules/code-review.mdc new file mode 100644 index 0000000..0e5fc27 --- /dev/null +++ b/.cursor/rules/code-review.mdc @@ -0,0 +1,41 @@ +--- +description: PR review checklist for @contentstack/utils — API docs, compatibility, security, testing +alwaysApply: true +--- + +# Code review checklist — `@contentstack/utils` + +Use severity labels (**Blocker / Major / Minor**) when triaging findings. + +## Public API and documentation + +- **Blocker/Major:** New or changed **exports** from `src/index.ts` need accurate **JSDoc** (or clear type names) matching runtime behavior. +- **Major:** README / CHANGELOG updates when behavior is user-visible or migration is needed. + +## Backward compatibility + +- **Blocker:** Unplanned breaking changes to **function signatures** or **default behavior** consumed by Delivery SDK integrations or documented `renderOption` contracts. +- **Major:** Stricter throwing on inputs that previously passed (especially `getContentstackEndpoint`, RTE traversals). + +## Errors + +- This package uses **plain `Error`** (e.g. `endpoints.ts`); new code should keep messages actionable. **Major:** Silent failures where callers need to detect bad input. + +## Null safety and RTE edge cases + +- **Major:** Missing guards on **null/undefined** node or entry fragments (historically sensitive in `entry-editable` / RTE paths). +- **Minor:** Align with **`strictNullChecks: false`** legacy but avoid widening undefined leaks into public types. + +## Dependencies and SCA + +- **Major:** New runtime deps are rare—justify any addition; **`prepublishOnly`** and hooks assume **`npm test`** and Snyk-friendly trees. +- Use **`npm audit` / Snyk** expectations per org policy. + +## Tests + +- **Blocker:** Behavioral fixes or new branches without **`__test__`** coverage when risk is high (RTE nesting, GQL URL rewriting, endpoint resolution). +- **Minor:** Snapshot-only tests where a small assertion would be clearer. + +## Terminology + +- **Major:** Docs/comments must describe this as **utils** alongside **CDA / Delivery / JSON RTE / GraphQL**, not as **CMA** unless the change is explicitly management-related. diff --git a/.cursor/rules/dev-workflow.md b/.cursor/rules/dev-workflow.md new file mode 100644 index 0000000..0453f3c --- /dev/null +++ b/.cursor/rules/dev-workflow.md @@ -0,0 +1,38 @@ +--- +description: Branching, CI, local commands, commit hooks, and release flow for contentstack-utils-javascript +alwaysApply: false +--- + +# Dev workflow — `@contentstack/utils` + +## Branches and PRs + +- **CI** (`Unit-Test-CI`) runs on **push/PR** to `development`, `staging`, and `master` (see `.github/workflows/ci.yml`). +- **Branch protection:** A workflow fails PRs that target **`staging`** when the head branch is **not** `development` (see `.github/workflows/check-branch.yml`). Prefer **`development`** as the integration branch when contributing upstream. +- Target the branch your team uses for integration; align with maintainers if unsure. + +## Local development + +| Task | Command / note | +|------|----------------| +| Build | `npm run build` (runs `prebuild`: clean `dist`, `download-regions`, then `tsc` + Rollup) | +| Test | `npm test` (includes `pretest` → build; Jest + coverage; `reports/`) | +| Format | `npm run format` (Prettier: `src/**/*.ts`) | +| ESLint | No `lint` script in `package.json`; run e.g. `npx eslint src __test__` using `eslint.config.js` | + +## Git hooks (Husky) + +- **`commit-msg`:** [Conventional Commits](https://www.conventionalcommits.org/) via **`commitlint`** (`.commitlintrc.json`). +- **`pre-commit`:** Requires **Snyk** (`snyk test --all-projects`) and **Talisman** installed locally. Set `SKIP_HOOK=1` to bypass (documented in the hook). + +## PR expectations + +- **`npm test`** passes (build + unit tests). +- **CHANGELOG.md** updated for user-visible changes when maintainers expect it. +- **Dependencies:** Be mindful of Snyk/SCA workflows; security-relevant bumps should be justified. + +## Releases and versioning + +- **Package version** lives in **`package.json`** (also reflected in **`CHANGELOG.md`**). +- **`prepublishOnly`** runs **`npm test`** before publish. +- **NPM / GitHub Packages:** Publishing is driven by **GitHub release `created`** (`.github/workflows/npm-publish.yml`); requires maintainer secrets (`NPM_TOKEN`, `GIT_TOKEN`). Bump version and changelog in the same change set as the release your team uses. diff --git a/.cursor/rules/testing.mdc b/.cursor/rules/testing.mdc new file mode 100644 index 0000000..1b7f67e --- /dev/null +++ b/.cursor/rules/testing.mdc @@ -0,0 +1,38 @@ +--- +description: Jest tests, mocks, reports, and environments for @contentstack/utils +globs: + - __test__/**/*.ts +alwaysApply: false +--- + +# Testing — `@contentstack/utils` + +## Framework + +- **Jest 29** with **`ts-jest`** preset (`jest.config.ts`). +- **Environment:** **`jsdom`** (suitable for HTML string assertions and DOM-related behavior). + +## Discovery and naming + +- **Pattern:** `**/__test__/**/?(*.)+(spec|test).[jt]s?(x)` — this repo uses `*.test.ts` under **`__test__/`**. +- **Mocks / fixtures:** `__test__/mock/*.ts` — follow existing mock naming (`*-mock.ts`). + +## Coverage and reports + +- **Coverage** is collected from `src/**` excluding `src/index.ts` (`collectCoverageFrom`). +- Outputs: **`reports/coverage/`**, **`reports/html/`** (jest-html-reporters), **`reports/junit/`** (jest-junit), **`reports/report.json`** (from `npm test` script). + +## Running tests + +| Command | Behavior | +|---------|----------| +| `npm test` | Runs **`pretest` → build** then Jest (CI-aligned). | +| `npm run test:debug` | Watch mode, `--runInBand`. | + +## Integration / live tests + +- **None** in this repo. No `.env` or stack credentials required for **`npm test`**. + +## Build dependency + +- **`npm test` always builds first** (`pretest`). Ensure **`src/assets/regions.json`** exists or can be downloaded so `endpoints` tests pass. diff --git a/.cursor/rules/typescript-contentstack-utils.mdc b/.cursor/rules/typescript-contentstack-utils.mdc new file mode 100644 index 0000000..70f23c6 --- /dev/null +++ b/.cursor/rules/typescript-contentstack-utils.mdc @@ -0,0 +1,34 @@ +--- +description: Contentstack utils package patterns — RTE, embedded items, GQL, endpoints (delivery-oriented companion, not CDA/CMA SDK) +globs: + - src/**/*.ts +alwaysApply: false +--- + +# `@contentstack/utils` — domain patterns + +This repository implements **companion utilities** for Contentstack **content consumption** scenarios (typically with the **Delivery SDK** and **CDA / GraphQL** responses). It does **not** implement stack configuration, delivery tokens, or HTTP clients—callers fetch entry JSON elsewhere and pass it into these helpers. + +## Mental model + +| Area | Source anchors | Notes | +|------|----------------|-------| +| Render options / callbacks | `src/options/`, `src/render-embedded-objects.ts` | `RenderOption`-style maps: node types, marks, `block` / `inline` embeds, `reference`, `display`, `default`. | +| JSON RTE → HTML | `src/json-to-html.ts`, `src/nodes/*`, `src/helper/*` | Supercharged RTE path uses `paths` arrays for nested fields (see `README.md`). | +| Embedded object types | `src/Models/embedded-object.ts`, `src/Models/json-rte-model.ts` | Align typings with shapes coming from **delivery** entry JSON, not management APIs. | +| GraphQL | `src/gql.ts`, `src/updateAssetURLForGQL.ts` | Docs/comments describe use **after** GraphQL fetches; asset URL rewriting is response-shape specific. | +| Live Preview / CSLP tags | `src/entry-editable.ts` | `addTags` / exported `addEditableTags` — preserve existing attribute and locale behavior when changing tag generation. | +| Region endpoints | `src/endpoints.ts` | **`getContentstackEndpoint(region, service?, omitHttps?)`** reads **`src/assets/regions.json`**; throws plain `Error` with human-readable messages on bad region/service. | + +## Terminology + +- Prefer **CDA / Delivery / JSON RTE / GraphQL** vocabulary when describing behavior—**not** CMA unless you are explicitly discussing something management-only (rare here). +- **“SDK”** in docs often means **this utils package** or the **Delivery SDK** together—disambiguate in user-facing text. + +## Concurrency / IO + +- Pure synchronous transforms dominate; no retry or rate-limit layer. Do not add HTTP clients without an explicit product requirement. + +## Official docs alignment + +- Behavior should stay consistent with current **Content Delivery** / **Live Preview** / **JSON RTE** documentation. When in doubt, cite the relevant Contentstack doc set in PR descriptions rather than guessing CMS semantics. diff --git a/.cursor/rules/typescript.mdc b/.cursor/rules/typescript.mdc new file mode 100644 index 0000000..ad2d6fb --- /dev/null +++ b/.cursor/rules/typescript.mdc @@ -0,0 +1,34 @@ +--- +description: TypeScript conventions for @contentstack/utils (src and tests) +globs: + - src/**/*.ts + - __test__/**/*.ts +alwaysApply: false +--- + +# TypeScript — `@contentstack/utils` + +## Tooling + +- **TypeScript ~4.9** (`package.json`, `tsconfig.json`). +- **Bundler output:** `tsc` emits to `dist/lib` with declarations in `dist/types`; **Rollup** produces `dist/index.es.js` (`rollup.config.js`). +- **Strict mode** is on with **`strictNullChecks: false`** — new code should still minimize unnecessary null/undefined gaps when touching APIs. + +## Layout + +- **Library code:** `src/**/*.ts` only (`tsconfig.json` `include`); **tests** are under `__test__/` (excluded from `tsc` program but type-checked via Jest/tsconfig paths). +- **Public exports:** Maintain **`src/index.ts`** as the single export surface unless intentionally adding secondary entry points. + +## Style and lint + +- Match existing naming (PascalCase types, camelCase functions, existing file layout under `Models/`, `nodes/`, `helper/`, `options/`). +- **ESLint** flat config: `eslint.config.js` — `@typescript-eslint` recommended for `__test__`; source files use `js.configs.recommended` baseline. +- **Prettier:** `npm run format` scopes `src/**/*.ts`; keep formatting consistent when editing tests too. + +## JSON / assets + +- **`src/assets/regions.json`:** Consumed by `src/endpoints.ts`; populated by **`npm run download-regions`** during `prebuild`. Do not assume the file is committed (see root `.gitignore`). + +## Logging + +- No shared logger dependency; avoid introducing `console` noise in library paths unless consistent with nearby code. diff --git a/.github/workflows/sca-scan.yml b/.github/workflows/sca-scan.yml index f09161f..2307d48 100644 --- a/.github/workflows/sca-scan.yml +++ b/.github/workflows/sca-scan.yml @@ -13,3 +13,6 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --all-projects --fail-on=all + json: true + continue-on-error: true + - uses: contentstack/sca-policy@main diff --git a/.talismanrc b/.talismanrc index dbc2d7e..78e5520 100644 --- a/.talismanrc +++ b/.talismanrc @@ -26,3 +26,9 @@ fileignoreconfig: checksum: a843710fc9f54bf4c7996f39561dc66491d62a9d9eeca50fa2c7c37bd6141f53 - filename: src/render-embedded-objects.ts checksum: 35d56d4f7b625611fef18414fccdbff014c1d90d02e17eb0efa4d6166b73e23b +- filename: .cursor/rules/code-review.mdc + checksum: 43d4fddb706e5ad6c92fe0af30bd5f44eec9b83c31dc93d3d4cc5e6208d351cc +- filename: .cursor/rules/dev-workflow.md + checksum: b9a4d68439ce9564730506ab6c4712f5034a645858bdb78ac57e43ba183cb981 +- filename: skills/code-review/SKILL.md + checksum: 4ec638a87a795e5cc0b0e66b569e04749cb27f9d3be29d4ea69f56b48225c943 diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..0798e0e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,52 @@ +# Agent guidance — `@contentstack/utils` + +## What this package is + +**[@contentstack/utils](https://www.npmjs.com/package/@contentstack/utils)** (`contentstack-utils-javascript`) is a **JavaScript/TypeScript utilities library** for Contentstack. It is **not** the Content Delivery API (CDA) SDK or the Content Management API (CMA) SDK. It focuses on **JSON RTE / Supercharged RTE** rendering (`jsonToHTML`), **embedded entry and asset** rendering (`render`, `renderContent`), **GraphQL-oriented helpers** (`GQL`, `updateAssetURLForGQL`), **Live Preview–style editable tags** (`addEditableTags` / `addTags`), and **region endpoint lookup** (`getContentstackEndpoint`). Typical usage is **alongside** the Delivery SDK (see repository `README.md` examples with `@contentstack/delivery-sdk`). + +- **Repository:** [github.com/contentstack/contentstack-utils-javascript](https://github.com/contentstack/contentstack-utils-javascript) + +## Tech stack + +| Area | Details | +|------|---------| +| Language | TypeScript **4.9** (`tsconfig.json`, `strict: true`, `strictNullChecks: false`) | +| Build | **TypeScript** (`tsc`) → `dist/lib`; **Rollup** (`rollup -c`) → `dist/index.es.js`; types in `dist/types/` | +| Test | **Jest 29** + **ts-jest**, **jsdom** environment (`jest.config.ts`) | +| Lint / format | **ESLint 9** flat config (`eslint.config.js`); **Prettier 3** (`npm run format`) — there is **no** `lint` npm script; use `npx eslint` as needed | +| Runtime HTTP / JSON for API calls | **None** in library code; `regions.json` is a **build-time** asset (see below) | + +## Source layout and public API + +| Role | Path | +|------|------| +| Public entry (sources) | `src/index.ts` | +| Options / render types | `src/options/` | +| RTE / node model | `src/Models/`, `src/nodes/` | +| Helpers | `src/helper/` | +| GQL + asset URL rewrite | `src/gql.ts`, `src/updateAssetURLForGQL.ts` | +| Endpoints helper | `src/endpoints.ts` + `src/assets/regions.json` (generated; see build) | +| Published bundle | `dist/` (per `package.json` `main` / `types`) | + +## Common commands + +| Command | Purpose | +|---------|---------| +| `npm run build` | Cleans `dist`, ensures `src/assets/regions.json` (download or warning), runs `tsc` + Rollup | +| `npm test` | Runs `pretest` → **build**, then Jest with coverage; outputs under `reports/` | +| `npm run test:debug` | Jest watch, in-band | +| `npm run format` | Prettier on `src/**/*.ts` | +| `npm run download-regions` | Fetches `regions.json` only (used by `prebuild`) | + +**Tests:** Unit tests only, under `__test__/**/*.test.ts`, with mocks in `__test__/mock/`. There are **no** live/integration tests requiring stack credentials in this repository. + +## Credentials / environment + +- **Unit tests:** No API keys or `.env` required. +- **Build:** `download-regions` calls a public URL (`artifacts.contentstack.com`); offline builds may warn and rely on an existing `src/assets/regions.json`. Note `regions.json` is listed in `.gitignore`; clones may need a successful `npm run build` (or manual file) before tests pass. +- **Publish:** GitHub release workflow uses `NPM_TOKEN` / `GIT_TOKEN` secrets (maintainers only). + +## More detail for AI / IDE rules + +- [`.cursor/rules/README.md`](.cursor/rules/README.md) — Cursor rules index (`alwaysApply`, globs, when to use). +- [`skills/README.md`](skills/README.md) — Topic skills (testing, code review, package mental model). diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 0000000..72354af --- /dev/null +++ b/skills/README.md @@ -0,0 +1,11 @@ +# Skills — `@contentstack/utils` + +Short-form guides for humans and agents. Root context: **[`AGENTS.md`](../AGENTS.md)**. Cursor rule index: **[`.cursor/rules/README.md`](../.cursor/rules/README.md)**. + +| Skill | When to use | +|-------|--------------| +| [`code-review/`](code-review/SKILL.md) | Before opening or approving a PR; expanded checklist (API docs, compatibility, errors, tests, terminology). | +| [`testing/`](testing/SKILL.md) | Running Jest, understanding `pretest`/build, mocks, reports, and why no live API tests exist here. | +| [`typescript-contentstack-utils/`](typescript-contentstack-utils/SKILL.md) | Mental map of RTE/embed/GQL/endpoints/Live Preview code paths and where to change behavior safely. | + +There is **no** separate `framework` skill: this repo has **no** shared HTTP client or retry layer. diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md new file mode 100644 index 0000000..066047c --- /dev/null +++ b/skills/code-review/SKILL.md @@ -0,0 +1,44 @@ +# Skill: Code review — `@contentstack/utils` + +## When to use + +Final pass before merge, or when authoring a PR to self-check against team expectations. + +## Checklist (expanded) + +### Public API and docs + +- Exported symbols from **`src/index.ts`** stay coherent: names match behavior, types match real JSON RTE / entry shapes from **delivery** content. +- **JSDoc** on public functions (`getContentstackEndpoint`, `jsonToHTML`, `render`, GQL helpers, etc.) matches parameters, throws, and return shapes. +- **README.md** examples remain valid for **`@contentstack/delivery-sdk`** + **`Contentstack.Utils`** style usage when touching those flows. + +### Backward compatibility + +- Avoid breaking **`RenderOption`** callback contracts or default HTML output without a major version plan and **CHANGELOG** entry. +- Changes to **`regions.json`** / endpoint keys must stay aligned with upstream region definitions. + +### Errors + +- Prefer clear **`Error`** messages for invalid regions, missing services, or malformed internal state—callers often log these verbatim. + +### Security and dependencies + +- New **npm dependencies** need justification (`package.json` is dev-heavy already). +- No secrets or tokens in code; **Talisman** pre-commit enforces secret scanning locally for contributors with hooks installed. + +### Tests + +- **`npm test`** must pass (includes full **build**). +- Add or update **`__test__`** cases for RTE edge cases, GQL URL rewriting, and endpoint error paths when logic changes. + +### Severity rubric (optional) + +| Level | Examples | +|-------|-----------| +| **Blocker** | Breaks published API, break consumers without semver major, removes tests on critical path | +| **Major** | Missing docs for new export, behavior change without tests, confusing error surfaces | +| **Minor** | Naming nits, internal refactors with equivalent coverage | + +### Terminology + +- Use **delivery / CDA / JSON RTE / GraphQL / Live Preview** context—not **CMA**—unless the work truly relates to management APIs. diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md new file mode 100644 index 0000000..0f8b834 --- /dev/null +++ b/skills/testing/SKILL.md @@ -0,0 +1,31 @@ +# Skill: Testing — `@contentstack/utils` + +## When to use + +Setting up locally, debugging failures, or adding tests. + +## Commands + +- **`npm test`** — Runs **`pretest`** (→ **`npm run build`**) then **Jest** with coverage. Builds **`dist/`** and ensures `regions.json` flow runs. +- **`npm run test:debug`** — Jest **`--watchAll`** in **`--runInBand`** mode. + +## Environment + +- **No API keys or `.env`** for tests—all **unit** tests with fixtures under **`__test__/mock/`**. +- First-time or clean machines: if **`src/assets/regions.json`** is missing, **`prebuild`** attempts **`download-regions`**; failures print a warning—see **`AGENTS.md`** / **package.json** `download-regions`. + +## Naming and layout + +- Tests live in **`__test__/**/*.test.ts`** (see **`jest.config.ts` `testMatch`**). +- Reuse **`__test__/mock/`** patterns (`entry-mock.ts`, `json-element-mock.ts`, etc.). + +## Reports + +- **Coverage:** `reports/coverage/` +- **HTML summary:** `reports/html/` +- **JUnit:** `reports/junit/` +- **CI** consumes junit / coverage patterns in `.github/workflows/ci.yml` and `code.cov.yml`. + +## Mocks + +- Prefer explicit mock objects over live fetches—this package does not ship an HTTP client; do not introduce network calls in tests unless the project later adds gated integration tests. diff --git a/skills/typescript-contentstack-utils/SKILL.md b/skills/typescript-contentstack-utils/SKILL.md new file mode 100644 index 0000000..41115cc --- /dev/null +++ b/skills/typescript-contentstack-utils/SKILL.md @@ -0,0 +1,45 @@ +# Skill: TypeScript — `@contentstack/utils` mental model + +## When to use + +Onboarding, feature design, or refactors touching RTE rendering, embeddings, GQL, or endpoints. + +## What this package is + +**`@contentstack/utils`** is a **TypeScript utility library**, not the **CDA** or **CMA** SDK. It transforms **entry JSON** already fetched via **Content Delivery** (REST or **GraphQL**) into HTML or enriched structures. + +## Where to change things + +| Goal | Start here | +|------|------------| +| Supercharged RTE / JSON → HTML | `src/json-to-html.ts`, `src/nodes/`, `src/helper/` | +| Custom element / embed rendering | `src/options/`, `src/render-embedded-objects.ts` | +| GraphQL-specific RTE or assets | `src/gql.ts`, `src/updateAssetURLForGQL.ts` | +| Live Preview / `data-cslp`-style tags | `src/entry-editable.ts` | +| Region → base URL lookup | `src/endpoints.ts`, `src/assets/regions.json` (build) | +| Public surface | `src/index.ts` only | + +## Data flow (conceptual) + +```mermaid +flowchart LR + subgraph external [Caller] + Delivery[Delivery SDK or GraphQL client] + end + subgraph utils [@contentstack/utils] + JSON[RTE JSON / entry object] + HTML[HTML string or tagged entry] + end + Delivery --> JSON + JSON --> HTML +``` + +## Conventions + +- Match existing **options** patterns (`RenderOption`, path arrays for nested fields). +- Preserve **pure** transform style—no hidden network I/O. +- Terminology in comments should say **delivery / JSON RTE / GraphQL**, not **CMA**, unless you explicitly touch management concerns (unlikely in this repo). + +## Docs + +- **Contentstack** product docs for **Delivery**, **Live Preview**, and **Rich Text / JSON RTE** are the authority for expected JSON shapes.