This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Install all dependencies (root + all packages)
npm install
# Run all tests across all packages
npm test
# Run tests for a single package
npm test -w packages/spacecat-shared-utils
# Run integration tests (data-access only, requires Docker)
npm run test:it -w packages/spacecat-shared-data-access
# Lint all packages
npm run lint
# Lint a single package
npm run lint -w packages/spacecat-shared-utils
# Generate API docs
npm run docs
# Dry-run semantic release (on non-main branches)
npm run semantic-release-dry
# Clean node_modules and lock file
npm run cleanNode >=22 <25 is required (see .nvmrc for exact version). The project is pure ESM ("type": "module").
Coverage enforcement: 100% lines/statements, 97% branches per package (see each package's .nycrc.json).
This is the foundation library layer for all SpaceCat Node.js services. It's an npm workspaces monorepo (no lerna/nx) containing 22 packages that provide data access, API clients, utilities, and auth used by spacecat-api-service, spacecat-audit-worker, spacecat-import-worker, and other platform services.
spacecat-shared/
├── packages/ # 22 npm workspace packages
│ ├── spacecat-shared-data-access/ # Core data layer (PostgREST + Aurora PostgreSQL)
│ ├── spacecat-shared-http-utils/ # HTTP response helpers + auth middleware
│ ├── spacecat-shared-utils/ # General utilities (validation, S3, SQS, helpers)
│ ├── spacecat-shared-rum-api-client/ # RUM Bundler API client
│ ├── spacecat-shared-vault-secrets/ # HashiCorp Vault secrets (replaces helix-shared-secrets)
│ ├── spacecat-shared-*-client/ # 13+ API clients (ahrefs, google, slack, etc.)
│ ├── spacecat-shared-html-analyzer/ # HTML analysis utilities
│ └── spacecat-shared-example/ # Example/template package
├── docs/ # Generated API docs
├── eslint.config.js # Root ESLint flat config
├── .releaserc.cjs # Root semantic-release config
└── package.json # Monorepo root (private, workspaces: ./packages/*)
| Category | Packages | Purpose |
|---|---|---|
| Data layer | data-access |
Entity models/collections backed by PostgreSQL via PostgREST |
| HTTP/Auth | http-utils |
HTTP response helpers, auth handlers (ScopedApiKey, LegacyApiKey, IMS) |
| Utilities | utils |
Validation, S3/SQS helpers, schemas, date functions |
| Secrets | vault-secrets |
HashiCorp Vault integration (AppRole auth, KV secrets) |
| HTML | html-analyzer |
HTML analysis and extraction |
| API clients | ahrefs-client, athena-client, brand-client, cloud-manager-client, content-client, drs-client, google-client, gpt-client, ims-client, launchdarkly-client, rum-api-client, scrape-client, slack-client, splunk-client, tier-client, tokowaka-client |
External service integrations |
| Example | example |
Template for creating new packages |
Some packages have their own CLAUDE.md with deeper architectural guidance:
packages/spacecat-shared-data-access/CLAUDE.md— Entity pattern, SchemaBuilder DSL, PostgREST queries, integration testspackages/spacecat-shared-vault-secrets/CLAUDE.md— Vault pipeline, AppRole auth, E2E validationpackages/spacecat-shared-google-client/docs/CLAUDE.md— GSC client, OAuth, environment variables
Each package follows this layout:
packages/spacecat-shared-<name>/
├── src/ # Source code
│ └── index.js # Package entry point (barrel exports)
├── test/ # Tests (mirrors src/ structure)
├── package.json # Package metadata, dependencies, scripts
├── .releaserc.cjs # semantic-release config (extends monorepo)
├── .nycrc.json # c8 coverage config
├── README.md
└── CHANGELOG.md # Auto-generated by semantic-release
The data-access package defines entities with 4 files per entity:
src/models/<entity>/
<entity>.schema.js # SchemaBuilder definition (attributes, references, indexes)
<entity>.model.js # Extends BaseModel (business logic, constants)
<entity>.collection.js # Extends BaseCollection (custom queries)
index.js # Re-exports model, collection, schema
See packages/spacecat-shared-data-access/CLAUDE.md for the SchemaBuilder DSL, attribute options, and field mapping details.
Models use camelCase, the database uses snake_case. Mapping is automatic via postgrest.utils.js. Override with postgrestField: 'custom_name' on individual attributes.
Packages provide .d.ts files for public APIs — no TypeScript source code. Type declarations live alongside the source files they describe.
API clients typically follow this structure:
export default class FooClient {
constructor(config, log) { /* ... */ }
async someOperation(params) { /* ... */ }
}
// Factory function exported from index.js
export function createFooClient(config, log) {
return new FooClient(config, log);
}Framework: Mocha + Chai + chai-as-promised + sinon + sinon-chai
Coverage: c8 (per-package .nycrc.json)
HTTP mocking: nock
Reporters: mocha-multi-reporters (spec + xunit)
# All packages
npm test
# Single package
npm test -w packages/spacecat-shared-utils
# Integration tests (data-access only — requires Docker + ECR access)
npm run test:it -w packages/spacecat-shared-data-access- Tests live in
test/(ortest/unit/) and mirror thesrc/directory structure - Use
describe/itblocks withexpectassertions - sinon stubs for external dependencies; nock for HTTP mocking
- Each test file uses a sandbox:
const sandbox = sinon.createSandbox()withafterEach(() => sandbox.restore()) - Coverage thresholds are enforced per package
Integration tests require the mysticat-data-service Docker image from ECR:
# ECR login (one-time)
aws ecr get-login-password --profile spacecat-dev --region us-east-1 \
| docker login --username AWS --password-stdin 682033462621.dkr.ecr.us-east-1.amazonaws.com
npm run test:it -w packages/spacecat-shared-data-accessSome packages depend on others in the monorepo (e.g., data-access depends on utils). These are declared as regular npm dependencies with the published @adobe/spacecat-shared-* package name and version.
Use the -w (workspace) flag:
npm test -w packages/spacecat-shared-<name>
npm run lint -w packages/spacecat-shared-<name>- Copy
packages/spacecat-shared-example/as a starting template - Rename the directory to
spacecat-shared-<name> - Update
package.json: name (@adobe/spacecat-shared-<name>), description, dependencies - Update
.releaserc.cjs(inherits from root) - Implement source in
src/, tests intest/ - Ensure 100% coverage with
.nycrc.jsonthresholds - The root
workspaces: ["./packages/*"]auto-discovers it
- Create 4 files in
src/models/<entity>/:schema.js,model.js,collection.js,index.js - Register the entity in
src/models/index.js - The corresponding DB migration must be created in mysticat-data-service
- Add unit tests in
test/unit/models/<entity>/
- Update three locations in
src/models/site/config.js:IMPORT_TYPES,IMPORT_TYPE_SCHEMAS,DEFAULT_IMPORT_CONFIGS - Update three corresponding assertions in
test/unit/models/site/config.test.js
See packages/spacecat-shared-data-access/CLAUDE.md for full details including code examples.
- Conventional commits are required — use
npm run commit(commitizen) or write them manually - Pre-commit hook (husky + lint-staged) runs ESLint on staged
.jsfiles - semantic-release with
semantic-release-monorepohandles per-package versioning - Release happens automatically on push to
main— each package is released independently based on commits touching its files - Branch:
mainis the only release branch
When a new version of a spacecat-shared-* package is published, update the dependency version in all consuming repos (spacecat-api-service, spacecat-audit-worker, spacecat-import-worker, etc.).
- Config:
eslint.config.js(ESLint flat config) - Base:
@adobe/eslint-config-helix(recommended + source + test presets) - Parser:
@babel/eslint-parserwith ESM + import assertions - Test overrides:
no-console: off,func-names: off - Ignored:
.vscode,.idea,coverage,docs,vendor,dist,.releaserc.cjs,test/fixtures