@microsoft/power-apps-native-host 0.2.25 → 0.3.3

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 (154) hide show
  1. package/README.md +21 -10
  2. package/compatibility/current.json +31 -4
  3. package/lib/NOTICE.txt +1325 -24
  4. package/lib/commonjs/auth/AuthContext.js +110 -33
  5. package/lib/commonjs/bridge/NativePowerAppsBridge.js +11 -18
  6. package/lib/commonjs/bridge/PowerPagesBridge.js +27 -8
  7. package/lib/commonjs/bridge/bridgeState.js +40 -0
  8. package/lib/commonjs/config/babelConfig.js +13 -0
  9. package/lib/commonjs/config/expoConfig.js +71 -0
  10. package/lib/commonjs/config/metroConfig.js +70 -0
  11. package/lib/commonjs/config/metroLogger.js +182 -0
  12. package/lib/commonjs/config/tamaguiConfig.js +98 -0
  13. package/lib/commonjs/connections/ConnectionSetupScreen.js +459 -80
  14. package/lib/commonjs/connections/PowerPlatformConnectionApi.js +946 -0
  15. package/lib/commonjs/connections/connectionMetadata.js +127 -0
  16. package/lib/commonjs/connections/connectionState.js +96 -0
  17. package/lib/commonjs/connections/disambiguate.js +19 -11
  18. package/lib/commonjs/connections/resolveConnections.js +348 -0
  19. package/lib/commonjs/connections/types.js +106 -0
  20. package/lib/commonjs/{platform → connections}/useConnectionRefs.js +130 -65
  21. package/lib/commonjs/connections/useConnectionSetup.js +111 -52
  22. package/lib/commonjs/controls/FilePicker.js +6 -0
  23. package/lib/commonjs/controls/ImagePicker.js +8 -0
  24. package/lib/commonjs/index.js +167 -4
  25. package/lib/commonjs/logger.js +9 -6
  26. package/lib/commonjs/offline/createOfflineHostActivationCallbacks.js +61 -0
  27. package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.js +48 -0
  28. package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.web.js +13 -0
  29. package/lib/commonjs/platform/DataverseDataSources.js +18 -0
  30. package/lib/commonjs/platform/DataverseGlobalDiscoveryApi.js +94 -0
  31. package/lib/commonjs/platform/GlobalDiscovery.js +51 -0
  32. package/lib/commonjs/platform/PowerPlatformEnvironmentApi.js +6 -106
  33. package/lib/commonjs/provider/PowerAppsHostProvider.js +157 -25
  34. package/lib/commonjs/provider/PowerAppsProvider.js +178 -134
  35. package/lib/commonjs/provider/SessionDetailsGesture.js +208 -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 +110 -33
  40. package/lib/module/bridge/NativePowerAppsBridge.js +12 -19
  41. package/lib/module/bridge/PowerPagesBridge.js +27 -8
  42. package/lib/module/bridge/bridgeState.js +34 -0
  43. package/lib/module/config/babelConfig.js +9 -0
  44. package/lib/module/config/expoConfig.js +67 -0
  45. package/lib/module/config/metroConfig.js +65 -0
  46. package/lib/module/config/metroLogger.js +175 -0
  47. package/lib/module/config/tamaguiConfig.js +93 -0
  48. package/lib/module/connections/ConnectionSetupScreen.js +460 -81
  49. package/lib/module/connections/PowerPlatformConnectionApi.js +932 -0
  50. package/lib/module/connections/connectionMetadata.js +112 -0
  51. package/lib/module/connections/connectionState.js +82 -0
  52. package/lib/module/connections/disambiguate.js +19 -12
  53. package/lib/module/connections/resolveConnections.js +343 -0
  54. package/lib/module/connections/types.js +91 -0
  55. package/lib/module/{platform → connections}/useConnectionRefs.js +131 -66
  56. package/lib/module/connections/useConnectionSetup.js +113 -54
  57. package/lib/module/controls/FilePicker.js +6 -0
  58. package/lib/module/controls/ImagePicker.js +8 -0
  59. package/lib/module/index.js +14 -4
  60. package/lib/module/logger.js +8 -6
  61. package/lib/module/offline/createOfflineHostActivationCallbacks.js +55 -0
  62. package/lib/module/offline/useOfflineIntegrationWithStartupGate.js +44 -0
  63. package/lib/module/offline/useOfflineIntegrationWithStartupGate.web.js +9 -0
  64. package/lib/module/platform/DataverseDataSources.js +13 -0
  65. package/lib/module/platform/DataverseGlobalDiscoveryApi.js +89 -0
  66. package/lib/module/platform/GlobalDiscovery.js +45 -0
  67. package/lib/module/platform/PowerPlatformEnvironmentApi.js +5 -104
  68. package/lib/module/provider/PowerAppsHostProvider.js +160 -28
  69. package/lib/module/provider/PowerAppsProvider.js +182 -138
  70. package/lib/module/provider/SessionDetailsGesture.js +203 -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 +1 -0
  76. package/lib/typescript/commonjs/bridge/bridgeState.d.ts +5 -0
  77. package/lib/typescript/commonjs/config/babelConfig.d.ts +12 -0
  78. package/lib/typescript/commonjs/config/expoConfig.d.ts +21 -0
  79. package/lib/typescript/commonjs/config/metroConfig.d.ts +6 -0
  80. package/lib/typescript/commonjs/config/metroLogger.d.ts +21 -0
  81. package/lib/typescript/commonjs/config/tamaguiConfig.d.ts +1792 -0
  82. package/lib/typescript/commonjs/connections/ConnectionSetupScreen.d.ts +28 -7
  83. package/lib/typescript/commonjs/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
  84. package/lib/typescript/commonjs/connections/connectionMetadata.d.ts +66 -0
  85. package/lib/typescript/commonjs/connections/connectionState.d.ts +16 -0
  86. package/lib/typescript/commonjs/connections/disambiguate.d.ts +4 -2
  87. package/lib/typescript/commonjs/{platform → connections}/resolveConnections.d.ts +22 -20
  88. package/lib/typescript/commonjs/connections/types.d.ts +129 -1
  89. package/lib/typescript/commonjs/{platform → connections}/useConnectionRefs.d.ts +36 -25
  90. package/lib/typescript/commonjs/connections/useConnectionSetup.d.ts +12 -8
  91. package/lib/typescript/commonjs/controls/FilePicker.d.ts +7 -1
  92. package/lib/typescript/commonjs/controls/ImagePicker.d.ts +9 -1
  93. package/lib/typescript/commonjs/index.d.ts +18 -10
  94. package/lib/typescript/commonjs/logger.d.ts +4 -4
  95. package/lib/typescript/commonjs/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
  96. package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
  97. package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
  98. package/lib/typescript/commonjs/platform/DataverseDataSources.d.ts +28 -0
  99. package/lib/typescript/commonjs/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
  100. package/lib/typescript/commonjs/platform/GlobalDiscovery.d.ts +4 -0
  101. package/lib/typescript/commonjs/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
  102. package/lib/typescript/commonjs/provider/PowerAppsHostProvider.d.ts +29 -18
  103. package/lib/typescript/commonjs/provider/PowerAppsProvider.d.ts +54 -9
  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 +1 -0
  110. package/lib/typescript/module/bridge/bridgeState.d.ts +5 -0
  111. package/lib/typescript/module/config/babelConfig.d.ts +12 -0
  112. package/lib/typescript/module/config/expoConfig.d.ts +21 -0
  113. package/lib/typescript/module/config/metroConfig.d.ts +6 -0
  114. package/lib/typescript/module/config/metroLogger.d.ts +21 -0
  115. package/lib/typescript/module/config/tamaguiConfig.d.ts +1792 -0
  116. package/lib/typescript/module/connections/ConnectionSetupScreen.d.ts +28 -7
  117. package/lib/typescript/module/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
  118. package/lib/typescript/module/connections/connectionMetadata.d.ts +66 -0
  119. package/lib/typescript/module/connections/connectionState.d.ts +16 -0
  120. package/lib/typescript/module/connections/disambiguate.d.ts +4 -2
  121. package/lib/typescript/module/{platform → connections}/resolveConnections.d.ts +22 -20
  122. package/lib/typescript/module/connections/types.d.ts +129 -1
  123. package/lib/typescript/module/{platform → connections}/useConnectionRefs.d.ts +36 -25
  124. package/lib/typescript/module/connections/useConnectionSetup.d.ts +12 -8
  125. package/lib/typescript/module/controls/FilePicker.d.ts +7 -1
  126. package/lib/typescript/module/controls/ImagePicker.d.ts +9 -1
  127. package/lib/typescript/module/index.d.ts +18 -10
  128. package/lib/typescript/module/logger.d.ts +4 -4
  129. package/lib/typescript/module/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
  130. package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
  131. package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
  132. package/lib/typescript/module/platform/DataverseDataSources.d.ts +28 -0
  133. package/lib/typescript/module/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
  134. package/lib/typescript/module/platform/GlobalDiscovery.d.ts +4 -0
  135. package/lib/typescript/module/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
  136. package/lib/typescript/module/provider/PowerAppsHostProvider.d.ts +29 -18
  137. package/lib/typescript/module/provider/PowerAppsProvider.d.ts +54 -9
  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 +52 -13
  143. package/scripts/build-codegen-package.js +283 -0
  144. package/scripts/start-web.mjs +9 -5
  145. package/scripts/upgrade/runtime.js +139 -24
  146. package/scripts/upgrade-authoring.js +274 -180
  147. package/scripts/upgrade.js +10 -16
  148. package/src/config/generated-config.d.ts +4 -0
  149. package/src/config/index.d.ts +3 -0
  150. package/src/config/tsconfig.json +26 -0
  151. package/lib/commonjs/platform/PowerPlatformConnectionApi.js +0 -606
  152. package/lib/commonjs/platform/resolveConnections.js +0 -264
  153. package/lib/module/platform/PowerPlatformConnectionApi.js +0 -595
  154. package/lib/module/platform/resolveConnections.js +0 -259
