@microsoft/power-apps-native-host 0.2.22 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +162 -26
- package/compatibility/current.json +87 -0
- package/lib/NOTICE.txt +140 -1226
- package/lib/commonjs/auth/AuthContext.js +74 -18
- package/lib/commonjs/auth/AuthContext.web.js +32 -0
- package/lib/commonjs/auth/completePowerAppsAuthSession.js +16 -0
- package/lib/commonjs/bridge/NativePowerAppsBridge.js +20 -17
- package/lib/commonjs/bridge/PowerPagesBridge.js +157 -0
- package/lib/commonjs/bridge/bridgeState.js +40 -0
- package/lib/commonjs/connections/ConnectionSetupScreen.js +459 -80
- package/lib/commonjs/connections/PowerPlatformConnectionApi.js +946 -0
- package/lib/commonjs/connections/connectionMetadata.js +127 -0
- package/lib/commonjs/connections/connectionState.js +96 -0
- package/lib/commonjs/connections/disambiguate.js +19 -11
- package/lib/commonjs/connections/resolveConnections.js +347 -0
- package/lib/commonjs/connections/types.js +106 -0
- package/lib/commonjs/{platform → connections}/useConnectionRefs.js +128 -65
- package/lib/commonjs/connections/useConnectionSetup.js +111 -52
- package/lib/commonjs/controls/FilePicker.js +6 -0
- package/lib/commonjs/controls/ImagePicker.js +8 -0
- package/lib/commonjs/index.js +188 -6
- package/lib/commonjs/logger.js +9 -6
- package/lib/commonjs/offline/createOfflineHostActivationCallbacks.js +61 -0
- package/lib/commonjs/offline/useOfflineIntegration.js +12 -0
- package/lib/commonjs/offline/useOfflineIntegration.web.js +11 -0
- package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.js +46 -0
- package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.web.js +13 -0
- package/lib/commonjs/platform/DataverseDataSources.js +14 -0
- package/lib/commonjs/platform/DataverseGlobalDiscoveryApi.js +49 -0
- package/lib/commonjs/platform/GlobalDiscovery.js +51 -0
- package/lib/commonjs/platform/PowerPlatformEnvironmentApi.js +6 -106
- package/lib/commonjs/provider/PowerAppsHostProvider.js +156 -25
- package/lib/commonjs/provider/PowerAppsHostProvider.web.js +41 -0
- package/lib/commonjs/provider/PowerAppsProvider.js +229 -133
- package/lib/commonjs/provider/SessionDetailsGesture.js +216 -0
- package/lib/commonjs/telemetry/OfflineSdkTelemetry.js +95 -0
- package/lib/commonjs/telemetry/OfflineSdkTelemetry.web.js +9 -0
- package/lib/commonjs/telemetry/index.js +22 -3
- package/lib/module/auth/AuthContext.js +74 -18
- package/lib/module/auth/AuthContext.web.js +26 -0
- package/lib/module/auth/completePowerAppsAuthSession.js +11 -0
- package/lib/module/bridge/NativePowerAppsBridge.js +21 -18
- package/lib/module/bridge/PowerPagesBridge.js +151 -0
- package/lib/module/bridge/bridgeState.js +34 -0
- package/lib/module/connections/ConnectionSetupScreen.js +460 -81
- package/lib/module/connections/PowerPlatformConnectionApi.js +932 -0
- package/lib/module/connections/connectionMetadata.js +112 -0
- package/lib/module/connections/connectionState.js +82 -0
- package/lib/module/connections/disambiguate.js +19 -12
- package/lib/module/connections/resolveConnections.js +342 -0
- package/lib/module/connections/types.js +91 -0
- package/lib/module/{platform → connections}/useConnectionRefs.js +129 -66
- package/lib/module/connections/useConnectionSetup.js +113 -54
- package/lib/module/controls/FilePicker.js +6 -0
- package/lib/module/controls/ImagePicker.js +8 -0
- package/lib/module/index.js +14 -6
- package/lib/module/logger.js +8 -6
- package/lib/module/offline/createOfflineHostActivationCallbacks.js +55 -0
- package/lib/module/offline/useOfflineIntegration.js +3 -0
- package/lib/module/offline/useOfflineIntegration.web.js +7 -0
- package/lib/module/offline/useOfflineIntegrationWithStartupGate.js +42 -0
- package/lib/module/offline/useOfflineIntegrationWithStartupGate.web.js +9 -0
- package/lib/module/platform/DataverseDataSources.js +10 -0
- package/lib/module/platform/DataverseGlobalDiscoveryApi.js +45 -0
- package/lib/module/platform/GlobalDiscovery.js +45 -0
- package/lib/module/platform/PowerPlatformEnvironmentApi.js +5 -104
- package/lib/module/provider/PowerAppsHostProvider.js +159 -28
- package/lib/module/provider/PowerAppsHostProvider.web.js +36 -0
- package/lib/module/provider/PowerAppsProvider.js +233 -137
- package/lib/module/provider/SessionDetailsGesture.js +211 -0
- package/lib/module/telemetry/OfflineSdkTelemetry.js +91 -0
- package/lib/module/telemetry/OfflineSdkTelemetry.web.js +5 -0
- package/lib/module/telemetry/index.js +15 -4
- package/lib/typescript/commonjs/auth/AuthContext.d.ts +3 -1
- package/lib/typescript/commonjs/auth/AuthContext.web.d.ts +21 -0
- package/lib/typescript/commonjs/auth/completePowerAppsAuthSession.d.ts +8 -0
- package/lib/typescript/commonjs/bridge/PowerPagesBridge.d.ts +18 -0
- package/lib/typescript/commonjs/bridge/bridgeState.d.ts +5 -0
- package/lib/typescript/commonjs/connections/ConnectionSetupScreen.d.ts +28 -7
- package/lib/typescript/commonjs/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
- package/lib/typescript/commonjs/connections/connectionMetadata.d.ts +66 -0
- package/lib/typescript/commonjs/connections/connectionState.d.ts +16 -0
- package/lib/typescript/commonjs/connections/disambiguate.d.ts +4 -2
- package/lib/typescript/commonjs/{platform → connections}/resolveConnections.d.ts +19 -19
- package/lib/typescript/commonjs/connections/types.d.ts +129 -1
- package/lib/typescript/commonjs/{platform → connections}/useConnectionRefs.d.ts +33 -24
- package/lib/typescript/commonjs/connections/useConnectionSetup.d.ts +12 -8
- package/lib/typescript/commonjs/controls/FilePicker.d.ts +7 -1
- package/lib/typescript/commonjs/controls/ImagePicker.d.ts +9 -1
- package/lib/typescript/commonjs/index.d.ts +20 -10
- package/lib/typescript/commonjs/logger.d.ts +4 -4
- package/lib/typescript/commonjs/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegration.d.ts +2 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegration.web.d.ts +4 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
- package/lib/typescript/commonjs/platform/DataverseDataSources.d.ts +27 -0
- package/lib/typescript/commonjs/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
- package/lib/typescript/commonjs/platform/GlobalDiscovery.d.ts +4 -0
- package/lib/typescript/commonjs/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
- package/lib/typescript/commonjs/provider/PowerAppsHostProvider.d.ts +29 -18
- package/lib/typescript/commonjs/provider/PowerAppsHostProvider.web.d.ts +5 -0
- package/lib/typescript/commonjs/provider/PowerAppsProvider.d.ts +32 -10
- package/lib/typescript/commonjs/provider/SessionDetailsGesture.d.ts +13 -0
- package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.d.ts +15 -0
- package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
- package/lib/typescript/commonjs/telemetry/index.d.ts +13 -1
- package/lib/typescript/module/auth/AuthContext.d.ts +3 -1
- package/lib/typescript/module/auth/AuthContext.web.d.ts +21 -0
- package/lib/typescript/module/auth/completePowerAppsAuthSession.d.ts +8 -0
- package/lib/typescript/module/bridge/PowerPagesBridge.d.ts +18 -0
- package/lib/typescript/module/bridge/bridgeState.d.ts +5 -0
- package/lib/typescript/module/connections/ConnectionSetupScreen.d.ts +28 -7
- package/lib/typescript/module/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
- package/lib/typescript/module/connections/connectionMetadata.d.ts +66 -0
- package/lib/typescript/module/connections/connectionState.d.ts +16 -0
- package/lib/typescript/module/connections/disambiguate.d.ts +4 -2
- package/lib/typescript/module/{platform → connections}/resolveConnections.d.ts +19 -19
- package/lib/typescript/module/connections/types.d.ts +129 -1
- package/lib/typescript/module/{platform → connections}/useConnectionRefs.d.ts +33 -24
- package/lib/typescript/module/connections/useConnectionSetup.d.ts +12 -8
- package/lib/typescript/module/controls/FilePicker.d.ts +7 -1
- package/lib/typescript/module/controls/ImagePicker.d.ts +9 -1
- package/lib/typescript/module/index.d.ts +24 -14
- package/lib/typescript/module/logger.d.ts +4 -4
- package/lib/typescript/module/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
- package/lib/typescript/module/offline/useOfflineIntegration.d.ts +2 -0
- package/lib/typescript/module/offline/useOfflineIntegration.web.d.ts +4 -0
- package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
- package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
- package/lib/typescript/module/platform/DataverseDataSources.d.ts +27 -0
- package/lib/typescript/module/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
- package/lib/typescript/module/platform/GlobalDiscovery.d.ts +4 -0
- package/lib/typescript/module/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
- package/lib/typescript/module/provider/PowerAppsHostProvider.d.ts +29 -18
- package/lib/typescript/module/provider/PowerAppsHostProvider.web.d.ts +5 -0
- package/lib/typescript/module/provider/PowerAppsProvider.d.ts +34 -12
- package/lib/typescript/module/provider/SessionDetailsGesture.d.ts +13 -0
- package/lib/typescript/module/telemetry/OfflineSdkTelemetry.d.ts +15 -0
- package/lib/typescript/module/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
- package/lib/typescript/module/telemetry/index.d.ts +13 -1
- package/package.json +43 -18
- package/scripts/build-ios-base.js +66 -27
- package/scripts/bundle.js +212 -5
- package/scripts/generate-connector-schemas.js +8 -6
- package/scripts/metro-logger.js +213 -0
- package/scripts/start-web.mjs +137 -0
- package/scripts/upgrade/runtime.js +463 -0
- package/scripts/upgrade/system.js +244 -0
- package/scripts/upgrade-authoring.js +534 -0
- package/scripts/upgrade.js +188 -0
- package/scripts/wrap.js +536 -0
- package/lib/commonjs/platform/PowerPlatformConnectionApi.js +0 -606
- package/lib/commonjs/platform/resolveConnections.js +0 -264
- package/lib/module/platform/PowerPlatformConnectionApi.js +0 -595
- package/lib/module/platform/resolveConnections.js +0 -259
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Power Apps canvas app inside an Expo shell:
|
|
8
8
|
*
|
|
9
9
|
* GestureHandlerRootView
|
|
10
|
-
* └── TamaguiProvider (defaults to @tamagui/config/
|
|
10
|
+
* └── TamaguiProvider (defaults to @tamagui/config/v5)
|
|
11
11
|
* └── PortalProvider (required by ToastViewport)
|
|
12
12
|
* └── ToastProvider + ToastViewport
|
|
13
13
|
* └── QueryClientProvider (own QueryClient, wired to NetInfo + AppState)
|
|
@@ -27,24 +27,28 @@
|
|
|
27
27
|
* </PowerAppsProvider>
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import React, {
|
|
31
|
-
import { AppState, Platform } from 'react-native';
|
|
30
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
31
|
+
import { AppState, Platform, ScrollView, StyleSheet, Text } from 'react-native';
|
|
32
32
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
33
33
|
import { createTamagui, TamaguiProvider } from '@tamagui/core';
|
|
34
34
|
import { PortalProvider } from '@tamagui/portal';
|
|
35
|
-
import {
|
|
35
|
+
import { defaultConfig as tamaguiDefaultConfig } from '@tamagui/config/v5';
|
|
36
36
|
import { ToastProvider, ToastViewport } from '@tamagui/toast';
|
|
37
|
-
import {
|
|
37
|
+
import { QueryClientProvider, focusManager, onlineManager } from '@tanstack/react-query';
|
|
38
38
|
import NetInfo from '@react-native-community/netinfo';
|
|
39
|
-
import { AuthProvider, useAuth } from
|
|
40
|
-
import { PowerAppsHostProvider } from
|
|
41
|
-
import {
|
|
39
|
+
import { AuthProvider, useAuth } from '../auth/AuthContext';
|
|
40
|
+
import { PowerAppsHostProvider } from './PowerAppsHostProvider';
|
|
41
|
+
import { powerPlatformScope } from "../platform/PowerPlatformEnvironmentApi.js";
|
|
42
42
|
import { ThemeProvider } from "../theme/ThemeProvider.js";
|
|
43
43
|
import { ErrorBoundary } from "../ErrorBoundary.js";
|
|
44
|
+
import { isDevPlayer } from "../utils/isDevPlayer.js";
|
|
44
45
|
import Constants from 'expo-constants';
|
|
45
|
-
import { configureAppLogger, getAppLogger, Logger, OneDsTelemetryProvider, resolveDeviceId, resolveTelemetryLocation, regionToClusterCategory, suppressKnownWarnings } from '@microsoft/power-apps-native-common';
|
|
46
|
+
import { ApplicationInsightsTelemetryProvider, configureAppLogger, configureCustomerTelemetryLogger, getAppLogger, Logger, OneDsTelemetryProvider, resolveDeviceId, resolveTelemetryLocation, regionToClusterCategory, suppressKnownWarnings } from '@microsoft/power-apps-native-common';
|
|
46
47
|
suppressKnownWarnings();
|
|
47
|
-
import {
|
|
48
|
+
import { createHostQueryClient } from "../offline/createOfflineHostActivationCallbacks.js";
|
|
49
|
+
import { useOfflineIntegrationWithStartupGate } from '../offline/useOfflineIntegrationWithStartupGate';
|
|
50
|
+
import { SessionDetailsGesture } from "./SessionDetailsGesture.js";
|
|
51
|
+
import { configureOfflineSdkTelemetry } from '../telemetry/OfflineSdkTelemetry';
|
|
48
52
|
|
|
49
53
|
// ---- React-Query wiring (runs once at module load) ----
|
|
50
54
|
|
|
@@ -52,6 +56,15 @@ import { useOfflineIntegration } from '@microsoft/power-apps-native-offline';
|
|
|
52
56
|
// (the default browser-event-based detection is a no-op in React Native).
|
|
53
57
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
54
58
|
onlineManager.setEventListener(setOnline => {
|
|
59
|
+
if (Platform.OS === 'web' && typeof window !== 'undefined') {
|
|
60
|
+
const updateOnlineState = () => setOnline(window.navigator.onLine);
|
|
61
|
+
window.addEventListener('online', updateOnlineState);
|
|
62
|
+
updateOnlineState();
|
|
63
|
+
return () => {
|
|
64
|
+
window.removeEventListener('online', updateOnlineState);
|
|
65
|
+
window.removeEventListener('offline', updateOnlineState);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
55
68
|
return NetInfo.addEventListener(state => setOnline(!!state.isConnected));
|
|
56
69
|
});
|
|
57
70
|
|
|
@@ -67,78 +80,55 @@ focusManager.setEventListener(handleFocus => {
|
|
|
67
80
|
|
|
68
81
|
// The app's tamagui.config.ts (generated by /tamagui-design-system) is always
|
|
69
82
|
// passed as the `tamaguiConfig` prop and owns all $surface* / $accent* tokens.
|
|
70
|
-
// The bare @tamagui/config/
|
|
83
|
+
// The bare @tamagui/config/v5 preset is only a last-resort fallback for tests
|
|
71
84
|
// and storybook — it will not resolve custom $surface* tokens.
|
|
72
85
|
const defaultTamaguiConfig = createTamagui(tamaguiDefaultConfig);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// resolution that @microsoft/power-apps-native-offline's useOfflineIntegration
|
|
76
|
-
// performs (offlineProfile prop → expo manifest `extra.__offlineProfile`;
|
|
77
|
-
// enabled defaults true unless the profile's `appConfig.enabled` is explicitly
|
|
78
|
-
// false), but computed synchronously here because the QueryClient's networkMode
|
|
79
|
-
// must be fixed BEFORE the first query runs. The SDK's own `isEnabled` is only
|
|
80
|
-
// known deep inside the tree (below QueryClientProvider), which is too late to
|
|
81
|
-
// configure the client without a race. Kept deliberately narrow: it only
|
|
82
|
-
// decides networkMode below.
|
|
83
|
-
function isOfflineEnabled(offlineProfile) {
|
|
84
|
-
// Only honour the prop when it carries a profileId — this mirrors the SDK's
|
|
85
|
-
// useOfflineIntegration, which ignores a profileId-less prop and falls through
|
|
86
|
-
// to the manifest. Without this guard a truthy-but-invalid prop (no profileId)
|
|
87
|
-
// short-circuits to `false` here while the SDK still resolves enabled from the
|
|
88
|
-
// manifest, leaving networkMode on 'online' (blank offline lists).
|
|
89
|
-
const propProfile = offlineProfile;
|
|
90
|
-
let profile = propProfile && propProfile.profileId ? propProfile : undefined;
|
|
91
|
-
if (!profile) {
|
|
92
|
-
const fromManifest = Constants.expoConfig?.extra?.__offlineProfile;
|
|
93
|
-
if (fromManifest && typeof fromManifest === 'object' && fromManifest.profileId) {
|
|
94
|
-
profile = fromManifest;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (profile) {
|
|
98
|
-
// Honour an explicit `appConfig.enabled: false`. This mirrors the SDK's
|
|
99
|
-
// useOfflineIntegration, whose validateConfig classifies `enabled === false`
|
|
100
|
-
// as "explicitly-disabled" and stays inert. A host shell's placeholder
|
|
101
|
-
// profile (e.g. Power Apps Dev Player's offline-profile.json, enabled:false)
|
|
102
|
-
// must NOT flip networkMode to 'always' for the loaded app — otherwise every
|
|
103
|
-
// scanned app gets paused queries / blank lists. Any other resolved profile
|
|
104
|
-
// (enabled true, or omitted → SDK defaults to true) enables offline.
|
|
105
|
-
const appConfig = profile.appConfig;
|
|
106
|
-
if (appConfig && appConfig.enabled === false) {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
111
|
-
return false;
|
|
86
|
+
function hasConfiguredValue(value) {
|
|
87
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
112
88
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
89
|
+
function hasEntries(value) {
|
|
90
|
+
return Boolean(value && typeof value === 'object' && Object.keys(value).length > 0);
|
|
91
|
+
}
|
|
92
|
+
function requiresPowerPlatformAuth(powerConfig) {
|
|
93
|
+
return Boolean(hasConfiguredValue(powerConfig.appId) || hasConfiguredValue(powerConfig.environmentId) || hasEntries(powerConfig.connectionReferences) || hasEntries(powerConfig.databaseReferences));
|
|
94
|
+
}
|
|
95
|
+
function MissingClientIdErrorScreen() {
|
|
96
|
+
return /*#__PURE__*/_jsxs(ScrollView, {
|
|
97
|
+
contentContainerStyle: styles.errorContainer,
|
|
98
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
99
|
+
style: styles.errorTitle,
|
|
100
|
+
children: "Missing auth client ID"
|
|
101
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
102
|
+
style: styles.errorBody,
|
|
103
|
+
children: "This app needs Power Platform authentication, but `auth.config.json` does not include `msal.clientId`."
|
|
104
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
105
|
+
style: styles.errorBody,
|
|
106
|
+
children: "Add the Entra app registration client ID to `auth.config.json`, rebuild the app bundle, and run it again in Power Apps Dev Player."
|
|
107
|
+
})]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function MissingAppIdErrorScreen() {
|
|
111
|
+
return /*#__PURE__*/_jsxs(ScrollView, {
|
|
112
|
+
contentContainerStyle: styles.errorContainer,
|
|
113
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
114
|
+
style: styles.errorTitle,
|
|
115
|
+
children: "App ID is missing"
|
|
116
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
117
|
+
style: styles.errorBody,
|
|
118
|
+
children: "This mobile app does not include an app ID. Push the mobile app to the Power Platform environment, rebuild it, and try again."
|
|
119
|
+
})]
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function MissingEnvironmentIdErrorScreen() {
|
|
123
|
+
return /*#__PURE__*/_jsxs(ScrollView, {
|
|
124
|
+
contentContainerStyle: styles.errorContainer,
|
|
125
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
126
|
+
style: styles.errorTitle,
|
|
127
|
+
children: "Environment ID is missing"
|
|
128
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
129
|
+
style: styles.errorBody,
|
|
130
|
+
children: "This mobile app does not include an environment ID. Push the mobile app to the Power Platform environment, rebuild it, and try again."
|
|
131
|
+
})]
|
|
142
132
|
});
|
|
143
133
|
}
|
|
144
134
|
|
|
@@ -146,6 +136,29 @@ function createQueryClient(offlineEnabled) {
|
|
|
146
136
|
|
|
147
137
|
/** Shape of power.config.json consumed by the provider. */
|
|
148
138
|
|
|
139
|
+
function readAppInsightsConfig(value) {
|
|
140
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
141
|
+
const config = value;
|
|
142
|
+
const minSeverity = config.minSeverity;
|
|
143
|
+
return {
|
|
144
|
+
enabled: config.enabled === true,
|
|
145
|
+
connectionString: typeof config.connectionString === 'string' ? config.connectionString : '',
|
|
146
|
+
appId: typeof config.appId === 'string' ? config.appId : '',
|
|
147
|
+
...(typeof config.appVersion === 'string' ? {
|
|
148
|
+
appVersion: config.appVersion
|
|
149
|
+
} : {}),
|
|
150
|
+
...(typeof config.environment === 'string' ? {
|
|
151
|
+
environment: config.environment
|
|
152
|
+
} : {}),
|
|
153
|
+
...(minSeverity === 'verbose' || minSeverity === 'info' || minSeverity === 'warning' || minSeverity === 'error' ? {
|
|
154
|
+
minSeverity
|
|
155
|
+
} : {}),
|
|
156
|
+
...(typeof config.includeUserId === 'boolean' ? {
|
|
157
|
+
includeUserId: config.includeUserId
|
|
158
|
+
} : {})
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
149
162
|
// ---- Inner component ----
|
|
150
163
|
// Separate from PowerAppsProvider only because useAuth() must be called inside
|
|
151
164
|
// AuthProvider. All auth-dependent wiring lives here.
|
|
@@ -156,53 +169,49 @@ function InnerProviders({
|
|
|
156
169
|
schemaMap,
|
|
157
170
|
renderOAuthWebView,
|
|
158
171
|
onDisambiguationNeeded,
|
|
172
|
+
onConnectionConsent,
|
|
173
|
+
onResourceConsent,
|
|
174
|
+
onConnectionConsentDeclined,
|
|
159
175
|
offlineProfile,
|
|
176
|
+
onOfflineEnabledChange,
|
|
160
177
|
children
|
|
161
178
|
}) {
|
|
162
179
|
const {
|
|
163
180
|
acquireToken,
|
|
164
181
|
isSignedIn,
|
|
165
|
-
hasRealAccount
|
|
182
|
+
hasRealAccount,
|
|
183
|
+
isAuthReady,
|
|
184
|
+
signOut
|
|
166
185
|
} = useAuth();
|
|
167
|
-
const connectionReferences = useMemo(() => powerConfig.connectionReferences ?? {}, [powerConfig.connectionReferences]);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// Adapter over the host's fetchInstanceUrl: the offline SDK's contract passes a
|
|
171
|
-
// 4th `signal?: AbortSignal` arg (which fetchInstanceUrl treats as bearerToken)
|
|
172
|
-
// and expects a `string | null` return, so drop the extra arg and normalise
|
|
173
|
-
// `undefined` -> `null`.
|
|
174
|
-
const resolveInstanceUrlForOffline = useCallback(async (environmentId, region, acqToken, _signal) => {
|
|
175
|
-
const url = await fetchInstanceUrl(environmentId, region, acqToken);
|
|
176
|
-
return url ?? null;
|
|
177
|
-
}, []);
|
|
178
|
-
|
|
179
|
-
// Gate offline engagement on a REAL account (`hasRealAccount`), not the
|
|
180
|
-
// `isSignedIn` flag — `isSignedIn` is inflated by noAuthMode (login-bypassed /
|
|
181
|
-
// demo sessions report signed-in but have no account, so `acquireToken` always
|
|
182
|
-
// returns null). Passing the inflated flag makes the SDK orchestrator engage
|
|
183
|
-
// and then spin in a perpetual "waiting-for-auth" 3s retry loop (each retry
|
|
184
|
-
// re-renders the provider subtree). With no obtainable token offline cannot
|
|
185
|
-
// sync anyway, so we only engage once a usable token exists.
|
|
186
|
-
const offline = useOfflineIntegration({
|
|
186
|
+
const connectionReferences = useMemo(() => isDevPlayer ? powerConfig.connectionReferences ?? {} : {}, [powerConfig.connectionReferences, isDevPlayer]);
|
|
187
|
+
const runtimeSchemaMap = useMemo(() => isDevPlayer ? schemaMap : {}, [schemaMap, isDevPlayer]);
|
|
188
|
+
const offline = useOfflineIntegrationWithStartupGate({
|
|
187
189
|
powerConfig,
|
|
188
190
|
offlineProfile,
|
|
189
191
|
acquireToken,
|
|
190
|
-
|
|
191
|
-
|
|
192
|
+
hasRealAccount,
|
|
193
|
+
isAuthReady
|
|
192
194
|
});
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
onOfflineEnabledChange(offline.isEnabled);
|
|
197
|
+
}, [offline.isEnabled, onOfflineEnabledChange]);
|
|
193
198
|
return /*#__PURE__*/_jsxs(PowerAppsHostProvider, {
|
|
194
199
|
acquireToken: acquireToken,
|
|
195
200
|
isSignedIn: isSignedIn,
|
|
201
|
+
onSignOut: signOut,
|
|
196
202
|
appId: powerConfig.appId ?? undefined,
|
|
197
203
|
environmentId: powerConfig.environmentId ?? '',
|
|
198
204
|
region: powerConfig.region ?? 'prod',
|
|
199
205
|
connectionReferences: connectionReferences,
|
|
200
|
-
schemaMap:
|
|
201
|
-
databaseReferences: powerConfig.databaseReferences,
|
|
206
|
+
schemaMap: runtimeSchemaMap,
|
|
207
|
+
databaseReferences: isDevPlayer ? powerConfig.databaseReferences : undefined,
|
|
202
208
|
isvClientId: msalConfig.clientId,
|
|
203
209
|
renderOAuthWebView: renderOAuthWebView,
|
|
204
210
|
onDisambiguationNeeded: onDisambiguationNeeded,
|
|
205
|
-
|
|
211
|
+
onConnectionConsent: onConnectionConsent,
|
|
212
|
+
onResourceConsent: onResourceConsent,
|
|
213
|
+
onConnectionConsentDeclined: onConnectionConsentDeclined,
|
|
214
|
+
children: [offline.shouldMountChildren && children, offline.StatusOverlay && /*#__PURE__*/_jsx(offline.StatusOverlay, {})]
|
|
206
215
|
});
|
|
207
216
|
}
|
|
208
217
|
|
|
@@ -229,8 +238,13 @@ export function PowerAppsProvider({
|
|
|
229
238
|
followSystemTheme = true,
|
|
230
239
|
renderOAuthWebView,
|
|
231
240
|
onDisambiguationNeeded,
|
|
241
|
+
onConnectionConsent,
|
|
242
|
+
onResourceConsent,
|
|
243
|
+
onConnectionConsentDeclined,
|
|
232
244
|
appName,
|
|
233
245
|
logger: loggerProp,
|
|
246
|
+
showSessionDetailsOnSwipe = true,
|
|
247
|
+
appInsightsConfig,
|
|
234
248
|
offlineProfile,
|
|
235
249
|
children
|
|
236
250
|
}) {
|
|
@@ -238,13 +252,17 @@ export function PowerAppsProvider({
|
|
|
238
252
|
// is stable (loggerProp is an object reference; re-running on every render
|
|
239
253
|
// would reconfigure and leak the previous provider).
|
|
240
254
|
const loggerPropRef = useRef(loggerProp);
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
const
|
|
255
|
+
const appInsightsConfigRef = useRef(appInsightsConfig ?? readAppInsightsConfig(Constants.expoConfig?.extra?.appInsightsConfig));
|
|
256
|
+
const [offlineTelemetryEnabled, setOfflineTelemetryEnabled] = useState();
|
|
257
|
+
const missingClientIdInDevPlayer = Platform.OS !== 'web' && isDevPlayer && !hasConfiguredValue(msalConfig.clientId) && requiresPowerPlatformAuth(powerConfig);
|
|
258
|
+
const missingAppId = !isDevPlayer && !hasConfiguredValue(powerConfig.appId);
|
|
259
|
+
const missingEnvironmentId = !isDevPlayer && !hasConfiguredValue(powerConfig.environmentId);
|
|
260
|
+
const appId = typeof powerConfig.appId === 'string' ? powerConfig.appId.trim() : '';
|
|
261
|
+
const bundleId = Platform.OS === 'ios' ? Constants.expoConfig?.ios?.bundleIdentifier : Platform.OS === 'android' ? Constants.expoConfig?.android?.package : undefined;
|
|
262
|
+
const appInstanceId = Constants.expoConfig?.extra?.telemetry?.appInstanceId;
|
|
263
|
+
const skillCorrelationId = typeof appInstanceId === 'string' ? appInstanceId.trim() : '';
|
|
264
|
+
const requiredAuthScopes = useMemo(() => [powerPlatformScope(powerConfig.region ?? 'prod')], [powerConfig.region]);
|
|
265
|
+
const queryClient = useMemo(() => createHostQueryClient(), []);
|
|
248
266
|
|
|
249
267
|
// Configure the app logger exactly once per mount inside useEffect so that
|
|
250
268
|
// side effects (provider construction, async resolveDeviceId) never run
|
|
@@ -252,6 +270,9 @@ export function PowerAppsProvider({
|
|
|
252
270
|
// silent no-op Logger, so any telemetry emitted before the first commit is
|
|
253
271
|
// silently dropped rather than crashing.
|
|
254
272
|
useEffect(() => {
|
|
273
|
+
// Customer telemetry is a no-op until a valid Application Insights
|
|
274
|
+
// provider is configured below.
|
|
275
|
+
configureCustomerTelemetryLogger(new Logger());
|
|
255
276
|
const lp = loggerPropRef.current;
|
|
256
277
|
if (lp === null) {
|
|
257
278
|
// Explicit opt-out — replace with a silent no-op Logger.
|
|
@@ -267,26 +288,63 @@ export function PowerAppsProvider({
|
|
|
267
288
|
clientType: appName ?? 'PowerAppsNative',
|
|
268
289
|
appVersion: Constants.expoConfig?.version,
|
|
269
290
|
minSeverity: __DEV__ ? 'verbose' : 'info',
|
|
270
|
-
telemetryLocation: resolveTelemetryLocation(powerConfig.geoRegion)
|
|
291
|
+
telemetryLocation: resolveTelemetryLocation(powerConfig.geoRegion),
|
|
292
|
+
commonProperties: {
|
|
293
|
+
...(appId ? {
|
|
294
|
+
appId
|
|
295
|
+
} : {}),
|
|
296
|
+
...(bundleId ? {
|
|
297
|
+
bundleId
|
|
298
|
+
} : {}),
|
|
299
|
+
...(skillCorrelationId ? {
|
|
300
|
+
skillCorrelationId
|
|
301
|
+
} : {})
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
const configureDefaultLogger = (deviceId = 'react-native') => {
|
|
305
|
+
const oneDsProvider = new OneDsTelemetryProvider({
|
|
306
|
+
...providerConfig,
|
|
307
|
+
deviceId
|
|
308
|
+
});
|
|
309
|
+
const providers = [oneDsProvider];
|
|
310
|
+
let appInsightsEnabled = false;
|
|
311
|
+
const configuredAppInsights = appInsightsConfigRef.current;
|
|
312
|
+
if (configuredAppInsights?.enabled) {
|
|
313
|
+
try {
|
|
314
|
+
const customerProvider = new ApplicationInsightsTelemetryProvider({
|
|
315
|
+
...configuredAppInsights,
|
|
316
|
+
appVersion: configuredAppInsights.appVersion ?? Constants.expoConfig?.version,
|
|
317
|
+
deviceId,
|
|
318
|
+
sessionId: oneDsProvider.sessionId
|
|
319
|
+
});
|
|
320
|
+
providers.push(customerProvider);
|
|
321
|
+
configureCustomerTelemetryLogger(new Logger({
|
|
322
|
+
providers: [customerProvider]
|
|
323
|
+
}));
|
|
324
|
+
appInsightsEnabled = true;
|
|
325
|
+
} catch (error) {
|
|
326
|
+
console.error('[PowerAppsProvider] Application Insights configuration is invalid.', error);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
const logger = new Logger({
|
|
330
|
+
providers
|
|
331
|
+
});
|
|
332
|
+
configureAppLogger(logger);
|
|
333
|
+
if (appInsightsEnabled) {
|
|
334
|
+
logger.trackActivityEvent('PowerAppsNative.ApplicationStarted', {
|
|
335
|
+
app_id: configuredAppInsights?.appId
|
|
336
|
+
});
|
|
337
|
+
}
|
|
271
338
|
};
|
|
272
339
|
// Resolve the stable device ID first so every event — including the
|
|
273
340
|
// very first — carries the real GUID rather than the 'react-native'
|
|
274
341
|
// fallback. Events emitted while this resolves are silently dropped
|
|
275
342
|
// by the no-op Logger that is active until configureAppLogger is called.
|
|
276
343
|
resolveDeviceId().then(deviceId => {
|
|
277
|
-
|
|
278
|
-
...providerConfig,
|
|
279
|
-
deviceId
|
|
280
|
-
});
|
|
281
|
-
configureAppLogger(new Logger({
|
|
282
|
-
providers: [provider]
|
|
283
|
-
}));
|
|
344
|
+
configureDefaultLogger(deviceId);
|
|
284
345
|
}).catch(_err => {
|
|
285
346
|
// SecureStore unavailable — fall back to a provider without a stable ID.
|
|
286
|
-
|
|
287
|
-
configureAppLogger(new Logger({
|
|
288
|
-
providers: [provider]
|
|
289
|
-
}));
|
|
347
|
+
configureDefaultLogger();
|
|
290
348
|
});
|
|
291
349
|
}
|
|
292
350
|
|
|
@@ -299,6 +357,11 @@ export function PowerAppsProvider({
|
|
|
299
357
|
};
|
|
300
358
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
301
359
|
}, []); // intentionally empty — logger is configured once per mount
|
|
360
|
+
|
|
361
|
+
useEffect(() => {
|
|
362
|
+
if (offlineTelemetryEnabled === undefined) return undefined;
|
|
363
|
+
return configureOfflineSdkTelemetry(offlineTelemetryEnabled);
|
|
364
|
+
}, [offlineTelemetryEnabled]);
|
|
302
365
|
return /*#__PURE__*/_jsx(ErrorBoundary, {
|
|
303
366
|
children: /*#__PURE__*/_jsx(GestureHandlerRootView, {
|
|
304
367
|
style: {
|
|
@@ -316,19 +379,32 @@ export function PowerAppsProvider({
|
|
|
316
379
|
children: /*#__PURE__*/_jsxs(ToastProvider, {
|
|
317
380
|
swipeDirection: "horizontal",
|
|
318
381
|
duration: 3000,
|
|
319
|
-
children: [/*#__PURE__*/_jsx(
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
382
|
+
children: [/*#__PURE__*/_jsx(SessionDetailsGesture, {
|
|
383
|
+
enabled: showSessionDetailsOnSwipe,
|
|
384
|
+
appName: appName ?? Constants.expoConfig?.name ?? 'Power Apps',
|
|
385
|
+
appId: appId || undefined,
|
|
386
|
+
environmentId: powerConfig.environmentId,
|
|
387
|
+
region: powerConfig.region ?? 'prod',
|
|
388
|
+
appVersion: Constants.expoConfig?.version,
|
|
389
|
+
children: /*#__PURE__*/_jsx(QueryClientProvider, {
|
|
390
|
+
client: queryClient,
|
|
391
|
+
children: missingAppId ? /*#__PURE__*/_jsx(MissingAppIdErrorScreen, {}) : missingEnvironmentId ? /*#__PURE__*/_jsx(MissingEnvironmentIdErrorScreen, {}) : missingClientIdInDevPlayer ? /*#__PURE__*/_jsx(MissingClientIdErrorScreen, {}) : /*#__PURE__*/_jsx(AuthProvider, {
|
|
325
392
|
msalConfig: msalConfig,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
393
|
+
intuneConfig: intuneConfig,
|
|
394
|
+
requiredScopes: requiredAuthScopes,
|
|
395
|
+
children: /*#__PURE__*/_jsx(InnerProviders, {
|
|
396
|
+
msalConfig: msalConfig,
|
|
397
|
+
powerConfig: powerConfig,
|
|
398
|
+
schemaMap: schemaMap,
|
|
399
|
+
renderOAuthWebView: renderOAuthWebView,
|
|
400
|
+
onDisambiguationNeeded: onDisambiguationNeeded,
|
|
401
|
+
onConnectionConsent: onConnectionConsent,
|
|
402
|
+
onResourceConsent: onResourceConsent,
|
|
403
|
+
onConnectionConsentDeclined: onConnectionConsentDeclined,
|
|
404
|
+
offlineProfile: offlineProfile,
|
|
405
|
+
onOfflineEnabledChange: setOfflineTelemetryEnabled,
|
|
406
|
+
children: children
|
|
407
|
+
})
|
|
332
408
|
})
|
|
333
409
|
})
|
|
334
410
|
}), /*#__PURE__*/_jsx(ToastViewport, {
|
|
@@ -342,4 +418,24 @@ export function PowerAppsProvider({
|
|
|
342
418
|
})
|
|
343
419
|
})
|
|
344
420
|
});
|
|
345
|
-
}
|
|
421
|
+
}
|
|
422
|
+
const styles = StyleSheet.create({
|
|
423
|
+
errorContainer: {
|
|
424
|
+
flexGrow: 1,
|
|
425
|
+
justifyContent: 'center',
|
|
426
|
+
padding: 24,
|
|
427
|
+
backgroundColor: '#F8F8F8'
|
|
428
|
+
},
|
|
429
|
+
errorTitle: {
|
|
430
|
+
color: '#A4262C',
|
|
431
|
+
fontSize: 22,
|
|
432
|
+
fontWeight: '700',
|
|
433
|
+
marginBottom: 12
|
|
434
|
+
},
|
|
435
|
+
errorBody: {
|
|
436
|
+
color: '#323130',
|
|
437
|
+
fontSize: 15,
|
|
438
|
+
lineHeight: 22,
|
|
439
|
+
marginBottom: 10
|
|
440
|
+
}
|
|
441
|
+
});
|