Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion plugins/mobile-apps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This template is an Expo, React Native, and TypeScript starter for building a st

## Requirements

- Node.js 22 LTS.
- Node.js 24 LTS.
- npm 10 or newer.
- The Power Apps Developer app from the Apple App Store or Google Play.

Expand Down Expand Up @@ -78,6 +78,18 @@ connector wiring.
environment-specific page and writes the pasted client ID to
`auth.config.json`.

### Required API permissions

The Microsoft Entra app registration requires these delegated permissions
from the **Power Platform API**:

Comment thread
ameyaapte1 marked this conversation as resolved.
- `PowerApps.Apps.Play`
- `PowerApps.Apps.Read`
- `Connectivity.Connectors.Read`
- `Connectivity.Connections.Read`
- `Connectivity.Connections.Write`
- `Connectivity.Connections.UserConsent`

5. Start mobile app:

Run the below command in a new terminal from the app directory.
Expand All @@ -98,6 +110,33 @@ This template is provided under the license in `LICENSE`.

The mobile-app plugin is stored in `plugins/mobile-apps` in the `power-platform-skills` marketplace. It works with GitHub Copilot in VS Code and Claude Code.

## Manual migration to a new template

To migrate without `upgrade-template`, create a new app from the latest template
instead of modifying the old app in place. Commit or back up the old app first.

1. Create the new app and install its dependencies.
2. Copy the contents of `app/` and `src/` from the old app into the same
directories in the new app:

```bash
cp -R ../old-app/app/. app/
cp -R ../old-app/src/. src/
```

3. Copy app-owned assets and settings such as `assets/`, `auth.config.json`,
`power.config.json`, and `offline-profile.json` as needed. Review each file
before replacing the version supplied by the new template.
4. Keep the new template's `package.json`, root configuration files,
`android/`, and `ios/`. Reapply old customizations selectively rather than
copying these files wholesale.
5. Run `npm install`, `npm run type-check`, and the bundle command for each
target platform, such as `npm run bundle:android` or `npm run bundle:ios`.
6. Give the resulting errors to GitHub Copilot in Agent mode and ask it to
update the migrated `app/` and `src/` code for the new template APIs while
preserving the new template configuration. Review the changes and rerun the
failing command until the build succeeds.

## Hello world — your first run

After the prereq sanity check passes:
Expand Down
4 changes: 1 addition & 3 deletions plugins/mobile-apps/template/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ web-build/
.env
.env*.local

# ── Wrap build config (contains secrets — never commit) ──────────────────────
wrap.config.json

# ── Build output / vendor ────────────────────────────────────────────────────
Comment thread
ameyaapte1 marked this conversation as resolved.
vendor/
Expand All @@ -32,7 +30,7 @@ ios/
# ── Auto-generated files ─────────────────────────────────────────────────────
# Generated by scripts/generate-connector-schemas.js.
src/generated/connectorSchemas.ts
power.config.json
.powernative/

# ── Vendor tarballs are committed intentionally — do NOT ignore ───────────────
# vendor/*.tgz
Expand Down
4 changes: 0 additions & 4 deletions plugins/mobile-apps/template/.powerapps-native/version.json

This file was deleted.

4 changes: 2 additions & 2 deletions plugins/mobile-apps/template/CUSTOMIZATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ In `app.config.js`, use `CUSTOMER APP SETTINGS` for app identity, package names,
icon, and version defaults. Use `CUSTOMIZATION` for additional Expo config
overrides.

Do not edit, move, or delete `.powerapps-native/version.json`. It records which
template upgrades have been applied.
Do not edit or delete `expo.extra.powerappsNative` in `app.json`. It records
which template upgrades have been applied.

The upgrader does not change `android/` or `ios/`. If you maintain native
projects, update them separately when required.
Expand Down
46 changes: 43 additions & 3 deletions plugins/mobile-apps/template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ iOS, Android, or hosted web app that connects to Power Platform data through

## Requirements

- Node.js 22 LTS.
- Node.js 24 LTS.
- npm 10 or newer.
- The Power Apps Developer app from the Apple App Store or Google Play.

Expand Down Expand Up @@ -82,6 +82,19 @@ connector wiring.
environment-specific page and writes the pasted client ID to
`auth.config.json`.

### Required API permissions

The Microsoft Entra app registration requires these delegated permissions from the **Power Platform API**.
If you create the registration via Power Apps Wrap, it configures these automatically; the list is for reference only.

- `PowerApps.Apps.Play`
- `PowerApps.Apps.Read`
- `Connectivity.Connectors.Read`
- `Connectivity.Connections.Read`
- `Connectivity.Connections.Write`
- `Connectivity.Connections.UserConsent`


5. Start mobile app:

Run the below command in a new terminal from the app directory.
Expand Down Expand Up @@ -112,8 +125,8 @@ npx --package @microsoft/power-apps-native-host@latest upgrade-template

Each run upgrades one template version, installs compatible dependencies, and
runs Expo validation. If another version is available, run the command again.
The current version is stored in `.powerapps-native/version.json`; do not edit
this file.
The current version is stored in `app.json` under
`expo.extra.powerappsNative`; do not edit this object.

