import { describe, expect, it } from 'vitest' import type { Price, UpdateMeterRequest } from '../src/index.js' // The package root must resolve operation-alias names to the operation envelope, // not to a raw domain model that shares the name. 18 names used to collide, and // the explicit model re-export in index.ts silently shadowed the operation alias // (ESM named exports win over `export type *`) with an incompatible shape — // e.g. `UpdateMeterRequest` resolved to the bare update body, missing `meterId`. // Checked at compile time by the tests typecheck; the runtime test only anchors // the file in the suite. type _UpdateMeterRequestIsEnvelope = UpdateMeterRequest extends { meterId: string body: unknown } ? true : { __error: 'UpdateMeterRequest lost its operation envelope shape' } const _updateMeterRequestIsEnvelope: _UpdateMeterRequestIsEnvelope = true // `Price` is a TypeSpec named union (`@discriminated union Price { free: ..., // flat: ..., ... }`); before the emitter aliased named unions to a `types.ts` // declaration, only its expansion (`PriceFree | PriceFlat | ...`) was // reachable at each use site, so `Price` itself could not be imported, // annotated, or narrowed by a standalone function. This narrows the imported // alias by its discriminator and reads a variant-specific field, so a // regression that inlines the union again (or drops the alias export) fails // to compile. function priceAmount(price: Price): string | number { switch (price.type) { case 'free': return 0 case 'flat': case 'unit': return price.amount case 'graduated': case 'volume': return price.tiers.length } } describe('package-root type exports', () => { it('resolves formerly colliding names to the operation envelope', () => { expect(_updateMeterRequestIsEnvelope).toBe(true) }) it('imports and narrows the named union alias Price', () => { const free: Price = { type: 'free' } const flat: Price = { type: 'flat', amount: '10' } expect(priceAmount(free)).toBe(0) expect(priceAmount(flat)).toBe('10') }) })