@novasamatech/host-container 0.7.9-4 → 0.7.9-6
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/createContainer.d.ts +2 -2
- package/dist/createContainer.js +24 -4
- package/dist/debugBus.d.ts +18 -0
- package/dist/debugBus.js +73 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/types.d.ts +27 -1
- package/package.json +3 -2
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Provider } from '@novasamatech/host-api';
|
|
2
|
-
import type { Container } from './types.js';
|
|
3
|
-
export declare function createContainer(provider: Provider): Container;
|
|
2
|
+
import type { Container, CreateContainerOptions } from './types.js';
|
|
3
|
+
export declare function createContainer(provider: Provider, options?: CreateContainerOptions): Container;
|
package/dist/createContainer.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ChatBotRegistrationErr, ChatMessagePostingErr, ChatRoomRegistrationErr, CreateProofErr, CreateTransactionErr, DeriveEntropyErr, DevicePermission, GenericError, GetUserIdErr, LoginErr, NavigateToErr, PaymentBalanceErr, PaymentRequestErr, PaymentStatusErr, PaymentTopUpErr, PreimageSubmitErr, RemotePermission, RequestCredentialsErr, ResourceAllocationErr, SigningErr, StatementProofErr, StorageErr, createTransport, enumValue, isEnumVariant, resultErr, resultOk, } from '@novasamatech/host-api';
|
|
1
|
+
import { ChatBotRegistrationErr, ChatMessagePostingErr, ChatRoomRegistrationErr, CreateProofErr, CreateTransactionErr, DeriveEntropyErr, DevicePermission, GenericError, GetUserIdErr, LoginErr, NavigateToErr, PaymentBalanceErr, PaymentRequestErr, PaymentStatusErr, PaymentTopUpErr, PreimageSubmitErr, PushNotificationError, RemotePermission, RequestCredentialsErr, ResourceAllocationErr, SigningErr, StatementProofErr, StorageErr, createTransport, enumValue, isEnumVariant, resultErr, resultOk, } from '@novasamatech/host-api';
|
|
2
2
|
import { err, errAsync, ok, okAsync } from 'neverthrow';
|
|
3
3
|
import { createChainConnectionManager } from './chainConnectionManager.js';
|
|
4
|
+
import { emitHostApiDebugMessage, registerHostApiDebugSource } from './debugBus.js';
|
|
4
5
|
const UNSUPPORTED_MESSAGE_FORMAT_ERROR = 'Unsupported message format';
|
|
5
6
|
const NOT_IMPLEMENTED = 'Not implemented';
|
|
6
7
|
function guardVersion(value, tag, error) {
|
|
@@ -12,11 +13,21 @@ function guardVersion(value, tag, error) {
|
|
|
12
13
|
}
|
|
13
14
|
return err(error);
|
|
14
15
|
}
|
|
15
|
-
export function createContainer(provider) {
|
|
16
|
+
export function createContainer(provider, options = {}) {
|
|
16
17
|
const transport = createTransport(provider);
|
|
17
18
|
if (!transport.isCorrectEnvironment()) {
|
|
18
19
|
throw new Error('Transport is not available: dapp provider has incorrect environment');
|
|
19
20
|
}
|
|
21
|
+
const { productId } = options;
|
|
22
|
+
// EXPERIMENTAL: forward every transport-level message into the
|
|
23
|
+
// process-global debug bus, tagged with this container's productId.
|
|
24
|
+
// The forwarder is registered as a bus *source* and only attaches to
|
|
25
|
+
// `transport.onDebugMessage` while the bus has at least one subscriber —
|
|
26
|
+
// otherwise the transport's lazy `Message.dec` path stays cold.
|
|
27
|
+
const unregisterGlobalDebugSource = registerHostApiDebugSource(() => transport.onDebugMessage(({ direction, requestId, payload }) => {
|
|
28
|
+
emitHostApiDebugMessage({ direction, productId, requestId, payload });
|
|
29
|
+
}));
|
|
30
|
+
transport.onDestroy(unregisterGlobalDebugSource);
|
|
20
31
|
function init() {
|
|
21
32
|
// init status subscription
|
|
22
33
|
transport.isReady();
|
|
@@ -176,7 +187,8 @@ export function createContainer(provider) {
|
|
|
176
187
|
const handleFeatureSupportedSlot = makeNotImplementedSlot('host_feature_supported', () => new GenericError({ reason: NOT_IMPLEMENTED }));
|
|
177
188
|
const handleDevicePermissionSlot = makeNotImplementedSlot('host_device_permission', () => new GenericError({ reason: NOT_IMPLEMENTED }));
|
|
178
189
|
const handleRemotePermissionSlot = makeNotImplementedSlot('remote_permission', () => new GenericError({ reason: NOT_IMPLEMENTED }));
|
|
179
|
-
const handlePushNotificationSlot = makeDevicePermissionGatedRequestSlot('host_push_notification', 'Notifications', () => new
|
|
190
|
+
const handlePushNotificationSlot = makeDevicePermissionGatedRequestSlot('host_push_notification', 'Notifications', () => new PushNotificationError.Unknown({ reason: NOT_IMPLEMENTED }));
|
|
191
|
+
const handlePushNotificationCancelSlot = makeDevicePermissionGatedRequestSlot('host_push_notification_cancel', 'Notifications', () => new GenericError({ reason: NOT_IMPLEMENTED }));
|
|
180
192
|
const handleNavigateToSlot = makeNotImplementedSlot('host_navigate_to', () => new NavigateToErr.Unknown({ reason: NOT_IMPLEMENTED }));
|
|
181
193
|
const handleChatCreateRoomSlot = makeNotImplementedSlot('host_chat_create_room', () => new ChatRoomRegistrationErr.Unknown({ reason: NOT_IMPLEMENTED }));
|
|
182
194
|
const handleChatBotRegistrationSlot = makeNotImplementedSlot('host_chat_register_bot', () => new ChatBotRegistrationErr.Unknown({ reason: NOT_IMPLEMENTED }));
|
|
@@ -211,7 +223,10 @@ export function createContainer(provider) {
|
|
|
211
223
|
return handleV1Request(handleRemotePermissionSlot, () => new GenericError({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR }), handler);
|
|
212
224
|
},
|
|
213
225
|
handlePushNotification(handler) {
|
|
214
|
-
return handleV1Request(handlePushNotificationSlot, () => new
|
|
226
|
+
return handleV1Request(handlePushNotificationSlot, () => new PushNotificationError.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR }), handler);
|
|
227
|
+
},
|
|
228
|
+
handlePushNotificationCancel(handler) {
|
|
229
|
+
return handleV1Request(handlePushNotificationCancelSlot, () => new GenericError({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR }), handler);
|
|
215
230
|
},
|
|
216
231
|
handleNavigateTo(handler) {
|
|
217
232
|
return handleV1Request(handleNavigateToSlot, () => new NavigateToErr.Unknown({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR }), handler);
|
|
@@ -621,5 +636,10 @@ export function createContainer(provider) {
|
|
|
621
636
|
dispose() {
|
|
622
637
|
transport.destroy();
|
|
623
638
|
},
|
|
639
|
+
onDebugMessage(callback) {
|
|
640
|
+
return transport.onDebugMessage(({ direction, requestId, payload }) => {
|
|
641
|
+
callback({ direction, productId, requestId, payload });
|
|
642
|
+
});
|
|
643
|
+
},
|
|
624
644
|
};
|
|
625
645
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HostApiDebugMessageEvent } from './types.js';
|
|
2
|
+
type DebugSource = () => VoidFunction;
|
|
3
|
+
/** @internal Used by `createContainer` to forward its transport's debug events. */
|
|
4
|
+
export declare function emitHostApiDebugMessage(event: HostApiDebugMessageEvent): void;
|
|
5
|
+
/**
|
|
6
|
+
* @internal Register a transport-level forwarder for the global bus.
|
|
7
|
+
* The source is activated only while the bus has at least one subscriber
|
|
8
|
+
* and deactivated when the last one unsubscribes — this preserves the
|
|
9
|
+
* transport's lazy decode path (no `Message.dec` per frame) when nobody
|
|
10
|
+
* is listening downstream.
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerHostApiDebugSource(source: DebugSource): VoidFunction;
|
|
13
|
+
/**
|
|
14
|
+
* EXPERIMENTAL. Subscribe to every host ↔ product message across all
|
|
15
|
+
* containers in the current process. Returns an unsubscribe function.
|
|
16
|
+
*/
|
|
17
|
+
export declare function onHostApiDebugMessage(callback: (event: HostApiDebugMessageEvent) => void): VoidFunction;
|
|
18
|
+
export {};
|
package/dist/debugBus.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createNanoEvents } from 'nanoevents';
|
|
2
|
+
/**
|
|
3
|
+
* EXPERIMENTAL: process-global bus that aggregates debug events from
|
|
4
|
+
* every container created in this process. Subscribing here gives a
|
|
5
|
+
* single subscriber visibility into all host ↔ product traffic across
|
|
6
|
+
* every active container, annotated with the `productId` passed to
|
|
7
|
+
* `createContainer` (if any).
|
|
8
|
+
*/
|
|
9
|
+
const bus = createNanoEvents();
|
|
10
|
+
const sources = new Set();
|
|
11
|
+
const activeSources = new Map();
|
|
12
|
+
let subscriberCount = 0;
|
|
13
|
+
function activateSource(source) {
|
|
14
|
+
if (activeSources.has(source))
|
|
15
|
+
return;
|
|
16
|
+
activeSources.set(source, source());
|
|
17
|
+
}
|
|
18
|
+
function deactivateSource(source) {
|
|
19
|
+
const unsubscribe = activeSources.get(source);
|
|
20
|
+
if (!unsubscribe)
|
|
21
|
+
return;
|
|
22
|
+
activeSources.delete(source);
|
|
23
|
+
unsubscribe();
|
|
24
|
+
}
|
|
25
|
+
/** @internal Used by `createContainer` to forward its transport's debug events. */
|
|
26
|
+
export function emitHostApiDebugMessage(event) {
|
|
27
|
+
bus.emit('message', event);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* @internal Register a transport-level forwarder for the global bus.
|
|
31
|
+
* The source is activated only while the bus has at least one subscriber
|
|
32
|
+
* and deactivated when the last one unsubscribes — this preserves the
|
|
33
|
+
* transport's lazy decode path (no `Message.dec` per frame) when nobody
|
|
34
|
+
* is listening downstream.
|
|
35
|
+
*/
|
|
36
|
+
export function registerHostApiDebugSource(source) {
|
|
37
|
+
sources.add(source);
|
|
38
|
+
if (subscriberCount > 0)
|
|
39
|
+
activateSource(source);
|
|
40
|
+
let disposed = false;
|
|
41
|
+
return () => {
|
|
42
|
+
if (disposed)
|
|
43
|
+
return;
|
|
44
|
+
disposed = true;
|
|
45
|
+
sources.delete(source);
|
|
46
|
+
deactivateSource(source);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* EXPERIMENTAL. Subscribe to every host ↔ product message across all
|
|
51
|
+
* containers in the current process. Returns an unsubscribe function.
|
|
52
|
+
*/
|
|
53
|
+
export function onHostApiDebugMessage(callback) {
|
|
54
|
+
const wasZero = subscriberCount === 0;
|
|
55
|
+
subscriberCount++;
|
|
56
|
+
if (wasZero) {
|
|
57
|
+
for (const source of sources)
|
|
58
|
+
activateSource(source);
|
|
59
|
+
}
|
|
60
|
+
const unsubscribe = bus.on('message', callback);
|
|
61
|
+
let disposed = false;
|
|
62
|
+
return () => {
|
|
63
|
+
if (disposed)
|
|
64
|
+
return;
|
|
65
|
+
disposed = true;
|
|
66
|
+
unsubscribe();
|
|
67
|
+
subscriberCount--;
|
|
68
|
+
if (subscriberCount === 0) {
|
|
69
|
+
for (const source of [...activeSources.keys()])
|
|
70
|
+
deactivateSource(source);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { createWebviewProvider } from './createWebviewProvider.js';
|
|
2
2
|
export { createIframeProvider } from './createIframeProvider.js';
|
|
3
3
|
export { createContainer } from './createContainer.js';
|
|
4
|
-
export type { Container, ContainerHandlerOf } from './types.js';
|
|
4
|
+
export type { Container, ContainerHandlerOf, CreateContainerOptions, HostApiDebugMessageEvent } from './types.js';
|
|
5
|
+
export { onHostApiDebugMessage } from './debugBus.js';
|
|
5
6
|
export { deriveProductEntropy } from './deriveEntropy.js';
|
|
6
7
|
export { createRateLimiter } from './rateLimiter.js';
|
|
7
8
|
export type { CreateRateLimiterConfig, RateLimiter, RateLimiterConfig, RateLimiterStrategy } from './rateLimiter.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { createWebviewProvider } from './createWebviewProvider.js';
|
|
2
2
|
export { createIframeProvider } from './createIframeProvider.js';
|
|
3
3
|
export { createContainer } from './createContainer.js';
|
|
4
|
+
export { onHostApiDebugMessage } from './debugBus.js';
|
|
4
5
|
export { deriveProductEntropy } from './deriveEntropy.js';
|
|
5
6
|
export { createRateLimiter } from './rateLimiter.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Codec, CodecType, ConnectionStatus, HexString, HostApiProtocol, Subscription, VersionedProtocolRequest, VersionedProtocolSubscription } from '@novasamatech/host-api';
|
|
1
|
+
import type { Codec, CodecType, ConnectionStatus, HexString, HostApiProtocol, MessagePayloadSchema, Subscription, VersionedProtocolRequest, VersionedProtocolSubscription } from '@novasamatech/host-api';
|
|
2
2
|
import { CustomRendererNode } from '@novasamatech/host-api';
|
|
3
3
|
import type { ResultAsync, errAsync } from 'neverthrow';
|
|
4
4
|
import { okAsync } from 'neverthrow';
|
|
@@ -52,11 +52,31 @@ type InferRequestHandler<V extends string, T extends VersionedProtocolRequest> =
|
|
|
52
52
|
type InferSubscribeHandler<V extends string, T extends VersionedProtocolSubscription> = (callback: (params: WithVersion<V, CodecValue<T['start']>>, send: (payload: WithVersion<V, CodecValue<T['receive']>>) => void, interrupt: (payload: WithVersion<V, CodecValue<T['interrupt']>>) => void) => VoidFunction) => VoidFunction;
|
|
53
53
|
type InferHandler<V extends string, T extends VersionedProtocolRequest | VersionedProtocolSubscription> = T extends VersionedProtocolRequest ? InferRequestHandler<V, T> : T extends VersionedProtocolSubscription ? InferSubscribeHandler<V, T> : never;
|
|
54
54
|
export type ContainerHandlerOf<T extends (...args: any[]) => any> = Parameters<T>[0];
|
|
55
|
+
/**
|
|
56
|
+
* EXPERIMENTAL. Event describing a single message observed on a
|
|
57
|
+
* container's transport, in decoded form, tagged with the productId
|
|
58
|
+
* that was passed to `createContainer`.
|
|
59
|
+
*/
|
|
60
|
+
export type HostApiDebugMessageEvent = {
|
|
61
|
+
direction: 'incoming' | 'outgoing';
|
|
62
|
+
productId: string | undefined;
|
|
63
|
+
requestId: string;
|
|
64
|
+
payload: MessagePayloadSchema;
|
|
65
|
+
};
|
|
66
|
+
export type CreateContainerOptions = {
|
|
67
|
+
/**
|
|
68
|
+
* Optional identifier for the product this container talks to.
|
|
69
|
+
* When set, every debug event emitted via `onDebugMessage` and the
|
|
70
|
+
* global `onHostApiDebugMessage` bus is tagged with this value.
|
|
71
|
+
*/
|
|
72
|
+
productId?: string;
|
|
73
|
+
};
|
|
55
74
|
export type Container = {
|
|
56
75
|
handleFeatureSupported: InferHandler<'v1', HostApiProtocol['host_feature_supported']>;
|
|
57
76
|
handleDevicePermission: InferHandler<'v1', HostApiProtocol['host_device_permission']>;
|
|
58
77
|
handlePermission: InferHandler<'v1', HostApiProtocol['remote_permission']>;
|
|
59
78
|
handlePushNotification: InferHandler<'v1', HostApiProtocol['host_push_notification']>;
|
|
79
|
+
handlePushNotificationCancel: InferHandler<'v1', HostApiProtocol['host_push_notification_cancel']>;
|
|
60
80
|
handleNavigateTo: InferHandler<'v1', HostApiProtocol['host_navigate_to']>;
|
|
61
81
|
handleDeriveEntropy: InferHandler<'v1', HostApiProtocol['host_derive_entropy']>;
|
|
62
82
|
handleLocalStorageRead: InferHandler<'v1', HostApiProtocol['host_local_storage_read']>;
|
|
@@ -101,5 +121,11 @@ export type Container = {
|
|
|
101
121
|
isReady(): Promise<boolean>;
|
|
102
122
|
dispose(): void;
|
|
103
123
|
subscribeProductConnectionStatus(callback: (connectionStatus: ConnectionStatus) => void): VoidFunction;
|
|
124
|
+
/**
|
|
125
|
+
* EXPERIMENTAL. Subscribe to every message crossing this container's
|
|
126
|
+
* transport in either direction, in decoded form. Returns an
|
|
127
|
+
* unsubscribe function.
|
|
128
|
+
*/
|
|
129
|
+
onDebugMessage(callback: (event: HostApiDebugMessageEvent) => void): VoidFunction;
|
|
104
130
|
};
|
|
105
131
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novasamatech/host-container",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.9-
|
|
4
|
+
"version": "0.7.9-6",
|
|
5
5
|
"description": "Host container for hosting and managing products within the Polkadot ecosystem.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"@noble/hashes": "2.2.0",
|
|
29
29
|
"polkadot-api": ">=2",
|
|
30
30
|
"@polkadot-api/substrate-client": "^0.7.0",
|
|
31
|
-
"@novasamatech/host-api": "0.7.9-
|
|
31
|
+
"@novasamatech/host-api": "0.7.9-6",
|
|
32
|
+
"nanoevents": "9.1.0",
|
|
32
33
|
"nanoid": "5.1.9",
|
|
33
34
|
"neverthrow": "^8.2.0"
|
|
34
35
|
},
|