@lgriffin/esi.ts 9.7.0 → 10.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +512 -0
- package/README.md +182 -236
- package/dist/EsiClient.d.mts +140 -0
- package/dist/EsiClient.d.ts +4 -0
- package/dist/EsiClient.d.ts.map +1 -1
- package/dist/EsiClientBuilder.d.mts +75 -0
- package/dist/EsiClientBuilder.d.ts.map +1 -1
- package/dist/auth/EsiTokenManager.d.mts +200 -0
- package/dist/auth/EsiTokenManager.d.ts +200 -0
- package/dist/auth/EsiTokenManager.d.ts.map +1 -0
- package/dist/auth/EveSsoClient.d.mts +88 -0
- package/dist/auth/EveSsoClient.d.ts +88 -0
- package/dist/auth/EveSsoClient.d.ts.map +1 -0
- package/dist/auth/errors.d.mts +42 -0
- package/dist/auth/errors.d.ts +42 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/index.d.mts +14 -0
- package/dist/auth/index.d.ts +14 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/jwt.d.mts +43 -0
- package/dist/auth/jwt.d.ts +43 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/pkce.d.mts +21 -0
- package/dist/auth/pkce.d.ts +21 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/storage/FileTokenStorage.d.mts +44 -0
- package/dist/auth/storage/FileTokenStorage.d.ts +44 -0
- package/dist/auth/storage/FileTokenStorage.d.ts.map +1 -0
- package/dist/auth/storage/MemoryTokenStorage.d.mts +18 -0
- package/dist/auth/storage/MemoryTokenStorage.d.ts +18 -0
- package/dist/auth/storage/MemoryTokenStorage.d.ts.map +1 -0
- package/dist/auth/types.d.mts +42 -0
- package/dist/auth/types.d.ts +42 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/chunk-3ZI5A37L.mjs +1065 -0
- package/dist/chunk-3ZI5A37L.mjs.map +1 -0
- package/dist/chunk-BBSHKVPI.js +71 -0
- package/dist/chunk-BBSHKVPI.js.map +1 -0
- package/dist/chunk-D5L5HZVF.mjs +417 -0
- package/dist/chunk-D5L5HZVF.mjs.map +1 -0
- package/dist/chunk-JIW4BXLP.mjs +17 -0
- package/dist/chunk-JIW4BXLP.mjs.map +1 -0
- package/dist/chunk-MSJHIJXA.js +1065 -0
- package/dist/chunk-MSJHIJXA.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-R7D7M2LQ.mjs +71 -0
- package/dist/chunk-R7D7M2LQ.mjs.map +1 -0
- package/dist/chunk-SAQBXXTM.js +2614 -0
- package/dist/chunk-SAQBXXTM.js.map +1 -0
- package/dist/chunk-VZS32UQ3.mjs +2614 -0
- package/dist/chunk-VZS32UQ3.mjs.map +1 -0
- package/dist/chunk-XIB2OXEZ.js +417 -0
- package/dist/chunk-XIB2OXEZ.js.map +1 -0
- package/dist/clients/AccessListsClient.d.mts +25 -0
- package/dist/clients/AllianceClient.d.mts +59 -0
- package/dist/clients/AllianceClient.d.ts.map +1 -1
- package/dist/clients/AssetsClient.d.mts +65 -0
- package/dist/clients/BaseEsiClient.d.mts +19 -0
- package/dist/clients/CalendarClient.d.mts +48 -0
- package/dist/clients/CharacterClient.d.mts +134 -0
- package/dist/clients/ClonesClient.d.mts +27 -0
- package/dist/clients/ContactsClient.d.mts +96 -0
- package/dist/clients/ContractsClient.d.mts +91 -0
- package/dist/clients/ContractsClient.d.ts +12 -9
- package/dist/clients/ContractsClient.d.ts.map +1 -1
- package/dist/clients/CorporationProjectsClient.d.mts +54 -0
- package/dist/clients/CorporationProjectsClient.d.ts +22 -12
- package/dist/clients/CorporationProjectsClient.d.ts.map +1 -1
- package/dist/clients/CorporationsClient.d.mts +219 -0
- package/dist/clients/CosmeticsClient.d.mts +11 -0
- package/dist/clients/DogmaClient.d.mts +42 -0
- package/dist/clients/FactionClient.d.mts +60 -0
- package/dist/clients/FactionClient.d.ts +4 -4
- package/dist/clients/FactionClient.d.ts.map +1 -1
- package/dist/clients/FittingsClient.d.mts +38 -0
- package/dist/clients/FleetClient.d.mts +134 -0
- package/dist/clients/FreelanceJobsClient.d.mts +61 -0
- package/dist/clients/FreelanceJobsClient.d.ts +3 -3
- package/dist/clients/FreelanceJobsClient.d.ts.map +1 -1
- package/dist/clients/IncursionsClient.d.mts +14 -0
- package/dist/clients/IndustryClient.d.mts +86 -0
- package/dist/clients/IndustryClient.d.ts +4 -4
- package/dist/clients/IndustryClient.d.ts.map +1 -1
- package/dist/clients/InsuranceClient.d.mts +14 -0
- package/dist/clients/KillmailsClient.d.mts +37 -0
- package/dist/clients/LocationClient.d.mts +32 -0
- package/dist/clients/LoyaltyClient.d.mts +28 -0
- package/dist/clients/MailClient.d.mts +104 -0
- package/dist/clients/MailClient.d.ts +4 -4
- package/dist/clients/MailClient.d.ts.map +1 -1
- package/dist/clients/MarketClient.d.mts +102 -0
- package/dist/clients/MercenaryClient.d.mts +42 -0
- package/dist/clients/MetaClient.d.mts +45 -0
- package/dist/clients/MetaClient.d.ts +3 -2
- package/dist/clients/MetaClient.d.ts.map +1 -1
- package/dist/clients/MilitaryCampaignsClient.d.mts +53 -0
- package/dist/clients/ParagonHubClient.d.mts +13 -0
- package/dist/clients/PiClient.d.mts +45 -0
- package/dist/clients/RouteClient.d.mts +25 -0
- package/dist/clients/SearchClient.d.mts +17 -0
- package/dist/clients/SkillsClient.d.mts +39 -0
- package/dist/clients/SkyhooksClient.d.mts +48 -0
- package/dist/clients/SovereigntyClient.d.mts +20 -0
- package/dist/clients/StatusClient.d.mts +14 -0
- package/dist/clients/UiClient.d.mts +44 -0
- package/dist/clients/UniverseClient.d.mts +212 -0
- package/dist/clients/WalletClient.d.mts +70 -0
- package/dist/clients/WalletClient.d.ts +4 -4
- package/dist/clients/WalletClient.d.ts.map +1 -1
- package/dist/clients/WarsClient.d.mts +33 -0
- package/dist/core/ApiClient.d.mts +73 -0
- package/dist/core/ApiClient.d.ts +4 -0
- package/dist/core/ApiClient.d.ts.map +1 -1
- package/dist/core/ApiClientBuilder.d.mts +24 -0
- package/dist/core/ApiRequestHandler.d.ts.map +1 -1
- package/dist/core/BatchRequestHandler.d.mts +12 -0
- package/dist/core/BatchRequestHandler.d.ts.map +1 -1
- package/dist/core/ClientRegistry.d.mts +45 -0
- package/dist/core/EsiDiagnostics.d.mts +35 -0
- package/dist/core/IDeduplicator.d.mts +22 -0
- package/dist/core/IDeduplicator.d.ts +16 -0
- package/dist/core/IDeduplicator.d.ts.map +1 -1
- package/dist/core/IRetryStrategy.d.mts +5 -0
- package/dist/core/RequestDeduplicator.d.mts +21 -0
- package/dist/core/RequestDeduplicator.d.ts +13 -0
- package/dist/core/RequestDeduplicator.d.ts.map +1 -1
- package/dist/core/RetryStrategy.d.mts +21 -0
- package/dist/core/RetryStrategy.d.ts +2 -0
- package/dist/core/RetryStrategy.d.ts.map +1 -1
- package/dist/core/cache/ETagCacheManager.d.mts +75 -0
- package/dist/core/cache/ETagCacheManager.d.ts +4 -0
- package/dist/core/cache/ETagCacheManager.d.ts.map +1 -1
- package/dist/core/cache/ICache.d.mts +27 -0
- package/dist/core/cache/cacheKey.d.ts +11 -0
- package/dist/core/cache/cacheKey.d.ts.map +1 -1
- package/dist/core/circuitBreaker/CircuitBreaker.d.mts +52 -0
- package/dist/core/circuitBreaker/CircuitBreaker.d.ts +3 -0
- package/dist/core/circuitBreaker/CircuitBreaker.d.ts.map +1 -1
- package/dist/core/circuitBreaker/ICircuitBreaker.d.mts +23 -0
- package/dist/core/configureApiClient.d.mts +18 -0
- package/dist/core/configureApiClient.d.ts.map +1 -1
- package/dist/core/constants.d.ts +2 -2
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/endpoints/EndpointDefinition.d.mts +63 -0
- package/dist/core/endpoints/accessListEndpoints.d.mts +34 -0
- package/dist/core/endpoints/allianceEndpoints.d.mts +43 -0
- package/dist/core/endpoints/assetEndpoints.d.mts +76 -0
- package/dist/core/endpoints/buildEndpointPath.d.mts +7 -0
- package/dist/core/endpoints/calendarEndpoints.d.mts +54 -0
- package/dist/core/endpoints/calendarEndpoints.d.ts +7 -7
- package/dist/core/endpoints/characterEndpoints.d.mts +185 -0
- package/dist/core/endpoints/characterEndpoints.d.ts +2 -2
- package/dist/core/endpoints/cloneEndpoints.d.mts +32 -0
- package/dist/core/endpoints/cloneEndpoints.d.ts +2 -2
- package/dist/core/endpoints/contactEndpoints.d.mts +106 -0
- package/dist/core/endpoints/contractEndpoints.d.mts +168 -0
- package/dist/core/endpoints/contractEndpoints.d.ts +15 -22
- package/dist/core/endpoints/contractEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/corporationEndpoints.d.mts +324 -0
- package/dist/core/endpoints/corporationEndpoints.d.ts +19 -22
- package/dist/core/endpoints/corporationEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/corporationProjectEndpoints.d.mts +102 -0
- package/dist/core/endpoints/corporationProjectEndpoints.d.ts +75 -23
- package/dist/core/endpoints/corporationProjectEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/cosmeticsEndpoints.d.mts +52 -0
- package/dist/core/endpoints/createClient.d.mts +69 -0
- package/dist/core/endpoints/createClient.d.ts.map +1 -1
- package/dist/core/endpoints/dogmaEndpoints.d.mts +89 -0
- package/dist/core/endpoints/dogmaEndpoints.d.ts +2 -2
- package/dist/core/endpoints/esi-cache-ttls.generated.d.ts.map +1 -1
- package/dist/core/endpoints/esi-rate-limit-groups.generated.d.mts +7 -0
- package/dist/core/endpoints/esi-rate-limit-groups.generated.d.ts.map +1 -1
- package/dist/core/endpoints/esi-scopes.generated.d.mts +3 -0
- package/dist/core/endpoints/esi-scopes.generated.d.ts.map +1 -1
- package/dist/core/endpoints/factionEndpoints.d.mts +194 -0
- package/dist/core/endpoints/factionEndpoints.d.ts +36 -36
- package/dist/core/endpoints/factionEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/fittingEndpoints.d.mts +34 -0
- package/dist/core/endpoints/fleetEndpoints.d.mts +137 -0
- package/dist/core/endpoints/fleetEndpoints.d.ts +1 -1
- package/dist/core/endpoints/freelanceJobsEndpoints.d.mts +181 -0
- package/dist/core/endpoints/freelanceJobsEndpoints.d.ts +131 -122
- package/dist/core/endpoints/freelanceJobsEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/incursionEndpoints.d.mts +19 -0
- package/dist/core/endpoints/industryEndpoints.d.mts +138 -0
- package/dist/core/endpoints/industryEndpoints.d.ts +6 -6
- package/dist/core/endpoints/industryEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/insuranceEndpoints.d.mts +17 -0
- package/dist/core/endpoints/killmailEndpoints.d.mts +62 -0
- package/dist/core/endpoints/locationEndpoints.d.mts +37 -0
- package/dist/core/endpoints/loyaltyEndpoints.d.mts +32 -0
- package/dist/core/endpoints/mailEndpoints.d.mts +111 -0
- package/dist/core/endpoints/mailEndpoints.d.ts +3 -5
- package/dist/core/endpoints/mailEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/marketEndpoints.d.mts +191 -0
- package/dist/core/endpoints/mercenaryEndpoints.d.mts +79 -0
- package/dist/core/endpoints/mercenaryEndpoints.d.ts +1 -1
- package/dist/core/endpoints/metaEndpoints.d.mts +50 -0
- package/dist/core/endpoints/metaEndpoints.d.ts +5 -1
- package/dist/core/endpoints/metaEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/militaryCampaignEndpoints.d.mts +87 -0
- package/dist/core/endpoints/paragonHubEndpoints.d.mts +163 -0
- package/dist/core/endpoints/piEndpoints.d.mts +101 -0
- package/dist/core/endpoints/piEndpoints.d.ts +2 -2
- package/dist/core/endpoints/routeEndpoints.d.mts +14 -0
- package/dist/core/endpoints/searchEndpoints.d.mts +26 -0
- package/dist/core/endpoints/skillEndpoints.d.mts +52 -0
- package/dist/core/endpoints/skyhookEndpoints.d.mts +111 -0
- package/dist/core/endpoints/sovereigntyEndpoints.d.mts +59 -0
- package/dist/core/endpoints/statusEndpoints.d.mts +14 -0
- package/dist/core/endpoints/statusEndpoints.d.ts +1 -1
- package/dist/core/endpoints/uiEndpoints.d.mts +43 -0
- package/dist/core/endpoints/universeEndpoints.d.mts +456 -0
- package/dist/core/endpoints/universeEndpoints.d.ts +22 -22
- package/dist/core/endpoints/walletEndpoints.d.mts +98 -0
- package/dist/core/endpoints/walletEndpoints.d.ts +2 -3
- package/dist/core/endpoints/walletEndpoints.d.ts.map +1 -1
- package/dist/core/endpoints/warEndpoints.d.mts +51 -0
- package/dist/core/logger/DefaultLogger.d.mts +31 -0
- package/dist/core/logger/DefaultLogger.d.ts +31 -0
- package/dist/core/logger/DefaultLogger.d.ts.map +1 -0
- package/dist/core/logger/ILogger.d.mts +17 -0
- package/dist/core/logger/ILogger.d.ts +14 -4
- package/dist/core/logger/ILogger.d.ts.map +1 -1
- package/dist/core/logger/NoopLogger.d.mts +7 -0
- package/dist/core/logger/NoopLogger.d.ts +4 -0
- package/dist/core/logger/NoopLogger.d.ts.map +1 -1
- package/dist/core/logger/clientLog.d.ts +11 -0
- package/dist/core/logger/clientLog.d.ts.map +1 -0
- package/dist/core/logger/logger.d.ts +11 -3
- package/dist/core/logger/logger.d.ts.map +1 -1
- package/dist/core/logger/loggerUtil.d.mts +11 -0
- package/dist/core/logger/loggerUtil.d.ts +8 -6
- package/dist/core/logger/loggerUtil.d.ts.map +1 -1
- package/dist/core/logger/resolveLogger.d.ts +10 -0
- package/dist/core/logger/resolveLogger.d.ts.map +1 -0
- package/dist/core/middleware/Middleware.d.mts +30 -0
- package/dist/core/pagination/AsyncPaginationIterator.d.mts +12 -0
- package/dist/core/pagination/AsyncPaginationIterator.d.ts.map +1 -1
- package/dist/core/pagination/CursorPaginationHandler.d.mts +68 -0
- package/dist/core/pagination/CursorPaginationHandler.d.ts.map +1 -1
- package/dist/core/pagination/PaginationHandler.d.ts.map +1 -1
- package/dist/core/rateLimiter/IRateLimiter.d.mts +27 -0
- package/dist/core/rateLimiter/RateLimiter.d.mts +62 -0
- package/dist/core/rateLimiter/RateLimiter.d.ts.map +1 -1
- package/dist/core/requestPipeline/cachePolicy.d.ts +25 -1
- package/dist/core/requestPipeline/cachePolicy.d.ts.map +1 -1
- package/dist/core/requestPipeline/fetchExecution.d.ts +1 -1
- package/dist/core/requestPipeline/fetchExecution.d.ts.map +1 -1
- package/dist/core/requestPipeline/headers.d.ts.map +1 -1
- package/dist/core/requestPipeline/index.d.ts +2 -2
- package/dist/core/requestPipeline/index.d.ts.map +1 -1
- package/dist/core/requestPipeline/paginationOrchestration.d.ts +1 -1
- package/dist/core/requestPipeline/paginationOrchestration.d.ts.map +1 -1
- package/dist/core/requestPipeline/statusHandling.d.ts +14 -2
- package/dist/core/requestPipeline/statusHandling.d.ts.map +1 -1
- package/dist/core/util/concurrency.d.ts +29 -0
- package/dist/core/util/concurrency.d.ts.map +1 -0
- package/dist/core/util/error.d.mts +37 -0
- package/dist/core/util/retry.d.mts +8 -0
- package/dist/core/util/retry.d.ts.map +1 -1
- package/dist/errors.d.mts +5 -0
- package/dist/errors.d.ts +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +53 -195
- package/dist/errors.js.map +1 -1
- package/dist/errors.mjs +37 -129
- package/dist/errors.mjs.map +1 -1
- package/dist/index.d.mts +81 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2195 -3517
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1833 -3044
- package/dist/index.mjs.map +1 -1
- package/dist/schemas/access-lists.d.mts +16 -0
- package/dist/schemas/alliance.d.mts +26 -0
- package/dist/schemas/assets.d.mts +24 -0
- package/dist/schemas/calendar.d.mts +27 -0
- package/dist/schemas/calendar.d.ts +9 -7
- package/dist/schemas/calendar.d.ts.map +1 -1
- package/dist/schemas/character.d.mts +109 -0
- package/dist/schemas/character.d.ts +2 -2
- package/dist/schemas/clones.d.mts +17 -0
- package/dist/schemas/clones.d.ts +2 -2
- package/dist/schemas/common.d.mts +74 -0
- package/dist/schemas/contacts.d.mts +14 -0
- package/dist/schemas/contracts.d.mts +104 -0
- package/dist/schemas/contracts.d.ts +69 -6
- package/dist/schemas/contracts.d.ts.map +1 -1
- package/dist/schemas/corporation-projects.d.mts +104 -0
- package/dist/schemas/corporation-projects.d.ts +96 -9
- package/dist/schemas/corporation-projects.d.ts.map +1 -1
- package/dist/schemas/corporation.d.mts +193 -0
- package/dist/schemas/corporation.d.ts +34 -22
- package/dist/schemas/corporation.d.ts.map +1 -1
- package/dist/schemas/cosmetics.d.mts +58 -0
- package/dist/schemas/dogma.d.mts +57 -0
- package/dist/schemas/dogma.d.ts +2 -2
- package/dist/schemas/esiEnum.d.mts +3 -0
- package/dist/schemas/faction-warfare.d.mts +203 -0
- package/dist/schemas/faction-warfare.d.ts +125 -12
- package/dist/schemas/faction-warfare.d.ts.map +1 -1
- package/dist/schemas/fittings.d.mts +13 -0
- package/dist/schemas/fleet.d.mts +37 -0
- package/dist/schemas/fleet.d.ts +1 -1
- package/dist/schemas/freelance-jobs.d.mts +171 -0
- package/dist/schemas/freelance-jobs.d.ts +52 -22
- package/dist/schemas/freelance-jobs.d.ts.map +1 -1
- package/dist/schemas/incursions.d.mts +12 -0
- package/dist/schemas/index.d.mts +39 -0
- package/dist/schemas/index.js +420 -2479
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/index.mjs +225 -2065
- package/dist/schemas/index.mjs.map +1 -1
- package/dist/schemas/industry.d.mts +99 -0
- package/dist/schemas/industry.d.ts +33 -0
- package/dist/schemas/industry.d.ts.map +1 -1
- package/dist/schemas/insurance.d.mts +10 -0
- package/dist/schemas/killmails.d.mts +38 -0
- package/dist/schemas/location.d.mts +18 -0
- package/dist/schemas/loyalty.d.mts +18 -0
- package/dist/schemas/mail.d.mts +53 -0
- package/dist/schemas/mail.d.ts +24 -5
- package/dist/schemas/mail.d.ts.map +1 -1
- package/dist/schemas/market.d.mts +123 -0
- package/dist/schemas/mercenary.d.mts +74 -0
- package/dist/schemas/mercenary.d.ts +1 -1
- package/dist/schemas/meta.d.mts +36 -0
- package/dist/schemas/meta.d.ts +12 -1
- package/dist/schemas/meta.d.ts.map +1 -1
- package/dist/schemas/military-campaigns.d.mts +26 -0
- package/dist/schemas/paragon-hub.d.mts +96 -0
- package/dist/schemas/pi.d.mts +71 -0
- package/dist/schemas/pi.d.ts +2 -2
- package/dist/schemas/skills.d.mts +28 -0
- package/dist/schemas/skyhooks.d.mts +129 -0
- package/dist/schemas/sovereignty.d.mts +56 -0
- package/dist/schemas/status.d.mts +8 -0
- package/dist/schemas/status.d.ts +1 -1
- package/dist/schemas/universe.d.mts +285 -0
- package/dist/schemas/universe.d.ts +22 -22
- package/dist/schemas/universe.d.ts.map +1 -1
- package/dist/schemas/wallet.d.mts +45 -0
- package/dist/schemas/wallet.d.ts +16 -0
- package/dist/schemas/wallet.d.ts.map +1 -1
- package/dist/schemas/wars.d.mts +27 -0
- package/dist/sde/IStaticDataProvider.d.mts +106 -0
- package/dist/sde/MemorySdeProvider.d.mts +167 -0
- package/dist/sde/SdeDataProvider.d.mts +119 -0
- package/dist/sde/SdeDataProvider.d.ts.map +1 -1
- package/dist/sde/SdeTestDataFactory.d.mts +33 -0
- package/dist/sde/errors.d.mts +23 -0
- package/dist/sde/index.d.mts +9 -0
- package/dist/sde/index.js +95 -1162
- package/dist/sde/index.js.map +1 -1
- package/dist/sde/index.mjs +73 -1091
- package/dist/sde/index.mjs.map +1 -1
- package/dist/sde/ingestion/SdeExtractor.d.ts.map +1 -1
- package/dist/sde/ingestion/metadata.d.ts +13 -0
- package/dist/sde/ingestion/metadata.d.ts.map +1 -0
- package/dist/sde/memory.d.mts +8 -0
- package/dist/sde/memory.js +21 -1095
- package/dist/sde/memory.js.map +1 -1
- package/dist/sde/memory.mjs +13 -1051
- package/dist/sde/memory.mjs.map +1 -1
- package/dist/sde/optionalPeers.d.ts +25 -0
- package/dist/sde/optionalPeers.d.ts.map +1 -0
- package/dist/sde/types.d.mts +1039 -0
- package/dist/sde/version.d.mts +7 -0
- package/dist/testing/TestDataFactory.d.mts +172 -0
- package/dist/testing/TestDataFactory.d.ts +28 -1
- package/dist/testing/TestDataFactory.d.ts.map +1 -1
- package/dist/testing/index.d.mts +2 -0
- package/dist/testing/index.js +116 -125
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/index.mjs +110 -82
- package/dist/testing/index.mjs.map +1 -1
- package/dist/types/access-lists.d.mts +5 -0
- package/dist/types/alliance.d.mts +7 -0
- package/dist/types/api-responses.d.mts +40 -0
- package/dist/types/assets.d.mts +6 -0
- package/dist/types/branded.d.mts +23 -0
- package/dist/types/calendar.d.mts +6 -0
- package/dist/types/character.d.mts +17 -0
- package/dist/types/clones.d.mts +4 -0
- package/dist/types/common.d.mts +19 -0
- package/dist/types/contacts.d.mts +5 -0
- package/dist/types/contracts.d.mts +9 -0
- package/dist/types/contracts.d.ts +4 -1
- package/dist/types/contracts.d.ts.map +1 -1
- package/dist/types/corporation-projects.d.mts +10 -0
- package/dist/types/corporation-projects.d.ts +5 -1
- package/dist/types/corporation-projects.d.ts.map +1 -1
- package/dist/types/corporation.d.mts +19 -0
- package/dist/types/cosmetics.d.mts +8 -0
- package/dist/types/dogma.d.mts +6 -0
- package/dist/types/faction-warfare.d.mts +17 -0
- package/dist/types/faction-warfare.d.ts +9 -1
- package/dist/types/faction-warfare.d.ts.map +1 -1
- package/dist/types/fittings.d.mts +4 -0
- package/dist/types/fleet.d.mts +7 -0
- package/dist/types/freelance-jobs.d.mts +12 -0
- package/dist/types/freelance-jobs.d.ts +2 -1
- package/dist/types/freelance-jobs.d.ts.map +1 -1
- package/dist/types/generated/esi-spec.generated.d.mts +2136 -0
- package/dist/types/generated/esi-spec.generated.d.ts +164 -16
- package/dist/types/generated/esi-spec.generated.d.ts.map +1 -1
- package/dist/types/generated/spec-alignment.check.d.ts +2 -2
- package/dist/types/incursions.d.mts +4 -0
- package/dist/types/industry.d.mts +11 -0
- package/dist/types/industry.d.ts +2 -1
- package/dist/types/industry.d.ts.map +1 -1
- package/dist/types/insurance.d.mts +4 -0
- package/dist/types/killmails.d.mts +5 -0
- package/dist/types/location.d.mts +6 -0
- package/dist/types/loyalty.d.mts +5 -0
- package/dist/types/mail.d.mts +6 -0
- package/dist/types/mail.d.ts +2 -1
- package/dist/types/mail.d.ts.map +1 -1
- package/dist/types/market.d.mts +12 -0
- package/dist/types/mercenary.d.mts +7 -0
- package/dist/types/meta.d.mts +9 -0
- package/dist/types/meta.d.ts +2 -1
- package/dist/types/meta.d.ts.map +1 -1
- package/dist/types/military-campaigns.d.mts +6 -0
- package/dist/types/paragon-hub.d.mts +8 -0
- package/dist/types/pi.d.mts +6 -0
- package/dist/types/skills.d.mts +5 -0
- package/dist/types/skyhooks.d.mts +8 -0
- package/dist/types/sovereignty.d.mts +6 -0
- package/dist/types/status.d.mts +4 -0
- package/dist/types/universe.d.mts +27 -0
- package/dist/types/wallet.d.mts +6 -0
- package/dist/types/wallet.d.ts +2 -1
- package/dist/types/wallet.d.ts.map +1 -1
- package/dist/types/wars.d.mts +4 -0
- package/package.json +137 -46
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/%40lgriffin%2Fesi.ts)
|
|
4
4
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
5
|
-
[](https://www.typescriptlang.org/)
|
|
6
6
|
[](https://github.com/lgriffin/ESI.ts/actions/workflows/ci.yml)
|
|
7
|
-
[](https://github.com/lgriffin/ESI.ts)
|
|
8
8
|
[](https://www.npmjs.com/package/@lgriffin/esi.ts)
|
|
9
9
|
[](https://scorecard.dev/viewer/?uri=github.com/lgriffin/ESI.ts)
|
|
10
10
|
|
|
@@ -41,7 +41,7 @@ Tools like `openapi-typescript` or `openapi-generator` can produce a typed clien
|
|
|
41
41
|
| **Batch operations** | None. | `batch()` with bounded concurrency for GET fan-out, `batchPost()` with auto-chunking for large POST payloads. |
|
|
42
42
|
| **Domain knowledge** | None — generic HTTP client. | 39 domain clients with typed methods, JSDoc documentation, and input validation (e.g., fleet wing/squad names are capped at 10 characters before hitting the API). |
|
|
43
43
|
| **Streaming pagination** | None. | 21 domain clients with 73+ `stream*` methods via `AsyncGenerator` — process large datasets page-by-page without loading everything into memory. |
|
|
44
|
-
| **Testing** | Whatever you write. |
|
|
44
|
+
| **Testing** | Whatever you write. | 171 test suites, 4,957 tests across 9 tiers including property-based fuzzing (fast-check), mutation testing (Stryker), deep contract tests against live OpenAPI spec, and consumer type tests (tsd). 52 runnable example scripts. |
|
|
45
45
|
|
|
46
46
|
### The real problem with generated clients
|
|
47
47
|
|
|
@@ -60,6 +60,8 @@ A generated client faithfully reproduces these spec bugs. ESI.ts fixes them.
|
|
|
60
60
|
npm install @lgriffin/esi.ts
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
+
Requires Node.js 18 or later. TypeScript projects need TypeScript 5.4 or later, with ES module or CommonJS code under `node16`, `nodenext` or `bundler` module resolution; the consumer contract checks each of those against the published tarball.
|
|
64
|
+
|
|
63
65
|
### Building from Source
|
|
64
66
|
|
|
65
67
|
```bash
|
|
@@ -78,7 +80,7 @@ Verify everything works:
|
|
|
78
80
|
|
|
79
81
|
```bash
|
|
80
82
|
npm run example:status # quick smoke test — checks ESI is reachable
|
|
81
|
-
npm test # run the full test suite (
|
|
83
|
+
npm test # run the full test suite (171 suites, 4,957 tests)
|
|
82
84
|
```
|
|
83
85
|
|
|
84
86
|
## Sub-path Exports
|
|
@@ -90,7 +92,7 @@ ESI.ts provides sub-path exports for targeted imports, reducing bundle size when
|
|
|
90
92
|
import { MarketOrderSchema } from '@lgriffin/esi.ts/schemas';
|
|
91
93
|
|
|
92
94
|
// Error classes and type guards
|
|
93
|
-
import { EsiError,
|
|
95
|
+
import { EsiError, isRetryable } from '@lgriffin/esi.ts/errors';
|
|
94
96
|
|
|
95
97
|
// Test utilities
|
|
96
98
|
import { TestDataFactory } from '@lgriffin/esi.ts/testing';
|
|
@@ -100,6 +102,15 @@ import { TestDataFactory } from '@lgriffin/esi.ts/testing';
|
|
|
100
102
|
|
|
101
103
|
ESI.ts includes a standalone module for querying CCP's EVE Online Static Data Export — 102 YAML files loaded into in-memory Maps with 109 typed interfaces, Zod validation, and ~97 query methods. No database, no external services.
|
|
102
104
|
|
|
105
|
+
Reading SDE files needs two optional peer dependencies, which `npm install @lgriffin/esi.ts` does not install:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npm install js-yaml # SdeDataProvider.fromDirectory and fromZip (parses the YAML)
|
|
109
|
+
npm install adm-zip # SdeDataProvider.fromZip (reads the ZIP archive)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`@lgriffin/esi.ts/sde` loads without them, and `MemorySdeProvider` never needs them. A method that needs one that is missing throws an `SdeError` naming the package and the install command.
|
|
113
|
+
|
|
103
114
|
```typescript
|
|
104
115
|
import { SdeDataProvider } from '@lgriffin/esi.ts/sde';
|
|
105
116
|
|
|
@@ -147,6 +158,28 @@ const wallet = await authedClient.wallet.getCharacterWallet(characterId);
|
|
|
147
158
|
await client.shutdown();
|
|
148
159
|
```
|
|
149
160
|
|
|
161
|
+
## Guides
|
|
162
|
+
|
|
163
|
+
The README orients; the guides are canonical. Each one opens with the [engineering charter](guides/CHARTER.md) requirements it implements.
|
|
164
|
+
|
|
165
|
+
| Guide | Covers |
|
|
166
|
+
| -------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
167
|
+
| [Architecture](guides/ARCHITECTURE.md) | Layers, request path, caching, retry, rate limiting, circuit breaker, interceptors |
|
|
168
|
+
| [Design rules](guides/DESIGN-RULES.md) | Naming and schema conventions, adding an endpoint, adding a client, generated files |
|
|
169
|
+
| [Errors](guides/ERRORS.md) | Error classes, type guards, retryability, token refresh, safe mode |
|
|
170
|
+
| [Logging](guides/LOGGING.md) | `ILogger`, per-client loggers, pino, `ESI_LOG_LEVEL`, silencing in tests |
|
|
171
|
+
| [Pagination](guides/PAGINATION.md) | Offset and cursor pagination, `stream*`, `fetchAll*`, batch helpers |
|
|
172
|
+
| [Runtime validation](guides/RUNTIME-VALIDATION.md) | Zod response and request validation |
|
|
173
|
+
| [Security](guides/SECURITY.md) | Runtime defences and supply-chain controls ([policy](SECURITY.md)) |
|
|
174
|
+
| [Testing](guides/TESTING.md) | Test tiers, coverage, EARS specification |
|
|
175
|
+
| [Mutation testing](guides/MUTATION-TESTING.md) | Stryker configuration and scores |
|
|
176
|
+
| [Quality gates](guides/QUALITY-GATES.md) | What runs at commit, push, PR, nightly and release; every workflow and script |
|
|
177
|
+
| [Release](guides/RELEASE.md) | Cutting a release, changelog, provenance, signatures, supported versions |
|
|
178
|
+
| [Semantic versioning](guides/SEMVER.md) | What is public, major/minor/patch decisions, breaking-change commits, merge buttons |
|
|
179
|
+
| [OKF bundle](guides/OKF.md) | The generated Open Knowledge Format catalogue of ESI |
|
|
180
|
+
| [Documentation](guides/DOCUMENTATION.md) | Documentation surfaces and the TypeDoc reference |
|
|
181
|
+
| [Beads](guides/BEADS.md) | Issue tracking workflow |
|
|
182
|
+
|
|
150
183
|
## Configuration
|
|
151
184
|
|
|
152
185
|
```typescript
|
|
@@ -172,9 +205,10 @@ const client = new EsiClient({
|
|
|
172
205
|
validateResponse: true, // Runtime Zod validation of ESI responses (default: true)
|
|
173
206
|
validateRequest: false, // Opt-in request body Zod validation for POST/PUT/DELETE (default: false)
|
|
174
207
|
retryStrategy: customRetryStrategy, // Injectable IRetryStrategy (default: built-in exponential backoff)
|
|
208
|
+
enableCircuitBreaker: false, // Opt-in circuit breaker (default: false); circuitBreakerConfig is ignored unless true
|
|
175
209
|
circuitBreakerConfig: {
|
|
176
210
|
keyStrategy: 'resolved', // CB keying: 'resolved' (per-URL) or 'template' (per-route) (default: 'resolved')
|
|
177
|
-
cleanupIntervalMs:
|
|
211
|
+
cleanupIntervalMs: 3600000, // Stale circuit cleanup interval (default: disabled)
|
|
178
212
|
},
|
|
179
213
|
});
|
|
180
214
|
```
|
|
@@ -278,6 +312,107 @@ Key behaviors:
|
|
|
278
312
|
- If the refresh callback throws (e.g., refresh token revoked), a `TOKEN_REFRESH_FAILED` error is raised
|
|
279
313
|
- Without a token provider, 401 errors throw immediately as before
|
|
280
314
|
|
|
315
|
+
### Token Manager (multi-character, persistent)
|
|
316
|
+
|
|
317
|
+
The refresh callback above is the low-level hook. For applications that hold tokens for one or many characters, `EsiTokenManager` does the whole lifecycle: the SSO code exchange, persistence through a pluggable storage adapter, proactive refresh ahead of expiry, coalescing of concurrent refreshes, persistence of the rotated refresh token, revocation tracking, and bulk refresh with a concurrency cap.
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import {
|
|
321
|
+
EsiTokenManager,
|
|
322
|
+
FileTokenStorage,
|
|
323
|
+
generateState,
|
|
324
|
+
} from '@lgriffin/esi.ts';
|
|
325
|
+
|
|
326
|
+
const tokens = new EsiTokenManager({
|
|
327
|
+
clientId: process.env.ESI_SSO_CLIENT_ID!,
|
|
328
|
+
clientSecret: process.env.ESI_SSO_CLIENT_SECRET, // omit for a public (PKCE) client
|
|
329
|
+
callbackUrl: 'https://my-app.example/callback',
|
|
330
|
+
storage: new FileTokenStorage('./tokens.json'), // or MemoryTokenStorage, or your own
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// 1. Send the player to SSO
|
|
334
|
+
const state = generateState();
|
|
335
|
+
const loginUrl = tokens.getAuthorizationUrl({
|
|
336
|
+
scopes: ['esi-wallet.read_character_wallet.v1'],
|
|
337
|
+
state,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// 2. On the callback, exchange the code. The character id, name and scopes
|
|
341
|
+
// are decoded from the token; you never have to say who just logged in.
|
|
342
|
+
const stored = await tokens.addCharacter(codeFromCallback);
|
|
343
|
+
console.log(`Added ${stored.characterName} (${stored.characterId})`);
|
|
344
|
+
|
|
345
|
+
// 3. Get a client bound to that character. Its token is refreshed before
|
|
346
|
+
// expiry, and again on a 401, through the manager.
|
|
347
|
+
const client = await tokens.createClient(stored.characterId);
|
|
348
|
+
const wallet = await client.wallet.getCharacterWallet(stored.characterId);
|
|
349
|
+
|
|
350
|
+
// Or just the access token, for use elsewhere
|
|
351
|
+
const accessToken = await tokens.getToken(stored.characterId);
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Public clients (desktop and CLI tools that cannot keep a secret) use PKCE:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
import { generatePkcePair } from '@lgriffin/esi.ts';
|
|
358
|
+
|
|
359
|
+
const pkce = generatePkcePair();
|
|
360
|
+
const loginUrl = tokens.getAuthorizationUrl({
|
|
361
|
+
scopes,
|
|
362
|
+
state,
|
|
363
|
+
codeChallenge: pkce.codeChallenge,
|
|
364
|
+
});
|
|
365
|
+
// ...later, on the callback:
|
|
366
|
+
await tokens.addCharacter(code, { codeVerifier: pkce.codeVerifier });
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### Bulk refresh
|
|
370
|
+
|
|
371
|
+
Applications holding many characters (corporation tools, alliance services) refresh in bulk. Per-character failures never reject the call; each character gets its own result. The one exception is a storage adapter that cannot list tokens, which rejects with the storage error.
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
const results = await tokens.refreshAll({
|
|
375
|
+
concurrency: 5, // simultaneous SSO requests (default 5)
|
|
376
|
+
expiringWithinMs: 5 * 60_000, // only tokens expiring in the next 5 minutes; omit for all
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
for (const r of results) {
|
|
380
|
+
switch (r.status) {
|
|
381
|
+
case 'refreshed':
|
|
382
|
+
break;
|
|
383
|
+
case 'skipped':
|
|
384
|
+
break; // not stale, or the run was aborted
|
|
385
|
+
case 'revoked':
|
|
386
|
+
console.log(`${r.characterId} must log in again`);
|
|
387
|
+
break;
|
|
388
|
+
case 'failed':
|
|
389
|
+
if (r.retryable) scheduleRetry(r.characterId);
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
#### Storage adapters
|
|
396
|
+
|
|
397
|
+
`ITokenStorage` is four async methods keyed by character id: `get`, `set`, `delete`, `list`. Two adapters ship with the library:
|
|
398
|
+
|
|
399
|
+
| Adapter | Use for |
|
|
400
|
+
| -------------------- | ---------------------------------------------------------------------- |
|
|
401
|
+
| `MemoryTokenStorage` | Tests, CLIs that log in every run, a cache in front of a durable store |
|
|
402
|
+
| `FileTokenStorage` | Single-process apps; atomic temp-file-and-rename writes, `0600` mode |
|
|
403
|
+
|
|
404
|
+
Implement the interface over Redis, Postgres, or a keychain for anything else. One rule matters: `set` must be durable before it resolves, because the manager persists the rotated refresh token before returning the new access token, and SSO invalidates the previous one.
|
|
405
|
+
|
|
406
|
+
Key behaviors:
|
|
407
|
+
|
|
408
|
+
- **One token per character** — re-authorizing replaces the stored token rather than accumulating a second one; a warning is logged if the new consent drops scopes
|
|
409
|
+
- **Proactive refresh** — `getToken` refreshes when the token is inside `refreshSkewMs` of expiry (default 60 s), so requests are never sent with a token about to fail
|
|
410
|
+
- **Coalescing** — concurrent refreshes for the same character share one SSO call, which matters because SSO rotates the refresh token on every use
|
|
411
|
+
- **Revocation tracking** — an `invalid_grant` from SSO marks the character revoked; later calls throw `TokenRevokedError` locally instead of hitting SSO again
|
|
412
|
+
- **Hooks** — `onRefresh`, `onRefreshError`, and `onRevoked` for logging, metrics, or prompting a re-login
|
|
413
|
+
- **No JWT signature verification** — tokens are trusted because they arrive directly from SSO over TLS; do not use `decodeAccessToken` to authenticate tokens presented by third parties
|
|
414
|
+
- **Single process per store** — two processes sharing one `FileTokenStorage` would each rotate refresh tokens the other cannot see
|
|
415
|
+
|
|
281
416
|
### Environment variables reference
|
|
282
417
|
|
|
283
418
|
| Variable | Description | Default |
|
|
@@ -382,47 +517,15 @@ See [guides/RUNTIME-VALIDATION.md](guides/RUNTIME-VALIDATION.md) for the full gu
|
|
|
382
517
|
|
|
383
518
|
## Caching
|
|
384
519
|
|
|
385
|
-
ETag caching is
|
|
386
|
-
|
|
387
|
-
1. Stores ETag and response data on GET requests
|
|
388
|
-
2. Sends `If-None-Match` on subsequent requests
|
|
389
|
-
3. Returns cached data on `304 Not Modified`
|
|
390
|
-
4. Parses `Cache-Control: max-age` from ESI for per-endpoint TTL
|
|
391
|
-
5. Serves stale cached data when ESI returns 5xx errors
|
|
392
|
-
6. Invalidates related GET caches when POST/PUT/DELETE requests are made
|
|
520
|
+
ETag caching is on by default and works in three tiers: a GET inside the spec-defined TTL is answered from cache with no HTTP call, an older entry is revalidated with `If-None-Match`, and a 5xx with a cached copy serves the stale body instead of throwing. Authenticated cache entries are isolated per token.
|
|
393
521
|
|
|
394
522
|
```typescript
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
console.log(`${stats.totalEntries}/${stats.maxEntries} entries cached`);
|
|
398
|
-
|
|
399
|
-
// Manual cache operations
|
|
523
|
+
const client = new EsiClient({ etagCacheConfig: { maxEntries: 2000 } });
|
|
524
|
+
client.getCacheStats();
|
|
400
525
|
client.clearCache();
|
|
401
|
-
client.updateCacheConfig({ maxEntries: 2000 });
|
|
402
|
-
|
|
403
|
-
// Disable caching entirely
|
|
404
|
-
const uncachedClient = new EsiClient({ enableETagCache: false });
|
|
405
526
|
```
|
|
406
527
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
The library reads `x-cache-age` from the ESI OpenAPI spec (126 of 195 endpoints). Within the TTL window, repeated GET requests return cached data with **zero HTTP calls** — not even a conditional GET.
|
|
410
|
-
|
|
411
|
-
This layers on top of ETag caching in three tiers:
|
|
412
|
-
|
|
413
|
-
1. **Spec TTL** — data can't have changed yet, return cached data immediately
|
|
414
|
-
2. **ETag conditional GET** — data might have changed, send `If-None-Match` to check
|
|
415
|
-
3. **Full request** — no cache entry, fetch fresh data
|
|
416
|
-
|
|
417
|
-
```typescript
|
|
418
|
-
const client = new EsiClient();
|
|
419
|
-
|
|
420
|
-
// First call — fetches from ESI
|
|
421
|
-
const alliances = await client.alliance.getAlliances();
|
|
422
|
-
|
|
423
|
-
// Second call within the next 3600s — returns cached data, zero HTTP calls
|
|
424
|
-
const same = await client.alliance.getAlliances();
|
|
425
|
-
```
|
|
528
|
+
See [Caching in the architecture guide](guides/ARCHITECTURE.md#4-caching) for TTL precedence, invalidation, keys and configuration.
|
|
426
529
|
|
|
427
530
|
## Batch Requests
|
|
428
531
|
|
|
@@ -433,7 +536,7 @@ import { EsiClient } from '@lgriffin/esi.ts';
|
|
|
433
536
|
|
|
434
537
|
const client = new EsiClient();
|
|
435
538
|
|
|
436
|
-
// Fetch 500 type details with at most 10 concurrent requests
|
|
539
|
+
// Fetch 500 type details with at most 10 concurrent requests (default 20)
|
|
437
540
|
const result = await client.batch(
|
|
438
541
|
typeIds,
|
|
439
542
|
(id) => client.universe.getTypeById(id),
|
|
@@ -448,129 +551,36 @@ const result = await client.batch(
|
|
|
448
551
|
console.log(`${result.results.size} succeeded, ${result.errors.size} failed`);
|
|
449
552
|
```
|
|
450
553
|
|
|
451
|
-
For POST endpoints that accept arrays (e.g., `
|
|
554
|
+
For POST endpoints that accept arrays (e.g., `postNamesAndCategories` with a 1000-ID limit), `batchPost` auto-chunks and concatenates:
|
|
452
555
|
|
|
453
556
|
```typescript
|
|
454
557
|
const allNames = await client.batchPost(
|
|
455
558
|
largeIdArray,
|
|
456
|
-
(chunk) => client.universe.
|
|
559
|
+
(chunk) => client.universe.postNamesAndCategories(chunk),
|
|
457
560
|
1000, // chunk size
|
|
458
561
|
);
|
|
459
562
|
```
|
|
460
563
|
|
|
461
564
|
## Streaming Pagination
|
|
462
565
|
|
|
463
|
-
|
|
566
|
+
Paginated endpoints can be consumed three ways: the plain method fetches every page and returns one array, `stream*` methods yield one validated page at a time, and `fetchAll*` methods fetch the remaining pages concurrently.
|
|
464
567
|
|
|
465
568
|
```typescript
|
|
466
|
-
import { EsiClient } from '@lgriffin/esi.ts';
|
|
467
|
-
|
|
468
|
-
const client = new EsiClient();
|
|
469
|
-
|
|
470
|
-
// Stream all market orders in The Forge, page by page
|
|
471
569
|
for await (const page of client.market.streamMarketOrders(10000002)) {
|
|
472
570
|
console.log(
|
|
473
571
|
`Page ${page.page}/${page.totalPages}: ${page.data.length} orders`,
|
|
474
572
|
);
|
|
475
|
-
|
|
476
|
-
// Process each order as it arrives
|
|
477
|
-
for (const order of page.data) {
|
|
478
|
-
if (order.is_buy_order && order.price > 1_000_000) {
|
|
479
|
-
console.log(`High-value buy: ${order.type_id} @ ${order.price} ISK`);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// Early termination — stops fetching remaining pages
|
|
484
|
-
if (page.page >= 3) break;
|
|
573
|
+
if (page.page >= 3) break; // stops fetching the remaining pages
|
|
485
574
|
}
|
|
486
575
|
```
|
|
487
576
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
Available streaming methods (representative selection):
|
|
491
|
-
|
|
492
|
-
- **MarketClient** — `streamMarketOrders`, `streamMarketTypes`, `streamCharacterOrderHistory`, `streamCorporationOrders`, `streamCorporationOrderHistory`, `streamMarketOrdersInStructure`
|
|
493
|
-
- **CorporationsClient** — `streamCorporationMembers`, `streamCorporationStructures`, `streamCorporationBlueprints`, + 14 more
|
|
494
|
-
- **CharacterClient** — `streamCharacterBlueprints`, `streamCharacterNotifications`, `streamCharacterStandings`, + 5 more
|
|
495
|
-
- **ContractsClient** — `streamPublicContracts`, `streamCharacterContracts`, `streamCorporationContracts`
|
|
496
|
-
- **WalletClient** — `streamCharacterWalletJournal`, `streamCorporationWalletJournal`, `streamCharacterWalletTransactions`
|
|
497
|
-
- **IndustryClient** — `streamCorporationIndustryJobs`, `streamCorporationMiningObservers`, + 6 more
|
|
498
|
-
- **ContactsClient** — `streamAllianceContacts`, `streamCharacterContacts`, `streamCorporationContacts`, + 3 more
|
|
499
|
-
- **AssetsClient** — `streamCharacterAssets`, `streamCorporationAssets`
|
|
500
|
-
- **KillmailsClient** — `streamCharacterRecentKillmails`, `streamCorporationRecentKillmails`
|
|
501
|
-
- **MailClient** — `streamCharacterMail`, `streamCharacterMailLabels`
|
|
502
|
-
- **FleetsClient** — `streamFleetMembers`, `streamFleetWings`
|
|
503
|
-
- **CalendarClient** — `streamCalendarEvents`
|
|
504
|
-
- **FittingsClient** — `streamCharacterFittings`
|
|
505
|
-
- **SkillsClient** — `streamCharacterSkillQueue`
|
|
506
|
-
- **LoyaltyClient** — `streamCorporationLoyaltyStoreOffers`
|
|
507
|
-
- **BookmarksClient** — `streamCharacterBookmarks`, `streamCorporationBookmarks`
|
|
508
|
-
- **ClonesClient** — `streamCharacterImplants`
|
|
509
|
-
- **PIClient** — `streamCharacterPlanets`
|
|
510
|
-
- **WarsClient** — `streamWars`
|
|
511
|
-
- **FactionWarfareClient** — `streamFactionWarfareStats`
|
|
512
|
-
- **AllianceClient** — `streamAllianceCorporations`
|
|
513
|
-
|
|
514
|
-
Try it: `npm run example:streaming`
|
|
577
|
+
Try it: `npm run example:streaming`. See [guides/PAGINATION.md](guides/PAGINATION.md) for the full method list, concurrency defaults and failure behaviour.
|
|
515
578
|
|
|
516
579
|
## Cursor-based Pagination
|
|
517
580
|
|
|
518
|
-
Newer ESI routes
|
|
519
|
-
|
|
520
|
-
```typescript
|
|
521
|
-
import { EsiClient, fetchAllCursorPages } from '@lgriffin/esi.ts';
|
|
522
|
-
|
|
523
|
-
const client = new EsiClient();
|
|
524
|
-
|
|
525
|
-
// Fetch first page — returns { cursor: { before, after }, freelance_jobs: [...] }
|
|
526
|
-
const page = await client.freelanceJobs.getFreelanceJobs();
|
|
527
|
-
console.log(page.freelance_jobs); // job records
|
|
528
|
-
console.log(page.cursor.after); // opaque token for next page
|
|
581
|
+
Newer ESI routes such as Freelance Jobs page with opaque `before` / `after` cursor tokens instead of page numbers. `fetchAllCursorPages` follows them to the end of the dataset, and a saved `after` token can be polled later for changed records.
|
|
529
582
|
|
|
530
|
-
|
|
531
|
-
const nextPage = await client.freelanceJobs.getFreelanceJobs(
|
|
532
|
-
undefined,
|
|
533
|
-
page.cursor.after,
|
|
534
|
-
);
|
|
535
|
-
|
|
536
|
-
// Auto-fetch all pages in one call
|
|
537
|
-
const allJobs = await fetchAllCursorPages(
|
|
538
|
-
(before, after) => client.freelanceJobs.getFreelanceJobs(before, after),
|
|
539
|
-
(response) => response.freelance_jobs,
|
|
540
|
-
(response) => response.cursor,
|
|
541
|
-
);
|
|
542
|
-
|
|
543
|
-
// Authenticated endpoints — character/corporation freelance jobs
|
|
544
|
-
const authedClient = new EsiClient({ accessToken: 'your-token' });
|
|
545
|
-
const myJobs =
|
|
546
|
-
await authedClient.freelanceJobs.getCharacterFreelanceJobs(characterId);
|
|
547
|
-
const corpJobs =
|
|
548
|
-
await authedClient.freelanceJobs.getCorporationFreelanceJobs(corporationId);
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
**Polling for changes** — cursor tokens persist across sessions, so you can save the last `after` token and poll later to get only records that changed:
|
|
552
|
-
|
|
553
|
-
```typescript
|
|
554
|
-
// After initial scan, save the final cursor
|
|
555
|
-
let savedCursor = lastPage.cursor.after;
|
|
556
|
-
|
|
557
|
-
// Later: check for updates (hours, days, or weeks later)
|
|
558
|
-
const updates = await client.freelanceJobs.getFreelanceJobs(
|
|
559
|
-
undefined,
|
|
560
|
-
savedCursor,
|
|
561
|
-
);
|
|
562
|
-
if (updates.freelance_jobs.length > 0) {
|
|
563
|
-
// Process changed records — duplicates are expected for modified records
|
|
564
|
-
savedCursor = updates.cursor.after;
|
|
565
|
-
}
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
Key points:
|
|
569
|
-
|
|
570
|
-
- Cursor tokens are **opaque strings** — never parse or validate them
|
|
571
|
-
- An **empty result array** signals the end of the dataset (not a short page)
|
|
572
|
-
- **Duplicates across pages** are expected when records are modified between requests
|
|
573
|
-
- Existing offset-based routes (`getMarketOrders`, etc.) are unchanged
|
|
583
|
+
See [guides/PAGINATION.md](guides/PAGINATION.md) for cursor semantics and examples.
|
|
574
584
|
|
|
575
585
|
## Generated Types
|
|
576
586
|
|
|
@@ -587,7 +597,12 @@ const order: EsiSpec.MarketsRegionIdOrdersGet = {
|
|
|
587
597
|
volume_remain: 1000,
|
|
588
598
|
volume_total: 5000,
|
|
589
599
|
is_buy_order: false,
|
|
590
|
-
|
|
600
|
+
duration: 90,
|
|
601
|
+
issued: '2026-09-01T12:00:00Z',
|
|
602
|
+
location_id: 60003760,
|
|
603
|
+
system_id: 30000142,
|
|
604
|
+
min_volume: 1,
|
|
605
|
+
range: 'region',
|
|
591
606
|
};
|
|
592
607
|
```
|
|
593
608
|
|
|
@@ -619,43 +634,20 @@ const scope: EsiScope = 'esi-assets.read_assets.v1';
|
|
|
619
634
|
|
|
620
635
|
## Error Handling
|
|
621
636
|
|
|
622
|
-
|
|
637
|
+
Failed calls throw `EsiError` (with `statusCode`, a sanitised `url` and `retryable`) or one of its subclasses, `TimeoutError` and `EsiValidationError`. An open circuit throws `CircuitOpenError`. Type guards such as `isRetryable`, `isTimeout`, `isValidationError` and `isCircuitOpen` narrow them, and `withSafeMode()` returns a result envelope instead of throwing.
|
|
623
638
|
|
|
624
639
|
```typescript
|
|
625
|
-
import {
|
|
626
|
-
EsiError,
|
|
627
|
-
TimeoutError,
|
|
628
|
-
EsiValidationError,
|
|
629
|
-
isTimeout,
|
|
630
|
-
isRetryable,
|
|
631
|
-
isValidationError,
|
|
632
|
-
isCircuitOpen,
|
|
633
|
-
} from '@lgriffin/esi.ts';
|
|
640
|
+
import { EsiError, isCircuitOpen } from '@lgriffin/esi.ts';
|
|
634
641
|
|
|
635
642
|
try {
|
|
636
|
-
|
|
637
|
-
console.log('Alliance:', alliance.name);
|
|
643
|
+
await client.alliance.getAllianceById(99999999);
|
|
638
644
|
} catch (err) {
|
|
639
|
-
if (isCircuitOpen(err)) {
|
|
640
|
-
|
|
641
|
-
} else if (isValidationError(err)) {
|
|
642
|
-
console.log('Response validation failed:', err.validationError);
|
|
643
|
-
} else if (isTimeout(err)) {
|
|
644
|
-
console.log(`Request timed out after ${err.timeoutMs}ms`);
|
|
645
|
-
} else if (err instanceof EsiError) {
|
|
646
|
-
console.log(`ESI error ${err.statusCode}: ${err.message}`);
|
|
647
|
-
console.log(`Retryable: ${err.retryable}`);
|
|
648
|
-
}
|
|
645
|
+
if (isCircuitOpen(err)) console.log(`Retry in ${err.retryAfterMs} ms`);
|
|
646
|
+
else if (err instanceof EsiError) console.log(err.statusCode, err.retryable);
|
|
649
647
|
}
|
|
650
648
|
```
|
|
651
649
|
|
|
652
|
-
|
|
653
|
-
- **304 Not Modified** — handled internally, returns cached data
|
|
654
|
-
- **4xx/5xx** — throws `EsiError`
|
|
655
|
-
- **5xx with cache** — returns stale cached data instead of throwing
|
|
656
|
-
- **Timeout** — throws `TimeoutError` (extends `EsiError` with `statusCode: 0` and `timeoutMs`)
|
|
657
|
-
- **Retryable errors** — `EsiError.retryable` returns `true` for 502, 503, 504, 420, 429, and timeouts
|
|
658
|
-
- **Validation errors** — throws `EsiValidationError` (extends `EsiError`) when response data doesn't match the expected Zod schema
|
|
650
|
+
See [guides/ERRORS.md](guides/ERRORS.md) for the class hierarchy, retryability rules and safe mode.
|
|
659
651
|
|
|
660
652
|
## Response Metadata
|
|
661
653
|
|
|
@@ -688,42 +680,17 @@ The `meta` object includes:
|
|
|
688
680
|
|
|
689
681
|
## Rate Limiting
|
|
690
682
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
Rate limiting works out of the box with no configuration. For multi-character applications, enable per-user bucketing:
|
|
683
|
+
Rate limiting is always on and needs no configuration. Each ESI rate-limit group from the OpenAPI spec gets its own bucket, the limiter learns remaining tokens from ESI's response headers, and a 420 or 429 blocks only the affected group. Multi-character applications can give each token its own buckets:
|
|
694
684
|
|
|
695
685
|
```typescript
|
|
696
|
-
import { EsiClient } from '@lgriffin/esi.ts';
|
|
697
|
-
|
|
698
686
|
const client = new EsiClient({
|
|
699
687
|
rateLimiterConfig: {
|
|
700
|
-
userKeyExtractor: (headers) => headers['
|
|
688
|
+
userKeyExtractor: (headers) => headers['Authorization'] ?? 'anon',
|
|
701
689
|
},
|
|
702
690
|
});
|
|
703
691
|
```
|
|
704
692
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
```typescript
|
|
708
|
-
const limiter = client.getRateLimiter();
|
|
709
|
-
|
|
710
|
-
// Worst-case across all groups (backward-compatible)
|
|
711
|
-
const status = limiter.getStatus();
|
|
712
|
-
console.log(status.remaining, status.limit, status.group);
|
|
713
|
-
|
|
714
|
-
// Specific group
|
|
715
|
-
const marketStatus = limiter.getGroupStatus('market-order');
|
|
716
|
-
console.log(marketStatus?.remaining); // tokens remaining in this group
|
|
717
|
-
|
|
718
|
-
// All active groups
|
|
719
|
-
const all = limiter.getAllGroupStatuses();
|
|
720
|
-
for (const [group, info] of all) {
|
|
721
|
-
console.log(`${group}: ${info.remaining}/${info.limit}`);
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
// Check if a specific group is blocked
|
|
725
|
-
console.log(limiter.isBlocked('char-notification')); // true if 429'd
|
|
726
|
-
```
|
|
693
|
+
See [Rate limiting in the architecture guide](guides/ARCHITECTURE.md#6-rate-limiting) for the throttling rules, per-endpoint overrides and monitoring. Retry, deduplication, the opt-in [circuit breaker](guides/ARCHITECTURE.md#7-circuit-breaker) and [request/response interceptors](guides/ARCHITECTURE.md#8-interceptors) are documented alongside it.
|
|
727
694
|
|
|
728
695
|
## Lightweight Clients
|
|
729
696
|
|
|
@@ -864,7 +831,9 @@ console.log(`Best sell: ${Math.min(...sellOrders.map((o) => o.price))}`);
|
|
|
864
831
|
|
|
865
832
|
Always call `shutdown()` when you're done to clean up cache timers:
|
|
866
833
|
|
|
867
|
-
```typescript
|
|
834
|
+
```typescript runnable
|
|
835
|
+
import { EsiClient } from '@lgriffin/esi.ts';
|
|
836
|
+
|
|
868
837
|
const client = new EsiClient();
|
|
869
838
|
try {
|
|
870
839
|
const status = await client.status.getStatus();
|
|
@@ -876,11 +845,11 @@ try {
|
|
|
876
845
|
|
|
877
846
|
## Testing
|
|
878
847
|
|
|
879
|
-
ESI.ts has a comprehensive multi-tier testing strategy with
|
|
848
|
+
ESI.ts has a comprehensive multi-tier testing strategy with 171 suites and 4,957 tests:
|
|
880
849
|
|
|
881
850
|
| Tier | Tests | Purpose |
|
|
882
851
|
| -------------------------- | ---------------- | ------------------------------------------------------------------ |
|
|
883
|
-
| **TDD unit tests** |
|
|
852
|
+
| **TDD unit tests** | 130 files | Every client method, endpoint path, query param, and body format |
|
|
884
853
|
| **BDD scenario tests** | 41 feature files | Behavioral specifications in Gherkin (Given/When/Then) |
|
|
885
854
|
| **Mocked integration** | Full suite | Cross-layer request flow with jest-fetch-mock |
|
|
886
855
|
| **Live smoke tests** | 46 examples | Every endpoint against live Tranquility |
|
|
@@ -894,17 +863,17 @@ ESI.ts has a comprehensive multi-tier testing strategy with 139 suites and 4,104
|
|
|
894
863
|
| **Spec-alignment** | Type assertions | Ensures hand-written types align with generated OpenAPI types |
|
|
895
864
|
|
|
896
865
|
```bash
|
|
897
|
-
npm test # Unit + BDD tests (
|
|
866
|
+
npm test # Unit + BDD tests (171 suites, 4,957 tests)
|
|
898
867
|
npm run coverage # Tests with coverage report (thresholds enforced)
|
|
899
868
|
npm run bdd # BDD scenario tests only
|
|
900
869
|
npm run contract # Contract tests (skipped without ESI_LIVE_TESTS=true)
|
|
901
870
|
npm run fuzz # Property-based fuzz tests (601 tests)
|
|
902
871
|
npm run mutation # Mutation testing (Stryker)
|
|
903
|
-
npm run benchmark #
|
|
872
|
+
npm run benchmark # Micro-benchmarks (mitata); npm run soak for the heap soak
|
|
904
873
|
npm run test:types # tsd consumer type tests
|
|
905
874
|
```
|
|
906
875
|
|
|
907
|
-
Coverage: statements 98.
|
|
876
|
+
Coverage: statements 98.37%, branches 95.14%, functions 96.09%, lines 98.17%. Thresholds enforced in CI: branches 80%, functions 75%, lines 90%, statements 90%.
|
|
908
877
|
|
|
909
878
|
See [guides/TESTING.md](guides/TESTING.md) for the full testing guide, and [guides/ARCHITECTURE.md](guides/ARCHITECTURE.md) for architecture diagrams.
|
|
910
879
|
|
|
@@ -941,14 +910,14 @@ npm run format # Format code with Prettier
|
|
|
941
910
|
npm run format:check # Check formatting without modifying
|
|
942
911
|
|
|
943
912
|
# Testing
|
|
944
|
-
npm test # Unit tests (
|
|
913
|
+
npm test # Unit tests (171 suites, 4,957 tests)
|
|
945
914
|
npm run test:all # Unit + BDD + integration + fuzz + type tests
|
|
946
915
|
npm run coverage # Tests with coverage report (thresholds enforced)
|
|
947
916
|
npm run bdd # BDD scenario tests
|
|
948
|
-
npm run contract:live
|
|
917
|
+
ESI_LIVE_TESTS=true npm run contract:live # Deep contract tests against live ESI spec (fails without the variable)
|
|
949
918
|
npm run fuzz # Property-based fuzz tests (fast-check)
|
|
950
919
|
npm run mutation # Mutation testing (Stryker)
|
|
951
|
-
npm run benchmark #
|
|
920
|
+
npm run benchmark # Micro-benchmarks (mitata)
|
|
952
921
|
npm run test:types # Consumer type tests (tsd)
|
|
953
922
|
npm run mock:esi # Start Prism mock ESI server on port 4010
|
|
954
923
|
|
|
@@ -989,32 +958,9 @@ The project uses husky with lint-staged to run ESLint and Prettier on staged fil
|
|
|
989
958
|
|
|
990
959
|
### CI/CD
|
|
991
960
|
|
|
992
|
-
Every pull
|
|
993
|
-
|
|
994
|
-
-
|
|
995
|
-
- Prettier formatting check
|
|
996
|
-
- TypeScript compilation
|
|
997
|
-
- Generated types staleness check (regenerates from live ESI OpenAPI spec and verifies no diff)
|
|
998
|
-
- Unit tests across Node.js 18, 20, and 22
|
|
999
|
-
- BDD scenario tests
|
|
1000
|
-
- Coverage threshold enforcement (branches: 80%, functions: 75%, lines: 90%, statements: 90%)
|
|
1001
|
-
- Auth/scopes cross-validation
|
|
1002
|
-
- Spec-alignment type assertions
|
|
1003
|
-
- Schema drift detection
|
|
1004
|
-
- Mutation testing (Stryker)
|
|
1005
|
-
- Dead code detection via knip
|
|
1006
|
-
- npm security audit — diff-aware on PRs (fails only on advisories the PR introduces), state-of-the-world nightly and at release, with a reviewed-acceptance allowlist in `scripts/audit-exceptions.json`
|
|
1007
|
-
|
|
1008
|
-
**Supply chain security:**
|
|
1009
|
-
|
|
1010
|
-
- All GitHub Actions pinned by SHA hash (not mutable tags) to prevent supply chain attacks
|
|
1011
|
-
- Least-privilege `permissions:` on all workflows and jobs
|
|
1012
|
-
- Script injection prevention (user-controlled inputs passed via `env:`, never interpolated in `run:`)
|
|
1013
|
-
- npm publish with `--provenance` for SLSA attestations (verifiable build origin)
|
|
1014
|
-
- GitHub release artifacts signed with Cosign (keyless) and published with SHA256 checksums
|
|
1015
|
-
- OpenSSF Scorecard runs weekly via the `scorecard.yml` workflow
|
|
1016
|
-
|
|
1017
|
-
See [.github/workflows/README.md](.github/workflows/README.md) for full workflow details.
|
|
961
|
+
Every push runs lint, format, build, typecheck and unit tests; pull requests to `master` run the full matrix behind a single Quality Gate check. Actions are SHA-pinned, packages publish with npm provenance, and release assets are cosign-signed.
|
|
962
|
+
|
|
963
|
+
See [guides/QUALITY-GATES.md](guides/QUALITY-GATES.md) for the gate matrix and every workflow, and [guides/SECURITY.md](guides/SECURITY.md) for the supply-chain controls.
|
|
1018
964
|
|
|
1019
965
|
## Contributing
|
|
1020
966
|
|