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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +21 -10
  2. package/compatibility/current.json +31 -4
  3. package/lib/NOTICE.txt +1325 -24
  4. package/lib/commonjs/auth/AuthContext.js +110 -33
  5. package/lib/commonjs/bridge/NativePowerAppsBridge.js +11 -18
  6. package/lib/commonjs/bridge/PowerPagesBridge.js +27 -8
  7. package/lib/commonjs/bridge/bridgeState.js +40 -0
  8. package/lib/commonjs/config/babelConfig.js +13 -0
  9. package/lib/commonjs/config/expoConfig.js +71 -0
  10. package/lib/commonjs/config/metroConfig.js +70 -0
  11. package/lib/commonjs/config/metroLogger.js +182 -0
  12. package/lib/commonjs/config/tamaguiConfig.js +98 -0
  13. package/lib/commonjs/connections/ConnectionSetupScreen.js +459 -80
  14. package/lib/commonjs/connections/PowerPlatformConnectionApi.js +946 -0
  15. package/lib/commonjs/connections/connectionMetadata.js +127 -0
  16. package/lib/commonjs/connections/connectionState.js +96 -0
  17. package/lib/commonjs/connections/disambiguate.js +19 -11
  18. package/lib/commonjs/connections/resolveConnections.js +348 -0
  19. package/lib/commonjs/connections/types.js +106 -0
  20. package/lib/commonjs/{platform → connections}/useConnectionRefs.js +130 -65
  21. package/lib/commonjs/connections/useConnectionSetup.js +111 -52
  22. package/lib/commonjs/controls/FilePicker.js +6 -0
  23. package/lib/commonjs/controls/ImagePicker.js +8 -0
  24. package/lib/commonjs/index.js +167 -4
  25. package/lib/commonjs/logger.js +9 -6
  26. package/lib/commonjs/offline/createOfflineHostActivationCallbacks.js +61 -0
  27. package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.js +48 -0
  28. package/lib/commonjs/offline/useOfflineIntegrationWithStartupGate.web.js +13 -0
  29. package/lib/commonjs/platform/DataverseDataSources.js +18 -0
  30. package/lib/commonjs/platform/DataverseGlobalDiscoveryApi.js +94 -0
  31. package/lib/commonjs/platform/GlobalDiscovery.js +51 -0
  32. package/lib/commonjs/platform/PowerPlatformEnvironmentApi.js +6 -106
  33. package/lib/commonjs/provider/PowerAppsHostProvider.js +157 -25
  34. package/lib/commonjs/provider/PowerAppsProvider.js +178 -134
  35. package/lib/commonjs/provider/SessionDetailsGesture.js +208 -0
  36. package/lib/commonjs/telemetry/OfflineSdkTelemetry.js +95 -0
  37. package/lib/commonjs/telemetry/OfflineSdkTelemetry.web.js +9 -0
  38. package/lib/commonjs/telemetry/index.js +22 -3
  39. package/lib/module/auth/AuthContext.js +110 -33
  40. package/lib/module/bridge/NativePowerAppsBridge.js +12 -19
  41. package/lib/module/bridge/PowerPagesBridge.js +27 -8
  42. package/lib/module/bridge/bridgeState.js +34 -0
  43. package/lib/module/config/babelConfig.js +9 -0
  44. package/lib/module/config/expoConfig.js +67 -0
  45. package/lib/module/config/metroConfig.js +65 -0
  46. package/lib/module/config/metroLogger.js +175 -0
  47. package/lib/module/config/tamaguiConfig.js +93 -0
  48. package/lib/module/connections/ConnectionSetupScreen.js +460 -81
  49. package/lib/module/connections/PowerPlatformConnectionApi.js +932 -0
  50. package/lib/module/connections/connectionMetadata.js +112 -0
  51. package/lib/module/connections/connectionState.js +82 -0
  52. package/lib/module/connections/disambiguate.js +19 -12
  53. package/lib/module/connections/resolveConnections.js +343 -0
  54. package/lib/module/connections/types.js +91 -0
  55. package/lib/module/{platform → connections}/useConnectionRefs.js +131 -66
  56. package/lib/module/connections/useConnectionSetup.js +113 -54
  57. package/lib/module/controls/FilePicker.js +6 -0
  58. package/lib/module/controls/ImagePicker.js +8 -0
  59. package/lib/module/index.js +14 -4
  60. package/lib/module/logger.js +8 -6
  61. package/lib/module/offline/createOfflineHostActivationCallbacks.js +55 -0
  62. package/lib/module/offline/useOfflineIntegrationWithStartupGate.js +44 -0
  63. package/lib/module/offline/useOfflineIntegrationWithStartupGate.web.js +9 -0
  64. package/lib/module/platform/DataverseDataSources.js +13 -0
  65. package/lib/module/platform/DataverseGlobalDiscoveryApi.js +89 -0
  66. package/lib/module/platform/GlobalDiscovery.js +45 -0
  67. package/lib/module/platform/PowerPlatformEnvironmentApi.js +5 -104
  68. package/lib/module/provider/PowerAppsHostProvider.js +160 -28
  69. package/lib/module/provider/PowerAppsProvider.js +182 -138
  70. package/lib/module/provider/SessionDetailsGesture.js +203 -0
  71. package/lib/module/telemetry/OfflineSdkTelemetry.js +91 -0
  72. package/lib/module/telemetry/OfflineSdkTelemetry.web.js +5 -0
  73. package/lib/module/telemetry/index.js +15 -4
  74. package/lib/typescript/commonjs/auth/AuthContext.d.ts +3 -1
  75. package/lib/typescript/commonjs/auth/AuthContext.web.d.ts +1 -0
  76. package/lib/typescript/commonjs/bridge/bridgeState.d.ts +5 -0
  77. package/lib/typescript/commonjs/config/babelConfig.d.ts +12 -0
  78. package/lib/typescript/commonjs/config/expoConfig.d.ts +21 -0
  79. package/lib/typescript/commonjs/config/metroConfig.d.ts +6 -0
  80. package/lib/typescript/commonjs/config/metroLogger.d.ts +21 -0
  81. package/lib/typescript/commonjs/config/tamaguiConfig.d.ts +1792 -0
  82. package/lib/typescript/commonjs/connections/ConnectionSetupScreen.d.ts +28 -7
  83. package/lib/typescript/commonjs/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
  84. package/lib/typescript/commonjs/connections/connectionMetadata.d.ts +66 -0
  85. package/lib/typescript/commonjs/connections/connectionState.d.ts +16 -0
  86. package/lib/typescript/commonjs/connections/disambiguate.d.ts +4 -2
  87. package/lib/typescript/commonjs/{platform → connections}/resolveConnections.d.ts +22 -20
  88. package/lib/typescript/commonjs/connections/types.d.ts +129 -1
  89. package/lib/typescript/commonjs/{platform → connections}/useConnectionRefs.d.ts +36 -25
  90. package/lib/typescript/commonjs/connections/useConnectionSetup.d.ts +12 -8
  91. package/lib/typescript/commonjs/controls/FilePicker.d.ts +7 -1
  92. package/lib/typescript/commonjs/controls/ImagePicker.d.ts +9 -1
  93. package/lib/typescript/commonjs/index.d.ts +18 -10
  94. package/lib/typescript/commonjs/logger.d.ts +4 -4
  95. package/lib/typescript/commonjs/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
  96. package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
  97. package/lib/typescript/commonjs/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
  98. package/lib/typescript/commonjs/platform/DataverseDataSources.d.ts +28 -0
  99. package/lib/typescript/commonjs/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
  100. package/lib/typescript/commonjs/platform/GlobalDiscovery.d.ts +4 -0
  101. package/lib/typescript/commonjs/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
  102. package/lib/typescript/commonjs/provider/PowerAppsHostProvider.d.ts +29 -18
  103. package/lib/typescript/commonjs/provider/PowerAppsProvider.d.ts +54 -9
  104. package/lib/typescript/commonjs/provider/SessionDetailsGesture.d.ts +13 -0
  105. package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.d.ts +15 -0
  106. package/lib/typescript/commonjs/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
  107. package/lib/typescript/commonjs/telemetry/index.d.ts +13 -1
  108. package/lib/typescript/module/auth/AuthContext.d.ts +3 -1
  109. package/lib/typescript/module/auth/AuthContext.web.d.ts +1 -0
  110. package/lib/typescript/module/bridge/bridgeState.d.ts +5 -0
  111. package/lib/typescript/module/config/babelConfig.d.ts +12 -0
  112. package/lib/typescript/module/config/expoConfig.d.ts +21 -0
  113. package/lib/typescript/module/config/metroConfig.d.ts +6 -0
  114. package/lib/typescript/module/config/metroLogger.d.ts +21 -0
  115. package/lib/typescript/module/config/tamaguiConfig.d.ts +1792 -0
  116. package/lib/typescript/module/connections/ConnectionSetupScreen.d.ts +28 -7
  117. package/lib/typescript/module/{platform → connections}/PowerPlatformConnectionApi.d.ts +52 -43
  118. package/lib/typescript/module/connections/connectionMetadata.d.ts +66 -0
  119. package/lib/typescript/module/connections/connectionState.d.ts +16 -0
  120. package/lib/typescript/module/connections/disambiguate.d.ts +4 -2
  121. package/lib/typescript/module/{platform → connections}/resolveConnections.d.ts +22 -20
  122. package/lib/typescript/module/connections/types.d.ts +129 -1
  123. package/lib/typescript/module/{platform → connections}/useConnectionRefs.d.ts +36 -25
  124. package/lib/typescript/module/connections/useConnectionSetup.d.ts +12 -8
  125. package/lib/typescript/module/controls/FilePicker.d.ts +7 -1
  126. package/lib/typescript/module/controls/ImagePicker.d.ts +9 -1
  127. package/lib/typescript/module/index.d.ts +18 -10
  128. package/lib/typescript/module/logger.d.ts +4 -4
  129. package/lib/typescript/module/offline/createOfflineHostActivationCallbacks.d.ts +12 -0
  130. package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.d.ts +15 -0
  131. package/lib/typescript/module/offline/useOfflineIntegrationWithStartupGate.web.d.ts +6 -0
  132. package/lib/typescript/module/platform/DataverseDataSources.d.ts +28 -0
  133. package/lib/typescript/module/platform/DataverseGlobalDiscoveryApi.d.ts +3 -0
  134. package/lib/typescript/module/platform/GlobalDiscovery.d.ts +4 -0
  135. package/lib/typescript/module/platform/PowerPlatformEnvironmentApi.d.ts +3 -74
  136. package/lib/typescript/module/provider/PowerAppsHostProvider.d.ts +29 -18
  137. package/lib/typescript/module/provider/PowerAppsProvider.d.ts +54 -9
  138. package/lib/typescript/module/provider/SessionDetailsGesture.d.ts +13 -0
  139. package/lib/typescript/module/telemetry/OfflineSdkTelemetry.d.ts +15 -0
  140. package/lib/typescript/module/telemetry/OfflineSdkTelemetry.web.d.ts +2 -0
  141. package/lib/typescript/module/telemetry/index.d.ts +13 -1
  142. package/package.json +52 -13
  143. package/scripts/build-codegen-package.js +283 -0
  144. package/scripts/start-web.mjs +9 -5
  145. package/scripts/upgrade/runtime.js +139 -24
  146. package/scripts/upgrade-authoring.js +274 -180
  147. package/scripts/upgrade.js +10 -16
  148. package/src/config/generated-config.d.ts +4 -0
  149. package/src/config/index.d.ts +3 -0
  150. package/src/config/tsconfig.json +26 -0
  151. package/lib/commonjs/platform/PowerPlatformConnectionApi.js +0 -606
  152. package/lib/commonjs/platform/resolveConnections.js +0 -264
  153. package/lib/module/platform/PowerPlatformConnectionApi.js +0 -595
  154. package/lib/module/platform/resolveConnections.js +0 -259
@@ -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
+ }