@novasamatech/host-container 0.7.1-0 → 0.7.1

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 CHANGED
@@ -74,9 +74,9 @@ container.handleDevicePermission(async (request, { ok, err }) => {
74
74
 
75
75
  ### handlePermission
76
76
 
77
- The `request` parameter is an **array** of `RemotePermission` items. Return `ok(true)` only when **all** permissions in the batch are granted.
77
+ The `request` parameter is a single `RemotePermission` item. Return `ok(true)` when the permission is granted, `ok(false)` when denied.
78
78
 
79
- Each item has one of these shapes:
79
+ The item has one of these shapes:
80
80
  - `{ tag: 'Remote', value: string[] }` — HTTP/WS domain patterns (exact or `*.wildcard`)
81
81
  - `{ tag: 'WebRTC', value: undefined }` — WebRTC access (may expose user IP)
82
82
  - `{ tag: 'ChainSubmit', value: undefined }` — broadcast transactions via `remote_chain_transaction_broadcast`
@@ -84,37 +84,19 @@ Each item has one of these shapes:
84
84
  - `{ tag: 'StatementSubmit', value: undefined }` — submit statements via `remote_statement_store_submit`
85
85
 
86
86
  ```ts
87
- container.handlePermission(async (permissions, { ok, err }) => {
88
- for (const permission of permissions) {
89
- switch (permission.tag) {
90
- case 'Remote': {
91
- const allowed = await checkDomainPermissions(permission.value);
92
- if (!allowed) return ok(false);
93
- break;
94
- }
95
- case 'WebRTC': {
96
- const allowed = await promptWebRTCPermission();
97
- if (!allowed) return ok(false);
98
- break;
99
- }
100
- case 'ChainSubmit': {
101
- const allowed = await promptChainSubmitPermission();
102
- if (!allowed) return ok(false);
103
- break;
104
- }
105
- case 'PreimageSubmit': {
106
- const allowed = await promptPreimageSubmitPermission();
107
- if (!allowed) return ok(false);
108
- break;
109
- }
110
- case 'StatementSubmit': {
111
- const allowed = await promptStatementSubmitPermission();
112
- if (!allowed) return ok(false);
113
- break;
114
- }
115
- }
87
+ container.handlePermission(async (permission, { ok, err }) => {
88
+ switch (permission.tag) {
89
+ case 'Remote':
90
+ return ok(await checkDomainPermissions(permission.value));
91
+ case 'WebRTC':
92
+ return ok(await promptWebRTCPermission());
93
+ case 'ChainSubmit':
94
+ return ok(await promptChainSubmitPermission());
95
+ case 'PreimageSubmit':
96
+ return ok(await promptPreimageSubmitPermission());
97
+ case 'StatementSubmit':
98
+ return ok(await promptStatementSubmitPermission());
116
99
  }
117
- return ok(true);
118
100
  });
119
101
  ```
120
102
 
@@ -1,4 +1,4 @@
1
- import { ChatBotRegistrationErr, ChatMessagePostingErr, ChatRoomRegistrationErr, CreateProofErr, CreateTransactionErr, DeriveEntropyErr, GenericError, LoginErr, NavigateToErr, PaymentRequestErr, PaymentTopUpErr, PreimageSubmitErr, RemotePermission, RequestCredentialsErr, SigningErr, StatementProofErr, StorageErr, createTransport, enumValue, isEnumVariant, resultErr, resultOk, } from '@novasamatech/host-api';
1
+ import { ChatBotRegistrationErr, ChatMessagePostingErr, ChatRoomRegistrationErr, CreateProofErr, CreateTransactionErr, DeriveEntropyErr, GenericError, LoginErr, NavigateToErr, PaymentBalanceErr, PaymentRequestErr, PaymentStatusErr, PaymentTopUpErr, PreimageSubmitErr, RemotePermission, RequestCredentialsErr, 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
4
  const UNSUPPORTED_MESSAGE_FORMAT_ERROR = 'Unsupported message format';
@@ -60,23 +60,24 @@ export function createContainer(provider) {
60
60
  const handler = async () => enumValue('v1', resultErr(makeError()));
61
61
  return makeRequestSlot(method, handler);
62
62
  }
63
- function makeInterruptSlot(method) {
63
+ function makeInterruptSlot(method, makeDefaultInterrupt) {
64
64
  // Cast needed: the default handler ignores typed params/send which TypeScript can't verify
65
65
  // matches the generic Method's subscription type without evaluating template literal types.
66
66
  const defaultHandler = ((_params, _send, interrupt) => {
67
- queueMicrotask(interrupt);
67
+ queueMicrotask(() => interrupt(makeDefaultInterrupt()));
68
68
  return () => {
69
69
  /* nothing to clean up */
70
70
  };
71
71
  });
72
- return makeSubscriptionSlot(method, defaultHandler);
72
+ const update = makeSubscriptionSlot(method, defaultHandler);
73
+ return { update, makeDefaultInterrupt };
73
74
  }
74
75
  function makePermissionGatedRequestSlot(method, permissionVariant, makeError) {
75
76
  const defaultHandler = async () => enumValue('v1', resultErr(makeError()));
76
77
  let current = defaultHandler;
77
78
  let version = 0;
78
79
  transport.handleRequest(method, async (params) => {
79
- const permissionResponse = await handleRemotePermissionSlot.call(enumValue('v1', [enumValue(permissionVariant, undefined)]));
80
+ const permissionResponse = await handleRemotePermissionSlot.call(enumValue('v1', enumValue(permissionVariant, undefined)));
80
81
  const permissionGranted = isEnumVariant(permissionResponse, 'v1') &&
81
82
  permissionResponse.value.success === true &&
82
83
  permissionResponse.value.value === true;
@@ -116,13 +117,13 @@ export function createContainer(provider) {
116
117
  const version = 'v1';
117
118
  const slotHandler = ((params, send, interrupt) => {
118
119
  return guardVersion(params, version, null)
119
- .map(p => handler(p, ((payload) => send(enumValue(version, payload))), interrupt))
120
- .orTee(interrupt)
120
+ .map(p => handler(p, ((payload) => send(enumValue(version, payload))), ((payload) => interrupt(enumValue(version, payload)))))
121
+ .orTee(() => interrupt(slot.makeDefaultInterrupt()))
121
122
  .unwrapOr(() => {
122
123
  /* empty */
123
124
  });
124
125
  });
125
- return slot(slotHandler);
126
+ return slot.update(slotHandler);
126
127
  }
127
128
  // account slots
128
129
  const handleAccountGetRootSlot = makeNotImplementedSlot('host_account_get_root', () => new RequestCredentialsErr.Unknown({ reason: NOT_IMPLEMENTED }));
@@ -160,14 +161,14 @@ export function createContainer(provider) {
160
161
  const handlePaymentRequestSlot = makeNotImplementedSlot('host_payment_request', () => new PaymentRequestErr.Unknown({ reason: NOT_IMPLEMENTED }));
161
162
  // subscription slots — default interrupts on next microtask so that
162
163
  // the caller has a chance to register an onInterrupt listener first
163
- const handleThemeSubscribeSlot = makeInterruptSlot('host_theme_subscribe');
164
- const handleAccountConnectionStatusSubscribeSlot = makeInterruptSlot('host_account_connection_status_subscribe');
165
- const handleChatListSubscribeSlot = makeInterruptSlot('host_chat_list_subscribe');
166
- const handleChatActionSubscribeSlot = makeInterruptSlot('host_chat_action_subscribe');
167
- const handleStatementStoreSubscribeSlot = makeInterruptSlot('remote_statement_store_subscribe');
168
- const handlePreimageLookupSubscribeSlot = makeInterruptSlot('remote_preimage_lookup_subscribe');
169
- const handlePaymentBalanceSubscribeSlot = makeInterruptSlot('host_payment_balance_subscribe');
170
- const handlePaymentStatusSubscribeSlot = makeInterruptSlot('host_payment_status_subscribe');
164
+ const handleThemeSubscribeSlot = makeInterruptSlot('host_theme_subscribe', () => enumValue('v1', undefined));
165
+ const handleAccountConnectionStatusSubscribeSlot = makeInterruptSlot('host_account_connection_status_subscribe', () => enumValue('v1', undefined));
166
+ const handleChatListSubscribeSlot = makeInterruptSlot('host_chat_list_subscribe', () => enumValue('v1', undefined));
167
+ const handleChatActionSubscribeSlot = makeInterruptSlot('host_chat_action_subscribe', () => enumValue('v1', undefined));
168
+ const handleStatementStoreSubscribeSlot = makeInterruptSlot('remote_statement_store_subscribe', () => enumValue('v1', undefined));
169
+ const handlePreimageLookupSubscribeSlot = makeInterruptSlot('remote_preimage_lookup_subscribe', () => enumValue('v1', undefined));
170
+ const handlePaymentBalanceSubscribeSlot = makeInterruptSlot('host_payment_balance_subscribe', () => enumValue('v1', new PaymentBalanceErr.Unknown({ reason: NOT_IMPLEMENTED })));
171
+ const handlePaymentStatusSubscribeSlot = makeInterruptSlot('host_payment_status_subscribe', () => enumValue('v1', new PaymentStatusErr.Unknown({ reason: NOT_IMPLEMENTED })));
171
172
  return {
172
173
  handleFeatureSupported(handler) {
173
174
  return handleV1Request(handleFeatureSupportedSlot, () => new GenericError({ reason: UNSUPPORTED_MESSAGE_FORMAT_ERROR }), handler);
@@ -296,7 +297,7 @@ export function createContainer(provider) {
296
297
  // Follow subscription
297
298
  cleanups.push(transport.handleSubscription('remote_chain_head_follow', (params, send, interrupt) => {
298
299
  if (!isEnumVariant(params, 'v1')) {
299
- interrupt();
300
+ interrupt(enumValue('v1', undefined));
300
301
  return () => {
301
302
  /* unsupported version */
302
303
  };
@@ -304,7 +305,7 @@ export function createContainer(provider) {
304
305
  const { genesisHash, withRuntime } = params.value;
305
306
  const entry = manager.getOrCreateChain(genesisHash);
306
307
  if (!entry) {
307
- interrupt();
308
+ interrupt(enumValue('v1', undefined));
308
309
  return () => {
309
310
  /* no chain provider available */
310
311
  };
@@ -525,7 +526,7 @@ export function createContainer(provider) {
525
526
  }
526
527
  const { genesisHash, transaction } = message.value;
527
528
  try {
528
- const permissionResponse = await handleRemotePermissionSlot.call(enumValue('v1', [enumValue('ChainSubmit', undefined)]));
529
+ const permissionResponse = await handleRemotePermissionSlot.call(enumValue('v1', enumValue('ChainSubmit', undefined)));
529
530
  const permissionGranted = isEnumVariant(permissionResponse, 'v1') &&
530
531
  permissionResponse.value.success === true &&
531
532
  permissionResponse.value.value === true;
package/dist/types.d.ts CHANGED
@@ -49,7 +49,7 @@ export type ContainerRequestHandler<V extends string, T extends VersionedProtoco
49
49
  err: typeof errAsync<never, UnwrapErrorResponse<V, CodecValue<T['response']>>>;
50
50
  }) => OrPromise<UnwrapVersionedResult<V, CodecValue<T['response']>>>;
51
51
  type InferRequestHandler<V extends string, T extends VersionedProtocolRequest> = (callback: ContainerRequestHandler<V, T>) => VoidFunction;
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: VoidFunction) => VoidFunction) => VoidFunction;
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
55
  export type Container = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@novasamatech/host-container",
3
3
  "type": "module",
4
- "version": "0.7.1-0",
4
+ "version": "0.7.1",
5
5
  "description": "Host container for hosting and managing products within the Polkadot ecosystem.",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -27,7 +27,7 @@
27
27
  "dependencies": {
28
28
  "@noble/hashes": "2.2.0",
29
29
  "polkadot-api": ">=2",
30
- "@novasamatech/host-api": "0.7.1-0",
30
+ "@novasamatech/host-api": "0.7.1",
31
31
  "nanoid": "5.1.9",
32
32
  "neverthrow": "^8.2.0"
33
33
  },