Skip to content

Latest commit

 

History

History
248 lines (173 loc) · 9.54 KB

File metadata and controls

248 lines (173 loc) · 9.54 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

# 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 clean

Node >=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).


Architecture Overview

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.

Monorepo Structure

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/*)

Package Catalog

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

Package-Level CLAUDE.md Files

Some packages have their own CLAUDE.md with deeper architectural guidance:


Key Patterns

Per-Package File Structure

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

Entity Pattern (data-access)

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.

Field Mapping Convention

Models use camelCase, the database uses snake_case. Mapping is automatic via postgrest.utils.js. Override with postgrestField: 'custom_name' on individual attributes.

TypeScript Declarations

Packages provide .d.ts files for public APIs — no TypeScript source code. Type declarations live alongside the source files they describe.

API Client Pattern

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);
}

Testing

Framework: Mocha + Chai + chai-as-promised + sinon + sinon-chai Coverage: c8 (per-package .nycrc.json) HTTP mocking: nock Reporters: mocha-multi-reporters (spec + xunit)

Running Tests

# 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

Test Conventions

  • Tests live in test/ (or test/unit/) and mirror the src/ directory structure
  • Use describe/it blocks with expect assertions
  • sinon stubs for external dependencies; nock for HTTP mocking
  • Each test file uses a sandbox: const sandbox = sinon.createSandbox() with afterEach(() => sandbox.restore())
  • Coverage thresholds are enforced per package

Integration Tests (data-access)

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-access

Working with the Monorepo

Inter-Package Dependencies

Some 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.

Running Commands for a Single Package

Use the -w (workspace) flag:

npm test -w packages/spacecat-shared-<name>
npm run lint -w packages/spacecat-shared-<name>

Adding a New Package

  1. Copy packages/spacecat-shared-example/ as a starting template
  2. Rename the directory to spacecat-shared-<name>
  3. Update package.json: name (@adobe/spacecat-shared-<name>), description, dependencies
  4. Update .releaserc.cjs (inherits from root)
  5. Implement source in src/, tests in test/
  6. Ensure 100% coverage with .nycrc.json thresholds
  7. The root workspaces: ["./packages/*"] auto-discovers it

Adding a New Entity (data-access)

  1. Create 4 files in src/models/<entity>/: schema.js, model.js, collection.js, index.js
  2. Register the entity in src/models/index.js
  3. The corresponding DB migration must be created in mysticat-data-service
  4. Add unit tests in test/unit/models/<entity>/

Adding a New Import Type (data-access)

  1. Update three locations in src/models/site/config.js: IMPORT_TYPES, IMPORT_TYPE_SCHEMAS, DEFAULT_IMPORT_CONFIGS
  2. 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.


Commits and Releases

  • Conventional commits are required — use npm run commit (commitizen) or write them manually
  • Pre-commit hook (husky + lint-staged) runs ESLint on staged .js files
  • semantic-release with semantic-release-monorepo handles per-package versioning
  • Release happens automatically on push to main — each package is released independently based on commits touching its files
  • Branch: main is the only release branch

After Publishing

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.).


Linting

  • Config: eslint.config.js (ESLint flat config)
  • Base: @adobe/eslint-config-helix (recommended + source + test presets)
  • Parser: @babel/eslint-parser with ESM + import assertions
  • Test overrides: no-console: off, func-names: off
  • Ignored: .vscode, .idea, coverage, docs, vendor, dist, .releaserc.cjs, test/fixtures