@condorinst/mobile-bridge 0.17.0 → 0.18.0

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/dist/index.d.ts CHANGED
@@ -82,6 +82,49 @@ interface DevPanelOptions {
82
82
  autoRespondDelayMs?: number;
83
83
  }
84
84
 
85
+ /**
86
+ * Detecção do host nativo + adapter pattern.
87
+ *
88
+ * **v0.1.0:** lançava erro quando `window.flutter_inappwebview` ausente.
89
+ * **v0.2.0:** ativa mock adapter (`createMockAdapter`) — destrava dev em
90
+ * browser comum sem buildar APK.
91
+ * **v0.18.0:** canal `window.CondorNative` (JavaScript channel do
92
+ * `webview_flutter`) — detectado **antes** do `flutter_inappwebview`, que
93
+ * segue suportado por transição. O canal só aceita string: a mensagem vai
94
+ * serializada em JSON. E o gancho `setOutgoingStamp` permite ao shell
95
+ * carimbar toda mensagem de saída (ex.: nonce da Camada 3) sem monkey-patch
96
+ * do host.
97
+ *
98
+ * Adapter ativo é cached na primeira chamada de `getActiveAdapter()`.
99
+ * Tests devem chamar `__resetAdapterForTests()` no `beforeEach` para
100
+ * forçar re-detecção (ex.: após instalar/remover `window.CondorNative`).
101
+ */
102
+
103
+ /**
104
+ * Nome do JavaScript channel registrado pelo nativo
105
+ * (`WebViewController.addJavaScriptChannel`). Não pode ser `CondorBridge`: o
106
+ * plugin publica o canal como `window.<nome>`, o que colidiria com o emitter
107
+ * `window.CondorBridge` instalado por este SDK.
108
+ */
109
+ declare const NATIVE_CHANNEL_NAME = "CondorNative";
110
+ interface FlutterInAppWebView {
111
+ callHandler(name: string, ...args: unknown[]): Promise<unknown>;
112
+ }
113
+ interface NativeChannel {
114
+ postMessage(message: string): void;
115
+ }
116
+ declare global {
117
+ interface Window {
118
+ flutter_inappwebview?: FlutterInAppWebView;
119
+ CondorNative?: NativeChannel;
120
+ }
121
+ }
122
+ /**
123
+ * Transforma toda mensagem JS → Native imediatamente antes do envio.
124
+ * Recebe e devolve o envelope `{type, version, payload}`.
125
+ */
126
+ type OutgoingStamp = (message: Record<string, unknown>) => Record<string, unknown>;
127
+
85
128
  /**
86
129
  * Catálogo das chaves do bridge JS↔Native.
87
130
  *
@@ -132,7 +175,8 @@ type BridgeKey = (typeof BRIDGE_KEYS)[keyof typeof BRIDGE_KEYS];
132
175
  */
133
176
  /**
134
177
  * Mensagem JS → Native, enviada via
135
- * `window.flutter_inappwebview.callHandler('CondorBridge', msg)`.
178
+ * `window.CondorNative.postMessage(JSON.stringify(msg))` (v0.18.0+) ou, no
179
+ * host legado, `window.flutter_inappwebview.callHandler('CondorBridge', msg)`.
136
180
  */
