Skip to content

Latest commit

 

History

History
77 lines (71 loc) · 9.33 KB

api-design.md

File metadata and controls

77 lines (71 loc) · 9.33 KB

api-design

Rules

  • Modules must never use export default; every export must be a named symbol. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:40-46 · high · sha:29344ed7df3d
  • index.ts must be the sole barrel re-exporting a package's public surface; every other module is an implementation detail free to move, rename, or split. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:53-57 · high · sha:29344ed7df3d
  • A package should have one barrel per feature folder, not per directory, since deep barrel chains create import cycles and defeat tree-shaking. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:58-58 · high · sha:29344ed7df3d
  • Functions should accept the narrowest interface describing only the members they actually use (consumer-defined interfaces), rather than a wide concrete class. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:81-86 · high · sha:29344ed7df3d
  • Functions must return the concrete, fully-specified, readonly type, never a wide unknown or a bare interface where a concrete readonly type is known. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:86-86 · high · sha:29344ed7df3d
  • Optional parameters must be collected into a single options object rather than a positional list past two parameters. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:94-97 · high · sha:29344ed7df3d
  • Each option's default value must live in exactly one place (the implementation) and be documented on the option field with a @default TSDoc tag. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:98-98 · high · sha:29344ed7df3d
  • The whole options object and every field within it must be optional and readonly, so a zero-config call works and a caller can override one field without restating the rest. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:99-99 · high · sha:29344ed7df3d
  • Parallel operations on a resource (e.g. getUser, listUsers, createUser) must share the same verb taxonomy, parameter order (resource argument first, options object last), and cancellation field name (signal). styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:112-116 · high · sha:29344ed7df3d
  • Parallel return shapes must match the operation semantics: get returns one item, list enumerates many, create returns the created item. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:116-116 · high · sha:29344ed7df3d
  • Divergence from the established API family pattern must be a deliberate, documented exception, not an accident of who wrote which method. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:116-116 · high · sha:29344ed7df3d
  • Data crossing an external boundary (a fetch response, a request body, a queue message) must be parsed into a domain type via a zod schema before interior code touches it. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:125-128 · high · sha:29344ed7df3d
  • The TypeScript type for wire data must be derived from the schema via z.infer, never hand-written alongside the schema, because a separately maintained type and schema silently drift. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:129-129 · high · sha:29344ed7df3d
  • A zod schema must be parsed once at the boundary where the data enters, with downstream code consuming the inferred type without re-validation. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:130-130 · high · sha:29344ed7df3d
  • .readonly() must be called on a zod schema so the parsed value is frozen at runtime and z.infer yields a readonly type, with no separate Readonly<> wrapper needed. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:130-130 · high · sha:29344ed7df3d
  • Every public operation must declare its failure modes with a @throws tag per catchable error type or a Result<T, E> return type, and must accept cancellation via a { signal }: AbortSignal option threaded to the underlying I/O. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:141-146 · high · sha:29344ed7df3d
  • A public symbol slated for removal must first be marked @deprecated, kept working as a thin shim for one major release cycle, then deleted. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:158-161 · high · sha:29344ed7df3d
  • A @deprecated tag must name a specific migration path (the replacement symbol) and the version in which the symbol will be removed. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:162-162 · high · sha:29344ed7df3d
  • A result set that could be large or unbounded must be returned as an AsyncIterable<T> rather than an eagerly materialized array. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:173-176 · high · sha:29344ed7df3d
  • Pagination logic (continuation-token plumbing) must live inside the async generator, hidden from the caller, which fetches the next page only when the consumer has drained the current one. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:177-177 · high · sha:29344ed7df3d
  • An AsyncIterable-returning operation must thread { signal } cancellation like every other operation so an abort stops the in-flight page fetch and the for await loop. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:178-178 · high · sha:29344ed7df3d
  • A streaming operation's public signature must declare the return type as AsyncIterable<T>, not a concrete generator type, so the implementation is free to change. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:178-178 · high · sha:29344ed7df3d

Constraints

  • import/no-default-export (from the gts baseline) enforces named-only exports and is allowed only where a framework demands a default export (e.g. a route module), confined to those files. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:51-51 · high · sha:29344ed7df3d
  • max-params 3 forces the use of an options object for functions with more than a couple of parameters. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:110-110 · high · sha:29344ed7df3d

Conclusions

  • New helpers, types, and classes default to unexported (private) status and are promoted into the barrel only once an outside caller genuinely needs them, because every export is a permanent contract that is expensive to remove once shipped. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:68-73 · high · sha:29344ed7df3d
  • Result is preferred over @throws for public API failure documentation because it cannot drift from the implementation, whereas a @throws comment can. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:145-145 · high · sha:29344ed7df3d

Reference

  • A package's public API is a contract kept for every caller, in every refactor, until a major version allows breaking it. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:3-3 · high · sha:29344ed7df3d
  • A default export has no canonical name at the import site, so each caller can invent a different local name for the same symbol. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:43-43 · high · sha:29344ed7df3d
  • A symbol marked export in a non-barrel module but never re-exported from index.ts is private to the package, even though TypeScript itself does not enforce that privacy. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:57-57 · high · sha:29344ed7df3d
  • The package.json exports field is the hard wall that makes import 'pkg/internal/x' fail to resolve, detailed separately in the Bun guide's build chapter. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:58-58 · high · sha:29344ed7df3d
  • The consumer-defined-interfaces input pattern is ported from Kotlin style guide chapter 10.2. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:85-85 · high · sha:29344ed7df3d
  • Removing or renaming a public symbol, narrowing a parameter type, or changing return semantics is a breaking change requiring a MAJOR semver bump; a new optional option or method is MINOR; a contract-preserving bug fix is PATCH. styleguide · /home/mohammad/Projects/dexpace/styleguide/typescript/10-api-design.md:163-163 · high · sha:29344ed7df3d

Conflicts

Superseded