@condorinst/mobile-bridge 0.16.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/CHANGELOG.md +68 -0
- package/README.md +9 -5
- package/dist/index.cjs +93 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +102 -4
- package/dist/index.d.ts +102 -4
- package/dist/index.js +91 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
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.
|
|
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;
|
|
@@ -207,6 +251,11 @@ interface UserDevicePayload {
|
|
|
207
251
|
* defensivamente. Não são opcionais no tipo de propósito — opcional
|
|
208
252
|
* esconderia o skew de versão em vez de deixá-lo explícito.
|
|
209
253
|
*
|
|
254
|
+
* ⚠️ O `nativeVersion` só chega ao cliente a partir do **SDK 0.17.0**: até a
|
|
255
|
+
* `0.16.x` o shell respondia o handshake do cliente apenas com o
|
|
256
|
+
* `shellVersion`, então essa checagem era impossível de cumprir de dentro do
|
|
257
|
+
* iframe.
|
|
258
|
+
*
|
|
210
259
|
* `null` significa **canal ausente nesta geração de hardware**, nunca "leitura
|
|
211
260
|
* zero": `0.0` é leitura válida. Mesma distinção que o backend faz com
|
|
212
261
|
* `float | null`.
|
|
@@ -557,8 +606,8 @@ interface MockState {
|
|
|
557
606
|
interface CondorBridge {
|
|
558
607
|
/**
|
|
559
608
|
* `true` quando o adapter ativo é mock (browser dev, sem
|
|
560
|
-
* `window.flutter_inappwebview`). `false` quando
|
|
561
|
-
* WebView Flutter.
|
|
609
|
+
* `window.CondorNative` nem `window.flutter_inappwebview`). `false` quando
|
|
610
|
+
* rodando dentro do WebView Flutter.
|
|
562
611
|
*/
|
|
563
612
|
readonly isMock: boolean;
|
|
564
613
|
/**
|
|
@@ -593,6 +642,16 @@ interface CondorBridge {
|
|
|
593
642
|
* `Bridge.send('openSettings')`.
|
|
594
643
|
*/
|
|
595
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;
|
|
596
655
|
/**
|
|
597
656
|
* Dispara `window.CondorBridge.emit(key, payload)` programaticamente —
|
|
598
657
|
* útil para simular eventos nativos em testes e dev em browser.
|
|
@@ -639,6 +698,16 @@ declare const Bridge: CondorBridge;
|
|
|
639
698
|
|
|
640
699
|
interface BridgeClientHandshakeAck {
|
|
641
700
|
shellVersion: string;
|
|
701
|
+
/**
|
|
702
|
+
* Versão do schema do **nativo**, repassada pelo shell — `null` se o nativo
|
|
703
|
+
* ainda não respondeu ou não existe (mock de browser).
|
|
704
|
+
*
|
|
705
|
+
* É por este número que um cliente decide se pode depender de capacidade
|
|
706
|
+
* nova: não há negociação de versão, e o cliente sandboxed não alcança o
|
|
707
|
+
* nativo por nenhum outro caminho. Ex.: canais crus de luz
|
|
708
|
+
* (`light_sensor_*` em `deviceLightSensors`) existem a partir da `0.16.0`.
|
|
709
|
+
*/
|
|
710
|
+
nativeVersion: string | null;
|
|
642
711
|
accepted: boolean;
|
|
643
712
|
}
|
|
644
713
|
interface CondorBridgeClient {
|
|
@@ -755,6 +824,7 @@ declare const ClientToShellMessage: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
|
755
824
|
readonly type: v.LiteralSchema<"sandbox-verify-response", undefined>;
|
|
756
825
|
readonly flutterBridgeReachable: v.BooleanSchema<undefined>;
|
|
757
826
|
readonly condorBridgeReachable: v.BooleanSchema<undefined>;
|
|
827
|
+
readonly nativeChannelReachable: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
758
828
|
}, undefined>], undefined>;
|
|
759
829
|
type ClientToShellMessage = v.InferOutput<typeof ClientToShellMessage>;
|
|
760
830
|
declare const ShellToClientMessage: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
@@ -765,6 +835,15 @@ declare const ShellToClientMessage: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
|
765
835
|
readonly type: v.LiteralSchema<"handshake-ack", undefined>;
|
|
766
836
|
readonly ack: v.ObjectSchema<{
|
|
767
837
|
readonly shellVersion: v.StringSchema<undefined>;
|
|
838
|
+
/**
|
|
839
|
+
* Versão do schema declarada pelo **nativo**, repassada pelo shell.
|
|
840
|
+
*
|
|
841
|
+
* `null` quando o nativo ainda não respondeu (ou não existe, como no
|
|
842
|
+
* mock de browser). O cliente roda dentro de um iframe sandboxed e não
|
|
843
|
+
* fala com o nativo diretamente, então este é o **único** caminho pelo
|
|
844
|
+
* qual ele descobre de qual versão são as capacidades disponíveis.
|
|
845
|
+
*/
|
|
846
|
+
readonly nativeVersion: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
768
847
|
readonly accepted: v.BooleanSchema<undefined>;
|
|
769
848
|
}, undefined>;
|
|
770
849
|
}, undefined>, v.ObjectSchema<{
|
|
@@ -817,6 +896,8 @@ interface ConfirmationRequest {
|
|
|
817
896
|
interface SandboxVerifyResult {
|
|
818
897
|
flutterBridgeReachable: boolean;
|
|
819
898
|
condorBridgeReachable: boolean;
|
|
899
|
+
/** `window.CondorNative` visível no iframe (v0.18.0). */
|
|
900
|
+
nativeChannelReachable: boolean;
|
|
820
901
|
ok: boolean;
|
|
821
902
|
}
|
|
822
903
|
|
|
@@ -868,6 +949,13 @@ declare class BridgeShell {
|
|
|
868
949
|
private readonly onConfirm?;
|
|
869
950
|
private readonly subscriptions;
|
|
870
951
|
private detached;
|
|
952
|
+
/**
|
|
953
|
+
* Versão do nativo, obtida uma vez e cacheada. `null` até o nativo
|
|
954
|
+
* responder — e permanentemente `null` num browser sem nativo.
|
|
955
|
+
*/
|
|
956
|
+
private nativeVersion;
|
|
957
|
+
/** Handshake com o nativo em voo; garante uma única chamada. */
|
|
958
|
+
private nativeHandshake;
|
|
871
959
|
private pendingVerifies;
|
|
872
960
|
constructor(opts: BridgeShellOptions);
|
|
873
961
|
/**
|
|
@@ -923,7 +1011,17 @@ declare class BridgeShell {
|
|
|
923
1011
|
private handleSubscribe;
|
|
924
1012
|
private handleUnsubscribe;
|
|
925
1013
|
private handleSend;
|
|
1014
|
+
/**
|
|
1015
|
+
* Obtém o `nativeVersion`, disparando o handshake com o nativo na primeira
|
|
1016
|
+
* vez e cacheando o resultado.
|
|
1017
|
+
*
|
|
1018
|
+
* ⚠️ `Bridge.handshake` **não tem timeout**: a Promise só resolve quando o
|
|
1019
|
+
* nativo emite `handshake-ack`. Num browser sem nativo ela nunca resolve,
|
|
1020
|
+
* então o `race` abaixo é o que garante que o cliente sempre receba
|
|
1021
|
+
* resposta — com `null` — em vez de ficar pendurado.
|
|
1022
|
+
*/
|
|
1023
|
+
private resolveNativeVersion;
|
|
926
1024
|
private postToClient;
|
|
927
1025
|
}
|
|
928
1026
|
|
|
929
|
-
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.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.
|
|
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;
|
|
@@ -207,6 +251,11 @@ interface UserDevicePayload {
|
|
|
207
251
|
* defensivamente. Não são opcionais no tipo de propósito — opcional
|
|
208
252
|
* esconderia o skew de versão em vez de deixá-lo explícito.
|
|
209
253
|
*
|
|
254
|
+
* ⚠️ O `nativeVersion` só chega ao cliente a partir do **SDK 0.17.0**: até a
|
|
255
|
+
* `0.16.x` o shell respondia o handshake do cliente apenas com o
|
|
256
|
+
* `shellVersion`, então essa checagem era impossível de cumprir de dentro do
|
|
257
|
+
* iframe.
|
|
258
|
+
*
|
|
210
259
|
* `null` significa **canal ausente nesta geração de hardware**, nunca "leitura
|
|
211
260
|
* zero": `0.0` é leitura válida. Mesma distinção que o backend faz com
|
|
212
261
|
* `float | null`.
|
|
@@ -557,8 +606,8 @@ interface MockState {
|
|
|
557
606
|
interface CondorBridge {
|
|
558
607
|
/**
|
|
559
608
|
* `true` quando o adapter ativo é mock (browser dev, sem
|
|
560
|
-
* `window.flutter_inappwebview`). `false` quando
|
|
561
|
-
* WebView Flutter.
|
|
609
|
+
* `window.CondorNative` nem `window.flutter_inappwebview`). `false` quando
|
|
610
|
+
* rodando dentro do WebView Flutter.
|
|
562
611
|
*/
|
|
563
612
|
readonly isMock: boolean;
|
|
564
613
|
/**
|
|
@@ -593,6 +642,16 @@ interface CondorBridge {
|
|
|
593
642
|
* `Bridge.send('openSettings')`.
|
|
594
643
|
*/
|
|
595
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;
|
|
596
655
|
/**
|
|
597
656
|
* Dispara `window.CondorBridge.emit(key, payload)` programaticamente —
|
|
598
657
|
* útil para simular eventos nativos em testes e dev em browser.
|
|
@@ -639,6 +698,16 @@ declare const Bridge: CondorBridge;
|
|
|
639
698
|
|
|
640
699
|
interface BridgeClientHandshakeAck {
|
|
641
700
|
shellVersion: string;
|
|
701
|
+
/**
|
|
702
|
+
* Versão do schema do **nativo**, repassada pelo shell — `null` se o nativo
|
|
703
|
+
* ainda não respondeu ou não existe (mock de browser).
|
|
704
|
+
*
|
|
705
|
+
* É por este número que um cliente decide se pode depender de capacidade
|
|
706
|
+
* nova: não há negociação de versão, e o cliente sandboxed não alcança o
|
|
707
|
+
* nativo por nenhum outro caminho. Ex.: canais crus de luz
|
|
708
|
+
* (`light_sensor_*` em `deviceLightSensors`) existem a partir da `0.16.0`.
|
|
709
|
+
*/
|
|
710
|
+
nativeVersion: string | null;
|
|
642
711
|
accepted: boolean;
|
|
643
712
|
}
|
|
644
713
|
interface CondorBridgeClient {
|
|
@@ -755,6 +824,7 @@ declare const ClientToShellMessage: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
|
755
824
|
readonly type: v.LiteralSchema<"sandbox-verify-response", undefined>;
|
|
756
825
|
readonly flutterBridgeReachable: v.BooleanSchema<undefined>;
|
|
757
826
|
readonly condorBridgeReachable: v.BooleanSchema<undefined>;
|
|
827
|
+
readonly nativeChannelReachable: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
758
828
|
}, undefined>], undefined>;
|
|
759
829
|
type ClientToShellMessage = v.InferOutput<typeof ClientToShellMessage>;
|
|
760
830
|
declare const ShellToClientMessage: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
@@ -765,6 +835,15 @@ declare const ShellToClientMessage: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
|
765
835
|
readonly type: v.LiteralSchema<"handshake-ack", undefined>;
|
|
766
836
|
readonly ack: v.ObjectSchema<{
|
|
767
837
|
readonly shellVersion: v.StringSchema<undefined>;
|
|
838
|
+
/**
|
|
839
|
+
* Versão do schema declarada pelo **nativo**, repassada pelo shell.
|
|
840
|
+
*
|
|
841
|
+
* `null` quando o nativo ainda não respondeu (ou não existe, como no
|
|
842
|
+
* mock de browser). O cliente roda dentro de um iframe sandboxed e não
|
|
843
|
+
* fala com o nativo diretamente, então este é o **único** caminho pelo
|
|
844
|
+
* qual ele descobre de qual versão são as capacidades disponíveis.
|
|
845
|
+
*/
|
|
846
|
+
readonly nativeVersion: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
768
847
|
readonly accepted: v.BooleanSchema<undefined>;
|
|
769
848
|
}, undefined>;
|
|
770
849
|
}, undefined>, v.ObjectSchema<{
|
|
@@ -817,6 +896,8 @@ interface ConfirmationRequest {
|
|
|
817
896
|
interface SandboxVerifyResult {
|
|
818
897
|
flutterBridgeReachable: boolean;
|
|
819
898
|
condorBridgeReachable: boolean;
|
|
899
|
+
/** `window.CondorNative` visível no iframe (v0.18.0). */
|
|
900
|
+
nativeChannelReachable: boolean;
|
|
820
901
|
ok: boolean;
|
|
821
902
|
}
|
|
822
903
|
|
|
@@ -868,6 +949,13 @@ declare class BridgeShell {
|
|
|
868
949
|
private readonly onConfirm?;
|
|
869
950
|
private readonly subscriptions;
|
|
870
951
|
private detached;
|
|
952
|
+
/**
|
|
953
|
+
* Versão do nativo, obtida uma vez e cacheada. `null` até o nativo
|
|
954
|
+
* responder — e permanentemente `null` num browser sem nativo.
|
|
955
|
+
*/
|
|
956
|
+
private nativeVersion;
|
|
957
|
+
/** Handshake com o nativo em voo; garante uma única chamada. */
|
|
958
|
+
private nativeHandshake;
|
|
871
959
|
private pendingVerifies;
|
|
872
960
|
constructor(opts: BridgeShellOptions);
|
|
873
961
|
/**
|
|
@@ -923,7 +1011,17 @@ declare class BridgeShell {
|
|
|
923
1011
|
private handleSubscribe;
|
|
924
1012
|
private handleUnsubscribe;
|
|
925
1013
|
private handleSend;
|
|
1014
|
+
/**
|
|
1015
|
+
* Obtém o `nativeVersion`, disparando o handshake com o nativo na primeira
|
|
1016
|
+
* vez e cacheando o resultado.
|
|
1017
|
+
*
|
|
1018
|
+
* ⚠️ `Bridge.handshake` **não tem timeout**: a Promise só resolve quando o
|
|
1019
|
+
* nativo emite `handshake-ack`. Num browser sem nativo ela nunca resolve,
|
|
1020
|
+
* então o `race` abaixo é o que garante que o cliente sempre receba
|
|
1021
|
+
* resposta — com `null` — em vez de ficar pendurado.
|
|
1022
|
+
*/
|
|
1023
|
+
private resolveNativeVersion;
|
|
926
1024
|
private postToClient;
|
|
927
1025
|
}
|
|
928
1026
|
|
|
929
|
-
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
|
|
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
|
|
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
|
-
|
|
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
|
},
|
|
@@ -632,6 +654,8 @@ function onMessage(event) {
|
|
|
632
654
|
pendingHandshake2 = null;
|
|
633
655
|
resolve({
|
|
634
656
|
shellVersion: msg.ack?.shellVersion ?? "unknown",
|
|
657
|
+
// `?? null` cobre o shell anterior à 0.17.0, que não mandava o campo.
|
|
658
|
+
nativeVersion: msg.ack?.nativeVersion ?? null,
|
|
635
659
|
accepted: msg.ack?.accepted ?? false
|
|
636
660
|
});
|
|
637
661
|
}
|
|
@@ -645,7 +669,8 @@ function onMessage(event) {
|
|
|
645
669
|
postToShell({
|
|
646
670
|
type: "sandbox-verify-response",
|
|
647
671
|
flutterBridgeReachable: typeof w.flutter_inappwebview !== "undefined",
|
|
648
|
-
condorBridgeReachable: typeof w.CondorBridge !== "undefined"
|
|
672
|
+
condorBridgeReachable: typeof w.CondorBridge !== "undefined",
|
|
673
|
+
nativeChannelReachable: typeof w.CondorNative !== "undefined"
|
|
649
674
|
});
|
|
650
675
|
break;
|
|
651
676
|
}
|
|
@@ -771,7 +796,9 @@ var JsErrorMessage = v.object({
|
|
|
771
796
|
var SandboxVerifyResponseMessage = v.object({
|
|
772
797
|
type: v.literal("sandbox-verify-response"),
|
|
773
798
|
flutterBridgeReachable: v.boolean(),
|
|
774
|
-
condorBridgeReachable: v.boolean()
|
|
799
|
+
condorBridgeReachable: v.boolean(),
|
|
800
|
+
// Opcional: clientes com SDK < 0.18.0 não enviam.
|
|
801
|
+
nativeChannelReachable: v.optional(v.boolean())
|
|
775
802
|
});
|
|
776
803
|
var ClientToShellMessage = v.variant("type", [
|
|
777
804
|
SubscribeMessage,
|
|
@@ -790,6 +817,15 @@ var HandshakeAckMessage = v.object({
|
|
|
790
817
|
type: v.literal("handshake-ack"),
|
|
791
818
|
ack: v.object({
|
|
792
819
|
shellVersion: v.string(),
|
|
820
|
+
/**
|
|
821
|
+
* Versão do schema declarada pelo **nativo**, repassada pelo shell.
|
|
822
|
+
*
|
|
823
|
+
* `null` quando o nativo ainda não respondeu (ou não existe, como no
|
|
824
|
+
* mock de browser). O cliente roda dentro de um iframe sandboxed e não
|
|
825
|
+
* fala com o nativo diretamente, então este é o **único** caminho pelo
|
|
826
|
+
* qual ele descobre de qual versão são as capacidades disponíveis.
|
|
827
|
+
*/
|
|
828
|
+
nativeVersion: v.nullable(v.string()),
|
|
793
829
|
accepted: v.boolean()
|
|
794
830
|
})
|
|
795
831
|
});
|
|
@@ -810,12 +846,14 @@ var ShellToClientMessage = v.variant("type", [
|
|
|
810
846
|
]);
|
|
811
847
|
|
|
812
848
|
// src/bridge-shell.ts
|
|
813
|
-
var SHELL_VERSION = "0.
|
|
849
|
+
var SHELL_VERSION = "0.6.0";
|
|
850
|
+
var NATIVE_HANDSHAKE_TIMEOUT_MS = 2e3;
|
|
814
851
|
var VERIFY_TIMEOUT_MS = 2e3;
|
|
815
852
|
var OVERRIDE_PREFIX = `<script>
|
|
816
853
|
(function(){
|
|
817
854
|
try { delete window.flutter_inappwebview; } catch (_) {}
|
|
818
855
|
try { delete window.CondorBridge; } catch (_) {}
|
|
856
|
+
try { delete window.CondorNative; } catch (_) {}
|
|
819
857
|
try {
|
|
820
858
|
Object.defineProperty(window, 'flutter_inappwebview', {
|
|
821
859
|
get: function(){ return undefined; },
|
|
@@ -823,6 +861,13 @@ var OVERRIDE_PREFIX = `<script>
|
|
|
823
861
|
configurable: false,
|
|
824
862
|
});
|
|
825
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 (_) {}
|
|
826
871
|
try {
|
|
827
872
|
Object.defineProperty(window, 'CondorBridge', {
|
|
828
873
|
get: function(){ return undefined; },
|
|
@@ -848,6 +893,13 @@ var BridgeShell = class {
|
|
|
848
893
|
constructor(opts) {
|
|
849
894
|
this.subscriptions = /* @__PURE__ */ new Map();
|
|
850
895
|
this.detached = false;
|
|
896
|
+
/**
|
|
897
|
+
* Versão do nativo, obtida uma vez e cacheada. `null` até o nativo
|
|
898
|
+
* responder — e permanentemente `null` num browser sem nativo.
|
|
899
|
+
*/
|
|
900
|
+
this.nativeVersion = null;
|
|
901
|
+
/** Handshake com o nativo em voo; garante uma única chamada. */
|
|
902
|
+
this.nativeHandshake = null;
|
|
851
903
|
// Map de `verify-sandbox` round-trips pendentes — key gerada por nonce.
|
|
852
904
|
this.pendingVerifies = /* @__PURE__ */ new Map();
|
|
853
905
|
this.onMessage = async (event) => {
|
|
@@ -872,9 +924,11 @@ var BridgeShell = class {
|
|
|
872
924
|
await this.handleSend(msg.command, msg.args ?? {});
|
|
873
925
|
break;
|
|
874
926
|
case "handshake":
|
|
875
|
-
this.
|
|
876
|
-
|
|
877
|
-
|
|
927
|
+
void this.resolveNativeVersion().then((nativeVersion) => {
|
|
928
|
+
this.postToClient({
|
|
929
|
+
type: "handshake-ack",
|
|
930
|
+
ack: { shellVersion: SHELL_VERSION, nativeVersion, accepted: true }
|
|
931
|
+
});
|
|
878
932
|
});
|
|
879
933
|
break;
|
|
880
934
|
case "jsError":
|
|
@@ -894,10 +948,12 @@ var BridgeShell = class {
|
|
|
894
948
|
if (pending) {
|
|
895
949
|
clearTimeout(pending.timer);
|
|
896
950
|
this.pendingVerifies.delete(first);
|
|
897
|
-
const
|
|
951
|
+
const nativeChannelReachable = msg.nativeChannelReachable ?? false;
|
|
952
|
+
const ok = !msg.flutterBridgeReachable && !msg.condorBridgeReachable && !nativeChannelReachable;
|
|
898
953
|
pending.resolve({
|
|
899
954
|
flutterBridgeReachable: msg.flutterBridgeReachable,
|
|
900
955
|
condorBridgeReachable: msg.condorBridgeReachable,
|
|
956
|
+
nativeChannelReachable,
|
|
901
957
|
ok
|
|
902
958
|
});
|
|
903
959
|
}
|
|
@@ -1053,6 +1109,29 @@ var BridgeShell = class {
|
|
|
1053
1109
|
}
|
|
1054
1110
|
Bridge.send(command, args);
|
|
1055
1111
|
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Obtém o `nativeVersion`, disparando o handshake com o nativo na primeira
|
|
1114
|
+
* vez e cacheando o resultado.
|
|
1115
|
+
*
|
|
1116
|
+
* ⚠️ `Bridge.handshake` **não tem timeout**: a Promise só resolve quando o
|
|
1117
|
+
* nativo emite `handshake-ack`. Num browser sem nativo ela nunca resolve,
|
|
1118
|
+
* então o `race` abaixo é o que garante que o cliente sempre receba
|
|
1119
|
+
* resposta — com `null` — em vez de ficar pendurado.
|
|
1120
|
+
*/
|
|
1121
|
+
async resolveNativeVersion() {
|
|
1122
|
+
if (this.nativeVersion !== null) return this.nativeVersion;
|
|
1123
|
+
if (!this.nativeHandshake) {
|
|
1124
|
+
this.nativeHandshake = Bridge.handshake({ clientVersion: SHELL_VERSION }).then((ack) => {
|
|
1125
|
+
this.nativeVersion = ack.nativeVersion;
|
|
1126
|
+
}).catch(() => {
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
await Promise.race([
|
|
1130
|
+
this.nativeHandshake,
|
|
1131
|
+
new Promise((resolve) => setTimeout(resolve, NATIVE_HANDSHAKE_TIMEOUT_MS))
|
|
1132
|
+
]);
|
|
1133
|
+
return this.nativeVersion;
|
|
1134
|
+
}
|
|
1056
1135
|
postToClient(msg) {
|
|
1057
1136
|
if (this.detached) return;
|
|
1058
1137
|
this.iframe.contentWindow?.postMessage(msg, "*");
|
|
@@ -1062,6 +1141,7 @@ export {
|
|
|
1062
1141
|
BRIDGE_KEYS,
|
|
1063
1142
|
Bridge,
|
|
1064
1143
|
BridgeClient,
|
|
1065
|
-
BridgeShell
|
|
1144
|
+
BridgeShell,
|
|
1145
|
+
NATIVE_CHANNEL_NAME
|
|
1066
1146
|
};
|
|
1067
1147
|
//# sourceMappingURL=index.js.map
|