Dart/Flutter SDK for the Astrology API v3. No code generation (no freezed/json_serializable) — uses plain Dart classes with manual toJson().
dart pub get# Install dependencies
dart pub get
# Analyze code
dart analyze
# Run tests
dart test
# Run tests with coverage
dart test --coverage=coverage
# Check publish readiness (dry run)
dart pub publish --dry-runPublishing to pub.dev is automated via GitHub Actions (.github/workflows/publish.yml). It triggers when a git tag matching v*.*.* is pushed. The tag version must exactly match pubspec.yaml — CI enforces this and fails the pipeline if they differ.
Steps to release:
# 1. Update version in pubspec.yaml
# e.g., change: version: 1.0.0
# to: version: 1.1.0
# 2. Update CHANGELOG.md
# - Move all items from [Unreleased] into a new versioned section:
# ## [1.1.0] - 2026-03-01
# - Add the new version comparison link at the bottom:
# [1.1.0]: https://github.com/astro-api/astroapi-flutter/compare/v1.0.0...v1.1.0
# - Update the [Unreleased] link to compare from the new tag:
# [Unreleased]: https://github.com/astro-api/astroapi-flutter/compare/v1.1.0...HEAD
# 3. Commit both files
git add pubspec.yaml CHANGELOG.md
git commit -m "chore: release v1.1.0"
# 4. Create an annotated git tag — must be "v" + exact pubspec version
git tag v1.1.0
# 5. Push the commit and the tag (tag push triggers publish.yml)
git push origin main
git push origin v1.1.0The CI pipeline then:
- Validates tag version == pubspec.yaml version
- Runs
dart analyze+dart formatcheck - Runs
dart test - Publishes via
dart pub publish --forceto pub.dev
Semantic versioning rules (follow semver.org):
PATCH(1.0.x) — bug fixes, no API changesMINOR(1.x.0) — new features, backwards-compatibleMAJOR(x.0.0) — breaking API changes
lib/
astroapi.dart # Barrel export (public API)
src/
client/astrology_client.dart # Main AstrologyClient class
config/astrology_client_config.dart # Config, RetryConfig, RequestOptions
http/
http_helper.dart # Abstract HttpHelper interface
dio_http_client.dart # Dio-based implementation with retry
errors/astrology_exception.dart # AstrologyException
categories/ # 16 category clients
base_category_client.dart # Base class all clients extend
models/
requests/ # Request types (toJson())
requests.dart # Omnibus file, ~1750 lines, all request classes
birth_data.dart, subject.dart # Core shared request models
chart_options.dart, data_options.dart, standard_options.dart
report_options.dart, date_time_location.dart, fixed_stars_config.dart
responses/
responses.dart # All response types (fromJson() + GenericResponse typedefs)
enums/ # Language, HouseSystem, ZodiacType, Tradition,
# PerspectiveType, DetailLevel
lib/astroapi.dart is the barrel export. Everything a user (or AI) needs is re-exported from here: the main client, config, errors, HttpHelper, all 16 category clients, all 6 enums, all request and response models.
Creates a single DioHttpClient from the config and passes it to all 16 category clients. Exposes them as named getters:
| Getter | Client class | Description |
|---|---|---|
.data |
DataClient |
Planetary positions, aspects, house cusps, lunar metrics |
.charts |
ChartsClient |
Natal, synastry, composite, transit, solar/lunar return charts |
.analysis |
AnalysisClient |
Natal, synastry, composite, compatibility, progression reports |
.horoscope |
HoroscopeClient |
Personal and sun-sign horoscopes (daily/weekly/monthly/yearly) |
.glossary |
GlossaryClient |
Zodiac signs, planets, aspects, house systems, cities lookup |
.astrocartography |
AstrocartographyClient |
Location analysis, power zones, relocation charts |
.chinese |
ChineseClient |
Ba Zi, zodiac, solar terms, element balance |
.eclipses |
EclipsesClient |
Upcoming eclipses, natal checks, interpretations |
.lunar |
LunarClient |
Moon phases, lunar mansions, void-of-course periods |
.numerology |
NumerologyClient |
Core numbers, comprehensive analysis, compatibility |
.tarot |
TarotClient |
Card draws, spreads, birth cards, daily cards |
.traditional |
TraditionalClient |
Dignities, receptions, almutens, lots, profections, firdaria |
.fixedStars |
FixedStarsClient |
Fixed star positions, conjunctions, presets |
.svg |
SvgClient |
SVG chart images — returns String, not JSON |
.enhanced |
EnhancedClient |
Enhanced personal and global analysis |
.insights |
InsightsClient |
Has 5 sub-clients (see below) |
InsightsClient exposes: .relationship, .pet, .wellness, .financial, .business
AstrologyClientConfig:apiKey(required),baseUrl,timeout(ms, default 10000),debug(bool),logger(function),retry(RetryConfig)- Env var fallbacks:
ASTROLOGY_API_KEY,ASTROLOGY_API_BASE_URL
- Env var fallbacks:
RetryConfig:attempts,delayMs,retryStatusCodes(default:[408, 425, 429, 500, 502, 503, 504])RequestOptions: per-requestheaders,queryParams,timeoutoverride, DioCancelToken
HttpHelper(abstract interface):get,post,put,delete— the only dependency injected into category clients; mock this in testsDioHttpClient(concrete Dio implementation):- Injects
Authorization: Bearer <apiKey>via Dio interceptor - Auto-unwraps
dataorresultenvelope keys from API responses - Implements retry logic based on
RetryConfig
- Injects
- All extend
BaseCategoryClient(holds theHttpHelperreference) - Each exposes typed
asyncmethods returning response model instances SvgClientis the exception: returns rawString(SVG markup), not a model
Plain Dart classes with toJson() — no code generation. The main file requests.dart is an omnibus (~1750 lines) with all request classes. Shared building blocks live in separate files (BirthData, Subject, ChartOptions, etc.) and are exported from the barrel.
Two strategies:
- Fully typed (commonly-accessed fields):
PlanetaryPositionsResponse,AspectsResponse,HouseCuspsResponse,ChartData— have realfromJson()factories GenericResponse(variable/complex schemas): wrapsMap<String, dynamic>; dozens oftypedefaliases provide semantic names (e.g.,typedef HoroscopeResponse = GenericResponse). This is intentional — not a TODO.
AstrologyException fields: statusCode, code, message. Factory fromDioError() normalises Dio errors into AstrologyException.
Uses mocktail to mock HttpHelper:
class MockHttpHelper extends Mock implements HttpHelper {}
final client = DataClient(MockHttpHelper());Test layout:
test/helpers/test_helpers.dart—MockHttpHelper, shared test data factoriestest/unit/client_test.dart—AstrologyClientconstruction and sub-client wiringtest/unit/errors/astrology_exception_test.dart— exception parsingtest/unit/categories/— one test file per category client (16 files)
import 'package:astroapi/astroapi.dart';
final client = AstrologyClient(
AstrologyClientConfig(
apiKey: 'your-api-key',
timeout: 15000,
retry: RetryConfig(attempts: 3, delayMs: 500),
),
);
// Get planetary positions
final positions = await client.data.getPositions(
PlanetaryPositionsRequest(
subject: Subject(
birthData: BirthData(
year: 1990, month: 5, day: 11,
hour: 14, minute: 30,
city: 'London', countryCode: 'GB',
),
),
),
);
print(positions.positions[0].sign);
// Get natal chart
final chart = await client.charts.getNatalChart(
NatalChartRequest(subject: subject),
);
// Insights sub-clients
final compat = await client.insights.relationship.getCompatibility(
CompatibilityRequest(subjects: [subject1, subject2]),
);
// SVG chart (returns String)
final svg = await client.svg.getNatalChartSvg(
NatalChartSvgRequest(subject: subject),
);- No code generation: Plain Dart classes instead of freezed/json_serializable for simplicity and faster compilation
- GenericResponse: Complex API responses use
GenericResponse(wrapsMap<String, dynamic>) — intentional, not a gap to fill - HttpHelper abstraction: The
HttpHelperinterface enables easy mocking in tests withmocktail - Retry logic: Built into
DioHttpClient, configurable viaRetryConfig - SVG responses:
SvgClientreturnsStringdirectly instead of JSON - InsightsClient: Has 5 sub-clients (relationship, pet, wellness, financial, business)
Add a new category client:
- Create
lib/src/categories/<name>_client.dart, extendBaseCategoryClient - Add a getter to
AstrologyClientinlib/src/client/astrology_client.dart - Export from
lib/astroapi.dart
Add a new request model:
- Add the class with
toJson()tolib/src/models/requests/requests.dart(or its own file) - Export from
lib/astroapi.dart
Add a new response model:
- Add
fromJson()factory tolib/src/models/responses/responses.dart - Export from
lib/astroapi.dart
Add a new enum:
- Create
lib/src/models/enums/<name>.dart - Export from
lib/astroapi.dart