@microsoft/power-apps-native-extension-sdk
v0.4.2
Published
Power Apps Native Extension SDK — the INativeExtension contract every Power Apps native extension implements. Pre-stable; graduates to 1.0.0 once the contract is proven stable across the first controls.
Readme
@microsoft/power-apps-native-extension-sdk
The contract package for Power Apps native extensions on iOS and Android.
Status: Pre-stable —
0.4.0. The contract may change in0.xminor bumps while it is validated against the first controls. It graduates to1.0.0with a stability commitment once the contract is proven. See VERSIONING.md for the rules, CHANGELOG.md for the history. Part of the native extensions monorepo — see the root README.
What is this package?
A Power Apps native extension lets a Canvas app reach native device capabilities (PDF rendering, camera, sensors, hardware SDKs) that the WebView alone cannot touch. Every native extension implements the INativeExtension interface from this package. The Power Apps Mobile (PAM) host's MessageReceiverOrchestrator dispatches messages from the Canvas WebView (via the CordovaV2 bridge) to the matching extension by looking up name.
This package contains only TypeScript type declarations. There is no runtime code. It is the contract between extension authors and the PAM host.
Who installs it?
| Consumer | Reason |
|---|---|
| Each control's extension package (@microsoft/power-apps-native-pdf-viewer, etc.) | Implements INativeExtension, types its versionInfo, types the parameters of handleMessageAsync |
| PAM HostingSDK | Stores Map<string, INativeExtension>, dispatches by name, types the orchestrator's calls |
Both sides depend on the same package — the contract is the same shape on both sides at compile time.
Install
pnpm add @microsoft/power-apps-native-extension-sdkThe package is published to the Microsoft internal Azure Artifacts feed (PowerApps-Client). Authentication is required for pnpm install.
Quick example
import {
IExtensionVersionInfo,
INativeExtension,
INativeExtensionContext,
INativeOperation,
} from '@microsoft/power-apps-native-extension-sdk';
export default class HelloWorldExtension implements INativeExtension {
public readonly name = 'HelloWorld';
public readonly versionInfo: IExtensionVersionInfo = {
version: '1.0.0',
minAppSdkVersion: '0.1.0',
};
constructor(_context: INativeExtensionContext) {}
public async handleMessageAsync(
message: string,
_operation: INativeOperation,
): Promise<string> {
const { name } = JSON.parse(message);
return JSON.stringify({ greeting: `Hello, ${name}!` });
}
}For a full walkthrough — building the iOS and Android native modules that pair with the TypeScript extension, wiring the Companion PCF, and running end-to-end through PAM — see an existing control under controls/ (e.g. the PDF Viewer) as a worked example.
API surface
Five exported types, all in src/index.ts:
| Type | Purpose |
|---|---|
| INativeExtension | The contract every extension implements |
| IExtensionVersionInfo | { version, minAppSdkVersion } — the shape of the versionInfo field |
| INativeOperation | Handle to an in-flight operation; supports streaming updates and follow-up messages |
| INativeExtensionContext | Host capabilities passed to each extension at construction time |
| INativeExtensionConstructor | Constructor signature for extension classes |
Each type has full TSDoc; hover over imports in your editor to see contracts at write time.
Development
pnpm install
pnpm run build # tsc → ./lib
pnpm run lint # eslint
pnpm run test # type-level fixtures via tsc --noEmitThe package has zero runtime code — pnpm run build produces lib/index.d.ts (declarations) and a near-empty lib/index.js.
Type tests
Fixtures live in tests/fixtures/. Negative cases use @ts-expect-error directives — if a broken case ever becomes valid (e.g. the contract is loosened), tsc flags the directive as "unused" and the test fails loudly. This catches unintentional contract weakening at PR time.
CI and publish
CI is the monorepo Azure DevOps pipeline (pipelines/ci.yml at the repo root). It builds/tests the whole workspace and, on main, publishes any package whose version isn't already on the feed.
To release a new version: bump version in package.json and merge to main — the pipeline publishes it automatically. See the root README for the full flow.
Contributing
This is a Microsoft-internal package. The contract is intentionally minimal — keep additions backward-compatible and follow VERSIONING.md before proposing changes.
When adding methods (only allowed pre-1.0 or as ?: optional post-1.0), follow VERSIONING.md.