@@ -9,9 +9,14 @@ var _reactNative = require("react-native");
9
9
  var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
10
10
  var _setupNativeHost = require("../bridge/setupNativeHost.js");
11
11
  var _NativePowerAppsBridge = require("../bridge/NativePowerAppsBridge.js");
12
- var _useConnectionRefs = require("../platform/useConnectionRefs.js");
12
+ var _useConnectionRefs = require("../connections/useConnectionRefs.js");
13
+ var _DataverseDataSources = require("../platform/DataverseDataSources.js");
13
14
  var _PowerPlatformEnvironmentApi = require("../platform/PowerPlatformEnvironmentApi.js");
14
15
  var _ConnectionSetupScreen = require("../connections/ConnectionSetupScreen.js");
16
+ var _types = require("../connections/types.js");
17
+ var _PowerPlatformConnectionApi = require("../connections/PowerPlatformConnectionApi.js");
18
+ var _connectionState = require("../connections/connectionState.js");
19
+ var _isDevPlayer = require("../utils/isDevPlayer.js");
15
20
  var _logger = require("../logger.js");
16
21
  var _index = require("../telemetry/index.js");
17
22
  var _jsxRuntime = require("react/jsx-runtime");
@@ -48,6 +53,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
48
53
  // Entra ID token scope for the APIM connector proxy (API Hub).
