@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.
- package/README.md +21 -10
- package/compatibility/current.json +31 -4
- package/lib/NOTICE.txt +1325 -24
- package/lib/commonjs/auth/AuthContext.js +110 -33
- package/lib/commonjs/bridge/NativePowerAppsBridge.js +11 -18
- package/lib/commonjs/bridge/PowerPagesBridge.js +27 -8
- package/lib/commonjs/bridge/bridgeState.js +40 -0
- package/lib/commonjs/config/babelConfig.js +13 -0
- package/lib/commonjs/config/expoConfig.js +71 -0
- package/lib/commonjs/config/metroConfig.js +70 -0
- package/lib/commonjs/config/metroLogger.js +182 -0
- package/lib/commonjs/config/tamaguiConfig.js +98 -0
- package/lib/commonjs/connections/ConnectionSetupScreen.js +459 -80
- package/lib/commonjs/connections/PowerPlatformConnectionApi.js +946 -0
- package/lib/commonjs/connections/connectionMetadata.js +127 -0
- package/lib/commonjs/connections/connectionState.js +96 -0
- package/lib/commonjs/connections/disambiguate.js +19 -11
- package/lib/commonjs/connections/resolveConnections.js +348 -0
- package/lib/commonjs/connections/types.js +106 -0
- package/lib/commonjs/{platform → connections}/useConnectionRefs.js +130 -65
- package/lib/commonjs/connections/useConnectionSetup.js +111 -52
- package/lib/commonjs/controls/FilePicker.js +6 -0
- package/lib/commonjs/controls/ImagePicker.js +8 -0
- package/lib/commonjs/index.js +167 -4
- package/lib/commonjs/logger.js +9 -6
- package/lib/commonjs/offline/createOfflineHostActivationCallbacks.js +61 -0
- package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.js +48 -0
- package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.web.js +13 -0
- package/lib/commonjs/platform/DataverseDataSources.js +18 -0
- package/lib/commonjs/platform/DataverseGlobalDiscoveryApi.js +94 -0
- package/lib/commonjs/platform/GlobalDiscovery.js +51 -0
- package/lib/commonjs/platform/PowerPlatformEnvironmentApi.js +6 -106
- package/lib/commonjs/provider/PowerAppsHostProvider.js +157 -25
- package/lib/commonjs/provider/PowerAppsProvider.js +178 -134
- package/lib/commonjs/provider/SessionDetailsGesture.js +208 -0
- package/lib/commonjs/telemetry/OfflineSdkTelemetry.js +95 -0
- package/lib/commonjs/telemetry/OfflineSdkTelemetry.web.js +9 -0
- package/lib/commonjs/telemetry/index.js +22 -3
- package/lib/module/auth/AuthContext.js +110 -33
- package/lib/module/bridge/NativePowerAppsBridge.js +12 -19
- package/lib/module/bridge/PowerPagesBridge.js +27 -8
- package/lib/module/bridge/bridgeState.js +34 -0
- package/lib/module/config/babelConfig.js +9 -0
- package/lib/module/config/expoConfig.js +67 -0
- package/lib/module/config/metroConfig.js +65 -0
- package/lib/module/config/metroLogger.js +175 -0
- package/lib/module/config/tamaguiConfig.js +93 -0
- package/lib/module/connections/ConnectionSetupScreen.js +460 -81
- package/lib/module/connections/PowerPlatformConnectionApi.js +932 -0
- package/lib/module/connections/connectionMetadata.js +112 -0
- package/lib/module/connections/connectionState.js +82 -0
- package/lib/module/connections/disambiguate.js +19 -12
- package/lib/module/connections/resolveConnections.js +343 -0
- package/lib/module/connections/types.js +91 -0
- package/lib/module/{platform → connections}/useConnectionRefs.js +131 -66
- package/lib/module/connections/useConnectionSetup.js +113 -54
- package/lib/module/controls/FilePicker.js +6 -0
- package/lib/module/controls/ImagePicker.js +8 -0
- package/lib/module/index.js +14 -4
- package/lib/module/logger.js +8 -6
- package/lib/module/offline/createOfflineHostActivationCallbacks.js +55 -0
- package/lib/module/offline/useOfflineIntegrationWithStartupGate.js +44 -0
- package/lib/module/offline/useOfflineIntegrationWithStartupGate.web.js +9 -0
- package/lib/module/platform/DataverseDataSources.js +13 -0
- package/lib/module/platform/DataverseGlobalDiscoveryApi.js +89 -0
- package/lib/module/platform/GlobalDiscovery.js +45 -0
- package/lib/module/platform/PowerPlatformEnvironmentApi.js +5 -104
- package/lib/module/provider/PowerAppsHostProvider.js +160 -28
- package/lib/module/provider/PowerAppsProvider.js +182 -138
- package/lib/module/provider/SessionDetailsGesture.js +203 -0
- package/lib/module/telemetry/OfflineSdkTelemetry.js +91 -0
- package/lib/module/telemetry/OfflineSdkTelemetry.web.js +5 -0
- package/lib/module/telemetry/index.js +15 -4
- package/lib/typescript/commonjs/auth/AuthContext.d.ts +3 -1
- package/lib/typescript/commonjs/auth/AuthContext.web.d.ts +1 -0
- package/lib/typescript/commonjs/bridge/bridgeState.d.ts +5 -0
- package/lib/typescript/commonjs/config/babelConfig.d.ts +12 -0
- package/lib/typescript/commonjs/config/expoConfig.d.ts +21 -0
- package/lib/typescript/commonjs/config/metroConfig.d.ts +6 -0
- package/lib/typescript/commonjs/config/metroLogger.d.ts +21 -0
- package/lib/typescript/commonjs/config/tamaguiConfig.d.ts +1792 -0
- package/lib/typescript/commonjs/connections/ConnectionSetupScreen.d.ts +28 -7
- package/lib/typescript/commonjs/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
- package/lib/typescript/commonjs/connections/connectionMetadata.d.ts +66 -0
- package/lib/typescript/commonjs/connections/connectionState.d.ts +16 -0
- package/lib/typescript/commonjs/connections/disambiguate.d.ts +4 -2
- package/lib/typescript/commonjs/{platform → connections}/resolveConnections.d.ts +22 -20
- package/lib/typescript/commonjs/connections/types.d.ts +129 -1
- package/lib/typescript/commonjs/{platform → connections}/useConnectionRefs.d.ts +36 -25
- package/lib/typescript/commonjs/connections/useConnectionSetup.d.ts +12 -8
- package/lib/typescript/commonjs/controls/FilePicker.d.ts +7 -1
- package/lib/typescript/commonjs/controls/ImagePicker.d.ts +9 -1
- package/lib/typescript/commonjs/index.d.ts +18 -10
- package/lib/typescript/commonjs/logger.d.ts +4 -4
- package/lib/typescript/commonjs/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
- package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
- package/lib/typescript/commonjs/platform/DataverseDataSources.d.ts +28 -0
- package/lib/typescript/commonjs/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
- package/lib/typescript/commonjs/platform/GlobalDiscovery.d.ts +4 -0
- package/lib/typescript/commonjs/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
- package/lib/typescript/commonjs/provider/PowerAppsHostProvider.d.ts +29 -18
- package/lib/typescript/commonjs/provider/PowerAppsProvider.d.ts +54 -9
- package/lib/typescript/commonjs/provider/SessionDetailsGesture.d.ts +13 -0
- package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.d.ts +15 -0
- package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
- package/lib/typescript/commonjs/telemetry/index.d.ts +13 -1
- package/lib/typescript/module/auth/AuthContext.d.ts +3 -1
- package/lib/typescript/module/auth/AuthContext.web.d.ts +1 -0
- package/lib/typescript/module/bridge/bridgeState.d.ts +5 -0
- package/lib/typescript/module/config/babelConfig.d.ts +12 -0
- package/lib/typescript/module/config/expoConfig.d.ts +21 -0
- package/lib/typescript/module/config/metroConfig.d.ts +6 -0
- package/lib/typescript/module/config/metroLogger.d.ts +21 -0
- package/lib/typescript/module/config/tamaguiConfig.d.ts +1792 -0
- package/lib/typescript/module/connections/ConnectionSetupScreen.d.ts +28 -7
- package/lib/typescript/module/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
- package/lib/typescript/module/connections/connectionMetadata.d.ts +66 -0
- package/lib/typescript/module/connections/connectionState.d.ts +16 -0
- package/lib/typescript/module/connections/disambiguate.d.ts +4 -2
- package/lib/typescript/module/{platform → connections}/resolveConnections.d.ts +22 -20
- package/lib/typescript/module/connections/types.d.ts +129 -1
- package/lib/typescript/module/{platform → connections}/useConnectionRefs.d.ts +36 -25
- package/lib/typescript/module/connections/useConnectionSetup.d.ts +12 -8
- package/lib/typescript/module/controls/FilePicker.d.ts +7 -1
- package/lib/typescript/module/controls/ImagePicker.d.ts +9 -1
- package/lib/typescript/module/index.d.ts +18 -10
- package/lib/typescript/module/logger.d.ts +4 -4
- package/lib/typescript/module/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
- package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
- package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
- package/lib/typescript/module/platform/DataverseDataSources.d.ts +28 -0
- package/lib/typescript/module/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
- package/lib/typescript/module/platform/GlobalDiscovery.d.ts +4 -0
- package/lib/typescript/module/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
- package/lib/typescript/module/provider/PowerAppsHostProvider.d.ts +29 -18
- package/lib/typescript/module/provider/PowerAppsProvider.d.ts +54 -9
- package/lib/typescript/module/provider/SessionDetailsGesture.d.ts +13 -0
- package/lib/typescript/module/telemetry/OfflineSdkTelemetry.d.ts +15 -0
- package/lib/typescript/module/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
- package/lib/typescript/module/telemetry/index.d.ts +13 -1
- package/package.json +52 -13
- package/scripts/build-codegen-package.js +283 -0
- package/scripts/start-web.mjs +9 -5
- package/scripts/upgrade/runtime.js +139 -24
- package/scripts/upgrade-authoring.js +274 -180
- package/scripts/upgrade.js +10 -16
- package/src/config/generated-config.d.ts +4 -0
- package/src/config/index.d.ts +3 -0
- package/src/config/tsconfig.json +26 -0
- package/lib/commonjs/platform/PowerPlatformConnectionApi.js +0 -606
- package/lib/commonjs/platform/resolveConnections.js +0 -264
- package/lib/module/platform/PowerPlatformConnectionApi.js +0 -595
- package/lib/module/platform/resolveConnections.js +0 -259
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createHostQueryClient = createHostQueryClient;
|
|
7
|
+
exports.createOfflineHostActivationCallbacks = createOfflineHostActivationCallbacks;
|
|
8
|
+
exports.resolveSdkMountDecision = resolveSdkMountDecision;
|
|
9
|
+
var _reactQuery = require("@tanstack/react-query");
|
|
10
|
+
function setNetworkMode(queryClient, networkMode) {
|
|
11
|
+
const current = queryClient.getDefaultOptions();
|
|
12
|
+
queryClient.setDefaultOptions({
|
|
13
|
+
...current,
|
|
14
|
+
queries: {
|
|
15
|
+
...current.queries,
|
|
16
|
+
staleTime: 60_000,
|
|
17
|
+
retry: 2,
|
|
18
|
+
networkMode
|
|
19
|
+
},
|
|
20
|
+
mutations: {
|
|
21
|
+
...current.mutations,
|
|
22
|
+
retry: 0,
|
|
23
|
+
networkMode
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function createHostQueryClient() {
|
|
28
|
+
return new _reactQuery.QueryClient({
|
|
29
|
+
defaultOptions: {
|
|
30
|
+
queries: {
|
|
31
|
+
staleTime: 60_000,
|
|
32
|
+
retry: 2
|
|
33
|
+
},
|
|
34
|
+
mutations: {
|
|
35
|
+
retry: 0
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function createOfflineHostActivationCallbacks(queryClient) {
|
|
41
|
+
return {
|
|
42
|
+
prepareForOfflineActivation: () => queryClient.cancelQueries(),
|
|
43
|
+
completeOfflineActivation: async () => {
|
|
44
|
+
setNetworkMode(queryClient, 'always');
|
|
45
|
+
await queryClient.invalidateQueries();
|
|
46
|
+
},
|
|
47
|
+
rollbackOfflineActivation: async () => {
|
|
48
|
+
setNetworkMode(queryClient, undefined);
|
|
49
|
+
await queryClient.invalidateQueries();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function resolveSdkMountDecision(value) {
|
|
54
|
+
return typeof value === 'boolean' ? {
|
|
55
|
+
shouldMountChildren: value,
|
|
56
|
+
contractSupported: true
|
|
57
|
+
} : {
|
|
58
|
+
shouldMountChildren: true,
|
|
59
|
+
contractSupported: false
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useOfflineIntegrationWithStartupGate = useOfflineIntegrationWithStartupGate;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _reactQuery = require("@tanstack/react-query");
|
|
9
|
+
var _powerAppsNativeCommon = require("@microsoft/power-apps-native-common");
|
|
10
|
+
var _DataverseGlobalDiscoveryApi = require("../platform/DataverseGlobalDiscoveryApi.js");
|
|
11
|
+
var _DataverseDataSources = require("../platform/DataverseDataSources.js");
|
|
12
|
+
var _index = require("../telemetry/index.js");
|
|
13
|
+
var _createOfflineHostActivationCallbacks = require("./createOfflineHostActivationCallbacks.js");
|
|
14
|
+
var _useOfflineIntegration = require("./useOfflineIntegration");
|
|
15
|
+
function useOfflineIntegrationWithStartupGate({
|
|
16
|
+
powerConfig,
|
|
17
|
+
offlineProfile,
|
|
18
|
+
acquireToken,
|
|
19
|
+
hasRealAccount,
|
|
20
|
+
isAuthReady
|
|
21
|
+
}) {
|
|
22
|
+
const queryClient = (0, _reactQuery.useQueryClient)();
|
|
23
|
+
const hasDataverse = (0, _DataverseDataSources.hasDataverseDatabaseReferences)(powerConfig.databaseReferences);
|
|
24
|
+
const resolveInstanceUrl = (0, _react.useCallback)(async (environmentId, region, acqToken) => hasDataverse ? (await (0, _DataverseGlobalDiscoveryApi.fetchInstanceUrl)(environmentId, region, acqToken)) ?? null : null, [hasDataverse]);
|
|
25
|
+
const hostActivationCallbacks = (0, _react.useMemo)(() => (0, _createOfflineHostActivationCallbacks.createOfflineHostActivationCallbacks)(queryClient), [queryClient]);
|
|
26
|
+
const offline = (0, _useOfflineIntegration.useOfflineIntegration)({
|
|
27
|
+
powerConfig,
|
|
28
|
+
offlineProfile,
|
|
29
|
+
acquireToken,
|
|
30
|
+
isSignedIn: hasRealAccount,
|
|
31
|
+
authState: isAuthReady ? hasRealAccount ? 'authenticated' : 'signed-out' : 'hydrating',
|
|
32
|
+
fetchInstanceUrl: resolveInstanceUrl,
|
|
33
|
+
hostActivationCallbacks
|
|
34
|
+
});
|
|
35
|
+
const mountDecision = (0, _createOfflineHostActivationCallbacks.resolveSdkMountDecision)(offline.shouldMountChildren);
|
|
36
|
+
(0, _react.useEffect)(() => {
|
|
37
|
+
if (!mountDecision.contractSupported) {
|
|
38
|
+
(0, _powerAppsNativeCommon.getAppLogger)().trackErrorEvent(_index.HostOperationNames.OfflineRoutingContractUnsupported, {
|
|
39
|
+
fallbackRoute: 'online'
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}, [mountDecision.contractSupported]);
|
|
43
|
+
return {
|
|
44
|
+
isEnabled: offline.isEnabled,
|
|
45
|
+
StatusOverlay: offline.StatusOverlay,
|
|
46
|
+
shouldMountChildren: mountDecision.shouldMountChildren
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useOfflineIntegrationWithStartupGate = useOfflineIntegrationWithStartupGate;
|
|
7
|
+
function useOfflineIntegrationWithStartupGate(_options) {
|
|
8
|
+
return {
|
|
9
|
+
isEnabled: false,
|
|
10
|
+
StatusOverlay: null,
|
|
11
|
+
shouldMountChildren: true
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.buildCdsDataSources = buildCdsDataSources;
|
|
7
|
+
exports.hasDataverseDatabaseReferences = hasDataverseDatabaseReferences;
|
|
8
|
+
function hasDataverseDatabaseReferences(databaseReferences) {
|
|
9
|
+
return Object.keys(databaseReferences ?? {}).length > 0;
|
|
10
|
+
}
|
|
11
|
+
function buildCdsDataSources(databaseReferences, dataverseOrgUrl) {
|
|
12
|
+
return Object.values(databaseReferences).flatMap(databaseReference => Object.values(databaseReference.dataSources ?? {}).map(dataSource => ({
|
|
13
|
+
runtimeUrl: dataverseOrgUrl ? `${dataverseOrgUrl}/api/data/v9.0/` : '',
|
|
14
|
+
entitySetName: dataSource.entitySetName ?? '',
|
|
15
|
+
logicalName: dataSource.logicalName ?? '',
|
|
16
|
+
version: '9.2'
|
|
17
|
+
})));
|
|
18
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.fetchInstanceUrl = fetchInstanceUrl;
|
|
7
|
+
var _http = require("@microsoft/power-apps-native-common/http");
|
|
8
|
+
var SecureStore = _interopRequireWildcard(require("expo-secure-store"));
|
|
9
|
+
var _index = require("../telemetry/index.js");
|
|
10
|
+
var _GlobalDiscovery = require("./GlobalDiscovery.js");
|
|
11
|
+
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); }
|
|
12
|
+
const INSTANCE_URL_CACHE_KEY_PREFIX = 'microsoft.power-apps-native-host.instance-url.v1';
|
|
13
|
+
const INSTANCE_URL_CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
14
|
+
function getInstanceUrlCacheKey(environmentId, region) {
|
|
15
|
+
return `${INSTANCE_URL_CACHE_KEY_PREFIX}.${region.toLowerCase()}.${environmentId.toLowerCase()}`;
|
|
16
|
+
}
|
|
17
|
+
async function getCachedInstanceUrl(environmentId, region) {
|
|
18
|
+
try {
|
|
19
|
+
const cachedValue = await SecureStore.getItemAsync(getInstanceUrlCacheKey(environmentId, region));
|
|
20
|
+
if (!cachedValue) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const entry = JSON.parse(cachedValue);
|
|
24
|
+
if (typeof entry.instanceUrl !== 'string' || typeof entry.expiresAt !== 'number' || entry.expiresAt <= Date.now()) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return entry.instanceUrl;
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function cacheInstanceUrl(environmentId, region, instanceUrl) {
|
|
33
|
+
try {
|
|
34
|
+
const entry = {
|
|
35
|
+
instanceUrl,
|
|
36
|
+
expiresAt: Date.now() + INSTANCE_URL_CACHE_TTL_MS
|
|
37
|
+
};
|
|
38
|
+
await SecureStore.setItemAsync(getInstanceUrlCacheKey(environmentId, region), JSON.stringify(entry));
|
|
39
|
+
} catch {
|
|
40
|
+
// SecureStore may be unavailable (for example, on web); discovery still succeeds.
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function getSafeErrorName(error) {
|
|
44
|
+
return error instanceof Error ? error.constructor.name : typeof error;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Fetch the Dataverse instance URL from the Dataverse Global Discovery Service. */
|
|
48
|
+
async function fetchInstanceUrl(environmentId, region, acquireToken, _bearerToken) {
|
|
49
|
+
const scenario = (0, _index.getAppLogger)().trackScenario(_index.HostOperationNames.PlatformFetchInstanceUrl, {
|
|
50
|
+
environmentId,
|
|
51
|
+
region
|
|
52
|
+
});
|
|
53
|
+
try {
|
|
54
|
+
const cachedInstanceUrl = await getCachedInstanceUrl(environmentId, region);
|
|
55
|
+
if (cachedInstanceUrl) {
|
|
56
|
+
scenario.complete({
|
|
57
|
+
hasInstanceUrl: true,
|
|
58
|
+
cacheHit: true
|
|
59
|
+
});
|
|
60
|
+
return cachedInstanceUrl;
|
|
61
|
+
}
|
|
62
|
+
const url = (0, _GlobalDiscovery.buildGlobalDiscoveryUrl)(environmentId, region);
|
|
63
|
+
const token = await acquireToken([(0, _GlobalDiscovery.globalDiscoveryScope)(region)]);
|
|
64
|
+
if (!token) {
|
|
65
|
+
throw new Error('fetchInstanceUrl: failed to acquire Dataverse Global Discovery token');
|
|
66
|
+
}
|
|
67
|
+
const response = await _index.platformHttpClient.request(url, {
|
|
68
|
+
method: 'GET',
|
|
69
|
+
headers: {
|
|
70
|
+
Authorization: `Bearer ${token}`,
|
|
71
|
+
'Content-Type': 'application/json'
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
throw new Error(`fetchInstanceUrl: Global Discovery returned ${response.status} ${response.statusText}`);
|
|
76
|
+
}
|
|
77
|
+
const result = await response.json();
|
|
78
|
+
const instanceUrl = result.value?.find(instance => instance.EnvironmentId?.toLowerCase() === environmentId.toLowerCase())?.ApiUrl;
|
|
79
|
+
if (instanceUrl) {
|
|
80
|
+
await cacheInstanceUrl(environmentId, region, instanceUrl);
|
|
81
|
+
}
|
|
82
|
+
scenario.complete({
|
|
83
|
+
hasInstanceUrl: instanceUrl !== undefined,
|
|
84
|
+
cacheHit: false,
|
|
85
|
+
...(0, _http.getHttpCorrelationProperties)(response.headers)
|
|
86
|
+
});
|
|
87
|
+
return instanceUrl;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
scenario.fail(undefined, {
|
|
90
|
+
errorName: getSafeErrorName(error)
|
|
91
|
+
});
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.buildGlobalDiscoveryUrl = buildGlobalDiscoveryUrl;
|
|
7
|
+
exports.globalDiscoveryEndpoint = globalDiscoveryEndpoint;
|
|
8
|
+
exports.globalDiscoveryScope = globalDiscoveryScope;
|
|
9
|
+
const GLOBAL_DISCOVERY_HOST = {
|
|
10
|
+
prod: 'globaldisco.crm.dynamics.com',
|
|
11
|
+
gcc: 'globaldisco.crm9.dynamics.com',
|
|
12
|
+
usg: 'globaldisco.crm.microsoftdynamics.us',
|
|
13
|
+
dod: 'globaldisco.crm.appsplatform.us',
|
|
14
|
+
china: 'globaldisco.crm.dynamics.cn'
|
|
15
|
+
};
|
|
16
|
+
const REGION_DISCOVERY_CLOUD = {
|
|
17
|
+
dev: 'prod',
|
|
18
|
+
test: 'prod',
|
|
19
|
+
preprod: 'prod',
|
|
20
|
+
preview: 'prod',
|
|
21
|
+
firstrelease: 'prod',
|
|
22
|
+
prod: 'prod',
|
|
23
|
+
gccmoderate: 'gcc',
|
|
24
|
+
gov: 'gcc',
|
|
25
|
+
gcchigh: 'usg',
|
|
26
|
+
high: 'usg',
|
|
27
|
+
dod: 'dod',
|
|
28
|
+
mooncake: 'china'
|
|
29
|
+
};
|
|
30
|
+
const ENVIRONMENT_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31
|
+
function globalDiscoveryEndpoint(region) {
|
|
32
|
+
const cloud = REGION_DISCOVERY_CLOUD[region];
|
|
33
|
+
if (!cloud) {
|
|
34
|
+
throw new Error(`Dataverse Global Discovery is not available for Power Platform region "${region}"`);
|
|
35
|
+
}
|
|
36
|
+
return `https://${GLOBAL_DISCOVERY_HOST[cloud]}`;
|
|
37
|
+
}
|
|
38
|
+
function globalDiscoveryScope(region) {
|
|
39
|
+
return `${globalDiscoveryEndpoint(region)}/user_impersonation`;
|
|
40
|
+
}
|
|
41
|
+
function buildGlobalDiscoveryUrl(environmentId, region) {
|
|
42
|
+
if (!ENVIRONMENT_ID_PATTERN.test(environmentId)) {
|
|
43
|
+
throw new Error(`Invalid Power Platform environment ID: "${environmentId}"`);
|
|
44
|
+
}
|
|
45
|
+
const normalizedEnvironmentId = environmentId.toLowerCase();
|
|
46
|
+
const query = new URLSearchParams({
|
|
47
|
+
'$select': 'ApiUrl,EnvironmentId',
|
|
48
|
+
'$filter': `EnvironmentId eq '${normalizedEnvironmentId}'`
|
|
49
|
+
});
|
|
50
|
+
return `${globalDiscoveryEndpoint(region)}/api/discovery/v2.0/Instances?${query.toString()}`;
|
|
51
|
+
}
|
|
@@ -4,22 +4,13 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.POWER_PLATFORM_API_SCOPE = void 0;
|
|
7
|
-
exports.buildCdsDataSources = buildCdsDataSources;
|
|
8
7
|
exports.buildEnvironmentEndpoint = buildEnvironmentEndpoint;
|
|
9
|
-
exports.
|
|
8
|
+
exports.connectionUserConsentScope = connectionUserConsentScope;
|
|
10
9
|
exports.powerPlatformScope = powerPlatformScope;
|
|
11
|
-
var _index = require("../telemetry/index.js");
|
|
12
10
|
/*!
|
|
13
11
|
* power-apps-native-host — PowerPlatformEnvironmentApi
|
|
14
12
|
*
|
|
15
|
-
*
|
|
16
|
-
* pattern: resolves the Power Platform environment-scoped API endpoint from the
|
|
17
|
-
* environment GUID and region, then fetches linkedEnvironmentMetadata to obtain
|
|
18
|
-
* the Dataverse instanceUrl.
|
|
19
|
-
*
|
|
20
|
-
* Reference (Host SDK):
|
|
21
|
-
* packages/power-apps-host/src/providers/defaults/DefaultAppMetadataProvider.ts
|
|
22
|
-
* packages/power-apps-common/src/services/PowerPlatformApiDiscovery.ts
|
|
13
|
+
* Resolves Power Platform RP endpoints and scopes.
|
|
23
14
|
*/
|
|
24
15
|
|
|
25
16
|
// ---------------------------------------------------------------------------
|
|
@@ -78,10 +69,6 @@ function buildEnvironmentEndpoint(environmentId, region) {
|
|
|
78
69
|
return `https://${hexPrefix}.${hexSuffix}.environment.${hostNameSuffix}`;
|
|
79
70
|
}
|
|
80
71
|
|
|
81
|
-
// ---------------------------------------------------------------------------
|
|
82
|
-
// Public API
|
|
83
|
-
// ---------------------------------------------------------------------------
|
|
84
|
-
|
|
85
72
|
/**
|
|
86
73
|
* Token scope for the Power Platform management API (prod cluster).
|
|
87
74
|
* Non-prod clusters (test, gov, high, dev, mooncake, etc.) host the management
|
|
@@ -99,96 +86,9 @@ function powerPlatformScope(region) {
|
|
|
99
86
|
const host = HOST_NAME_SUFFIX[region] ?? HOST_NAME_SUFFIX['prod'];
|
|
100
87
|
return `https://${host}/.default`;
|
|
101
88
|
}
|
|
102
|
-
function getSafeErrorName(error) {
|
|
103
|
-
return error instanceof Error ? error.constructor.name : typeof error;
|
|
104
|
-
}
|
|
105
89
|
|
|
106
|
-
/**
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
* `databaseReferences[*].databaseDetails.linkedEnvironmentMetadata`.
|
|
111
|
-
*
|
|
112
|
-
* @param environmentId - Environment GUID (from power.config.json `environmentId`).
|
|
113
|
-
* @param region - Cluster region string (from power.config.json `region`, default "prod").
|
|
114
|
-
* @param acquireToken - Callback to obtain a bearer token for the given scopes.
|
|
115
|
-
* Scope will be {@link powerPlatformScope}`(region)`.
|
|
116
|
-
* @param bearerToken - Optional pre-fetched bearer token for {@link powerPlatformScope}`(region)`.
|
|
117
|
-
* Pass this to avoid a redundant `acquireToken` round-trip when the
|
|
118
|
-
* caller has already obtained a token for the same audience.
|
|
119
|
-
* @returns The Dataverse org URL (e.g. "https://org12345.crm.dynamics.com"), or
|
|
120
|
-
* `undefined` if the environment has no linked CDS database.
|
|
121
|
-
*/
|
|
122
|
-
async function fetchInstanceUrl(environmentId, region, acquireToken, bearerToken) {
|
|
123
|
-
const scenario = (0, _index.getAppLogger)().trackScenario(_index.HostOperationNames.PlatformFetchInstanceUrl, {
|
|
124
|
-
environmentId,
|
|
125
|
-
region
|
|
126
|
-
});
|
|
127
|
-
try {
|
|
128
|
-
const baseUrl = buildEnvironmentEndpoint(environmentId, region);
|
|
129
|
-
const url = `${baseUrl}/powerapps/environment?api-version=1&%24filter=name+eq+%27${encodeURIComponent(environmentId)}%27`;
|
|
130
|
-
const token = bearerToken ?? (await acquireToken([powerPlatformScope(region)]));
|
|
131
|
-
if (!token) {
|
|
132
|
-
throw new Error('fetchInstanceUrl: failed to acquire Power Platform API token');
|
|
133
|
-
}
|
|
134
|
-
const response = await fetch(url, {
|
|
135
|
-
method: 'GET',
|
|
136
|
-
headers: {
|
|
137
|
-
Authorization: `Bearer ${token}`,
|
|
138
|
-
'Content-Type': 'application/json'
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
if (!response.ok) {
|
|
142
|
-
throw new Error(`fetchInstanceUrl: environment API returned ${response.status} ${response.statusText}`);
|
|
143
|
-
}
|
|
144
|
-
const env = await response.json();
|
|
145
|
-
const instanceUrl = env.properties?.linkedEnvironmentMetadata?.instanceUrl;
|
|
146
|
-
scenario.complete({
|
|
147
|
-
hasInstanceUrl: instanceUrl !== undefined
|
|
148
|
-
});
|
|
149
|
-
return instanceUrl;
|
|
150
|
-
} catch (e) {
|
|
151
|
-
scenario.fail(undefined, {
|
|
152
|
-
errorName: getSafeErrorName(e)
|
|
153
|
-
});
|
|
154
|
-
throw e;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// ---------------------------------------------------------------------------
|
|
159
|
-
// buildCdsDataSources
|
|
160
|
-
// ---------------------------------------------------------------------------
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Shape of a single Dataverse table entry inside power.config.json
|
|
164
|
-
* `databaseReferences[*].dataSources[*]`.
|
|
165
|
-
*/
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Shape of a single database reference entry inside power.config.json
|
|
169
|
-
* `databaseReferences`.
|
|
170
|
-
*/
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Build the CDS data source config array that the SDK reads via
|
|
174
|
-
* AppPowerAppsClientPlugin.getAppCdsDataSourceConfigsAsync.
|
|
175
|
-
*
|
|
176
|
-
* Pass the resolved Dataverse org URL (from useConnectionRefs) and the
|
|
177
|
-
* databaseReferences map from power.config.json. The resulting array is
|
|
178
|
-
* passed directly to <PowerAppsHostProvider dataSources={...} />.
|
|
179
|
-
*
|
|
180
|
-
* @param databaseReferences - The `databaseReferences` map from power.config.json.
|
|
181
|
-
* @param dataverseOrgUrl - The resolved Dataverse org URL
|
|
182
|
-
* (connectionRefs['commondataserviceforapps']?.datasetName).
|
|
183
|
-
* Pass an empty string before the org URL is known;
|
|
184
|
-
* the host provider will receive empty runtimeUrl entries
|
|
185
|
-
* and the SDK will not attempt Dataverse calls.
|
|
186
|
-
*/
|
|
187
|
-
function buildCdsDataSources(databaseReferences, dataverseOrgUrl) {
|
|
188
|
-
return Object.values(databaseReferences).flatMap(dbRef => Object.values(dbRef.dataSources ?? {}).map(ds => ({
|
|
189
|
-
runtimeUrl: dataverseOrgUrl ? `${dataverseOrgUrl}/api/data/v9.0/` : '',
|
|
190
|
-
entitySetName: ds.entitySetName ?? '',
|
|
191
|
-
logicalName: ds.logicalName ?? '',
|
|
192
|
-
version: '9.2'
|
|
193
|
-
})));
|
|
90
|
+
/** Delegated permission required by the connection user-consent endpoint. */
|
|
91
|
+
function connectionUserConsentScope(region) {
|
|
92
|
+
const host = HOST_NAME_SUFFIX[region] ?? HOST_NAME_SUFFIX['prod'];
|
|
93
|
+
return `https://${host}/Connectivity.Connections.UserConsent`;
|
|
194
94
|
}
|