@peers-app/peers-sdk 0.23.10 → 0.23.12
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/contracts/__tests__/builder.test.js +25 -0
- package/dist/contracts/__tests__/contract-provider-router.test.js +45 -0
- package/dist/contracts/__tests__/contract-proxy.test.js +67 -0
- package/dist/contracts/__tests__/contract-resolvers.test.js +133 -0
- package/dist/contracts/__tests__/remote-contract-transport.test.d.ts +1 -0
- package/dist/contracts/__tests__/remote-contract-transport.test.js +89 -0
- package/dist/contracts/builder.d.ts +47 -1
- package/dist/contracts/builder.js +80 -22
- package/dist/contracts/contract-provider-router.d.ts +6 -0
- package/dist/contracts/contract-provider-router.js +25 -3
- package/dist/contracts/contract-proxy.d.ts +41 -1
- package/dist/contracts/contract-proxy.js +103 -0
- package/dist/contracts/contract-resolvers.d.ts +47 -13
- package/dist/contracts/contract-resolvers.js +125 -35
- package/dist/contracts/extract.d.ts +4 -1
- package/dist/contracts/extract.js +3 -1
- package/dist/contracts/index.d.ts +4 -3
- package/dist/contracts/index.js +10 -2
- package/dist/contracts/remote-contract-transport.d.ts +69 -0
- package/dist/contracts/remote-contract-transport.js +95 -0
- package/dist/contracts/types.d.ts +57 -0
- package/dist/data/tools.d.ts +4 -0
- package/dist/data/tools.js +7 -0
- package/dist/package-loader/isolated-artifact.d.ts +44 -5
- package/dist/package-loader/isolated-artifact.js +82 -4
- package/dist/package-loader/isolated-artifact.test.js +51 -3
- package/dist/package-loader/isolated-runtime.d.ts +17 -2
- package/dist/package-loader/isolated-runtime.js +3 -1
- package/dist/package-loader/isolated-table-gateway.d.ts +1 -1
- package/dist/package-loader/isolated-table-gateway.js +54 -0
- package/dist/package-loader/isolated-table-gateway.test.js +61 -0
- package/dist/package-loader/package-loader.d.ts +15 -1
- package/dist/package-loader/package-loader.js +48 -0
- package/dist/package-loader/resolve-consumed-contracts.d.ts +6 -2
- package/dist/package-loader/resolve-consumed-contracts.js +30 -2
- package/dist/package-loader/resolve-consumed-contracts.test.js +43 -0
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { ContractBuilder, definePackage, PackageBuilder } from "./builder";
|
|
2
2
|
export { type ContractCallAuthorizer, type ContractProviderEndpointResolver, type ContractProviderPackageResolver, createContractProviderRouter, type IAuthorizedContractRoute, type IContractProviderEndpointRequest, type IContractProviderRouter, type IContractProviderRouterOptions, } from "./contract-provider-router";
|
|
3
3
|
export { ContractProviders, ContractProvidersTable, contractProvidersMetaData, contractProvidersSchema, type IContractProviderRecord, } from "./contract-providers.table";
|
|
4
|
-
export { CONTRACT_CALL_RPC, type ContractMemberType, type ContractNotificationSink, type ContractPermissionCheck, createContractConsumer, createContractProvider, createContractProviderEndpoint, createContractProviderSession, type IContractCall, type IContractCallContext, type IContractConsumer, type IContractConsumerBase, type IContractNotification, type IContractProviderEndpoint, type IContractProviderEndpointOptions, type IContractProviderSession, type IContractProviderSessionOptions, type IContractResolution, type IContractTableProxy, type IContractToolContext, type ITableProxy, sameUserContractPermissionCheck, } from "./contract-proxy";
|
|
5
|
-
export { type ContractRemoteIdentity, type ContractResolver, createLocalUserContextContractProviderRouter, createUserContextContractProviderRouter, getContractResolver, handleContractCall, type IContractResolverRegistrationOptions, type ILocalContractVariableRequest, isSelfTrustedContractCaller, type LocalContractVariableResolver, registerContractResolver, } from "./contract-resolvers";
|
|
4
|
+
export { CONTRACT_CALL_RPC, type ContractMemberType, type ContractNotificationSink, type ContractPermissionCheck, createContractConsumer, createContractProvider, createContractProviderEndpoint, createContractProviderSession, createRemoteContractConsumer, type IContractCall, type IContractCallContext, type IContractConsumer, type IContractConsumerBase, type IContractNotification, type IContractProviderEndpoint, type IContractProviderEndpointOptions, type IContractProviderSession, type IContractProviderSessionOptions, type IContractResolution, type IContractTableProxy, type IContractToolContext, type ITableProxy, sameUserContractPermissionCheck, } from "./contract-proxy";
|
|
5
|
+
export { authorizeRemoteContractCall, type ContractRemoteIdentity, type ContractResolver, createLocalUserContextContractProviderRouter, createUserContextContractProviderRouter, getContractResolver, handleContractCall, type IContractResolverRegistrationOptions, type ILocalContractVariableRequest, isSelfTrustedContractCaller, type LocalContractVariableResolver, registerContractResolver, verifyRemoteContractIdentity, } from "./contract-resolvers";
|
|
6
6
|
export { CONTRACT_NOTIFY_CHANNEL, CONTRACT_REQUEST_CHANNEL, connectionContractTransport, type IContractTransport, type IDuplexEmitter, inProcessTransportPair, } from "./contract-transport";
|
|
7
7
|
export { Contracts, ContractsTable, contractsMetaData, contractsSchema, type IContractRecord, } from "./contracts.table";
|
|
8
8
|
export { createLocalContractConsumer } from "./create-local-consumer";
|
|
@@ -10,11 +10,12 @@ export { extractTableShape, extractToolShape, type IExtractableTableDef, type IE
|
|
|
10
10
|
export { getHostContractTransport, type HostContractTransportListener, registerHostContractTransport, subscribeHostContractTransport, waitForHostContractTransport, } from "./host-contract-transport";
|
|
11
11
|
export { PersistentContractRegistry } from "./persistent-registry";
|
|
12
12
|
export { ContractRegistry, type IContractProviderRegistration } from "./registry";
|
|
13
|
+
export { createRemoteContractEndpoint, getRemoteContractTransportFactory, type IRemoteContractHost, type IRemoteContractTarget, type RemoteContractTransportFactory, resolveRemoteTargetEndpoint, setRemoteContractTransportFactory, } from "./remote-contract-transport";
|
|
13
14
|
export { DEVICE_OPERATIONS_CONTRACT_VERSION, DEVICE_OPERATIONS_MAX_QUERY_LENGTH, DEVICE_OPERATIONS_MAX_RESULT_BYTES, DEVICE_OPERATIONS_MAX_ROWS, DEVICE_OPERATIONS_MAX_TOOLS, type DeviceOperationCapability, deviceOperationsProviderPackageId, deviceOperationsToolIds, getDeviceOperationsContractDefinition, type IDeviceDatabaseQueryInput, type IDeviceDatabaseQueryResult, type IDeviceOperationStatus, type IDeviceToolListInput, type IDeviceToolLookupInput, type IDeviceToolLookupResult, type IDeviceToolRunInput, } from "./system/device-operations-contract";
|
|
14
15
|
export { getLogsContractDefinition, type ILogsConsumer, LOGS_CONTRACT_VERSION, resolveLogsContract, } from "./system/logs-contract";
|
|
15
16
|
export * from "./system/network-contracts";
|
|
16
17
|
export { getToolAccessControlContractDefinition, type IToolAccessControlConsumer, TOOL_ACCESS_CONTROL_CONTRACT_VERSION, } from "./system/tool-access-control-contract";
|
|
17
18
|
export { type ISystemContractRegistration, installSystemContracts, listSystemContracts, registerSystemContract, } from "./system-contracts";
|
|
18
|
-
export type { IAlsoImplementsDeclaration, IConsumedContract, IConsumedContractHandle, IConsumedContractOptions, IContractDefinition, IContractEvent, IContractObservable, IContractTable, IContractTool, IPackageDefinitionResult, IResolvedContract, IValidationError, IValidationResult, } from "./types";
|
|
19
|
+
export type { IAlsoImplementsDeclaration, IConsumedContract, IConsumedContractHandle, IConsumedContractOptions, IContractDefinition, IContractEvent, IContractObservable, IContractTable, IContractTool, IPackageDefinitionResult, IRemoteContract, IRemoteContractConsumer, IRemoteContractHandle, IResolvedContract, IValidationError, IValidationResult, } from "./types";
|
|
19
20
|
export { contractKey } from "./types";
|
|
20
21
|
export { validateAlsoImplements, validateImmutability, validateProviderSatisfiesContract, } from "./validate";
|
package/dist/contracts/index.js
CHANGED
|
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
18
|
-
exports.validateProviderSatisfiesContract = exports.validateImmutability = exports.validateAlsoImplements = exports.contractKey = exports.registerSystemContract = exports.listSystemContracts = exports.installSystemContracts = exports.TOOL_ACCESS_CONTROL_CONTRACT_VERSION = void 0;
|
|
17
|
+
exports.DEVICE_OPERATIONS_MAX_TOOLS = exports.DEVICE_OPERATIONS_MAX_ROWS = exports.DEVICE_OPERATIONS_MAX_RESULT_BYTES = exports.DEVICE_OPERATIONS_MAX_QUERY_LENGTH = exports.DEVICE_OPERATIONS_CONTRACT_VERSION = exports.setRemoteContractTransportFactory = exports.resolveRemoteTargetEndpoint = exports.getRemoteContractTransportFactory = exports.createRemoteContractEndpoint = exports.ContractRegistry = exports.PersistentContractRegistry = exports.waitForHostContractTransport = exports.subscribeHostContractTransport = exports.registerHostContractTransport = exports.getHostContractTransport = exports.setSchemaToFieldsFn = exports.extractToolShape = exports.extractTableShape = exports.createLocalContractConsumer = exports.contractsSchema = exports.contractsMetaData = exports.ContractsTable = exports.Contracts = exports.inProcessTransportPair = exports.connectionContractTransport = exports.CONTRACT_REQUEST_CHANNEL = exports.CONTRACT_NOTIFY_CHANNEL = exports.verifyRemoteContractIdentity = exports.registerContractResolver = exports.isSelfTrustedContractCaller = exports.handleContractCall = exports.getContractResolver = exports.createUserContextContractProviderRouter = exports.createLocalUserContextContractProviderRouter = exports.authorizeRemoteContractCall = exports.sameUserContractPermissionCheck = exports.createRemoteContractConsumer = exports.createContractProviderSession = exports.createContractProviderEndpoint = exports.createContractProvider = exports.createContractConsumer = exports.CONTRACT_CALL_RPC = exports.contractProvidersSchema = exports.contractProvidersMetaData = exports.ContractProvidersTable = exports.ContractProviders = exports.createContractProviderRouter = exports.PackageBuilder = exports.definePackage = exports.ContractBuilder = void 0;
|
|
18
|
+
exports.validateProviderSatisfiesContract = exports.validateImmutability = exports.validateAlsoImplements = exports.contractKey = exports.registerSystemContract = exports.listSystemContracts = exports.installSystemContracts = exports.TOOL_ACCESS_CONTROL_CONTRACT_VERSION = exports.getToolAccessControlContractDefinition = exports.resolveLogsContract = exports.LOGS_CONTRACT_VERSION = exports.getLogsContractDefinition = exports.getDeviceOperationsContractDefinition = exports.deviceOperationsToolIds = exports.deviceOperationsProviderPackageId = void 0;
|
|
19
19
|
var builder_1 = require("./builder");
|
|
20
20
|
Object.defineProperty(exports, "ContractBuilder", { enumerable: true, get: function () { return builder_1.ContractBuilder; } });
|
|
21
21
|
Object.defineProperty(exports, "definePackage", { enumerable: true, get: function () { return builder_1.definePackage; } });
|
|
@@ -33,14 +33,17 @@ Object.defineProperty(exports, "createContractConsumer", { enumerable: true, get
|
|
|
33
33
|
Object.defineProperty(exports, "createContractProvider", { enumerable: true, get: function () { return contract_proxy_1.createContractProvider; } });
|
|
34
34
|
Object.defineProperty(exports, "createContractProviderEndpoint", { enumerable: true, get: function () { return contract_proxy_1.createContractProviderEndpoint; } });
|
|
35
35
|
Object.defineProperty(exports, "createContractProviderSession", { enumerable: true, get: function () { return contract_proxy_1.createContractProviderSession; } });
|
|
36
|
+
Object.defineProperty(exports, "createRemoteContractConsumer", { enumerable: true, get: function () { return contract_proxy_1.createRemoteContractConsumer; } });
|
|
36
37
|
Object.defineProperty(exports, "sameUserContractPermissionCheck", { enumerable: true, get: function () { return contract_proxy_1.sameUserContractPermissionCheck; } });
|
|
37
38
|
var contract_resolvers_1 = require("./contract-resolvers");
|
|
39
|
+
Object.defineProperty(exports, "authorizeRemoteContractCall", { enumerable: true, get: function () { return contract_resolvers_1.authorizeRemoteContractCall; } });
|
|
38
40
|
Object.defineProperty(exports, "createLocalUserContextContractProviderRouter", { enumerable: true, get: function () { return contract_resolvers_1.createLocalUserContextContractProviderRouter; } });
|
|
39
41
|
Object.defineProperty(exports, "createUserContextContractProviderRouter", { enumerable: true, get: function () { return contract_resolvers_1.createUserContextContractProviderRouter; } });
|
|
40
42
|
Object.defineProperty(exports, "getContractResolver", { enumerable: true, get: function () { return contract_resolvers_1.getContractResolver; } });
|
|
41
43
|
Object.defineProperty(exports, "handleContractCall", { enumerable: true, get: function () { return contract_resolvers_1.handleContractCall; } });
|
|
42
44
|
Object.defineProperty(exports, "isSelfTrustedContractCaller", { enumerable: true, get: function () { return contract_resolvers_1.isSelfTrustedContractCaller; } });
|
|
43
45
|
Object.defineProperty(exports, "registerContractResolver", { enumerable: true, get: function () { return contract_resolvers_1.registerContractResolver; } });
|
|
46
|
+
Object.defineProperty(exports, "verifyRemoteContractIdentity", { enumerable: true, get: function () { return contract_resolvers_1.verifyRemoteContractIdentity; } });
|
|
44
47
|
var contract_transport_1 = require("./contract-transport");
|
|
45
48
|
Object.defineProperty(exports, "CONTRACT_NOTIFY_CHANNEL", { enumerable: true, get: function () { return contract_transport_1.CONTRACT_NOTIFY_CHANNEL; } });
|
|
46
49
|
Object.defineProperty(exports, "CONTRACT_REQUEST_CHANNEL", { enumerable: true, get: function () { return contract_transport_1.CONTRACT_REQUEST_CHANNEL; } });
|
|
@@ -66,6 +69,11 @@ var persistent_registry_1 = require("./persistent-registry");
|
|
|
66
69
|
Object.defineProperty(exports, "PersistentContractRegistry", { enumerable: true, get: function () { return persistent_registry_1.PersistentContractRegistry; } });
|
|
67
70
|
var registry_1 = require("./registry");
|
|
68
71
|
Object.defineProperty(exports, "ContractRegistry", { enumerable: true, get: function () { return registry_1.ContractRegistry; } });
|
|
72
|
+
var remote_contract_transport_1 = require("./remote-contract-transport");
|
|
73
|
+
Object.defineProperty(exports, "createRemoteContractEndpoint", { enumerable: true, get: function () { return remote_contract_transport_1.createRemoteContractEndpoint; } });
|
|
74
|
+
Object.defineProperty(exports, "getRemoteContractTransportFactory", { enumerable: true, get: function () { return remote_contract_transport_1.getRemoteContractTransportFactory; } });
|
|
75
|
+
Object.defineProperty(exports, "resolveRemoteTargetEndpoint", { enumerable: true, get: function () { return remote_contract_transport_1.resolveRemoteTargetEndpoint; } });
|
|
76
|
+
Object.defineProperty(exports, "setRemoteContractTransportFactory", { enumerable: true, get: function () { return remote_contract_transport_1.setRemoteContractTransportFactory; } });
|
|
69
77
|
var device_operations_contract_1 = require("./system/device-operations-contract");
|
|
70
78
|
Object.defineProperty(exports, "DEVICE_OPERATIONS_CONTRACT_VERSION", { enumerable: true, get: function () { return device_operations_contract_1.DEVICE_OPERATIONS_CONTRACT_VERSION; } });
|
|
71
79
|
Object.defineProperty(exports, "DEVICE_OPERATIONS_MAX_QUERY_LENGTH", { enumerable: true, get: function () { return device_operations_contract_1.DEVICE_OPERATIONS_MAX_QUERY_LENGTH; } });
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { UserContext } from "../context/user-context";
|
|
2
|
+
import type { IContractProviderEndpointRequest } from "./contract-provider-router";
|
|
3
|
+
import type { IContractProviderEndpoint } from "./contract-proxy";
|
|
4
|
+
import { type IContractTransport } from "./contract-transport";
|
|
5
|
+
/** Destination of a device-targeted contract call. */
|
|
6
|
+
export interface IRemoteContractTarget {
|
|
7
|
+
/** Device that should execute the call. */
|
|
8
|
+
deviceId: string;
|
|
9
|
+
/**
|
|
10
|
+
* Data context the call is scoped to. Required so the transport can seal the message
|
|
11
|
+
* to the right group or personal keys and the remote device can authorize membership.
|
|
12
|
+
*/
|
|
13
|
+
dataContextId: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Host-registered factory that produces an outbound {@link IContractTransport} to one
|
|
17
|
+
* remote device. `peers-device` registers a `sendDeviceMessage`-backed implementation;
|
|
18
|
+
* the SDK stays transport-agnostic and only knows how to ask for one.
|
|
19
|
+
*/
|
|
20
|
+
export type RemoteContractTransportFactory = (target: IRemoteContractTarget) => IContractTransport;
|
|
21
|
+
/** Trusted host state used to decide whether and how to forward a route. */
|
|
22
|
+
export interface IRemoteContractHost {
|
|
23
|
+
/** This device's id (`userContext.deviceId()`); a matching target resolves locally. */
|
|
24
|
+
localDeviceId?: string;
|
|
25
|
+
/** Owning user context, used to pick a per-context transport factory. */
|
|
26
|
+
userContext?: UserContext;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Register (or clear, with `undefined`) the factory used to reach other devices for
|
|
30
|
+
* contract tool calls. A connection manager registers one for its own `UserContext`;
|
|
31
|
+
* omitting `opts.userContext` sets the process-wide fallback. Call before any package
|
|
32
|
+
* invokes a `pkg.remote(...)` device consumer.
|
|
33
|
+
*
|
|
34
|
+
* @param factory Factory returning an outbound transport, or `undefined` to unregister.
|
|
35
|
+
* @param opts.userContext Scope the registration to one user context.
|
|
36
|
+
*/
|
|
37
|
+
export declare function setRemoteContractTransportFactory(factory: RemoteContractTransportFactory | undefined, opts?: {
|
|
38
|
+
userContext?: UserContext;
|
|
39
|
+
}): void;
|
|
40
|
+
/**
|
|
41
|
+
* Return the transport factory for a user context, falling back to the process default.
|
|
42
|
+
*
|
|
43
|
+
* @param userContext Optional owning user context.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getRemoteContractTransportFactory(userContext?: UserContext): RemoteContractTransportFactory | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Shared chokepoint for trusted local hosts: when an authorized route names a device
|
|
48
|
+
* other than this one, return a forwarding endpoint; otherwise return `undefined` so the
|
|
49
|
+
* caller resolves the provider locally. A target equal to the local device is treated as
|
|
50
|
+
* local so `remote.device(myOwnDeviceId)` behaves like a plain consumer.
|
|
51
|
+
*
|
|
52
|
+
* @param request Authorized route from a router serving a *local* principal.
|
|
53
|
+
* @param host This device's id and owning user context.
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveRemoteTargetEndpoint(request: IContractProviderEndpointRequest, host: IRemoteContractHost): IContractProviderEndpoint | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Build a provider endpoint that forwards authorized calls to another device.
|
|
58
|
+
*
|
|
59
|
+
* The endpoint is created only by a trusted local host after it has authorized the
|
|
60
|
+
* *local* caller for the route. It strips {@link IContractCall.targetDeviceId} before
|
|
61
|
+
* emitting so the receiving device sees an ordinary call addressed to itself and the
|
|
62
|
+
* message is signed with this device's own identity. Only tool runs are forwarded; the
|
|
63
|
+
* router rejects other members before reaching this endpoint.
|
|
64
|
+
*
|
|
65
|
+
* @param request Authorized route whose `targetDeviceId` and `dataContextId` are set.
|
|
66
|
+
* @param factory Transport factory; defaults to the process-wide registration.
|
|
67
|
+
* @throws If no factory is available or the route lacks a target device or data context.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createRemoteContractEndpoint(request: IContractProviderEndpointRequest, factory?: RemoteContractTransportFactory | undefined): IContractProviderEndpoint;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setRemoteContractTransportFactory = setRemoteContractTransportFactory;
|
|
4
|
+
exports.getRemoteContractTransportFactory = getRemoteContractTransportFactory;
|
|
5
|
+
exports.resolveRemoteTargetEndpoint = resolveRemoteTargetEndpoint;
|
|
6
|
+
exports.createRemoteContractEndpoint = createRemoteContractEndpoint;
|
|
7
|
+
const contract_transport_1 = require("./contract-transport");
|
|
8
|
+
const factoriesByUserContext = new WeakMap();
|
|
9
|
+
let defaultFactory;
|
|
10
|
+
/**
|
|
11
|
+
* Register (or clear, with `undefined`) the factory used to reach other devices for
|
|
12
|
+
* contract tool calls. A connection manager registers one for its own `UserContext`;
|
|
13
|
+
* omitting `opts.userContext` sets the process-wide fallback. Call before any package
|
|
14
|
+
* invokes a `pkg.remote(...)` device consumer.
|
|
15
|
+
*
|
|
16
|
+
* @param factory Factory returning an outbound transport, or `undefined` to unregister.
|
|
17
|
+
* @param opts.userContext Scope the registration to one user context.
|
|
18
|
+
*/
|
|
19
|
+
function setRemoteContractTransportFactory(factory, opts = {}) {
|
|
20
|
+
if (opts.userContext) {
|
|
21
|
+
if (factory) {
|
|
22
|
+
factoriesByUserContext.set(opts.userContext, factory);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
factoriesByUserContext.delete(opts.userContext);
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
defaultFactory = factory;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Return the transport factory for a user context, falling back to the process default.
|
|
33
|
+
*
|
|
34
|
+
* @param userContext Optional owning user context.
|
|
35
|
+
*/
|
|
36
|
+
function getRemoteContractTransportFactory(userContext) {
|
|
37
|
+
return (userContext && factoriesByUserContext.get(userContext)) ?? defaultFactory;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Shared chokepoint for trusted local hosts: when an authorized route names a device
|
|
41
|
+
* other than this one, return a forwarding endpoint; otherwise return `undefined` so the
|
|
42
|
+
* caller resolves the provider locally. A target equal to the local device is treated as
|
|
43
|
+
* local so `remote.device(myOwnDeviceId)` behaves like a plain consumer.
|
|
44
|
+
*
|
|
45
|
+
* @param request Authorized route from a router serving a *local* principal.
|
|
46
|
+
* @param host This device's id and owning user context.
|
|
47
|
+
*/
|
|
48
|
+
function resolveRemoteTargetEndpoint(request, host) {
|
|
49
|
+
if (!request.targetDeviceId || request.targetDeviceId === host.localDeviceId) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
return createRemoteContractEndpoint(request, getRemoteContractTransportFactory(host.userContext));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build a provider endpoint that forwards authorized calls to another device.
|
|
56
|
+
*
|
|
57
|
+
* The endpoint is created only by a trusted local host after it has authorized the
|
|
58
|
+
* *local* caller for the route. It strips {@link IContractCall.targetDeviceId} before
|
|
59
|
+
* emitting so the receiving device sees an ordinary call addressed to itself and the
|
|
60
|
+
* message is signed with this device's own identity. Only tool runs are forwarded; the
|
|
61
|
+
* router rejects other members before reaching this endpoint.
|
|
62
|
+
*
|
|
63
|
+
* @param request Authorized route whose `targetDeviceId` and `dataContextId` are set.
|
|
64
|
+
* @param factory Transport factory; defaults to the process-wide registration.
|
|
65
|
+
* @throws If no factory is available or the route lacks a target device or data context.
|
|
66
|
+
*/
|
|
67
|
+
function createRemoteContractEndpoint(request, factory = getRemoteContractTransportFactory()) {
|
|
68
|
+
const { targetDeviceId, dataContextId } = request;
|
|
69
|
+
if (!targetDeviceId) {
|
|
70
|
+
throw new Error("Remote contract endpoint requires a target device id");
|
|
71
|
+
}
|
|
72
|
+
if (!dataContextId) {
|
|
73
|
+
throw new Error("Remote contract endpoint requires an authorized data context id");
|
|
74
|
+
}
|
|
75
|
+
if (!factory) {
|
|
76
|
+
throw new Error(`Cannot reach device ${targetDeviceId}: no remote contract transport is registered on this host`);
|
|
77
|
+
}
|
|
78
|
+
const transport = factory({ deviceId: targetDeviceId, dataContextId });
|
|
79
|
+
let disposed = false;
|
|
80
|
+
return {
|
|
81
|
+
handleCall(call) {
|
|
82
|
+
if (disposed) {
|
|
83
|
+
return Promise.reject(new Error(`Remote contract endpoint for ${targetDeviceId} is disposed`));
|
|
84
|
+
}
|
|
85
|
+
if (call.member !== "tool" || call.operation !== "run") {
|
|
86
|
+
return Promise.reject(new Error(`Contract ${call.member} '${call.name}'.${call.operation} cannot be forwarded to a remote device`));
|
|
87
|
+
}
|
|
88
|
+
const { targetDeviceId: _stripped, ...outbound } = call;
|
|
89
|
+
return transport.emit(contract_transport_1.CONTRACT_REQUEST_CHANNEL, { ...outbound, dataContextId });
|
|
90
|
+
},
|
|
91
|
+
dispose() {
|
|
92
|
+
disposed = true;
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -39,6 +39,13 @@ export interface IContractTool {
|
|
|
39
39
|
usageDescription: string;
|
|
40
40
|
inputFields: IField[];
|
|
41
41
|
outputFields: IField[];
|
|
42
|
+
/**
|
|
43
|
+
* Minimum group access level (0–100) a caller on **another device** needs to run
|
|
44
|
+
* this tool. Absent means the tool is local-only: consumers on the same device can
|
|
45
|
+
* call it, but remote devices are denied. Self-trusted callers (the provider's own
|
|
46
|
+
* account) are never gated by this value. Policy only — not part of shape validation.
|
|
47
|
+
*/
|
|
48
|
+
remoteAccessLevel?: number;
|
|
42
49
|
}
|
|
43
50
|
/** Observable value exposed by a contract. */
|
|
44
51
|
export interface IContractObservable {
|
|
@@ -111,6 +118,51 @@ export interface IConsumedContract {
|
|
|
111
118
|
/** Deferred handle returned by `consumes()` for this dependency. */
|
|
112
119
|
handle?: IConsumedContractHandle<IContractConsumerBase | undefined>;
|
|
113
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Resolved value of a {@link PackageBuilder.remote} handle: a factory of tools-only
|
|
123
|
+
* consumers whose calls execute on other devices.
|
|
124
|
+
*
|
|
125
|
+
* Unlike a consumed contract, no local provider is required — the executing device
|
|
126
|
+
* selects its own provider and authorizes the call against the caller's group role and
|
|
127
|
+
* the tool's {@link IContractTool.remoteAccessLevel}. Only `tools` are reachable on the
|
|
128
|
+
* returned consumers today; `tables`, `observables`, and `events` throw on access.
|
|
129
|
+
*
|
|
130
|
+
* @typeParam T - Consumer proxy type (defaults to {@link IContractConsumer}).
|
|
131
|
+
*/
|
|
132
|
+
export interface IRemoteContractConsumer<T extends IContractConsumerBase = IContractConsumer> {
|
|
133
|
+
contractId: string;
|
|
134
|
+
version: number;
|
|
135
|
+
/**
|
|
136
|
+
* Consumer whose tool calls run on `deviceId`. Instances are cached per device; passing
|
|
137
|
+
* this device's own id behaves like a plain local consumer.
|
|
138
|
+
*
|
|
139
|
+
* @param deviceId Device that should run the calls.
|
|
140
|
+
*/
|
|
141
|
+
device(deviceId: string): T;
|
|
142
|
+
/** Idempotently dispose every per-device consumer created by this factory. */
|
|
143
|
+
dispose(): void;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Deferred handle returned by {@link PackageBuilder.remote}.
|
|
147
|
+
*
|
|
148
|
+
* Like {@link IConsumedContractHandle}, the handle is not thenable — await
|
|
149
|
+
* {@link consumer} from runtime code after `definePackage` finishes. The
|
|
150
|
+
* package-loader settles it once the contract definition is known locally.
|
|
151
|
+
*/
|
|
152
|
+
export interface IRemoteContractHandle<T extends IContractConsumerBase = IContractConsumer> {
|
|
153
|
+
/** Resolves to the per-device consumer factory. */
|
|
154
|
+
readonly consumer: Promise<IRemoteContractConsumer<T>>;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* A contract a package calls on other devices. Recorded during `definePackage`;
|
|
158
|
+
* the loader settles the handle without requiring a local provider.
|
|
159
|
+
*/
|
|
160
|
+
export interface IRemoteContract {
|
|
161
|
+
contractId: string;
|
|
162
|
+
version: number;
|
|
163
|
+
/** Deferred handle returned by `remote()` for this declaration. */
|
|
164
|
+
handle?: IRemoteContractHandle<IContractConsumerBase>;
|
|
165
|
+
}
|
|
114
166
|
/**
|
|
115
167
|
* Declares that the owning contract's implementation also satisfies another
|
|
116
168
|
* contract (single version or inclusive range).
|
|
@@ -132,6 +184,11 @@ export interface IPackageDefinitionResult {
|
|
|
132
184
|
contracts: IContractDefinition[];
|
|
133
185
|
/** Contracts this package depends on. */
|
|
134
186
|
consumes: IConsumedContract[];
|
|
187
|
+
/**
|
|
188
|
+
* Contracts this package calls on other devices via `pkg.remote()`. Optional so
|
|
189
|
+
* bundles built with an older SDK still load.
|
|
190
|
+
*/
|
|
191
|
+
remotes?: IRemoteContract[];
|
|
135
192
|
/** `alsoImplements` declarations keyed by the owning contractId+version. */
|
|
136
193
|
alsoImplements: Map<string, IAlsoImplementsDeclaration[]>;
|
|
137
194
|
/** Package-level items not part of any contract. */
|
package/dist/data/tools.d.ts
CHANGED
|
@@ -220,6 +220,7 @@ export declare const toolSchema: z.ZodObject<{
|
|
|
220
220
|
isAssistantRunner: z.ZodOptional<z.ZodBoolean>;
|
|
221
221
|
packageId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
222
222
|
accessLevel: z.ZodDefault<z.ZodNumber>;
|
|
223
|
+
remoteAccessLevel: z.ZodOptional<z.ZodNumber>;
|
|
223
224
|
}, "strip", z.ZodTypeAny, {
|
|
224
225
|
code: string;
|
|
225
226
|
name: string;
|
|
@@ -266,6 +267,7 @@ export declare const toolSchema: z.ZodObject<{
|
|
|
266
267
|
codeRepository?: string | undefined;
|
|
267
268
|
isAssistantRunner?: boolean | undefined;
|
|
268
269
|
packageId?: string | undefined;
|
|
270
|
+
remoteAccessLevel?: number | undefined;
|
|
269
271
|
}, {
|
|
270
272
|
name: string;
|
|
271
273
|
toolId: string;
|
|
@@ -312,6 +314,7 @@ export declare const toolSchema: z.ZodObject<{
|
|
|
312
314
|
isAssistantRunner?: boolean | undefined;
|
|
313
315
|
packageId?: string | undefined;
|
|
314
316
|
accessLevel?: number | undefined;
|
|
317
|
+
remoteAccessLevel?: number | undefined;
|
|
315
318
|
}>;
|
|
316
319
|
/** A tool definition stored in the Tools table. */
|
|
317
320
|
export type ITool = z.infer<typeof toolSchema>;
|
|
@@ -373,4 +376,5 @@ export declare function Tools(dataContext?: DataContext): import("..").Table<{
|
|
|
373
376
|
codeRepository?: string | undefined;
|
|
374
377
|
isAssistantRunner?: boolean | undefined;
|
|
375
378
|
packageId?: string | undefined;
|
|
379
|
+
remoteAccessLevel?: number | undefined;
|
|
376
380
|
}>;
|
package/dist/data/tools.js
CHANGED
|
@@ -49,6 +49,13 @@ exports.toolSchema = zod_1.z.object({
|
|
|
49
49
|
.describe("Whether this tool is a model that can be used to run an assistant"),
|
|
50
50
|
packageId: zod_types_1.zodPeerId.optional().describe("The package that installed this tool, if any"),
|
|
51
51
|
accessLevel: access_level_1.accessLevelSchema.describe("Required access level (0-100) to run this tool. Unclassified tools default to 100 (Self)."),
|
|
52
|
+
remoteAccessLevel: zod_1.z
|
|
53
|
+
.number()
|
|
54
|
+
.int()
|
|
55
|
+
.min(access_level_1.MIN_ACCESS_LEVEL)
|
|
56
|
+
.max(access_level_1.MAX_ACCESS_LEVEL)
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("Minimum group access level (0-100) a caller on another device needs to run this tool. Omit to keep the tool local-only."),
|
|
52
59
|
});
|
|
53
60
|
const metaData = {
|
|
54
61
|
name: "Tools",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IAlsoImplementsDeclaration, IConsumedContract, IContractDefinition, IContractObservable, IContractTool } from "../contracts/types";
|
|
1
|
+
import type { IAlsoImplementsDeclaration, IConsumedContract, IContractDefinition, IContractEvent, IContractObservable, IContractTool } from "../contracts/types";
|
|
2
2
|
import { type PersistentVarScope } from "../data/persistent-var-identity";
|
|
3
3
|
import type { IAppNav } from "../types/app-nav";
|
|
4
4
|
import { type IField } from "../types/field-type";
|
|
@@ -20,16 +20,21 @@ export interface IIsolatedContractToolRef {
|
|
|
20
20
|
/**
|
|
21
21
|
* Tool advertised on an isolated provided contract.
|
|
22
22
|
*
|
|
23
|
-
* Shape matches {@link IContractTool}. `suggestedAccessLevel` is
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Shape matches {@link IContractTool}. `suggestedAccessLevel` is the default
|
|
24
|
+
* effective level until install-time approval exists and calls `approveTool`.
|
|
25
|
+
* Omit it to keep the fail-closed Self default.
|
|
26
26
|
*/
|
|
27
27
|
export interface IIsolatedContractTool extends Omit<IContractTool, "inputFields" | "outputFields"> {
|
|
28
28
|
/** Defaults to `[]` during validation when omitted. */
|
|
29
29
|
inputFields?: IField[];
|
|
30
30
|
/** Defaults to `[]` during validation when omitted. */
|
|
31
31
|
outputFields?: IField[];
|
|
32
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Default effective access level for this tool.
|
|
34
|
+
*
|
|
35
|
+
* Used until an administrator explicitly approves the tool at install time.
|
|
36
|
+
* Omit to keep the fail-closed Self default.
|
|
37
|
+
*/
|
|
33
38
|
suggestedAccessLevel?: number;
|
|
34
39
|
}
|
|
35
40
|
/**
|
|
@@ -60,6 +65,18 @@ export interface IIsolatedContractPersistentVarBinding {
|
|
|
60
65
|
export interface IIsolatedContractObservable extends IContractObservable {
|
|
61
66
|
persistentVar: IIsolatedContractPersistentVarBinding;
|
|
62
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Event an isolated provider may emit from an active tool invocation.
|
|
70
|
+
*
|
|
71
|
+
* Shape matches {@link IContractEvent}. `payloadFields` defaults to `[]`
|
|
72
|
+
* during validation when omitted. Events are host-owned: the worker emits via
|
|
73
|
+
* `emitContractEvent`, and local consumers subscribe through the contract
|
|
74
|
+
* proxy. Events are fire-and-forget (no replay) and local-only in this slice.
|
|
75
|
+
*/
|
|
76
|
+
export interface IIsolatedContractEvent extends Omit<IContractEvent, "payloadFields"> {
|
|
77
|
+
/** Defaults to `[]` during validation when omitted. */
|
|
78
|
+
payloadFields?: IField[];
|
|
79
|
+
}
|
|
63
80
|
/** Contract this package implements and serves from its isolated worker. */
|
|
64
81
|
export interface IIsolatedProvidedContract {
|
|
65
82
|
contractId: string;
|
|
@@ -71,6 +88,8 @@ export interface IIsolatedProvidedContract {
|
|
|
71
88
|
tables?: IIsolatedContractTableRef[];
|
|
72
89
|
/** Pvar-backed observable values exposed to consumers. */
|
|
73
90
|
observables?: IIsolatedContractObservable[];
|
|
91
|
+
/** Events the worker may emit during an active invocation. */
|
|
92
|
+
events?: IIsolatedContractEvent[];
|
|
74
93
|
/** Older contract versions this provider shape also satisfies. */
|
|
75
94
|
alsoImplements?: IAlsoImplementsDeclaration[];
|
|
76
95
|
}
|
|
@@ -132,6 +151,8 @@ export declare const ISOLATED_CONSUME_HOST_MEMBER = "contract.consume";
|
|
|
132
151
|
export declare const ISOLATED_TABLE_HOST_MEMBER = "package.table";
|
|
133
152
|
/** Host-contract member guests use to read or write package-prefixed pvars. */
|
|
134
153
|
export declare const ISOLATED_PERSISTENT_VAR_HOST_MEMBER = "package.pvar";
|
|
154
|
+
/** Host-contract member guests use to emit a provided-contract event. */
|
|
155
|
+
export declare const ISOLATED_EVENT_HOST_MEMBER = "contract.emit";
|
|
135
156
|
/**
|
|
136
157
|
* True when `bundle` starts with {@link ISOLATED_PACKAGE_MAGIC}.
|
|
137
158
|
*
|
|
@@ -210,6 +231,24 @@ export declare function findProvidedContractTable(provides: IIsolatedProvidedCon
|
|
|
210
231
|
* @param observableName Public observable name.
|
|
211
232
|
*/
|
|
212
233
|
export declare function findProvidedContractObservable(provides: IIsolatedProvidedContract[], contractId: string, version: number, observableName: string): IIsolatedContractObservable | undefined;
|
|
234
|
+
/**
|
|
235
|
+
* Return a declared event from a provided contract.
|
|
236
|
+
*
|
|
237
|
+
* @param provides Provided contracts from the manifest.
|
|
238
|
+
* @param contractId Target contract ID.
|
|
239
|
+
* @param version Target contract version.
|
|
240
|
+
* @param eventName Event name on that contract.
|
|
241
|
+
*/
|
|
242
|
+
export declare function findProvidedContractEvent(provides: IIsolatedProvidedContract[], contractId: string, version: number, eventName: string): IIsolatedContractEvent | undefined;
|
|
243
|
+
/**
|
|
244
|
+
* True when the package advertises this event on a provided contract.
|
|
245
|
+
*
|
|
246
|
+
* @param provides - Provided contracts from the manifest.
|
|
247
|
+
* @param contractId - Target contract id.
|
|
248
|
+
* @param version - Target contract version.
|
|
249
|
+
* @param eventName - Event name on that contract.
|
|
250
|
+
*/
|
|
251
|
+
export declare function packageProvidesEvent(provides: IIsolatedProvidedContract[], contractId: string, version: number, eventName: string): boolean;
|
|
213
252
|
/**
|
|
214
253
|
* True when the package declares a private table.
|
|
215
254
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ISOLATED_PERSISTENT_VAR_HOST_MEMBER = exports.ISOLATED_TABLE_HOST_MEMBER = exports.ISOLATED_CONSUME_HOST_MEMBER = exports.ISOLATED_PACKAGE_MAGIC = void 0;
|
|
3
|
+
exports.ISOLATED_EVENT_HOST_MEMBER = exports.ISOLATED_PERSISTENT_VAR_HOST_MEMBER = exports.ISOLATED_TABLE_HOST_MEMBER = exports.ISOLATED_CONSUME_HOST_MEMBER = exports.ISOLATED_PACKAGE_MAGIC = void 0;
|
|
4
4
|
exports.looksLikeIsolatedPackageArtifact = looksLikeIsolatedPackageArtifact;
|
|
5
5
|
exports.validateIsolatedPackageArtifact = validateIsolatedPackageArtifact;
|
|
6
6
|
exports.parseIsolatedPackageArtifact = parseIsolatedPackageArtifact;
|
|
@@ -10,6 +10,8 @@ exports.packageDeclaresConsume = packageDeclaresConsume;
|
|
|
10
10
|
exports.packageProvidesTool = packageProvidesTool;
|
|
11
11
|
exports.findProvidedContractTable = findProvidedContractTable;
|
|
12
12
|
exports.findProvidedContractObservable = findProvidedContractObservable;
|
|
13
|
+
exports.findProvidedContractEvent = findProvidedContractEvent;
|
|
14
|
+
exports.packageProvidesEvent = packageProvidesEvent;
|
|
13
15
|
exports.packageProvidesTable = packageProvidesTable;
|
|
14
16
|
exports.findPackageTable = findPackageTable;
|
|
15
17
|
exports.toConsumedContracts = toConsumedContracts;
|
|
@@ -29,6 +31,8 @@ exports.ISOLATED_CONSUME_HOST_MEMBER = "contract.consume";
|
|
|
29
31
|
exports.ISOLATED_TABLE_HOST_MEMBER = "package.table";
|
|
30
32
|
/** Host-contract member guests use to read or write package-prefixed pvars. */
|
|
31
33
|
exports.ISOLATED_PERSISTENT_VAR_HOST_MEMBER = "package.pvar";
|
|
34
|
+
/** Host-contract member guests use to emit a provided-contract event. */
|
|
35
|
+
exports.ISOLATED_EVENT_HOST_MEMBER = "contract.emit";
|
|
32
36
|
const FIELD_TYPES = new Set(Object.values(field_type_1.FieldType));
|
|
33
37
|
const OBSERVABLE_FIELD_TYPES = new Set([
|
|
34
38
|
field_type_1.FieldType.id,
|
|
@@ -209,6 +213,7 @@ function validateProvidedContract(contract, index, packageTables) {
|
|
|
209
213
|
"tools",
|
|
210
214
|
"tables",
|
|
211
215
|
"observables",
|
|
216
|
+
"events",
|
|
212
217
|
"alsoImplements",
|
|
213
218
|
], label);
|
|
214
219
|
assertPeerId(contract.contractId, `${label}.contractId`);
|
|
@@ -228,7 +233,14 @@ function validateProvidedContract(contract, index, packageTables) {
|
|
|
228
233
|
if (!tool || typeof tool !== "object" || Array.isArray(tool)) {
|
|
229
234
|
throw new Error(`${toolLabel} must be an object`);
|
|
230
235
|
}
|
|
231
|
-
assertOnlyKeys(tool, [
|
|
236
|
+
assertOnlyKeys(tool, [
|
|
237
|
+
"name",
|
|
238
|
+
"usageDescription",
|
|
239
|
+
"inputFields",
|
|
240
|
+
"outputFields",
|
|
241
|
+
"suggestedAccessLevel",
|
|
242
|
+
"remoteAccessLevel",
|
|
243
|
+
], toolLabel);
|
|
232
244
|
if (typeof tool.name !== "string" || tool.name.trim() === "") {
|
|
233
245
|
throw new Error(`${toolLabel}.name is required`);
|
|
234
246
|
}
|
|
@@ -248,6 +260,13 @@ function validateProvidedContract(contract, index, packageTables) {
|
|
|
248
260
|
throw new Error(`${toolLabel}.suggestedAccessLevel must be an integer 0–100`);
|
|
249
261
|
}
|
|
250
262
|
}
|
|
263
|
+
if (tool.remoteAccessLevel !== undefined) {
|
|
264
|
+
if (!Number.isInteger(tool.remoteAccessLevel) ||
|
|
265
|
+
tool.remoteAccessLevel < access_level_1.MIN_ACCESS_LEVEL ||
|
|
266
|
+
tool.remoteAccessLevel > access_level_1.MAX_ACCESS_LEVEL) {
|
|
267
|
+
throw new Error(`${toolLabel}.remoteAccessLevel must be an integer 0–100`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
251
270
|
}
|
|
252
271
|
if (contract.tables === undefined) {
|
|
253
272
|
contract.tables = [];
|
|
@@ -325,7 +344,36 @@ function validateProvidedContract(contract, index, packageTables) {
|
|
|
325
344
|
pvarBindings.add(bindingKey);
|
|
326
345
|
validateObservableDefault(binding.defaultValue, observable.valueType, `${observableLabel}.persistentVar.defaultValue`);
|
|
327
346
|
}
|
|
328
|
-
if (contract.
|
|
347
|
+
if (contract.events === undefined) {
|
|
348
|
+
contract.events = [];
|
|
349
|
+
}
|
|
350
|
+
if (!Array.isArray(contract.events)) {
|
|
351
|
+
throw new Error(`${label}.events must be an array`);
|
|
352
|
+
}
|
|
353
|
+
const eventNames = new Set();
|
|
354
|
+
for (const [eventIndex, event] of contract.events.entries()) {
|
|
355
|
+
const eventLabel = `${label}.events[${eventIndex}]`;
|
|
356
|
+
if (!event || typeof event !== "object" || Array.isArray(event)) {
|
|
357
|
+
throw new Error(`${eventLabel} must be an object`);
|
|
358
|
+
}
|
|
359
|
+
assertOnlyKeys(event, ["name", "description", "payloadFields"], eventLabel);
|
|
360
|
+
if (typeof event.name !== "string" || event.name.trim() === "") {
|
|
361
|
+
throw new Error(`${eventLabel}.name is required`);
|
|
362
|
+
}
|
|
363
|
+
if (eventNames.has(event.name)) {
|
|
364
|
+
throw new Error(`${label} declares duplicate event "${event.name}"`);
|
|
365
|
+
}
|
|
366
|
+
eventNames.add(event.name);
|
|
367
|
+
if (typeof event.description !== "string") {
|
|
368
|
+
throw new Error(`${eventLabel}.description is required`);
|
|
369
|
+
}
|
|
370
|
+
event.payloadFields = validateFields(event.payloadFields, `${eventLabel}.payloadFields`);
|
|
371
|
+
}
|
|
372
|
+
if (contract.tools.length +
|
|
373
|
+
contract.tables.length +
|
|
374
|
+
contract.observables.length +
|
|
375
|
+
contract.events.length ===
|
|
376
|
+
0) {
|
|
329
377
|
throw new Error(`${label} must declare at least one contract member`);
|
|
330
378
|
}
|
|
331
379
|
if (contract.alsoImplements === undefined) {
|
|
@@ -530,6 +578,7 @@ function isolatedContractToDefinition(contract, packageTables) {
|
|
|
530
578
|
usageDescription: tool.usageDescription,
|
|
531
579
|
inputFields: tool.inputFields ?? [],
|
|
532
580
|
outputFields: tool.outputFields ?? [],
|
|
581
|
+
...(tool.remoteAccessLevel !== undefined ? { remoteAccessLevel: tool.remoteAccessLevel } : {}),
|
|
533
582
|
}));
|
|
534
583
|
const tables = (contract.tables ?? []).map((tableRef) => {
|
|
535
584
|
const table = findPackageTable(packageTables, tableRef.name);
|
|
@@ -549,6 +598,11 @@ function isolatedContractToDefinition(contract, packageTables) {
|
|
|
549
598
|
valueType: observable.valueType,
|
|
550
599
|
writable: observable.writable,
|
|
551
600
|
}));
|
|
601
|
+
const events = (contract.events ?? []).map((event) => ({
|
|
602
|
+
name: event.name,
|
|
603
|
+
description: event.description,
|
|
604
|
+
payloadFields: event.payloadFields ?? [],
|
|
605
|
+
}));
|
|
552
606
|
return {
|
|
553
607
|
contractId: contract.contractId,
|
|
554
608
|
version: contract.version,
|
|
@@ -557,7 +611,7 @@ function isolatedContractToDefinition(contract, packageTables) {
|
|
|
557
611
|
tables,
|
|
558
612
|
tools,
|
|
559
613
|
observables,
|
|
560
|
-
events
|
|
614
|
+
events,
|
|
561
615
|
};
|
|
562
616
|
}
|
|
563
617
|
/**
|
|
@@ -608,6 +662,30 @@ function findProvidedContractObservable(provides, contractId, version, observabl
|
|
|
608
662
|
.find((contract) => contract.contractId === contractId && contract.version === version)
|
|
609
663
|
?.observables?.find((observable) => observable.name === observableName);
|
|
610
664
|
}
|
|
665
|
+
/**
|
|
666
|
+
* Return a declared event from a provided contract.
|
|
667
|
+
*
|
|
668
|
+
* @param provides Provided contracts from the manifest.
|
|
669
|
+
* @param contractId Target contract ID.
|
|
670
|
+
* @param version Target contract version.
|
|
671
|
+
* @param eventName Event name on that contract.
|
|
672
|
+
*/
|
|
673
|
+
function findProvidedContractEvent(provides, contractId, version, eventName) {
|
|
674
|
+
return provides
|
|
675
|
+
.find((contract) => contract.contractId === contractId && contract.version === version)
|
|
676
|
+
?.events?.find((event) => event.name === eventName);
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* True when the package advertises this event on a provided contract.
|
|
680
|
+
*
|
|
681
|
+
* @param provides - Provided contracts from the manifest.
|
|
682
|
+
* @param contractId - Target contract id.
|
|
683
|
+
* @param version - Target contract version.
|
|
684
|
+
* @param eventName - Event name on that contract.
|
|
685
|
+
*/
|
|
686
|
+
function packageProvidesEvent(provides, contractId, version, eventName) {
|
|
687
|
+
return findProvidedContractEvent(provides, contractId, version, eventName) !== undefined;
|
|
688
|
+
}
|
|
611
689
|
/**
|
|
612
690
|
* True when the package declares a private table.
|
|
613
691
|
*
|