diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md new file mode 100644 index 0000000..b145041 --- /dev/null +++ b/.cursor/rules/README.md @@ -0,0 +1,5 @@ +# Cursor (optional) + +**Cursor** users: start at **[`AGENTS.md`](../../AGENTS.md)**. All conventions live in **`skills/*/SKILL.md`**. + +This folder only points contributors to **`AGENTS.md`** so editor-specific config does not duplicate the canonical docs. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e5096a1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,48 @@ +# Contentstack DataSync Asset Store (AWS S3) – 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/datasync-asset-store-aws-s3](https://github.com/contentstack/datasync-asset-store-aws-s3) (npm: `contentstack-asset-store-aws-s3`; consumers often use `@contentstack/datasync-asset-store-aws-s3` per product docs) | +| **Purpose:** | TypeScript library that plugs into Contentstack DataSync to download assets from Contentstack and store them in Amazon S3 (publish/unpublish/delete flows). | +| **Out of scope (if any):** | Not a standalone HTTP server or full DataSync stack—use with [DataSync Manager](https://github.com/contentstack/datasync-manager), webhook listener, and a content store. No separate CLI beyond `example/`. | + +## Tech stack (at a glance) + +| Area | Details | +| --- | --- | +| Language | TypeScript (see `tsconfig.json`; `engines.node` >= 22) | +| Build | `npm run build-ts` — `tsc` outputs to `dist/`, declarations to `typings/` | +| Tests | Jest + ts-jest; tests under `test/**/*.ts` (`jest.config.js`) | +| Lint / coverage | TSLint (`tslint.json`, `npm run tslint`); Jest `--coverage` → `coverage/` (JSON + HTML) | +| Other | AWS SDK v2 (`aws-sdk`), `debug`, `lodash`; optional Husky pre-commit runs Talisman + Snyk (see `skills/dev-workflow/SKILL.md`) | + +## Commands (quick reference) + +| Command type | Command | +| --- | --- | +| Build | `npm run build-ts` | +| Test | `npm test` | +| Lint | `npm run tslint` | + +CI / security: PR workflows under [`.github/workflows/`](.github/workflows/) — e.g. [SCA scan](.github/workflows/sca-scan.yml), [CodeQL](.github/workflows/codeql-analysis.yml), [policy scan](.github/workflows/policy-scan.yml), [Jira issues](.github/workflows/issues-jira.yml). + +## Where the documentation lives: skills + +| Skill | Path | What it covers | +| --- | --- | --- | +| Dev workflow | [`skills/dev-workflow/SKILL.md`](skills/dev-workflow/SKILL.md) | Branches, build/test/lint, Husky/Talisman/Snyk, CI pointers | +| Asset store API & DataSync | [`skills/datasync-asset-store-s3/SKILL.md`](skills/datasync-asset-store-s3/SKILL.md) | Public entry points, `S3` class, config, integration with DataSync Manager | +| TypeScript conventions | [`skills/typescript-style/SKILL.md`](skills/typescript-style/SKILL.md) | Layout, `tsconfig`, patterns matching this repo | +| Testing | [`skills/testing/SKILL.md`](skills/testing/SKILL.md) | Jest layout, mocks, coverage, credentials policy | +| Code review | [`skills/code-review/SKILL.md`](skills/code-review/SKILL.md) | PR checklist for this package | +| Framework & platform | [`skills/framework/SKILL.md`](skills/framework/SKILL.md) | AWS S3, `aws-sdk` v2, env/config boundaries | + +An index with “when to use” hints is in [`skills/README.md`](skills/README.md). + +## 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/package-lock.json b/package-lock.json index 971a9f5..3887408 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +1,23 @@ { "name": "contentstack-asset-store-aws-s3", - "version": "0.0.4", + "version": "0.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "contentstack-asset-store-aws-s3", - "version": "0.0.4", + "version": "0.0.5", "license": "MIT", "dependencies": { "aws-sdk": "^2.1693.0", "debug": "^4.4.3", - "lodash": "^4.17.23" + "lodash": "4.18.1" }, "devDependencies": { "@types/aws-sdk": "^2.7.0", "@types/debug": "0.0.31", "@types/jest": "^23.3.11", - "@types/lodash": "4.14.119", + "@types/lodash": "4.17.24", "@types/nock": "^9.3.0", "@types/node": "10.12.12", "@types/request": "^2.48.1", @@ -211,23 +211,23 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, "license": "MIT", "dependencies": { @@ -1056,9 +1056,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.14.119", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.119.tgz", - "integrity": "sha512-Z3TNyBL8Vd/M9D9Ms2S3LmFq2sSMzahodD6rCS9V2N44HUMINb75jNkSuwAx7eo2ufqTdfOdtGQpNbieUjPQmw==", + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", "dev": true, "license": "MIT" }, @@ -1549,9 +1549,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.7", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.7.tgz", - "integrity": "sha512-1ghYO3HnxGec0TCGBXiDLVns4eCSx4zJpxnHrlqFQajmhfKMQBzUGDdkMK7fUW7PTHTeLf+j87aTuKuuwWzMGw==", + "version": "2.10.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.13.tgz", + "integrity": "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1572,9 +1572,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -1596,9 +1596,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "dev": true, "funding": [ { @@ -1616,11 +1616,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -1748,9 +1748,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001778", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001778.tgz", - "integrity": "sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==", + "version": "1.0.30001784", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001784.tgz", + "integrity": "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==", "dev": true, "funding": [ { @@ -2188,9 +2188,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.313", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz", - "integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==", + "version": "1.5.331", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.331.tgz", + "integrity": "sha512-IbxXrsTlD3hRodkLnbxAPP4OuJYdWCeM3IOdT+CpcMoIwIoDfCmRpEtSPfwBXxVkg9xmBeY7Lz2Eo2TDn/HC3Q==", "dev": true, "license": "ISC" }, @@ -2683,9 +2683,9 @@ "license": "MIT" }, "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3963,9 +3963,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.memoize": { @@ -4237,9 +4237,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "version": "2.0.37", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", + "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", "dev": true, "license": "MIT" }, @@ -7050,9 +7050,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -7828,19 +7828,19 @@ } }, "node_modules/ts-jest": { - "version": "29.4.6", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", - "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", + "version": "29.4.9", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", + "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", "dev": true, "license": "MIT", "dependencies": { "bs-logger": "^0.2.6", "fast-json-stable-stringify": "^2.1.0", - "handlebars": "^4.7.8", + "handlebars": "^4.7.9", "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.3", + "semver": "^7.7.4", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -7857,7 +7857,7 @@ "babel-jest": "^29.0.0 || ^30.0.0", "jest": "^29.0.0 || ^30.0.0", "jest-util": "^29.0.0 || ^30.0.0", - "typescript": ">=4.3 <6" + "typescript": ">=4.3 <7" }, "peerDependenciesMeta": { "@babel/core": { diff --git a/package.json b/package.json index c9d7d51..4598497 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,19 @@ { "name": "contentstack-asset-store-aws-s3", "author": "Contentstack Ecosystem", - "version": "0.0.4", + "version": "0.0.5", "description": "Store asset files downloaded from Contentstack", "main": "dist", "dependencies": { "aws-sdk": "^2.1693.0", "debug": "^4.4.3", - "lodash": "^4.17.23" + "lodash": "4.18.1" }, "devDependencies": { "@types/aws-sdk": "^2.7.0", "@types/debug": "0.0.31", "@types/jest": "^23.3.11", - "@types/lodash": "4.14.119", + "@types/lodash": "4.17.24", "@types/nock": "^9.3.0", "@types/node": "10.12.12", "@types/request": "^2.48.1", diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 0000000..b784ad6 --- /dev/null +++ b/skills/README.md @@ -0,0 +1,16 @@ +# Skills – Contentstack DataSync Asset Store (AWS S3) + +Source of truth for detailed guidance. Read [`AGENTS.md`](../AGENTS.md) first, then open the skill that matches your task. + +## When to use which skill + +| Skill folder | Use when | +| --- | --- | +| `dev-workflow` | Setting up the repo, running build/test/lint, Husky hooks, or understanding CI workflows | +| `datasync-asset-store-s3` | Changing or using the public API, S3 asset flows, or DataSync Manager integration | +| `typescript-style` | Editing TypeScript source, matching compiler and project layout conventions | +| `testing` | Adding or changing Jest tests, coverage, or test doubles | +| `code-review` | Preparing or reviewing a PR for this repository | +| `framework` | AWS S3 / `aws-sdk` usage, streaming uploads, or deployment-related assumptions | + +Each folder contains `SKILL.md` with YAML frontmatter (`name`, `description`). diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md new file mode 100644 index 0000000..63c7677 --- /dev/null +++ b/skills/code-review/SKILL.md @@ -0,0 +1,33 @@ +--- +name: code-review +description: PR expectations and review checklist for the DataSync AWS S3 asset store TypeScript package. +--- + +# Code review – Contentstack DataSync Asset Store (AWS S3) + +## When to use + +- You are opening or reviewing a pull request that touches this repository +- You need a quick quality bar aligned with a small npm library and DataSync consumers + +## Instructions + +### Before approving + +- **Build**: `npm run build-ts` succeeds; `dist/` / `typings/` changes are intentional if committed +- **Tests**: `npm test` passes; new behavior has tests or a clear reason if not testable +- **Lint**: `npm run tslint` passes for touched files +- **API contract**: changes to `start`, `setConfig`, or `S3` public methods are backward compatible or version/docs updated +- **Security**: no secrets in code; Talisman/Snyk expectations respected for teams using Husky hooks +- **Docs**: user-visible config or behavior changes reflected in root `README.md` when appropriate + +### Severity (optional) + +- **Blocker**: broken build, failing tests, secret leak, or breaking change without semver/docs +- **Major**: missing tests for non-trivial logic, unclear error handling for S3/network failures +- **Minor**: naming, comment updates, small refactors for readability + +## References + +- [`../datasync-asset-store-s3/SKILL.md`](../datasync-asset-store-s3/SKILL.md) — API surface +- [`../testing/SKILL.md`](../testing/SKILL.md) — test expectations diff --git a/skills/datasync-asset-store-s3/SKILL.md b/skills/datasync-asset-store-s3/SKILL.md new file mode 100644 index 0000000..a221abc --- /dev/null +++ b/skills/datasync-asset-store-s3/SKILL.md @@ -0,0 +1,45 @@ +--- +name: datasync-asset-store-s3 +description: Public API, S3 asset store class, configuration, and DataSync Manager boundaries for the AWS S3 asset store package. +--- + +# Asset store API & DataSync – Contentstack DataSync Asset Store (AWS S3) + +## When to use + +- You are changing how assets are downloaded from Contentstack and stored in S3 +- You are documenting or wiring `syncManager.setAssetStore(...)` for DataSync +- You need the canonical config shape (`assetStore` / credentials / bucket) + +## Instructions + +### Entry module + +- **Package entry**: compiled `dist/` from [`src/index.ts`](../../src/index.ts) (`main` / `types` in `package.json`) +- **Primary exports**: `start`, `setConfig`, `getConfig`, `setLogger`, types `IConfig`, `ILogger` +- **`start(optionalConfig)`**: merges internal default config, validates `assetStore`, calls [`setup.init`](../../src/setup.ts), resolves an [`S3`](../../src/s3.ts) instance used by DataSync for publish/unpublish/delete flows + +### S3 class (`src/s3.ts`) + +- **`download(asset)`** — stream asset from Contentstack URL into S3 (published asset) +- **`unpublish(asset)`** / **`delete(assets: IAsset[])`** — remove or adjust objects per validations in [`src/util/validations.ts`](../../src/util/validations.ts) +- Uses **`request`** for HTTP download and **AWS SDK v2** S3 client passed in from setup + +### Configuration + +- Documented in the root [`README.md`](../../README.md): `pattern`, `region`, `apiVersion`, `credentials`, `bucketParams`, `uploadParams`, `CORSConfiguration`, `Policy`, etc. +- Validation errors and messages are centralized in [`src/util/messages.ts`](../../src/util/messages.ts) + +### Integration boundary + +- Intended use: `require('@contentstack/datasync-asset-store-aws-s3')` (or equivalent) with [DataSync Manager](https://github.com/contentstack/datasync-manager); do not assume this repo runs the webhook listener or content store + +### Versioning + +- Follow semver for npm releases; breaking changes to `start`’s resolved object or config contract need a major bump and README/changelog updates + +## References + +- [`../typescript-style/SKILL.md`](../typescript-style/SKILL.md) — TypeScript layout +- [`../framework/SKILL.md`](../framework/SKILL.md) — AWS SDK and S3 specifics +- [`README.md`](../../README.md) — end-user configuration tables diff --git a/skills/dev-workflow/SKILL.md b/skills/dev-workflow/SKILL.md new file mode 100644 index 0000000..9c56ecc --- /dev/null +++ b/skills/dev-workflow/SKILL.md @@ -0,0 +1,45 @@ +--- +name: dev-workflow +description: Branches, local commands, Husky pre-commit (Talisman/Snyk), and GitHub Actions for this DataSync AWS S3 asset store repo. +--- + +# Development workflow – Contentstack DataSync Asset Store (AWS S3) + +## When to use + +- You are cloning the repo, installing dependencies, or running build/test/lint locally +- You need to know what runs on commit or in CI +- You are aligning branch/PR practice with the rest of Contentstack DataSync modules + +## Instructions + +### Prerequisites + +- **Node.js** >= 22 (`package.json` `engines`) +- **npm** for install and scripts +- For **commits** (if Husky hook is active): [Talisman](https://thoughtworks.github.io/talisman/) and [Snyk CLI](https://snyk.io/) installed locally, or set `SKIP_HOOK=1` only when policy allows (see `.husky/pre-commit`) + +### Common commands + +- Install: `npm install` +- Clean + compile: `npm run build-ts` (outputs `dist/`, declarations in `typings/`) +- Watch compile: `npm run watch-ts` +- Tests with coverage: `npm test` +- Lint (TSLint): `npm run tslint` +- Husky setup (maintainers): `npm run pre-commit` (installs Husky and prepares hook) + +### CI / automation + +- Pull requests trigger workflows in `.github/workflows/`, including SCA (Snyk), CodeQL, and policy scans—see filenames for scope +- No dedicated “unit test only” workflow in-repo; rely on `npm test` locally before push + +### Branches and PRs + +- Use feature branches; target the repo’s default branch per team process (not hard-coded here) +- Keep changes scoped; this package is consumed by DataSync Manager—avoid breaking the exported `start` / asset store contract without coordination + +## References + +- [`../datasync-asset-store-s3/SKILL.md`](../datasync-asset-store-s3/SKILL.md) — public API and integration +- [`../testing/SKILL.md`](../testing/SKILL.md) — Jest and coverage +- [DataSync Manager](https://github.com/contentstack/datasync-manager) — consumer integration diff --git a/skills/framework/SKILL.md b/skills/framework/SKILL.md new file mode 100644 index 0000000..12ae6bc --- /dev/null +++ b/skills/framework/SKILL.md @@ -0,0 +1,37 @@ +--- +name: framework +description: AWS SDK v2, S3 usage, streaming uploads, and runtime assumptions for the DataSync asset store. +--- + +# Framework & platform – Contentstack DataSync Asset Store (AWS S3) + +## When to use + +- You are changing S3 calls, regions, bucket policies, or upload streams +- You are upgrading or pinning `aws-sdk` (v2) +- You need to understand HTTP download (`request`) vs AWS client responsibilities + +## Instructions + +### AWS SDK + +- Library uses **`aws-sdk`** v2 (not AWS SDK for JavaScript v3 modular clients) +- S3 client is constructed in [`src/setup.ts`](../../src/setup.ts) and injected into [`S3`](../../src/s3.ts) + +### Streaming and HTTP + +- Asset bytes are pulled via **`request`** and piped into S3 upload streams—be mindful of backpressure, errors on `response`, and connection close handling (see `download` in `s3.ts`) +- Changing HTTP client would be a cross-cutting decision (tests, typings, error semantics) + +### Configuration + +- Region, API version, bucket ACL, CORS, and credentials map to AWS S3 expectations documented in the main README—keep behavior aligned with [AWS S3 documentation](https://docs.aws.amazon.com/s3/) + +### Node.js + +- Target runtime is **Node >= 22** per `engines`; avoid APIs that require newer Node unless `engines` and docs are updated together + +## References + +- [`../datasync-asset-store-s3/SKILL.md`](../datasync-asset-store-s3/SKILL.md) — config and public API +- [AWS SDK for JavaScript v2 — S3](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html) diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md new file mode 100644 index 0000000..5767a37 --- /dev/null +++ b/skills/testing/SKILL.md @@ -0,0 +1,44 @@ +--- +name: testing +description: Jest + ts-jest setup, test file locations, coverage, and safe handling of AWS or Contentstack credentials in tests. +--- + +# Testing – Contentstack DataSync Asset Store (AWS S3) + +## When to use + +- You are adding or fixing tests under `test/` +- You need coverage settings or to mock HTTP/S3 +- You are deciding whether to commit secrets or real endpoints in tests + +## Instructions + +### Runner and config + +- **Command**: `npm test` — runs Jest with `--coverage --verbose` per `package.json` +- **Config**: [`jest.config.js`](../../jest.config.js) — `ts-jest`, Node environment, `testMatch` includes `test/**/*.ts` +- **Ignored paths**: e.g. `test/assets/*`, `test/config.ts` in `testPathIgnorePatterns` — respect these when adding files + +### Layout + +- Tests colocated under [`test/`](../../test/) (e.g. `download.ts`, `delete.ts`, `unpublish.ts`, `config.ts`, `validations.ts`) +- Use existing helpers in [`test/util.ts`](../../test/util.ts) where applicable + +### Mocking + +- **HTTP**: project uses **nock** in devDependencies — prefer nock over live URLs for download/stream tests +- **AWS**: mock S3 client behavior rather than requiring real buckets unless you have an isolated integration environment + +### Credentials policy + +- **Never** commit AWS keys, Contentstack tokens, or real stack URLs in tests or fixtures +- Use env vars or local-only config files that are gitignored for true integration runs + +### Coverage + +- Reports: `coverage/` (JSON + HTML per Jest config); ensure new code paths are covered when fixing bugs or adding behavior + +## References + +- [`../dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) — `npm test` in local workflow +- [`../framework/SKILL.md`](../framework/SKILL.md) — AWS S3 behavior under test diff --git a/skills/typescript-style/SKILL.md b/skills/typescript-style/SKILL.md new file mode 100644 index 0000000..3c7914c --- /dev/null +++ b/skills/typescript-style/SKILL.md @@ -0,0 +1,35 @@ +--- +name: typescript-style +description: TypeScript compiler settings, source layout, and conventions for src/ and typings/ in this repo. +--- + +# TypeScript – Contentstack DataSync Asset Store (AWS S3) + +## When to use + +- You are adding or editing `.ts` files under `src/` +- You need to match strictness (`noUnusedLocals`, `noImplicitReturns`, etc.) or output layout + +## Instructions + +### Layout + +- **Source**: `src/**/*.ts` — compiled to `dist/` with **declaration** output to `typings/` (`tsconfig.json`) +- **Generated**: do not hand-edit `dist/` or committed typings if your workflow regenerates them; prefer `npm run build-ts` after changes +- **Tests**: live under `test/`, not under `src/` (see [`../testing/SKILL.md`](../testing/SKILL.md)) + +### Compiler + +- **Module**: CommonJS; **target**: ES6; **strict** patterns via `alwaysStrict`, unused checks, `noFallthroughCasesInSwitch` +- **Interop**: `esModuleInterop` enabled for default imports (e.g. `debug`, `request`) +- **Libs**: `es2015` — avoid newer runtime APIs without polyfills or target updates + +### Style + +- TSLint is the configured linter (`tslint.json`); run `npm run tslint` before merge +- Prefer existing patterns: class `S3` with public methods, small `util/` helpers, `debug` namespaces per file + +## References + +- [`../datasync-asset-store-s3/SKILL.md`](../datasync-asset-store-s3/SKILL.md) — exported API surface +- [`../dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) — build commands