@microsoft/power-apps-native-host 0.2.22

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 (104) hide show
  1. package/LICENSE +112 -0
  2. package/README.md +59 -0
  3. package/app.plugin.js +4 -0
  4. package/lib/NOTICE.txt +1659 -0
  5. package/lib/commonjs/ErrorBoundary.js +128 -0
  6. package/lib/commonjs/auth/AuthContext.js +281 -0
  7. package/lib/commonjs/bridge/NativePowerAppsBridge.js +279 -0
  8. package/lib/commonjs/bridge/setupNativeHost.js +65 -0
  9. package/lib/commonjs/connections/ConnectionSetupScreen.js +531 -0
  10. package/lib/commonjs/connections/disambiguate.js +88 -0
  11. package/lib/commonjs/connections/types.js +58 -0
  12. package/lib/commonjs/connections/useConnectionSetup.js +236 -0
  13. package/lib/commonjs/controls/FilePicker.js +183 -0
  14. package/lib/commonjs/controls/ImagePicker.js +236 -0
  15. package/lib/commonjs/index.js +246 -0
  16. package/lib/commonjs/logger.js +27 -0
  17. package/lib/commonjs/package.json +1 -0
  18. package/lib/commonjs/platform/PowerPlatformConnectionApi.js +606 -0
  19. package/lib/commonjs/platform/PowerPlatformEnvironmentApi.js +194 -0
  20. package/lib/commonjs/platform/resolveConnections.js +264 -0
  21. package/lib/commonjs/platform/useConnectionRefs.js +270 -0
  22. package/lib/commonjs/provider/PowerAppsHostProvider.js +336 -0
  23. package/lib/commonjs/provider/PowerAppsProvider.js +351 -0
  24. package/lib/commonjs/telemetry/index.js +70 -0
  25. package/lib/commonjs/theme/ThemeProvider.js +80 -0
  26. package/lib/commonjs/theme/tokens.js +50 -0
  27. package/lib/commonjs/utils/dataverseUtils.js +98 -0
  28. package/lib/commonjs/utils/isDevPlayer.js +27 -0
  29. package/lib/module/ErrorBoundary.js +122 -0
  30. package/lib/module/auth/AuthContext.js +276 -0
  31. package/lib/module/bridge/NativePowerAppsBridge.js +273 -0
  32. package/lib/module/bridge/setupNativeHost.js +62 -0
  33. package/lib/module/connections/ConnectionSetupScreen.js +526 -0
  34. package/lib/module/connections/disambiguate.js +83 -0
  35. package/lib/module/connections/types.js +60 -0
  36. package/lib/module/connections/useConnectionSetup.js +233 -0
  37. package/lib/module/controls/FilePicker.js +178 -0
  38. package/lib/module/controls/ImagePicker.js +231 -0
  39. package/lib/module/index.js +41 -0
  40. package/lib/module/logger.js +22 -0
  41. package/lib/module/package.json +1 -0
  42. package/lib/module/platform/PowerPlatformConnectionApi.js +595 -0
  43. package/lib/module/platform/PowerPlatformEnvironmentApi.js +186 -0
  44. package/lib/module/platform/resolveConnections.js +259 -0
  45. package/lib/module/platform/useConnectionRefs.js +267 -0
  46. package/lib/module/provider/PowerAppsHostProvider.js +332 -0
  47. package/lib/module/provider/PowerAppsProvider.js +345 -0
  48. package/lib/module/telemetry/index.js +55 -0
  49. package/lib/module/theme/ThemeProvider.js +63 -0
  50. package/lib/module/theme/tokens.js +46 -0
  51. package/lib/module/utils/dataverseUtils.js +90 -0
  52. package/lib/module/utils/isDevPlayer.js +23 -0
  53. package/lib/typescript/commonjs/ErrorBoundary.d.ts +30 -0
  54. package/lib/typescript/commonjs/auth/AuthContext.d.ts +57 -0
  55. package/lib/typescript/commonjs/bridge/NativePowerAppsBridge.d.ts +112 -0
  56. package/lib/typescript/commonjs/bridge/setupNativeHost.d.ts +39 -0
  57. package/lib/typescript/commonjs/connections/ConnectionSetupScreen.d.ts +107 -0
  58. package/lib/typescript/commonjs/connections/disambiguate.d.ts +43 -0
  59. package/lib/typescript/commonjs/connections/types.d.ts +91 -0
  60. package/lib/typescript/commonjs/connections/useConnectionSetup.d.ts +96 -0
  61. package/lib/typescript/commonjs/controls/FilePicker.d.ts +65 -0
  62. package/lib/typescript/commonjs/controls/ImagePicker.d.ts +76 -0
  63. package/lib/typescript/commonjs/index.d.ts +42 -0
  64. package/lib/typescript/commonjs/logger.d.ts +11 -0
  65. package/lib/typescript/commonjs/package.json +1 -0
  66. package/lib/typescript/commonjs/platform/PowerPlatformConnectionApi.d.ts +205 -0
  67. package/lib/typescript/commonjs/platform/PowerPlatformEnvironmentApi.d.ts +108 -0
  68. package/lib/typescript/commonjs/platform/resolveConnections.d.ts +86 -0
  69. package/lib/typescript/commonjs/platform/useConnectionRefs.d.ts +126 -0
  70. package/lib/typescript/commonjs/provider/PowerAppsHostProvider.d.ts +123 -0
  71. package/lib/typescript/commonjs/provider/PowerAppsProvider.d.ts +148 -0
  72. package/lib/typescript/commonjs/telemetry/index.d.ts +48 -0
  73. package/lib/typescript/commonjs/theme/ThemeProvider.d.ts +30 -0
  74. package/lib/typescript/commonjs/theme/tokens.d.ts +27 -0
  75. package/lib/typescript/commonjs/utils/dataverseUtils.d.ts +39 -0
  76. package/lib/typescript/commonjs/utils/isDevPlayer.d.ts +19 -0
  77. package/lib/typescript/module/ErrorBoundary.d.ts +30 -0
  78. package/lib/typescript/module/auth/AuthContext.d.ts +57 -0
  79. package/lib/typescript/module/bridge/NativePowerAppsBridge.d.ts +112 -0
  80. package/lib/typescript/module/bridge/setupNativeHost.d.ts +39 -0
  81. package/lib/typescript/module/connections/ConnectionSetupScreen.d.ts +107 -0
  82. package/lib/typescript/module/connections/disambiguate.d.ts +43 -0
  83. package/lib/typescript/module/connections/types.d.ts +91 -0
  84. package/lib/typescript/module/connections/useConnectionSetup.d.ts +96 -0
  85. package/lib/typescript/module/controls/FilePicker.d.ts +65 -0
  86. package/lib/typescript/module/controls/ImagePicker.d.ts +76 -0
  87. package/lib/typescript/module/index.d.ts +42 -0
  88. package/lib/typescript/module/logger.d.ts +11 -0
  89. package/lib/typescript/module/package.json +1 -0
  90. package/lib/typescript/module/platform/PowerPlatformConnectionApi.d.ts +205 -0
  91. package/lib/typescript/module/platform/PowerPlatformEnvironmentApi.d.ts +108 -0
  92. package/lib/typescript/module/platform/resolveConnections.d.ts +86 -0
  93. package/lib/typescript/module/platform/useConnectionRefs.d.ts +126 -0
  94. package/lib/typescript/module/provider/PowerAppsHostProvider.d.ts +123 -0
  95. package/lib/typescript/module/provider/PowerAppsProvider.d.ts +148 -0
  96. package/lib/typescript/module/telemetry/index.d.ts +48 -0
  97. package/lib/typescript/module/theme/ThemeProvider.d.ts +30 -0
  98. package/lib/typescript/module/theme/tokens.d.ts +27 -0
  99. package/lib/typescript/module/utils/dataverseUtils.d.ts +39 -0
  100. package/lib/typescript/module/utils/isDevPlayer.d.ts +19 -0
  101. package/package.json +119 -0
  102. package/scripts/build-ios-base.js +96 -0
  103. package/scripts/bundle.js +95 -0
  104. package/scripts/generate-connector-schemas.js +75 -0
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.PowerAppsProvider = PowerAppsProvider;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _reactNativeGestureHandler = require("react-native-gesture-handler");
10
+ var _core = require("@tamagui/core");
11
+ var _portal = require("@tamagui/portal");
12
+ var _v = require("@tamagui/config/v3");
13
+ var _toast = require("@tamagui/toast");
14
+ var _reactQuery = require("@tanstack/react-query");
15
+ var _netinfo = _interopRequireDefault(require("@react-native-community/netinfo"));
16
+ var _AuthContext = require("../auth/AuthContext.js");
17
+ var _PowerAppsHostProvider = require("./PowerAppsHostProvider.js");
18
+ var _PowerPlatformEnvironmentApi = require("../platform/PowerPlatformEnvironmentApi.js");
19
+ var _ThemeProvider = require("../theme/ThemeProvider.js");
20
+ var _ErrorBoundary = require("../ErrorBoundary.js");
21
+ var _expoConstants = _interopRequireDefault(require("expo-constants"));
22
+ var _powerAppsNativeCommon = require("@microsoft/power-apps-native-common");
23
+ var _powerAppsNativeOffline = require("@microsoft/power-apps-native-offline");
24
+ var _jsxRuntime = require("react/jsx-runtime");
25
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
26
+ 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); }
27
+ /*!
28
+ * power-apps-native-host — PowerAppsProvider
29
+ *
30
+ * A single provider that composes all infrastructure required to run a
31
+ * Power Apps canvas app inside an Expo shell:
32
+ *
33
+ * GestureHandlerRootView
34
+ * └── TamaguiProvider (defaults to @tamagui/config/v3)
35
+ * └── PortalProvider (required by ToastViewport)
36
+ * └── ToastProvider + ToastViewport
37
+ * └── QueryClientProvider (own QueryClient, wired to NetInfo + AppState)
38
+ * └── AuthProvider
39
+ * └── PowerAppsHostProvider (connected via useAuth)
40
+ * └── children
41
+ *
42
+ * Usage:
43
+ *
44
+ * <PowerAppsProvider
45
+ * msalConfig={authConfig.msal}
46
+ * powerConfig={powerConfig}
47
+ * schemaMap={schemaMap}
48
+ * >
49
+ * <StatusBar style="auto" />
50
+ * <Slot />
51
+ * </PowerAppsProvider>
52
+ */
53
+
54
+ (0, _powerAppsNativeCommon.suppressKnownWarnings)();
55
+
56
+ // ---- React-Query wiring (runs once at module load) ----
57
+
58
+ // Wire onlineManager to NetInfo so refetchOnReconnect fires on mobile
59
+ // (the default browser-event-based detection is a no-op in React Native).
60
+ _reactQuery.onlineManager.setEventListener(setOnline => {
61
+ return _netinfo.default.addEventListener(state => setOnline(!!state.isConnected));
62
+ });
63
+
64
+ // Wire focusManager to AppState so queries refetch when the app foregrounds.
65
+ _reactQuery.focusManager.setEventListener(handleFocus => {
66
+ const sub = _reactNative.AppState.addEventListener('change', status => {
67
+ if (_reactNative.Platform.OS !== 'web') handleFocus(status === 'active');
68
+ });
69
+ return () => sub.remove();
70
+ });
71
+
72
+ // ---- Singletons ----
73
+
74
+ // The app's tamagui.config.ts (generated by /tamagui-design-system) is always
75
+ // 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
77
+ // 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;
118
+ }
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
+ }
148
+ });
149
+ }
150
+
151
+ // ---- Types ----
152
+
153
+ /** Shape of power.config.json consumed by the provider. */
154
+
155
+ // ---- Inner component ----
156
+ // Separate from PowerAppsProvider only because useAuth() must be called inside
157
+ // AuthProvider. All auth-dependent wiring lives here.
158
+
159
+ function InnerProviders({
160
+ msalConfig,
161
+ powerConfig,
162
+ schemaMap,
163
+ renderOAuthWebView,
164
+ onDisambiguationNeeded,
165
+ offlineProfile,
166
+ children
167
+ }) {
168
+ const {
169
+ acquireToken,
170
+ isSignedIn,
171
+ hasRealAccount
172
+ } = (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)({
193
+ powerConfig,
194
+ offlineProfile,
195
+ acquireToken,
196
+ isSignedIn: hasRealAccount,
197
+ fetchInstanceUrl: resolveInstanceUrlForOffline
198
+ });
199
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_PowerAppsHostProvider.PowerAppsHostProvider, {
200
+ acquireToken: acquireToken,
201
+ isSignedIn: isSignedIn,
202
+ appId: powerConfig.appId ?? undefined,
203
+ environmentId: powerConfig.environmentId ?? '',
204
+ region: powerConfig.region ?? 'prod',
205
+ connectionReferences: connectionReferences,
206
+ schemaMap: schemaMap,
207
+ databaseReferences: powerConfig.databaseReferences,
208
+ isvClientId: msalConfig.clientId,
209
+ renderOAuthWebView: renderOAuthWebView,
210
+ onDisambiguationNeeded: onDisambiguationNeeded,
211
+ children: [children, offline.StatusOverlay && /*#__PURE__*/(0, _jsxRuntime.jsx)(offline.StatusOverlay, {})]
212
+ });
213
+ }
214
+
215
+ // ---- Public component ----
216
+
217
+ /**
218
+ * Top-level provider for Power Apps canvas apps running inside an Expo shell.
219
+ *
220
+ * Composes GestureHandlerRootView, TamaguiProvider, ToastProvider,
221
+ * QueryClientProvider, AuthProvider, and PowerAppsHostProvider into a single
222
+ * component, eliminating all provider boilerplate from the consuming app's
223
+ * root layout.
224
+ */
225
+ function PowerAppsProvider({
226
+ msalConfig,
227
+ intuneConfig,
228
+ powerConfig,
229
+ schemaMap,
230
+ tamaguiConfig = defaultTamaguiConfig,
231
+ // override with app's tamagui.config.ts
232
+ defaultTheme = 'light',
233
+ theme,
234
+ darkTheme,
235
+ followSystemTheme = true,
236
+ renderOAuthWebView,
237
+ onDisambiguationNeeded,
238
+ appName,
239
+ logger: loggerProp,
240
+ offlineProfile,
241
+ children
242
+ }) {
243
+ // Capture the logger-prop identity at mount time so the effect dep array
244
+ // is stable (loggerProp is an object reference; re-running on every render
245
+ // would reconfigure and leak the previous provider).
246
+ 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]);
254
+
255
+ // Configure the app logger exactly once per mount inside useEffect so that
256
+ // side effects (provider construction, async resolveDeviceId) never run
257
+ // during the render phase. This is safe because AppLogger.ts starts with a
258
+ // silent no-op Logger, so any telemetry emitted before the first commit is
259
+ // silently dropped rather than crashing.
260
+ (0, _react.useEffect)(() => {
261
+ const lp = loggerPropRef.current;
262
+ if (lp === null) {
263
+ // Explicit opt-out — replace with a silent no-op Logger.
264
+ (0, _powerAppsNativeCommon.configureAppLogger)(new _powerAppsNativeCommon.Logger());
265
+ } else if (lp !== undefined) {
266
+ // Caller supplied their own fully-configured logger.
267
+ (0, _powerAppsNativeCommon.configureAppLogger)(lp);
268
+ } else {
269
+ // Default: auto-wire the 1DS JS adapter so telemetry flows out of the
270
+ // box without any boilerplate in the consuming app.
271
+ const providerConfig = {
272
+ clusterCategory: (0, _powerAppsNativeCommon.regionToClusterCategory)(powerConfig.region ?? 'dev'),
273
+ clientType: appName ?? 'PowerAppsNative',
274
+ appVersion: _expoConstants.default.expoConfig?.version,
275
+ minSeverity: __DEV__ ? 'verbose' : 'info',
276
+ telemetryLocation: (0, _powerAppsNativeCommon.resolveTelemetryLocation)(powerConfig.geoRegion)
277
+ };
278
+ // Resolve the stable device ID first so every event — including the
279
+ // very first — carries the real GUID rather than the 'react-native'
280
+ // fallback. Events emitted while this resolves are silently dropped
281
+ // by the no-op Logger that is active until configureAppLogger is called.
282
+ (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
+ }));
290
+ }).catch(_err => {
291
+ // 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
+ }));
296
+ });
297
+ }
298
+
299
+ // Flush any queued telemetry when this component unmounts (dev reload /
300
+ // process exit). Placed inside this effect so the cleanup is paired with
301
+ // the setup — if the effect re-runs (which it won't here, empty deps),
302
+ // the previous provider is flushed before the new one is configured.
303
+ return () => {
304
+ void (0, _powerAppsNativeCommon.getAppLogger)().flush();
305
+ };
306
+ // eslint-disable-next-line react-hooks/exhaustive-deps
307
+ }, []); // intentionally empty — logger is configured once per mount
308
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ErrorBoundary.ErrorBoundary, {
309
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureHandlerRootView, {
310
+ style: {
311
+ flex: 1
312
+ },
313
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ThemeProvider.ThemeProvider, {
314
+ theme: theme,
315
+ darkTheme: darkTheme,
316
+ followSystem: followSystemTheme,
317
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_core.TamaguiProvider, {
318
+ config: tamaguiConfig,
319
+ defaultTheme: defaultTheme,
320
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_portal.PortalProvider, {
321
+ shouldAddRootHost: true,
322
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_toast.ToastProvider, {
323
+ swipeDirection: "horizontal",
324
+ 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, {
331
+ msalConfig: msalConfig,
332
+ powerConfig: powerConfig,
333
+ schemaMap: schemaMap,
334
+ renderOAuthWebView: renderOAuthWebView,
335
+ onDisambiguationNeeded: onDisambiguationNeeded,
336
+ offlineProfile: offlineProfile,
337
+ children: children
338
+ })
339
+ })
340
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_toast.ToastViewport, {
341
+ top: 50,
342
+ left: 0,
343
+ right: 0
344
+ })]
345
+ })
346
+ })
347
+ })
348
+ })
349
+ })
350
+ });
351
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.HostOperationNames = void 0;
7
+ Object.defineProperty(exports, "configureAppLogger", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _powerAppsNativeCommon.configureAppLogger;
11
+ }
12
+ });
13
+ Object.defineProperty(exports, "getAppLogger", {
14
+ enumerable: true,
15
+ get: function () {
16
+ return _powerAppsNativeCommon.getAppLogger;
17
+ }
18
+ });
19
+ var _powerAppsNativeCommon = require("@microsoft/power-apps-native-common");
20
+ /*!
21
+ * Copyright (C) Microsoft Corporation. All rights reserved.
22
+ *
23
+ * power-apps-native-host — package telemetry
24
+ *
25
+ * The shared logger singleton lives in `@microsoft/power-apps-native-common`
26
+ * (`getAppLogger` / `configureAppLogger`). This module re-exports those
27
+ * alongside the canonical host operation-name constants.
28
+ */
29
+
30
+ /**
31
+ * Canonical operation names for host package telemetry.
32
+ * Follow the `PowerAppsHost.<Subsystem>.<Action>` convention so events are
33
+ * filterable in Kusto by prefix.
34
+ */
35
+ const HostOperationNames = exports.HostOperationNames = {
36
+ // ── Auth ─────────────────────────────────────────────────────────────────
37
+ /** MSAL PublicClientApplication.init() + initial account resolution. */
38
+ AuthInit: 'PowerAppsHost.Auth.Init',
39
+ /** Interactive sign-in (acquireToken interactive). */
40
+ AuthSignIn: 'PowerAppsHost.Auth.SignIn',
41
+ /** Sign-out (token cache clear + broker logout). */
42
+ AuthSignOut: 'PowerAppsHost.Auth.SignOut',
43
+ /** Silent token acquisition. Recorded only on failure. */
44
+ AuthAcquireTokenSilentFailed: 'PowerAppsHost.Auth.AcquireTokenSilent.Failed',
45
+ /** Intune MAM enrollment after sign-in. */
46
+ AuthIntuneEnroll: 'PowerAppsHost.Auth.Intune.Enroll',
47
+ /** Intune MAM unenrollment during sign-out. */
48
+ AuthIntuneUnenroll: 'PowerAppsHost.Auth.Intune.Unenroll',
49
+ // ── Bridge / HTTP ─────────────────────────────────────────────────────────
50
+ /** SDK-originated HTTP request relayed through NativePowerAppsBridge. */
51
+ BridgeHttpRequest: 'PowerAppsHost.Bridge.HttpRequest',
52
+ /** Plugin call forwarded through NativePowerAppsBridge (verbose; also used for unhandled). */
53
+ BridgeUnhandledPlugin: 'PowerAppsHost.Bridge.PluginCall',
54
+ /** Connector/Dataverse token acquisition for the bridge. Recorded only on failure. */
55
+ BridgeTokenAcquireFailed: 'PowerAppsHost.Bridge.TokenAcquire.Failed',
56
+ // ── Runtime ───────────────────────────────────────────────────────────────
57
+ /** Top-level React error boundary caught an unhandled JS error. */
58
+ RuntimeUnhandledJsError: 'PowerAppsHost.Runtime.UnhandledJsError',
59
+ // ── Platform APIs ─────────────────────────────────────────────────────────
60
+ /** Resolve Dataverse instanceUrl from Power Platform environment API. */
61
+ PlatformFetchInstanceUrl: 'PowerAppsHost.Platform.FetchInstanceUrl',
62
+ /** useConnectionRefs failed to resolve connections (recoverable). Recorded only on failure. */
63
+ PlatformLoadConnectionsFailed: 'PowerAppsHost.Platform.LoadConnections.Failed',
64
+ /** Create a new Power Platform connection. */
65
+ PlatformCreateConnection: 'PowerAppsHost.Platform.CreateConnection',
66
+ /** Resolve app connection references for the current launch. */
67
+ PlatformResolveConnectionRefs: 'PowerAppsHost.Platform.ResolveConnectionRefs',
68
+ /** Grant this app access to a Power Platform connection ACL. */
69
+ PlatformConnectionAclGrant: 'PowerAppsHost.Platform.ConnectionAclGrant'
70
+ };
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ThemeProvider = ThemeProvider;
7
+ Object.defineProperty(exports, "darkTheme", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _tokens.darkTheme;
11
+ }
12
+ });
13
+ Object.defineProperty(exports, "lightTheme", {
14
+ enumerable: true,
15
+ get: function () {
16
+ return _tokens.lightTheme;
17
+ }
18
+ });
19
+ exports.useThemeControl = useThemeControl;
20
+ exports.useThemeTokens = useThemeTokens;
21
+ var _react = _interopRequireWildcard(require("react"));
22
+ var _reactNative = require("react-native");
23
+ var _tokens = require("./tokens.js");
24
+ var _jsxRuntime = require("react/jsx-runtime");
25
+ 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); }
26
+ /**
27
+ * ThemeProvider — distributes {@link ThemeTokens} through the component tree.
28
+ *
29
+ * `PowerAppsProvider` mounts this automatically. Use directly only when
30
+ * composing providers manually.
31
+ */
32
+
33
+ // ── Contexts ─────────────────────────────────────────────────────────────────
34
+ const ThemeContext = /*#__PURE__*/(0, _react.createContext)(_tokens.lightTheme);
35
+ const ThemeControlContext = /*#__PURE__*/(0, _react.createContext)({
36
+ setTheme: () => {},
37
+ resetTheme: () => {}
38
+ });
39
+
40
+ // ── Provider ─────────────────────────────────────────────────────────────────
41
+
42
+ function ThemeProvider({
43
+ theme = _tokens.lightTheme,
44
+ darkTheme = _tokens.darkTheme,
45
+ followSystem = true,
46
+ children
47
+ }) {
48
+ const colorScheme = (0, _reactNative.useColorScheme)();
49
+ const [override, setOverride] = (0, _react.useState)(null);
50
+ const resolved = (0, _react.useMemo)(() => {
51
+ if (override !== null) return override;
52
+ return followSystem && colorScheme === 'dark' ? darkTheme : theme;
53
+ }, [theme, darkTheme, followSystem, colorScheme, override]);
54
+ const control = (0, _react.useMemo)(() => ({
55
+ setTheme: tokens => setOverride(tokens),
56
+ resetTheme: () => setOverride(null)
57
+ }), []);
58
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(ThemeControlContext.Provider, {
59
+ value: control,
60
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ThemeContext.Provider, {
61
+ value: resolved,
62
+ children: children
63
+ })
64
+ });
65
+ }
66
+
67
+ // ── Hooks ─────────────────────────────────────────────────────────────────────
68
+
69
+ /** Returns current {@link ThemeTokens} from the nearest ThemeProvider. */
70
+ function useThemeTokens() {
71
+ return (0, _react.useContext)(ThemeContext);
72
+ }
73
+
74
+ /**
75
+ * Returns `{ setTheme, resetTheme }` for imperative theme overrides.
76
+ * Stable reference — does not re-render consumers on theme change.
77
+ */
78
+ function useThemeControl() {
79
+ return (0, _react.useContext)(ThemeControlContext);
80
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.lightTheme = exports.darkTheme = void 0;
7
+ /**
8
+ * Theme token schema and built-in palettes for power-apps-native-host.
9
+ *
10
+ * Pass a custom {@link ThemeTokens} object to `PowerAppsProvider` to override
11
+ * the default Microsoft blue palette.
12
+ */
13
+
14
+ // ── Built-in themes ──────────────────────────────────────────────────────────
15
+
16
+ /** Microsoft blue light palette (default). */
17
+ const lightTheme = exports.lightTheme = {
18
+ surface0: '#ffffff',
19
+ surface1: '#f7f7f8',
20
+ surface2: '#efeff1',
21
+ surface3: '#e3e3e7',
22
+ surface4: '#d0d0d6',
23
+ text0: '#111113',
24
+ text1: '#2e2e33',
25
+ text2: '#696969',
26
+ text3: '#9e9e9e',
27
+ accentDeep: '#004578',
28
+ accentBase: '#0078d4',
29
+ accentSoft: '#deecf9',
30
+ accentOnAccent: '#ffffff',
31
+ isDark: false
32
+ };
33
+
34
+ /** Microsoft blue dark palette (default). */
35
+ const darkTheme = exports.darkTheme = {
36
+ surface0: '#111113',
37
+ surface1: '#1c1c1f',
38
+ surface2: '#28282c',
39
+ surface3: '#333338',
40
+ surface4: '#404047',
41
+ text0: '#ededef',
42
+ text1: '#c8c8cc',
43
+ text2: '#9898a0',
44
+ text3: '#6b6b75',
45
+ accentDeep: '#82c7ff',
46
+ accentBase: '#2899f5',
47
+ accentSoft: '#0a2238',
48
+ accentOnAccent: '#ffffff',
49
+ isDark: true
50
+ };
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.base64ToDataUri = base64ToDataUri;
7
+ exports.base64ToDataverseUploadFile = base64ToDataverseUploadFile;
8
+ exports.base64ToUint8Array = base64ToUint8Array;
9
+ exports.createDataverseUploadFile = createDataverseUploadFile;
10
+ exports.detectImageMime = detectImageMime;
11
+ exports.readFileAsUint8Array = readFileAsUint8Array;
12
+ var _legacy = require("expo-file-system/legacy");
13
+ /**
14
+ * Utilities for reading local file:// URIs and converting them into the binary
15
+ * format expected by the Dataverse upload endpoint via NativePowerAppsBridge.
16
+ *
17
+ * Background:
18
+ * - `fetch('file://')` fails silently on Android.
19
+ * - `fetch('data:...')` throws "Network request failed" on Android.
20
+ * - `new Blob([Uint8Array])` crashes Hermes ("ArrayBufferView not supported").
21
+ * - NativePowerAppsBridge accepts `Uint8Array` and extracts `.buffer` as the
22
+ * fetch body, which React Native sends as raw bytes correctly.
23
+ *
24
+ * Solution: read via `readAsStringAsync` (base64) → `atob` → `Uint8Array`.
25
+ */
26
+
27
+ /**
28
+ * Read a local `file://` URI and return its contents as a `Uint8Array`.
29
+ * Safe on both Android and iOS.
30
+ */
31
+ async function readFileAsUint8Array(uri) {
32
+ const base64 = await (0, _legacy.readAsStringAsync)(uri, {
33
+ encoding: _legacy.EncodingType.Base64
34
+ });
35
+ return base64ToUint8Array(base64);
36
+ }
37
+
38
+ /**
39
+ * Detect the image MIME type from the first bytes of a base64-encoded string.
40
+ * Returns 'image/jpeg' as a safe default.
41
+ */
42
+ function detectImageMime(base64) {
43
+ const normalized = normalizeBase64(base64);
44
+ if (normalized.startsWith('iVBOR')) return 'image/png';
45
+ if (normalized.startsWith('R0lG')) return 'image/gif';
46
+ if (normalized.startsWith('Qk')) return 'image/bmp';
47
+ if (normalized.startsWith('UklGR')) return 'image/webp';
48
+ return 'image/jpeg';
49
+ }
50
+ function normalizeBase64(base64) {
51
+ return base64.includes('base64,') ? base64.slice(base64.indexOf('base64,') + 'base64,'.length) : base64;
52
+ }
53
+
54
+ /** Convert a base64 string into bytes suitable for Dataverse binary upload APIs. */
55
+ function base64ToUint8Array(base64) {
56
+ const normalized = normalizeBase64(base64);
57
+ const binaryString = atob(normalized);
58
+ const uint8 = new Uint8Array(binaryString.length);
59
+ for (let i = 0; i < binaryString.length; i++) {
60
+ uint8[i] = binaryString.charCodeAt(i);
61
+ }
62
+ return uint8;
63
+ }
64
+ function uint8ArrayToArrayBuffer(bytes) {
65
+ const copy = new Uint8Array(bytes.byteLength);
66
+ copy.set(bytes);
67
+ return copy.buffer;
68
+ }
69
+
70
+ /**
71
+ * Create a lightweight File-compatible object for generated Dataverse upload methods.
72
+ * React Native does not consistently provide a browser File implementation, but the
73
+ * generated services only require `name` and `arrayBuffer()`.
74
+ */
75
+ function createDataverseUploadFile(name, mimeType, bytes) {
76
+ return {
77
+ name,
78
+ type: mimeType,
79
+ size: bytes.byteLength,
80
+ arrayBuffer: async () => uint8ArrayToArrayBuffer(bytes)
81
+ };
82
+ }
83
+
84
+ /** Create a File-compatible image object from Dataverse-style base64 image content. */
85
+ function base64ToDataverseUploadFile(base64, name = 'image') {
86
+ const bytes = base64ToUint8Array(base64);
87
+ const mimeType = detectImageMime(base64);
88
+ const extension = mimeType.slice('image/'.length).replace('jpeg', 'jpg');
89
+ return createDataverseUploadFile(name.includes('.') ? name : `${name}.${extension}`, mimeType, bytes);
90
+ }
91
+
92
+ /**
93
+ * Build a `data:<mime>;base64,<data>` URI from a raw base64 string returned
94
+ * by Dataverse for an image column.
95
+ */
96
+ function base64ToDataUri(base64) {
97
+ return `data:${detectImageMime(base64)};base64,${base64}`;
98
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isDevPlayer = void 0;
7
+ var _reactNative = require("react-native");
8
+ var _expoConstants = _interopRequireDefault(require("expo-constants"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ /**
11
+ * True when the JS bundle is running inside the Power Apps Dev Player shell.
12
+ *
13
+ * Two signals are combined to cover both execution paths:
14
+ *
15
+ * 1. `Constants.expoConfig.extra.isDevPlayer` — set in apps/dev-player/app.config.js.
16
+ * Fires when the dev-player's **own** JS bundle is active (e.g. the launcher screen).
17
+ *
18
+ * 2. `NativeModules.PowerAppsDevLauncher` — the dev-player's Expo native module,
19
+ * registered in the dev-player APK/IPA regardless of which JS bundle is loaded.
20
+ * Fires when a template bundle is loaded via QR-code/URL into the dev-player shell,
21
+ * because expo-constants then reflects the template's manifest (no isDevPlayer flag)
22
+ * but the native module is still present in the host binary.
23
+ *
24
+ * Neither signal fires in a standalone release APK generated from the template, so
25
+ * `isDevPlayer` is false there and all debug logging is silenced.
26
+ */
27
+ const isDevPlayer = exports.isDevPlayer = _expoConstants.default.expoConfig?.extra?.isDevPlayer === true || !!_reactNative.NativeModules.PowerAppsDevLauncher;