137
181
  interface BridgeIncomingMessage {
138
182
  type: string;
@@ -562,8 +606,8 @@ interface MockState {
562
606
  interface CondorBridge {
563
607
  /**
564
608
  * `true` quando o adapter ativo é mock (browser dev, sem
565
- * `window.flutter_inappwebview`). `false` quando rodando dentro do
566
- * WebView Flutter.
609
+ * `window.CondorNative` nem `window.flutter_inappwebview`). `false` quando
610
+ * rodando dentro do WebView Flutter.
567
611
  */
568
612
  readonly isMock: boolean;
569
613
  /**
@@ -598,6 +642,16 @@ interface CondorBridge {
598
642
  * `Bridge.send('openSettings')`.
599
643
  */
600
644
  openSettings(): void;
645
+ /**
646
+ * Registra uma transformação aplicada a **toda** mensagem JS → Native
647
+ * (`handshake` inclusive) imediatamente antes do envio. `null` remove.
648
+ *
649
+ * Existe para o shell carimbar o nonce da Camada 3
650
+ * (`payload._shellNonce`) num ponto único — antes da 0.18.0 isso exigia
651
+ * monkey-patch de `flutter_inappwebview.callHandler`, que não existe no
652
+ * canal `CondorNative`. Código de cliente não deve usar.
653
+ */
654
+ setOutgoingStamp(stamp: OutgoingStamp | null): void;
601
655
  /**
602
656
  * Dispara `window.CondorBridge.emit(key, payload)` programaticamente —
603
657
  * útil para simular eventos nativos em testes e dev em browser.
@@ -770,6 +824,7 @@ declare const ClientToShellMessage: v.VariantSchema<"type", [v.ObjectSchema<{
770
824
  readonly type: v.LiteralSchema<"sandbox-verify-response", undefined>;
771
825
  readonly flutterBridgeReachable: v.BooleanSchema<undefined>;
772
826
  readonly condorBridgeReachable: v.BooleanSchema<undefined>;
827
+ readonly nativeChannelReachable: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
773
828
  }, undefined>], undefined>;
774
829
  type ClientToShellMessage = v.InferOutput<typeof ClientToShellMessage>;
775
830
  declare const ShellToClientMessage: v.VariantSchema<"type", [v.ObjectSchema<{
@@ -841,6 +896,8 @@ interface ConfirmationRequest {
841
896
  interface SandboxVerifyResult {
842
897
  flutterBridgeReachable: boolean;
843
898
  condorBridgeReachable: boolean;
899
+ /** `window.CondorNative` visível no iframe (v0.18.0). */
900
+ nativeChannelReachable: boolean;
844
901
  ok: boolean;
845
902
  }
846
903
 
@@ -967,4 +1024,4 @@ declare class BridgeShell {
967
1024
  private postToClient;
968
1025
  }
969
1026
 
970
- export { type AutoRespondResponse, BRIDGE_KEYS, Bridge, BridgeClient, type BridgeClientHandshakeAck, type BridgeIncomingMessage, type BridgeKey, type BridgeOutgoingEvent, BridgeShell, type BridgeShellOptions, ClientToShellMessage, type CondorBridge, type CondorBridgeClient, type ConfirmationRequest, type DeleteMemoryAckPayload, type DevPanelOptions, type DeviceConnectionPayload, type DeviceLightSensorsPayload, type DeviceNotificationPayload, type HandshakeAck, type HandshakeOptions, type KeyPayloads, type LanguagePayload, type LightSensorsActlumus1Data, type LightSensorsActlumus2Data, type LightSensorsRawChannels, type MockMessage, type MockState, type PayloadOf, type PingPongPayload, type RealTimeAckPayload, type RequestPermissionPayload, type SandboxVerifyResult, type SensorLogPayload, type SensorLogQueryPayload, type ShellPolicy, ShellToClientMessage, type SyncTimeAckPayload, type SystemStatusPayload, type UserDevicePayload };
1027
+ export { type AutoRespondResponse, BRIDGE_KEYS, Bridge, BridgeClient, type BridgeClientHandshakeAck, type BridgeIncomingMessage, type BridgeKey, type BridgeOutgoingEvent, BridgeShell, type BridgeShellOptions, ClientToShellMessage, type CondorBridge, type CondorBridgeClient, type ConfirmationRequest, type DeleteMemoryAckPayload, type DevPanelOptions, type DeviceConnectionPayload, type DeviceLightSensorsPayload, type DeviceNotificationPayload, type HandshakeAck, type HandshakeOptions, type KeyPayloads, type LanguagePayload, type LightSensorsActlumus1Data, type LightSensorsActlumus2Data, type LightSensorsRawChannels, type MockMessage, type MockState, NATIVE_CHANNEL_NAME, type OutgoingStamp, type PayloadOf, type PingPongPayload, type RealTimeAckPayload, type RequestPermissionPayload, type SandboxVerifyResult, type SensorLogPayload, type SensorLogQueryPayload, type ShellPolicy, ShellToClientMessage, type SyncTimeAckPayload, type SystemStatusPayload, type UserDevicePayload };
package/dist/index.js CHANGED
@@ -430,8 +430,22 @@ function createMockAdapter() {
430
430
  }
431
431
 
432
432
  // src/internal/native.ts
433
+ var NATIVE_CHANNEL_NAME = "CondorNative";
434
+ var outgoingStamp = null;
435
+ function setOutgoingStamp(stamp) {
436
+ outgoingStamp = stamp;
437
+ }
433
438
  var activeAdapter = null;
434
- function createRealAdapter(host) {
439
+ function createChannelAdapter(channel) {
440
+ return {
441
+ isMock: false,
442
+ // Canal único: o `handlerName` não viaja — o nativo roteia por `type`.
443
+ callHandler(_handlerName, payload) {
444
+ channel.postMessage(JSON.stringify(payload));
445
+ }
446
+ };
447
+ }
448
+ function createLegacyAdapter(host) {
435
449
  return {
436
450
  isMock: false,
437
451
  callHandler(handlerName, payload) {
@@ -443,9 +457,13 @@ function detectAdapter() {
443
457
  if (typeof window === "undefined") {
444
458
  return createMockAdapter();
445
459
  }
460
+ const channel = window.CondorNative;
461
+ if (channel && typeof channel.postMessage === "function") {
462
+ return createChannelAdapter(channel);
463
+ }
446
464
  const host = window.flutter_inappwebview;
447
465
  if (host && typeof host.callHandler === "function") {
448
- return createRealAdapter(host);
466
+ return createLegacyAdapter(host);
449
467
  }
450
468
  return createMockAdapter();
451
469
  }
@@ -456,7 +474,8 @@ function getActiveAdapter() {
456
474
  return activeAdapter;
457
475
  }
458
476
  function callNative(handlerName, payload) {
459
- getActiveAdapter().callHandler(handlerName, payload);
477
+ const stamped = outgoingStamp ? outgoingStamp(payload) : payload;
478
+ getActiveAdapter().callHandler(handlerName, stamped);
460
479
  }
461
480
 
462
481
  // src/internal/subscribers.ts
@@ -572,6 +591,9 @@ var Bridge = {
572
591
  openSettings() {
573
592
  this.send("openSettings");
574
593
  },
594
+ setOutgoingStamp(stamp) {
595
+ setOutgoingStamp(stamp);
596
+ },
575
597
  mockEmit(key, payload) {
576
598
  requireMockAdapter().triggerEmit(key, payload ?? {});
577
599
  },
@@ -647,7 +669,8 @@ function onMessage(event) {
647
669
  postToShell({
648
670
  type: "sandbox-verify-response",
649
671
  flutterBridgeReachable: typeof w.flutter_inappwebview !== "undefined",
650
- condorBridgeReachable: typeof w.CondorBridge !== "undefined"
672
+ condorBridgeReachable: typeof w.CondorBridge !== "undefined",
673
+ nativeChannelReachable: typeof w.CondorNative !== "undefined"
651
674
  });
652
675
  break;
653
676
  }
@@ -773,7 +796,9 @@ var JsErrorMessage = v.object({
773
796
  var SandboxVerifyResponseMessage = v.object({
774
797
  type: v.literal("sandbox-verify-response"),
775
798
  flutterBridgeReachable: v.boolean(),
776
- condorBridgeReachable: v.boolean()
799
+ condorBridgeReachable: v.boolean(),
800
+ // Opcional: clientes com SDK < 0.18.0 não enviam.
801
+ nativeChannelReachable: v.optional(v.boolean())
777
802
  });
778
803
  var ClientToShellMessage = v.variant("type", [
779
804
  SubscribeMessage,
@@ -828,6 +853,7 @@ var OVERRIDE_PREFIX = `<script>
828
853
  (function(){
829
854
  try { delete window.flutter_inappwebview; } catch (_) {}
830
855
  try { delete window.CondorBridge; } catch (_) {}
856
+ try { delete window.CondorNative; } catch (_) {}
831
857
  try {
832
858
  Object.defineProperty(window, 'flutter_inappwebview', {
833
859
  get: function(){ return undefined; },
@@ -835,6 +861,13 @@ var OVERRIDE_PREFIX = `<script>
835
861
  configurable: false,
836
862
  });
837
863
  } catch (_) {}
864
+ try {
865
+ Object.defineProperty(window, 'CondorNative', {
866
+ get: function(){ return undefined; },
867
+ set: function(_){ /* no-op: bloqueia o canal do webview_flutter no iframe */ },
868
+ configurable: false,
869
+ });
870
+ } catch (_) {}
838
871
  try {
839
872
  Object.defineProperty(window, 'CondorBridge', {
840
873
  get: function(){ return undefined; },
@@ -915,10 +948,12 @@ var BridgeShell = class {
915
948
  if (pending) {
916
949
  clearTimeout(pending.timer);
917
950
  this.pendingVerifies.delete(first);
918
- const ok = !msg.flutterBridgeReachable && !msg.condorBridgeReachable;
951
+ const nativeChannelReachable = msg.nativeChannelReachable ?? false;
952
+ const ok = !msg.flutterBridgeReachable && !msg.condorBridgeReachable && !nativeChannelReachable;
919
953
  pending.resolve({
920
954
  flutterBridgeReachable: msg.flutterBridgeReachable,
921
955
  condorBridgeReachable: msg.condorBridgeReachable,
956
+ nativeChannelReachable,
922
957
  ok
923
958
  });
924
959
  }
@@ -1106,6 +1141,7 @@ export {
1106
1141
  BRIDGE_KEYS,
1107
1142
  Bridge,
1108
1143
  BridgeClient,
1109
- BridgeShell
1144
+ BridgeShell,
1145
+ NATIVE_CHANNEL_NAME
1110
1146
  };
1111
1147
  //# sourceMappingURL=index.js.map