Development
This section provides information for developers who want to contribute to the Substack API client library.
Development Setup
Prerequisites
- Node.js 14 or higher
- npm or yarn package manager
- Git
Getting Started
-
Clone the repository:
bash git clone https://github.com/jakub-k-slys/substack-api.git cd substack-api -
Install dependencies:
bash npm install -
Build the project:
bash npm run build
Project Structure
substack-api/
├── src/
│ ├── client.ts # Main Substack class implementation
│ ├── tests/ # Unit tests
│ ├── types.ts # TypeScript type definitions
│ └── index.ts # Public API exports
├── tests/
│ └── unit/ # Unit tests
├── docs/
│ └── source/ # Documentation source files
├── dist/ # Compiled JavaScript files
├── .env.example # Environment variables template
├── jest.config.js # Jest configuration for unit tests
├── package.json # Project configuration
├── tsconfig.json # TypeScript configuration
└── README.md # Project overview
Development Workflow
Building
To build the project:
npm run build
This will: 1. Clean the dist directory 2. Compile TypeScript files 3. Generate type definitions
Testing
Run the test suite:
npm test # Run unit tests
Run tests in watch mode during development:
npm run test:watch # Unit tests
The project uses Jest for testing:
- Unit tests (
tests/unit/): Test individual functions and node logic using mocked Substack client methods
The unit tests use direct mocking of the substack-api module to test node logic without any HTTP dependencies, providing fast and reliable testing.
For detailed testing information, see TESTING.md.
Code Style
The project follows TypeScript best practices:
- Use explicit types where beneficial
- Document public APIs with JSDoc comments
- Follow consistent naming conventions
- Write unit tests for new functionality
Documentation
Documentation is written in Markdown and built using Sphinx with MyST parser:
-
Install documentation dependencies:
bash pip install sphinx sphinx-rtd-theme myst-parser -
Build the documentation:
bash cd docs make html
The built documentation will be available in docs/build/html.
Contributing
Contribution Process
- Fork the repository
- Create a feature branch
- Make your changes
- Write or update tests
- Update documentation
- Submit a pull request
Pull Request Guidelines
- Keep changes focused and atomic
- Follow existing code style
- Include tests for new functionality
- Update documentation as needed
- Describe your changes in the PR description
Running Checks
Before submitting a PR, ensure:
-
All tests pass:
bash npm test -
TypeScript compiles without errors:
bash npm run build -
Documentation builds successfully:
bash cd docs make html
Release Process
- Update version in package.json
- Update CHANGELOG.md
-
Build the project:
bash npm run build -
Run tests:
bash npm test -
Commit changes:
bash git add . git commit -m "Release v1.x.x" git tag v1.x.x git push origin main --tags -
Publish to npm:
bash npm publish
Development Tips
TypeScript Configuration
The project uses a strict TypeScript configuration. Key settings in tsconfig.json:
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"declaration": true
}
}
Testing Tips
- Use Jest's mock capabilities for testing API calls
- Test error conditions and edge cases
- Use TypeScript in test files for better type checking
Example test structure:
import { Substack, SubstackError } from './client';
describe('Substack', () => {
let client: Substack;
beforeEach(() => {
client = new Substack();
});
it('should handle successful requests', async () => {
// Test implementation
});
it('should handle errors', async () => {
// Test implementation
});
});
Debugging
For debugging during development:
- Use the
debugnpm package for logging -
Add source maps in tsconfig.json:
json { "compilerOptions": { "sourceMap": true } } -
Use the VS Code debugger with the following launch configuration: ```json { "type": "node", "request": "launch", "name": "Debug Tests", "program": "${workspaceFolder}/node_modules/.bin/jest", "args": ["--runInBand"], "console": "integratedTerminal", "internalConsoleOptions": "neverOpen" }