docs/react-v9/contributing/rfcs/shared/build-system/package-public-api.md
@hotell
We want to control which parts of API surface of our packages are being exposed to public.
During v9 pre-release phase we ran into various situation where we didn't want to propagate APIs as ready to go, thus we established _unstable identifiers naming suffix to mark those as unstable. To complement this approach we also introduced */unstable deep imports for API's that are not STABLE. This works to some extent but fails short as it's a manual work that is not checked by automation. This led to scenarios that we unintentionally exposed INTERNAL apis to public which led to breaking changes which we want to avoid at all costs as we follow proper semver.
We expose all APIs of our packages as a PUBLIC from barrel files (src/index.ts) to consumers, which introduces problems as we can expose apis that were supposed to be used only internally within our repo or only be available in particular pre-release stage (ALPHA/BETA versions).
We want to provide style guide/common approach how to annotate package APIs with proper ACCESS modifiers which will be processed/verified by tooling automation.
Note that our approach will be applied only on Type Declaration emit level as we consider TypeScript surface as only source of truth for our package APIs.
This means that if users use only vanilla JavaScript nothing will stop them from using those API's - as we don't support that kind of usage users take the risk that things may/will break for them unfortunately and also they will not get any support from our side.
@internalIt indicates that an API item is meant only for usage by other NPM packages from the same repo. Third parties should never use “internal” APIs.
/unstable API surface.Example:
// @filename package-a/src/index.ts
/**
*
* @internal
*/
export function doSomething(): void {}
export function hello(): void {}
↓↓ transforms to ↓↓
// @filename package-a/dist/index.d.ts
export declare function hello(): void;
@alphaIt indicates that an API item is eventually intended to be public, but currently is in an early stage of development
/unstable API surface/unstable API surface.Example:
// @filename package-a/src/unstable/index.ts
/**
*
* @alpha
*/
export function doSomething(): void {}
export function hello(): void {}
↓↓ transforms to ↓↓
// @filename package-a/dist/unstable.d.ts
export function doSomething(): void;
export declare function hello(): void;
// @filename package-a/src/index.ts
// 🚨🚨🚨 NOTE THAT THIS IS PROBABLY A MISTAKE BUT TOOLING WILL COVER YOU
/**
*
* @alpha
*/
export function doSomething(): void {}
/**
*
* @public
*/
export function hello(): void {}
↓↓ transforms to ↓↓
// @filename package-a/dist/index.d.ts
export declare function hello(): void;
@betaIt indicates that an API item has been released as a preview or for experimental purposes. Third parties are encouraged to try it and provide feedback. However, a “beta” API should NOT be used in production, because it may be changed or removed in a future version.
/unstable API surface/unstable API surface.Example:
// @filename package-a/src/unstable/index.ts
/**
*
* @beta
*/
export function doSomething(): void {}
export function hello(): void {}
↓↓ transforms to ↓↓
// @filename package-a/dist/unstable.d.ts
export function doSomething(): void;
export declare function hello(): void;
// @filename package-a/src/index.ts
// 🚨🚨🚨 NOTE THAT THIS IS PROBABLY A MISTAKE BUT TOOLING WILL COVER YOU
/**
*
* @beta
*/
export function doSomething(): void {}
/**
*
* @public
*/
export function hello(): void {}
↓↓ transforms to ↓↓
// @filename package-a/dist/index.d.ts
export declare function hello(): void;
@publicIt indicates that an API item has been officially released, and is now part of the supported contract for a package. Semver versioning is used and enforced thus the API signature cannot be changed without a MAJOR version increment.
/unstable API surfaceExample:
// @filename package-a/src/index.ts
/**
*
* @internal
*/
export function doSomething(): void {}
/**
*
* @public
*/
export function hello(): void {}
↓↓ transforms to ↓↓
// @filename package-a/dist/index.d.ts
export declare function hello(): void;
Access modifiers introduced in this document will create following package API patterns:
graph TD
A["@alpha,@beta"] -- access from path --> U["@fluentui/package-name/unstable"]
B["@public"] -- access from path --> S["@fluentui/package-name"]
C["@internal"] -- access from path --> E((X))
/unstable api to be shipped in consuming package as stable APITo follow all release stage types we should support also @rc annotation for "release candidate".
Even better, to simplify differentiation between stable and unstable we would like to introduce @unstable annotation that would replace @alpha/@beta/@rc as from API access perspective there isn't any native JS tooling yet that would notify all consumers that they are using alpha/beta/rc APIs. For that reason we will go with unstable subpath and @unstable annotation for better tooling automation within our codebase.
_unstable suffix for identifiers ?
@internal apis with _ ? (problematic with react hooks)
Pros:
Cons:
generate api for all package dependencies within repo to be able to generate api report and catch api issues