Apps created before this version file existed must specify their source template
version:
Expand All @@ -130,6 +143,33 @@ for manual resolution. Failed validation restores files managed by the upgrade.
Supported package managers are npm, pnpm, and Bun. See
[CUSTOMIZATION.md](CUSTOMIZATION.md) before changing root configuration files.

### Manual migration to a new template

To migrate without `upgrade-template`, create a new app from the latest template
instead of modifying the old app in place. Commit or back up the old app first.

1. Create the new app and install its dependencies.
2. Copy the contents of `app/` and `src/` from the old app into the same
directories in the new app:

```bash
cp -R ../old-app/app/. app/
cp -R ../old-app/src/. src/
```

3. Copy app-owned assets and settings such as `assets/`, `auth.config.json`,
`power.config.json`, and `offline-profile.json` as needed. Review each file
before replacing the version supplied by the new template.
4. Keep the new template's `package.json`, lock file, root configuration files,
`android/`, and `ios/`. Reapply old customizations selectively rather than
copying these files wholesale.
5. Run `npm install`, `npm run type-check`, and the bundle command for each
target platform, such as `npm run bundle:android` or `npm run bundle:ios`.
6. Give the resulting errors to GitHub Copilot in Agent mode and ask it to
update the migrated `app/` and `src/` code for the new template APIs while
preserving the new template configuration. Review the changes and rerun the
failing command until the build succeeds.

## Web

Start the browser app:
Expand Down
19 changes: 19 additions & 0 deletions plugins/mobile-apps/template/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"expo": {
"extra": {
"telemetry": {
"appInstanceId": null
},
"appInsightsConfig": {
"enabled": false,
"connectionString": "",
"appId": "",
"environment": ""
},
"powerappsNative": {
"schemaVersion": 1,
"templateVersion": 1
}
}
}
}
18 changes: 17 additions & 1 deletion plugins/mobile-apps/template/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,33 @@ import powerConfig from '../power.config.json';
// @ts-ignore - connectorSchemas is auto-generated at build time
import { schemaMap } from '../src/generated/connectorSchemas';

declare const require: (id: string) => unknown;
function isMissingOfflineProfile(error: unknown): boolean {
return error instanceof Error && (
error.message === "Cannot find module '../offline-profile.json'" ||
error.message === 'Cannot find module'
);
}

let offlineProfile: Record<string, unknown> | undefined;
try {
offlineProfile = require('../offline-profile.json') as Record<string, unknown>;
} catch (error: unknown) {
if (!isMissingOfflineProfile(error)) throw error;
Comment thread
ameyaapte1 marked this conversation as resolved.
offlineProfile = undefined;
}

export default function RootLayout() {
return (
<PowerAppsProvider
msalConfig={authConfig.msal}
powerConfig={powerConfig}
schemaMap={schemaMap}
tamaguiConfig={tamaguiConfig}
offlineProfile={offlineProfile}
>
<StatusBar style="auto" />
<Slot />
</PowerAppsProvider>
);
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 13 additions & 9 deletions plugins/mobile-apps/template/metro.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { getDefaultConfig } = require('expo/metro-config');
const { withPowerNativeMetroLogging } = require('@microsoft/power-apps-native-host/metro-logger');

// CUSTOMIZATION START - DO NOT REMOVE OR RENAME THE COMMENT
// Add Metro config changes in this function only.
Expand All @@ -12,15 +13,18 @@ const config = getDefaultConfig(__dirname);
config.resolver.sourceExts = [...config.resolver.sourceExts, 'mjs'];
config.server = {
...config.server,
enhanceMiddleware: (middleware) => (req, res, next) => {
if (req.url === '/__pawrap_verify') {
res.setHeader('Content-Type', 'application/json');
res.setHeader('Access-Control-Allow-Origin', '*');
res.end(JSON.stringify({ type: 'pawrap-app', version: '1' }));
return;
}
middleware(req, res, next);
},
enhanceMiddleware: (middleware) => withPowerNativeMetroLogging(
(req, res, next) => {
if (req.url === '/__pawrap_verify') {
res.setHeader('Content-Type', 'application/json');
res.setHeader('Access-Control-Allow-Origin', '*');
res.end(JSON.stringify({ type: 'pawrap-app', version: '1' }));
return;
}
middleware(req, res, next);
},
{ projectRoot: __dirname },
),
};

// Force a single copy of these regardless of where the importing module lives.
Expand Down
4 changes: 2 additions & 2 deletions plugins/mobile-apps/template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"@expo/metro-runtime": "55.0.11",
"@expo/vector-icons": "15.1.1",
"@microsoft/power-apps": "1.2.7",
"@microsoft/power-apps-native-host": "^0.2.25",
"@microsoft/power-apps-native-offline": "^0.1.3",
"@microsoft/power-apps-native-host": "^0.3.0",
"@microsoft/power-apps-native-offline": "^0.1.32",
"@react-native-async-storage/async-storage": "^2.1.2",
"@react-native-community/datetimepicker": "8.6.0",
"@react-native-community/netinfo": "11.5.2",
Expand Down
Loading