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