@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,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import { getDefaultConfig } from 'expo/metro-config.js';
|
|
7
|
+
import { withPowerNativeMetroLogging } from "./metroLogger.js";
|
|
8
|
+
function nativeRuntimeVersions(projectRoot) {
|
|
9
|
+
const appConfig = JSON.parse(fs.readFileSync(path.join(projectRoot, 'app.json'), 'utf8'));
|
|
10
|
+
const versions = appConfig.expo?.extra?.powerappsNative?.nativeRuntimeVersions;
|
|
11
|
+
if (!Number.isInteger(versions?.android) || versions.android < 1 || !Number.isInteger(versions?.ios) || versions.ios < 1) {
|
|
12
|
+
throw new Error('app.json is missing valid expo.extra.powerappsNative.nativeRuntimeVersions');
|
|
13
|
+
}
|
|
14
|
+
return versions;
|
|
15
|
+
}
|
|
16
|
+
function templateVersion(projectRoot) {
|
|
17
|
+
const appConfig = JSON.parse(fs.readFileSync(path.join(projectRoot, 'app.json'), 'utf8'));
|
|
18
|
+
const version = appConfig.expo?.extra?.powerappsNative?.templateVersion;
|
|
19
|
+
if (!Number.isInteger(version) || version < 1) {
|
|
20
|
+
throw new Error('app.json is missing a valid expo.extra.powerappsNative.templateVersion');
|
|
21
|
+
}
|
|
22
|
+
return version;
|
|
23
|
+
}
|
|
24
|
+
export function createPowerAppsMetroConfig(projectRoot, customize = config => config) {
|
|
25
|
+
const projectRequire = createRequire(path.join(projectRoot, 'package.json'));
|
|
26
|
+
const config = getDefaultConfig(projectRoot);
|
|
27
|
+
config.resolver.sourceExts = [...config.resolver.sourceExts, 'mjs'];
|
|
28
|
+
config.server = {
|
|
29
|
+
...config.server,
|
|
30
|
+
enhanceMiddleware: middleware => withPowerNativeMetroLogging((request, response, next) => {
|
|
31
|
+
if (request.url === '/__pawrap_verify') {
|
|
32
|
+
response.setHeader('Content-Type', 'application/json');
|
|
33
|
+
response.setHeader('Access-Control-Allow-Origin', '*');
|
|
34
|
+
response.end(JSON.stringify({
|
|
35
|
+
type: 'pawrap-app',
|
|
36
|
+
version: '1',
|
|
37
|
+
templateVersion: templateVersion(projectRoot),
|
|
38
|
+
nativeRuntimeVersions: nativeRuntimeVersions(projectRoot)
|
|
39
|
+
}));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
middleware(request, response, next);
|
|
43
|
+
}, {
|
|
44
|
+
projectRoot
|
|
45
|
+
})
|
|
46
|
+
};
|
|
47
|
+
const defaultResolver = config.resolver.resolveRequest;
|
|
48
|
+
const resolveRequest = (context, moduleName, platform) => {
|
|
49
|
+
const isNodeRenderer = context.customResolverOptions?.environment === 'node';
|
|
50
|
+
if (!isNodeRenderer && (moduleName === 'react' || moduleName.startsWith('react/')) || moduleName === 'react-native' && platform !== 'web' || moduleName.startsWith('@babel/runtime')) {
|
|
51
|
+
return {
|
|
52
|
+
filePath: projectRequire.resolve(moduleName, {
|
|
53
|
+
paths: [path.resolve(projectRoot, 'node_modules')]
|
|
54
|
+
}),
|
|
55
|
+
type: 'sourceFile'
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return defaultResolver ? defaultResolver(context, moduleName, platform) : context.resolveRequest(context, moduleName, platform);
|
|
59
|
+
};
|
|
60
|
+
config.resolver = {
|
|
61
|
+
...config.resolver,
|
|
62
|
+
resolveRequest
|
|
63
|
+
};
|
|
64
|
+
return customize(config);
|
|
65
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
const SENSITIVE_LINE_PATTERN = /\b(?:authorization|bearer|client[_-]?secret|password|token|access[_-]?token|refresh[_-]?token|id[_-]?token|api[_-]?key|accountkey|sharedaccesskey)\b|[?&](?:sig|se|sp|sv|token|access_token|code|client_secret)=|\b(?:AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{30,}|sk-[A-Za-z0-9]{20,})\b/i;
|
|
6
|
+
const DEFAULT_MAX_ERROR_BODY_BYTES = 256 * 1024;
|
|
7
|
+
const stateByRoot = new Map();
|
|
8
|
+
function stripAnsi(value) {
|
|
9
|
+
return String(value).replace(/[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d\/#&.:=?%@~_]+)*)?\u0007)|(?:(?:\d{1,4}(?:[;:]\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g, '');
|
|
10
|
+
}
|
|
11
|
+
export function redactMetroLog(value) {
|
|
12
|
+
return stripAnsi(value).replace(/[^\r\n]*(?:\r\n|\r|\n)|[^\r\n]+$/g, line => {
|
|
13
|
+
if (!SENSITIVE_LINE_PATTERN.test(line)) return line;
|
|
14
|
+
const ending = line.endsWith('\r\n') ? '\r\n' : line.endsWith('\n') ? '\n' : line.endsWith('\r') ? '\r' : '';
|
|
15
|
+
return `[powernative] [REDACTED_SENSITIVE_LINE]${ending}`;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function toError(value) {
|
|
19
|
+
return value instanceof Error ? value : new Error(String(value));
|
|
20
|
+
}
|
|
21
|
+
function writeDiagnostic(state, message) {
|
|
22
|
+
try {
|
|
23
|
+
state.diagnosticWrite(message);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
state.diagnosticWriteError = toError(error);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function reportInstrumentationError(state, error, phase) {
|
|
29
|
+
if (state.instrumentationError) return;
|
|
30
|
+
const normalizedError = toError(error);
|
|
31
|
+
const context = {
|
|
32
|
+
phase,
|
|
33
|
+
logPath: state.logPath
|
|
34
|
+
};
|
|
35
|
+
state.instrumentationError = {
|
|
36
|
+
error: normalizedError,
|
|
37
|
+
context
|
|
38
|
+
};
|
|
39
|
+
if (state.onError) {
|
|
40
|
+
try {
|
|
41
|
+
state.onError(normalizedError, context);
|
|
42
|
+
return;
|
|
43
|
+
} catch (callbackError) {
|
|
44
|
+
state.onErrorFailure = toError(callbackError);
|
|
45
|
+
writeDiagnostic(state, `[powernative] Metro logging instrumentation failed during ${phase}: ${normalizedError.message}; onError callback also failed: ${state.onErrorFailure.message}\n`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
writeDiagnostic(state, `[powernative] Metro logging instrumentation failed during ${phase}: ${normalizedError.message}\n`);
|
|
50
|
+
}
|
|
51
|
+
function createMetroLogState(projectRoot, onError) {
|
|
52
|
+
const root = path.resolve(projectRoot || process.cwd());
|
|
53
|
+
const logDir = path.join(root, '.powernative', 'metro-logs');
|
|
54
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
55
|
+
const patchedWrite = process.stderr.write;
|
|
56
|
+
const stderrWrite = patchedWrite.__powerNativeMetroLoggerOriginal || patchedWrite;
|
|
57
|
+
const state = {
|
|
58
|
+
root,
|
|
59
|
+
logDir,
|
|
60
|
+
stamp,
|
|
61
|
+
port: 'unknown',
|
|
62
|
+
logPath: path.join(logDir, `metro-${stamp}-pid-${process.pid}-port-unknown.log`),
|
|
63
|
+
onError: onError || null,
|
|
64
|
+
instrumentationError: null,
|
|
65
|
+
diagnosticWrite: message => Reflect.apply(stderrWrite, process.stderr, [message])
|
|
66
|
+
};
|
|
67
|
+
stateByRoot.set(root, state);
|
|
68
|
+
return state;
|
|
69
|
+
}
|
|
70
|
+
function getMetroLogState(projectRoot, onError) {
|
|
71
|
+
const root = path.resolve(projectRoot || process.cwd());
|
|
72
|
+
const state = stateByRoot.get(root) || createMetroLogState(root, onError);
|
|
73
|
+
if (onError) state.onError = onError;
|
|
74
|
+
return state;
|
|
75
|
+
}
|
|
76
|
+
function appendMetroLog(state, value) {
|
|
77
|
+
try {
|
|
78
|
+
fs.mkdirSync(state.logDir, {
|
|
79
|
+
recursive: true
|
|
80
|
+
});
|
|
81
|
+
fs.appendFileSync(state.logPath, redactMetroLog(value));
|
|
82
|
+
} catch (error) {
|
|
83
|
+
reportInstrumentationError(state, error, 'log persistence');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function setMetroLogPort(state, port) {
|
|
87
|
+
if (!Number.isInteger(port) || port <= 0 || String(port) === state.port) return;
|
|
88
|
+
const previousPath = state.logPath;
|
|
89
|
+
state.port = String(port);
|
|
90
|
+
state.logPath = path.join(state.logDir, `metro-${state.stamp}-pid-${process.pid}-port-${state.port}.log`);
|
|
91
|
+
try {
|
|
92
|
+
fs.mkdirSync(state.logDir, {
|
|
93
|
+
recursive: true
|
|
94
|
+
});
|
|
95
|
+
if (fs.existsSync(previousPath) && previousPath !== state.logPath) {
|
|
96
|
+
fs.renameSync(previousPath, state.logPath);
|
|
97
|
+
}
|
|
98
|
+
} catch (error) {
|
|
99
|
+
state.logPath = previousPath;
|
|
100
|
+
reportInstrumentationError(state, error, 'port-tagged log rename');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function extractMetroPort(value) {
|
|
104
|
+
const match = String(value).match(/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\]):(\d{2,5})/);
|
|
105
|
+
const port = match ? Number(match[1]) : null;
|
|
106
|
+
return Number.isInteger(port) && Number(port) > 0 && Number(port) <= 65535 ? port : null;
|
|
107
|
+
}
|
|
108
|
+
function patchStream(stream, key, state) {
|
|
109
|
+
const originalWrite = stream.write;
|
|
110
|
+
if (originalWrite.__powerNativeMetroLoggerPatched) return;
|
|
111
|
+
const patchedWrite = function (chunk, ...args) {
|
|
112
|
+
try {
|
|
113
|
+
const text = Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk);
|
|
114
|
+
appendMetroLog(state, text);
|
|
115
|
+
const port = extractMetroPort(text);
|
|
116
|
+
if (port) setMetroLogPort(state, port);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
reportInstrumentationError(state, error, `${key} capture`);
|
|
119
|
+
}
|
|
120
|
+
return Reflect.apply(originalWrite, stream, [chunk, ...args]);
|
|
121
|
+
};
|
|
122
|
+
patchedWrite.__powerNativeMetroLoggerPatched = true;
|
|
123
|
+
patchedWrite.__powerNativeMetroLoggerOriginal = originalWrite;
|
|
124
|
+
stream.write = patchedWrite;
|
|
125
|
+
}
|
|
126
|
+
export function enablePowerNativeMetroLogging(options = {}) {
|
|
127
|
+
const state = getMetroLogState(options.projectRoot, options.onError);
|
|
128
|
+
try {
|
|
129
|
+
patchStream(process.stdout, 'stdout', state);
|
|
130
|
+
patchStream(process.stderr, 'stderr', state);
|
|
131
|
+
appendMetroLog(state, `[powernative] Metro log started pid=${process.pid}\n`);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
reportInstrumentationError(state, error, 'stream setup');
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
logDir: state.logDir,
|
|
137
|
+
logPath: state.logPath
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export function withPowerNativeMetroLogging(middleware, options = {}) {
|
|
141
|
+
const state = getMetroLogState(options.projectRoot, options.onError);
|
|
142
|
+
const maxBodyBytes = Number.isInteger(options.maxBodyBytes) && Number(options.maxBodyBytes) > 0 ? Number(options.maxBodyBytes) : DEFAULT_MAX_ERROR_BODY_BYTES;
|
|
143
|
+
enablePowerNativeMetroLogging(options);
|
|
144
|
+
return (request, response, next) => {
|
|
145
|
+
try {
|
|
146
|
+
setMetroLogPort(state, Number(request.socket.localPort));
|
|
147
|
+
const chunks = [];
|
|
148
|
+
let capturedBytes = 0;
|
|
149
|
+
const write = response.write.bind(response);
|
|
150
|
+
const end = response.end.bind(response);
|
|
151
|
+
function captureChunk(chunk, encoding) {
|
|
152
|
+
if (!chunk || capturedBytes >= maxBodyBytes) return;
|
|
153
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk), typeof encoding === 'string' ? encoding : undefined);
|
|
154
|
+
const remaining = maxBodyBytes - capturedBytes;
|
|
155
|
+
chunks.push(buffer.length > remaining ? buffer.subarray(0, remaining) : buffer);
|
|
156
|
+
capturedBytes += Math.min(buffer.length, remaining);
|
|
157
|
+
}
|
|
158
|
+
response.write = (chunk, ...args) => {
|
|
159
|
+
captureChunk(chunk, args[0]);
|
|
160
|
+
return Reflect.apply(write, response, [chunk, ...args]);
|
|
161
|
+
};
|
|
162
|
+
response.end = (chunk, ...args) => {
|
|
163
|
+
captureChunk(chunk, args[0]);
|
|
164
|
+
if (response.statusCode >= 400) {
|
|
165
|
+
const body = Buffer.concat(chunks).toString('utf8').slice(0, maxBodyBytes);
|
|
166
|
+
appendMetroLog(state, `\n[powernative] HTTP ${request.method} ${request.url} -> ${response.statusCode}\n${body}\n`);
|
|
167
|
+
}
|
|
168
|
+
return Reflect.apply(end, response, [chunk, ...args]);
|
|
169
|
+
};
|
|
170
|
+
} catch (error) {
|
|
171
|
+
reportInstrumentationError(state, error, 'HTTP middleware setup');
|
|
172
|
+
}
|
|
173
|
+
return middleware(request, response, next);
|
|
174
|
+
};
|
|
175
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { createTamagui } from '@tamagui/core';
|
|
4
|
+
import { defaultConfig } from '@tamagui/config/v5';
|
|
5
|
+
import { animations } from '@tamagui/config/v5-rn';
|
|
6
|
+
function parseColorChannels(color) {
|
|
7
|
+
const hexMatch = color.match(/^#([\da-f]{3}|[\da-f]{6})$/i);
|
|
8
|
+
if (hexMatch) {
|
|
9
|
+
const hex = hexMatch[1].length === 3 ? [...hexMatch[1]].map(value => `${value}${value}`).join('') : hexMatch[1];
|
|
10
|
+
return [0, 2, 4].map(offset => Number.parseInt(hex.slice(offset, offset + 2), 16) / 255);
|
|
11
|
+
}
|
|
12
|
+
const rgbMatch = color.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)$/i);
|
|
13
|
+
if (rgbMatch) {
|
|
14
|
+
const values = rgbMatch.slice(1, 4).map(Number);
|
|
15
|
+
if (values.some(value => !Number.isFinite(value) || value < 0 || value > 255)) return null;
|
|
16
|
+
const alpha = rgbMatch[4] === undefined ? 1 : Number(rgbMatch[4]);
|
|
17
|
+
if (!Number.isFinite(alpha) || alpha !== 1) return null;
|
|
18
|
+
return values.map(value => value / 255);
|
|
19
|
+
}
|
|
20
|
+
const hslMatch = color.match(/^hsla?\(\s*([-\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%(?:\s*,\s*([\d.]+))?\s*\)$/i);
|
|
21
|
+
if (!hslMatch) return null;
|
|
22
|
+
const hsl = hslMatch.slice(1, 4).map(Number);
|
|
23
|
+
if (hsl.some(value => !Number.isFinite(value))) return null;
|
|
24
|
+
const alpha = hslMatch[4] === undefined ? 1 : Number(hslMatch[4]);
|
|
25
|
+
if (!Number.isFinite(alpha) || alpha !== 1) return null;
|
|
26
|
+
const hue = (hsl[0] % 360 + 360) % 360;
|
|
27
|
+
const saturation = hsl[1] / 100;
|
|
28
|
+
const lightness = hsl[2] / 100;
|
|
29
|
+
if (saturation < 0 || saturation > 1 || lightness < 0 || lightness > 1) return null;
|
|
30
|
+
const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;
|
|
31
|
+
const intermediate = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
|
|
32
|
+
const offset = lightness - chroma / 2;
|
|
33
|
+
const segment = Math.floor(hue / 60);
|
|
34
|
+
const rgb = [[chroma, intermediate, 0], [intermediate, chroma, 0], [0, chroma, intermediate], [0, intermediate, chroma], [intermediate, 0, chroma], [chroma, 0, intermediate]][segment];
|
|
35
|
+
return rgb.map(value => value + offset);
|
|
36
|
+
}
|
|
37
|
+
function readableForeground(background, fallback) {
|
|
38
|
+
if (!background) return fallback;
|
|
39
|
+
const channels = parseColorChannels(background);
|
|
40
|
+
if (!channels) return fallback;
|
|
41
|
+
const linearChannels = channels.map(value => value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4);
|
|
42
|
+
const luminance = 0.2126 * linearChannels[0] + 0.7152 * linearChannels[1] + 0.0722 * linearChannels[2];
|
|
43
|
+
return luminance > 0.179 ? '#000000' : '#ffffff';
|
|
44
|
+
}
|
|
45
|
+
export function withPowerAppsSemanticAliases(theme, brand = {}) {
|
|
46
|
+
return {
|
|
47
|
+
...theme,
|
|
48
|
+
surface0: brand.bg ?? theme.background,
|
|
49
|
+
surface1: brand.surface ?? theme.color3,
|
|
50
|
+
surface2: theme.color4,
|
|
51
|
+
surface3: brand.border ?? theme.color5,
|
|
52
|
+
mediaSurface: theme.color4,
|
|
53
|
+
accentDeep: brand.primary ?? theme.blue11,
|
|
54
|
+
accentBase: brand.primary ?? theme.blue10,
|
|
55
|
+
accentSoft: brand.accent ?? theme.blue3,
|
|
56
|
+
accentOnAccent: brand.onPrimary ?? readableForeground(brand.primary ?? theme.blue10, theme.color1),
|
|
57
|
+
text0: brand.text ?? theme.color12,
|
|
58
|
+
text1: brand.textMuted ?? theme.color11,
|
|
59
|
+
text2: theme.color10,
|
|
60
|
+
text3: theme.color9,
|
|
61
|
+
statusComplete: brand.statusSuccess ?? theme.green11,
|
|
62
|
+
statusCompleteBg: theme.green3,
|
|
63
|
+
statusPending: brand.statusWarning ?? theme.yellow11,
|
|
64
|
+
statusPendingBg: theme.yellow3,
|
|
65
|
+
statusOverdue: brand.statusDanger ?? theme.red11,
|
|
66
|
+
statusOverdueBg: theme.red3,
|
|
67
|
+
statusInProgress: brand.statusInfo ?? theme.blue11,
|
|
68
|
+
statusInProgressBg: theme.blue3,
|
|
69
|
+
statusDraft: theme.color10,
|
|
70
|
+
statusDraftBg: theme.color3,
|
|
71
|
+
statusCancelled: theme.red11,
|
|
72
|
+
statusCancelledBg: theme.red3
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const powerAppsTamaguiDefaults = {
|
|
76
|
+
...defaultConfig,
|
|
77
|
+
animations,
|
|
78
|
+
themes: {
|
|
79
|
+
...defaultConfig.themes,
|
|
80
|
+
light: withPowerAppsSemanticAliases(defaultConfig.themes.light),
|
|
81
|
+
dark: withPowerAppsSemanticAliases(defaultConfig.themes.dark)
|
|
82
|
+
},
|
|
83
|
+
fonts: {
|
|
84
|
+
...defaultConfig.fonts,
|
|
85
|
+
mono: defaultConfig.fonts.body
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
export function createPowerAppsTamaguiConfig(overrides = {}) {
|
|
89
|
+
return createTamagui({
|
|
90
|
+
...powerAppsTamaguiDefaults,
|
|
91
|
+
...overrides
|
|
92
|
+
});
|
|
93
|
+
}
|