diff --git a/CHANGELOG.md b/CHANGELOG.md index e145e8b..a621f27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] +## [2.8.0] - 2026-09-22 + +### Added +- `AccountResult.organization`: the organization the API key belongs to, as + `{ id, name }`, with the exported `OrganizationInfo` type. The plan, the + credits and the prepaid balance `account.get()` reports are that + organization's. The field is optional: check it before reading `id` or `name`. + +Nothing was removed or renamed. + ## [2.7.1] - 2026-09-19 ### Fixed diff --git a/README.md b/README.md index f9b63a7..a08cf8c 100644 --- a/README.md +++ b/README.md @@ -439,6 +439,7 @@ console.log(account.usage.creditsLimit) // 5000 (Starter 5K) console.log(account.usage.prepaidBalance) // 12.5 console.log(account.usage.prepaidBalanceCurrency) // 'USD' console.log(account.apiKey.totalRequests) // 1234 +console.log(account.organization?.name) // 'Acme Prints' ``` An account is funded either by a subscription allowance or by a prepaid balance, diff --git a/package-lock.json b/package-lock.json index 8b746a2..d9588c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sudomock", - "version": "2.7.1", + "version": "2.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sudomock", - "version": "2.7.1", + "version": "2.8.0", "license": "MIT", "devDependencies": { "@types/node": "^22.19.15", diff --git a/package.json b/package.json index a63c439..cfa7f91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sudomock", - "version": "2.7.1", + "version": "2.8.0", "description": "Official Node.js/TypeScript SDK for the SudoMock API - mockup generation from PSD files", "type": "module", "main": "./dist/index.cjs", diff --git a/src/index.ts b/src/index.ts index b144ba5..271a39e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -227,6 +227,7 @@ export type { SubscriptionInfo, UsageInfo, ApiKeyInfo, + OrganizationInfo, CreateSessionParams, SessionResult, StudioSessionUi, diff --git a/src/resources/account.ts b/src/resources/account.ts index bdb1942..1411302 100644 --- a/src/resources/account.ts +++ b/src/resources/account.ts @@ -71,6 +71,16 @@ export class AccountResource { lastUsedAt: result.apiKey.lastUsedAt, totalRequests: result.apiKey.totalRequests, }, + // Same allowlist rule as `usage` above: without this block the API's + // `organization` is dropped without a trace. Left out, not defaulted, + // when the API does not send it, so the optional type stays honest + // against a deployment that predates the field. + ...(result.organization && { + organization: { + id: result.organization.id, + name: result.organization.name, + }, + }), } } } diff --git a/src/types.ts b/src/types.ts index f204312..476427d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1199,11 +1199,24 @@ export interface ApiKeyInfo { totalRequests: number } +export interface OrganizationInfo { + /** Organization UUID. */ + id: string + name: string +} + export interface AccountResult { account: AccountInfo subscription: SubscriptionInfo usage: UsageInfo apiKey: ApiKeyInfo + /** + * The organization the API key belongs to. The plan, the credits and the + * prepaid balance on this result are that organization's. + * + * Optional: check it before reading `id` or `name`. + */ + organization?: OrganizationInfo } // --------------------------------------------------------------------------- diff --git a/tests/client.test.ts b/tests/client.test.ts index 901866d..855c912 100644 --- a/tests/client.test.ts +++ b/tests/client.test.ts @@ -10,7 +10,12 @@ import { ConnectionError, TimeoutError, } from '../src/errors' -import { TEST_API_KEY, TEST_BASE_URL, server } from './setup' +import { + MOCK_ACCOUNT_RESPONSE, + TEST_API_KEY, + TEST_BASE_URL, + server, +} from './setup' function createClient(overrides: Record = {}) { return new SudoMock(TEST_API_KEY, { baseUrl: TEST_BASE_URL, ...overrides }) @@ -348,6 +353,38 @@ describe('case conversion', () => { }) }) +// --------------------------------------------------------------------------- +// Account allowlist +// --------------------------------------------------------------------------- + +describe('account', () => { + // account.get() rebuilds the response key by key, so a block the map does not + // name vanishes without an error. That shipped once (CHANGELOG 2.5.1). + it('surfaces organization when the API sends it', async () => { + server.use( + http.get(`${TEST_BASE_URL}/api/v1/me`, () => + HttpResponse.json({ + ...MOCK_ACCOUNT_RESPONSE, + data: { + ...MOCK_ACCOUNT_RESPONSE.data, + organization: { + id: '55555555-5555-5555-5555-555555555555', + name: 'Test Organization', + private_state: 'internal', + }, + }, + }), + ), + ) + + const result = await createClient().account.get() + expect(result.organization).toEqual({ + id: '55555555-5555-5555-5555-555555555555', + name: 'Test Organization', + }) + }) +}) + // --------------------------------------------------------------------------- // Error hierarchy // ---------------------------------------------------------------------------