49
54
  const CONNECTOR_SCOPE = 'https://apihub.azure.com/.default';
50
55
  const EMPTY_DATABASE_REFERENCES = {};
56
+ const EMPTY_CONNECTION_REFERENCES = {};
51
57
  /**
52
58
  * Initialises the NativePowerAppsBridge and manages the full pre-launch
53
59
  * pipeline — connection resolution, disambiguation, and creation — before
@@ -58,6 +64,7 @@ const EMPTY_DATABASE_REFERENCES = {};
58
64
  function PowerAppsHostProvider({
59
65
  acquireToken,
60
66
  isSignedIn,
67
+ onSignOut,
61
68
  appId,
62
69
  environmentId,
63
70
  region = 'prod',
@@ -67,18 +74,75 @@ function PowerAppsHostProvider({
67
74
  renderOAuthWebView,
68
75
  isvClientId,
69
76
  onDisambiguationNeeded,
77
+ onConnectionConsent,
78
+ onResourceConsent,
79
+ onConnectionConsentDeclined,
70
80
  children
71
81
  }) {
72
82
  // Extra refs produced by ConnectionSetupScreen for newly-created connections.
73
83
  const [extraConnectionRefs, setExtraConnectionRefs] = (0, _react.useState)({});
74
-
75
- // setupDone is derived — true as soon as extraConnectionRefs is populated.
76
- const setupDone = Object.keys(extraConnectionRefs).length > 0;
84
+ const [consentApproved, setConsentApproved] = (0, _react.useState)(false);
85
+ const setupDone = consentApproved;
86
+ const renderConnectionError = (title, messages, useNeutralText = false) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
87
+ style: {
88
+ flex: 1,
89
+ padding: 24,
90
+ justifyContent: 'center',
91
+ backgroundColor: '#F8F8F8'
92
+ },
93
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
94
+ style: {
95
+ fontSize: 20,
96
+ fontWeight: '700',
97
+ color: '#1A1A1A',
98
+ marginBottom: 12
99
+ },
100
+ children: title
101
+ }), messages.map(message => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
102
+ style: {
103
+ fontSize: 14,
104
+ color: useNeutralText ? '#323130' : '#C4262E',
105
+ lineHeight: 20,
106
+ marginBottom: 8
107
+ },
108
+ children: message
109
+ }, message)), isSignedIn && onSignOut ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
110
+ accessibilityRole: "button",
111
+ onPress: () => {
112
+ void onSignOut();
113
+ },
114
+ style: {
115
+ alignSelf: 'flex-start',
116
+ backgroundColor: '#0F6CBD',
117
+ paddingHorizontal: 20,
118
+ paddingVertical: 12,
119
+ borderRadius: 4,
120
+ marginTop: 12
121
+ },
122
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
123
+ style: {
124
+ color: '#FFFFFF',
125
+ fontSize: 15,
126
+ fontWeight: '600'
127
+ },
128
+ children: "Sign out"
129
+ })
130
+ }) : null]
131
+ });
77
132
  const {
78
133
  connectionRefs,
79
134
  isReady,
135
+ error: connectionError,
136
+ errorKind: connectionErrorKind,
80
137
  missingConnectors,
81
- dataverseOrgUrl
138
+ missingConnectionReferences,
139
+ connectionRequirements,
140
+ resourceConsents: launchResourceConsents,
141
+ configurationErrors,
142
+ requiresConnectionConsent,
143
+ resolvedConfigKey,
144
+ dataverseOrgUrl,
145
+ databaseReferences: resolvedDatabaseReferences
82
146
  } = (0, _useConnectionRefs.useConnectionRefs)({
83
147
  isSignedIn,
84
148
  acquireToken,
@@ -86,6 +150,7 @@ function PowerAppsHostProvider({
86
150
  environmentId,
87
151
  region,
88
152
  connectionReferences,
153
+ hasDataverse: (0, _DataverseDataSources.hasDataverseDatabaseReferences)(databaseReferences),
89
154
  schemaMap,
90
155
  onDisambiguationNeeded,
91
156
  isvClientId
@@ -96,39 +161,43 @@ function PowerAppsHostProvider({
96
161
  if (!isSignedIn) {
97
162
  (0, _logger.debugLog)('[PAHost] user signed out — resetting bridge state');
98
163
  setExtraConnectionRefs({});
164
+ setConsentApproved(false);
99
165
  }
100
166
  }, [isSignedIn]);
167
+ (0, _react.useEffect)(() => {
168
+ setExtraConnectionRefs({});
169
+ setConsentApproved(false);
170
+ }, [appId, environmentId, connectionReferences]);
101
171
 
102
172
  // Merge hook refs with anything the setup screen created.
103
173
  const mergedRefs = (0, _react.useMemo)(() => ({
104
174
  ...connectionRefs,
105
175
  ...extraConnectionRefs
106
176
  }), [connectionRefs, extraConnectionRefs]);
107
- const staticConnectionRefs = (0, _react.useMemo)(() => (0, _NativePowerAppsBridge.buildConnectionReferences)(connectionReferences), [connectionReferences]);
177
+ const staticConnectionRefs = (0, _react.useMemo)(() => _isDevPlayer.isDevPlayer ? (0, _NativePowerAppsBridge.buildConnectionReferences)(connectionReferences) : EMPTY_CONNECTION_REFERENCES, [connectionReferences, _isDevPlayer.isDevPlayer]);
108
178
 
109
179
  // dataverseOrgUrl comes directly from useConnectionRefs (fetched from the
110
180
  // environment metadata regardless of whether a commondataserviceforapps
111
181
  // connection reference is configured). This allows Dataverse calls to work
112
182
  // even when there is no explicit Dataverse connection in connectionReferences.
113
- const cdsDataSources = (0, _react.useMemo)(() => (0, _PowerPlatformEnvironmentApi.buildCdsDataSources)(databaseReferences ?? EMPTY_DATABASE_REFERENCES, dataverseOrgUrl), [databaseReferences, dataverseOrgUrl]);
183
+ const cdsDataSources = (0, _react.useMemo)(() => (0, _DataverseDataSources.buildCdsDataSources)(_isDevPlayer.isDevPlayer ? databaseReferences ?? EMPTY_DATABASE_REFERENCES : resolvedDatabaseReferences, dataverseOrgUrl), [databaseReferences, resolvedDatabaseReferences, dataverseOrgUrl, _isDevPlayer.isDevPlayer]);
114
184
 
115
185
  // Build the missing-connector entries for ConnectionSetupScreen.
116
- const missingEntries = (0, _react.useMemo)(() => missingConnectors.map(apiId => {
117
- const localRefId = Object.keys(connectionReferences).find(k => connectionReferences[k].id === apiId) ?? apiId;
118
- return {
119
- apiId,
120
- localRefId
121
- };
122
- }), [missingConnectors, connectionReferences]);
186
+ const missingEntries = (0, _react.useMemo)(() => missingConnectionReferences, [missingConnectionReferences]);
187
+ const resourceConsents = (0, _react.useMemo)(() => [...new Map(launchResourceConsents.map(resource => [resource.resourceId.toLowerCase(), resource])).values()], [launchResourceConsents]);
188
+ const currentConfigKey = (0, _react.useMemo)(() => (0, _types.buildConnectionResolutionKey)(appId, environmentId, _isDevPlayer.isDevPlayer ? connectionReferences : {}), [appId, environmentId, connectionReferences, _isDevPlayer.isDevPlayer]);
189
+ const resolutionMatchesCurrentConfig = resolvedConfigKey === currentConfigKey;
190
+ const needsConsent = (0, _connectionState.shouldShowConnectionReview)(_isDevPlayer.isDevPlayer, requiresConnectionConsent, resourceConsents.length > 0);
123
191
 
124
192
  // Called by ConnectionSetupScreen once every missing connector is resolved.
125
- const handleSetupComplete = (0, _react.useCallback)(resolvedIds => {
193
+ const handleSetupComplete = (0, _react.useCallback)(async resolvedIds => {
126
194
  const refs = {};
127
- for (const [apiId, connectionId] of Object.entries(resolvedIds)) {
128
- const localRefId = Object.keys(connectionReferences).find(k => connectionReferences[k].id === apiId);
129
- if (!localRefId) continue;
130
- const dataSources = connectionReferences[localRefId].dataSources;
131
- const runtimeUrl = dataSources.map(ds => schemaMap[ds]?.properties?.primaryRuntimeUrl).find(Boolean) ?? '';
195
+ for (const [localRefId, connectionId] of Object.entries(resolvedIds)) {
196
+ const requirement = connectionRequirements.find(item => item.localRefId === localRefId);
197
+ if (!requirement) continue;
198
+ const apiId = requirement.apiId;
199
+ const dataSources = requirement.dataSources;
200
+ const runtimeUrl = dataSources.map(ds => connectionRefsRef.current[ds]?.runtimeUrl ?? (_isDevPlayer.isDevPlayer ? schemaMap[ds]?.properties?.primaryRuntimeUrl : undefined)).find(Boolean) ?? '';
132
201
  for (const ds of dataSources) {
133
202
  refs[ds] = {
134
203
  apiId,
@@ -142,7 +211,44 @@ function PowerAppsHostProvider({
142
211
  }
143
212
  }
144
213
  setExtraConnectionRefs(refs);
145
- }, [connectionReferences, schemaMap]);
214
+ const mergedForConsent = {
215
+ ...connectionRefsRef.current,
216
+ ...refs
217
+ };
218
+ const usages = connectionRequirements.map(requirement => ({
219
+ localRefId: requirement.localRefId,
220
+ apiId: requirement.apiId,
221
+ connectionId: requirement.dataSources.map(dataSource => mergedForConsent[dataSource]?.connectionName).find(Boolean) ?? '',
222
+ dataSources: requirement.dataSources,
223
+ appActions: requirement.appActions ?? [],
224
+ apiScopes: requirement.apiScopes
225
+ }));
226
+ if (usages.some(usage => !usage.connectionId)) {
227
+ throw new Error('Not all required connections have been resolved.');
228
+ }
229
+ if (!_isDevPlayer.isDevPlayer && resourceConsents.length > 0 && !onResourceConsent) {
230
+ throw new Error('Protected resource consent requires an onResourceConsent persistence callback.');
231
+ }
232
+ const shouldPersistUsages = (0, _connectionState.shouldPersistConnectionUsages)(_isDevPlayer.isDevPlayer, appId);
233
+ if (shouldPersistUsages && appId && usages.length > 0) {
234
+ const token = await acquireToken([(0, _PowerPlatformEnvironmentApi.powerPlatformScope)(region)]);
235
+ if (!token) throw new Error('Unable to acquire a token to register connection usage.');
236
+ await Promise.all(usages.map(usage => (0, _PowerPlatformConnectionApi.postConnectionUsage)(appId, usage, environmentId, region, token)));
237
+ await (0, _PowerPlatformConnectionApi.reportScopeConsents)(appId, usages, environmentId, region, token);
238
+ }
239
+ if (!_isDevPlayer.isDevPlayer) {
240
+ await onConnectionConsent?.(usages);
241
+ await onResourceConsent?.(resourceConsents);
242
+ }
243
+ setConsentApproved(true);
244
+ }, [acquireToken, appId, environmentId, region, schemaMap, connectionRequirements, onConnectionConsent, onResourceConsent, resourceConsents, _isDevPlayer.isDevPlayer]);
245
+ const consentDetails = (0, _react.useMemo)(() => connectionRequirements.map(requirement => ({
246
+ localRefId: requirement.localRefId,
247
+ connectorId: requirement.connectorId,
248
+ displayName: requirement.displayName ?? requirement.connectorId.replace(/^shared_/, ''),
249
+ description: `Uses ${requirement.dataSources.join(', ')}`,
250
+ appActions: requirement.appActions ?? []
251
+ })), [connectionRequirements]);
146
252
 
147
253
  // ---- Bridge wiring ----
148
254
 
@@ -154,7 +260,7 @@ function PowerAppsHostProvider({
154
260
  connectionRefsRef.current = connectionRefs;
155
261
  const configuredBridgeInputsRef = (0, _react.useRef)(undefined);
156
262
  const [, setBridgeRegistrationVersion] = (0, _react.useState)(0);
157
- const hasResolvedConnections = isSignedIn && isReady && (missingConnectors.length === 0 || setupDone);
263
+ const hasResolvedConnections = isSignedIn && isReady && resolutionMatchesCurrentConfig && (missingConnectors.length === 0 || consentApproved) && (!needsConsent || consentApproved);
158
264
  const isBridgeConfiguredFor = (connections, dataSources) => {
159
265
  const currentInputs = configuredBridgeInputsRef.current;
160
266
  return currentInputs?.connections === connections && currentInputs.dataSources === dataSources;
@@ -254,13 +360,34 @@ function PowerAppsHostProvider({
254
360
  }
255
361
  }, [isSignedIn, isReady]);
256
362
  (0, _react.useEffect)(() => {
257
- if (isSignedIn && isReady && missingConnectors.length > 0 && !setupDone) {
363
+ if (isSignedIn && isReady && (missingConnectors.length > 0 || needsConsent) && !setupDone) {
258
364
  (0, _logger.debugLog)(`[PAHost] render: showing ConnectionSetupScreen for ${missingConnectors.length} missing connector(s):`, missingConnectors.join(', '));
259
365
  }
260
- }, [isSignedIn, isReady, missingConnectors, setupDone]);
366
+ }, [isSignedIn, isReady, missingConnectors, needsConsent, setupDone]);
261
367
 
262
368
  // ---- Render ----
263
369
 
370
+ if (connectionError) {
371
+ const accessDenied = connectionErrorKind === 'app-access-denied';
372
+ return renderConnectionError(accessDenied ? 'You don’t have access' : 'Unable to load app', [connectionError], accessDenied);
373
+ }
374
+ if (configurationErrors.length > 0) {
375
+ return renderConnectionError('Connection configuration error', configurationErrors);
376
+ }
377
+ if (isSignedIn && !resolutionMatchesCurrentConfig) {
378
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
379
+ style: {
380
+ flex: 1,
381
+ alignItems: 'center',
382
+ justifyContent: 'center',
383
+ backgroundColor: '#F8F8F8'
384
+ },
385
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
386
+ size: "large"
387
+ })
388
+ });
389
+ }
390
+
264
391
  // First mount: register the native bridge with static manifest refs before
265
392
  // any route children can mount and call into @microsoft/power-apps.
266
393
  if (!staticBridgeRegistered && !hasResolvedConnections) {
@@ -296,7 +423,7 @@ function PowerAppsHostProvider({
296
423
  // Wrapped in SafeAreaProvider so useSafeAreaInsets() works even when the
297
424
  // consuming app hasn't mounted its own SafeAreaProvider yet. Nesting is
298
425
  // safe — react-native-safe-area-context treats inner providers as no-ops.
299
- if (isSignedIn && isReady && missingConnectors.length > 0 && !setupDone) {
426
+ if (isSignedIn && isReady && (missingConnectors.length > 0 || needsConsent) && !setupDone) {
300
427
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSafeAreaContext.SafeAreaProvider, {
301
428
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConnectionSetupScreen.ConnectionSetupScreen, {
302
429
  missingConnectors: missingEntries,
@@ -304,8 +431,13 @@ function PowerAppsHostProvider({
304
431
  environmentId: environmentId,
305
432
  region: region,
306
433
  acquireToken: acquireToken,
434
+ onSignOut: isSignedIn ? onSignOut : undefined,
307
435
  isvClientId: isvClientId,
308
436
  onAllConnected: handleSetupComplete,
437
+ consentDetails: consentDetails,
438
+ resourceConsents: resourceConsents,
439
+ onConsentDeclined: onConnectionConsentDeclined,
440
+ showReview: !_isDevPlayer.isDevPlayer,
309
441
  renderOAuthWebView: renderOAuthWebView
310
442
  // No onSkip — connections are required.
311
443
  })