@peers-app/peers-sdk 0.21.1 → 0.21.3

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.
Files changed (44) hide show
  1. package/dist/context/user-context.d.ts +10 -3
  2. package/dist/context/user-context.js +12 -12
  3. package/dist/contracts/__tests__/builder.test.js +158 -4
  4. package/dist/contracts/__tests__/contract-resolvers.test.js +94 -0
  5. package/dist/contracts/__tests__/host-contract-transport.test.d.ts +1 -0
  6. package/dist/contracts/__tests__/host-contract-transport.test.js +51 -0
  7. package/dist/contracts/__tests__/registry.test.js +45 -303
  8. package/dist/contracts/__tests__/system-contracts.test.d.ts +1 -0
  9. package/dist/contracts/__tests__/system-contracts.test.js +61 -0
  10. package/dist/contracts/builder.d.ts +43 -2
  11. package/dist/contracts/builder.js +79 -5
  12. package/dist/contracts/contract-proxy.d.ts +61 -21
  13. package/dist/contracts/contract-resolvers.d.ts +20 -0
  14. package/dist/contracts/contract-resolvers.js +57 -0
  15. package/dist/contracts/create-local-consumer.d.ts +12 -0
  16. package/dist/contracts/create-local-consumer.js +19 -0
  17. package/dist/contracts/host-contract-transport.d.ts +38 -0
  18. package/dist/contracts/host-contract-transport.js +107 -0
  19. package/dist/contracts/index.d.ts +8 -4
  20. package/dist/contracts/index.js +29 -1
  21. package/dist/contracts/registry.d.ts +17 -0
  22. package/dist/contracts/registry.js +36 -0
  23. package/dist/contracts/system/device-operations-contract.js +7 -0
  24. package/dist/contracts/system/index.d.ts +10 -0
  25. package/dist/contracts/system/index.js +38 -0
  26. package/dist/contracts/system/logs-contract.d.ts +18 -1
  27. package/dist/contracts/system/logs-contract.js +8 -2
  28. package/dist/contracts/system/network-contracts.d.ts +231 -0
  29. package/dist/contracts/system/network-contracts.js +192 -0
  30. package/dist/contracts/system-contracts.d.ts +47 -0
  31. package/dist/contracts/system-contracts.js +69 -0
  32. package/dist/contracts/types.d.ts +44 -0
  33. package/dist/package-loader/contract-package-loader.test.d.ts +1 -0
  34. package/dist/package-loader/contract-package-loader.test.js +88 -0
  35. package/dist/package-loader/package-loader.d.ts +8 -0
  36. package/dist/package-loader/package-loader.js +17 -1
  37. package/dist/package-loader/package-loader.test.js +17 -0
  38. package/dist/package-loader/resolve-consumed-contracts.d.ts +13 -0
  39. package/dist/package-loader/resolve-consumed-contracts.js +55 -0
  40. package/dist/package-loader/resolve-consumed-contracts.test.d.ts +1 -0
  41. package/dist/package-loader/resolve-consumed-contracts.test.js +123 -0
  42. package/dist/system-ids.d.ts +4 -0
  43. package/dist/system-ids.js +5 -1
  44. package/package.json +1 -1
@@ -89,8 +89,9 @@ export interface IContractNotification {
89
89
  * subscribable that rides the notify channel like a generic event (subscription-gated).
90
90
  *
91
91
  * Declared as an intersection so `dataChanged` type-checks as a subscribable while
92
- * `.list(...)`, `.save(...)`, etc. still type-check as async methods. This is a widening
93
- * of precise per-table typing (deferred to a later phase).
92
+ * `.list(...)`, `.save(...)`, etc. still type-check as async methods. Prefer
93
+ * {@link ITableProxy} when declaring typed contract consumers — this open form does
94
+ * not contribute named IntelliSense for table methods.
94
95
  */
95
96
  export type IContractTableProxy = Record<string, (...args: any[]) => Promise<any>> & {
96
97
  /**
@@ -102,14 +103,68 @@ export type IContractTableProxy = Record<string, (...args: any[]) => Promise<any
102
103
  subscribe(handler: (event: any) => void): ISubscriptionResult;
103
104
  };
104
105
  };
106
+ /** Standard {@link Table} methods the contract provider allows over the wire. */
107
+ type StandardRemoteTableMethodName = "get" | "list" | "count" | "findOne" | "save" | "insert" | "update" | "delete";
108
+ /**
109
+ * Payload type of `TTable.dataChanged.subscribe` when the table exposes one.
110
+ */
111
+ type TableDataChangedPayload<TTable> = TTable extends {
112
+ dataChanged: {
113
+ subscribe: (handler: (event: infer E) => any, ...args: any[]) => any;
114
+ };
115
+ } ? E : unknown;
116
+ /**
117
+ * Consumer-side view of a real table class over a contract proxy.
118
+ *
119
+ * Picks the remotely callable standard {@link Table} methods (and optional extras such
120
+ * as `@ProxyClientTableMethodCalls` methods) with their real signatures, plus a
121
+ * `dataChanged` subscribe surface. Does **not** claim to be a literal {@link Table}
122
+ * instance — non-remote members (`dataSource`, `metaData`, `cursor`, …) are omitted.
123
+ *
124
+ * No open string index signature, so IntelliSense lists the actual method names.
125
+ *
126
+ * @typeParam TTable - Concrete table class (e.g. `ConsoleLogsTable`).
127
+ * @typeParam TExtraMethods - Additional remotely callable method names on `TTable`.
128
+ */
129
+ export type ITableProxy<TTable, TExtraMethods extends keyof TTable = never> = Pick<TTable, Extract<keyof TTable, StandardRemoteTableMethodName> | TExtraMethods> & {
130
+ /**
131
+ * Subscribe to the provider table's `dataChanged` event over the transport.
132
+ * Same subscribe shape as a local table, without Event helpers like `next` / `union`.
133
+ */
134
+ dataChanged: {
135
+ subscribe(handler: (event: TableDataChangedPayload<TTable>) => void): ISubscriptionResult;
136
+ };
137
+ };
138
+ /**
139
+ * Minimal contract-consumer identity shared by typed consumers and the open
140
+ * {@link IContractConsumer} runtime shape. Typed consumers may omit empty
141
+ * `tools` / `events` / `observables` bags.
142
+ */
143
+ export interface IContractConsumerBase {
144
+ contractId: string;
145
+ version: number;
146
+ /**
147
+ * Resolves once every observable's initial snapshot has loaded (so reads are meaningful),
148
+ * then is re-chained on each local observable write so `await consumer.loadingPromise`
149
+ * also awaits write durability. Always resolves (never rejects).
150
+ */
151
+ loadingPromise: Promise<void>;
152
+ /**
153
+ * Idempotently detach everything this consumer opened. New remote calls and
154
+ * subscriptions reject after disposal.
155
+ */
156
+ dispose(): void;
157
+ }
105
158
  /**
106
159
  * A live proxy over a contract, handed to a **consumer**. Every member access is
107
160
  * turned into an {@link IContractCall} and dispatched through the transport, so the
108
161
  * consumer interacts with the contract identically no matter where the provider runs.
162
+ *
163
+ * This is the open runtime shape from {@link createContractConsumer}. Prefer a
164
+ * hand-maintained (or later generated) typed consumer that extends
165
+ * {@link IContractConsumerBase} and lists only the members that contract exposes.
109
166
  */
110
- export interface IContractConsumer {
111
- contractId: string;
112
- version: number;
167
+ export interface IContractConsumer extends IContractConsumerBase {
113
168
  /**
114
169
  * `tables[name].<method>(...args)` → the remote table method's result, or
115
170
  * `tables[name].dataChanged.subscribe(handler)` → a subscription to the remote table's
@@ -139,22 +194,6 @@ export interface IContractConsumer {
139
194
  events: Record<string, {
140
195
  subscribe: (handler: (value: any) => void) => ISubscriptionResult;
141
196
  }>;
142
- /**
143
- * Resolves once every observable's initial snapshot has loaded (so reads are meaningful),
144
- * then is re-chained on each local observable write so `await consumer.loadingPromise`
145
- * also awaits write durability. Mirrors the persistent-var `loadingPromise` pattern
146
- * ([`persistent-vars.ts`](../data/persistent-vars.ts)). Always resolves (never rejects);
147
- * a failed writable set is logged once and leaves the optimistic mirror in place until
148
- * the next provider push reconciles it.
149
- */
150
- loadingPromise: Promise<void>;
151
- /**
152
- * Idempotently detach everything this consumer opened: generic events, table events,
153
- * always-on observable streams, observable write observers, and its notify listener.
154
- * New remote table/tool calls and subscriptions reject after disposal; cached observable
155
- * reads remain available, but observable writes throw.
156
- */
157
- dispose(): void;
158
197
  }
159
198
  /**
160
199
  * Build the **consumer** side of a contract proxy from a contract definition and a
@@ -331,3 +370,4 @@ export declare function createContractProviderEndpoint(resolution: IContractReso
331
370
  * @param opts Optional permission gate and default caller context.
332
371
  */
333
372
  export declare function createContractProviderSession(resolution: IContractResolution, transport: IContractTransport, opts?: IContractProviderSessionOptions): IContractProviderSession;
373
+ export {};
@@ -30,6 +30,26 @@ export declare function getContractResolver(contractId: string, version: number)
30
30
  * {@link TrustLevel.Self}. Unsigned discovery stubs and key mismatches fail closed.
31
31
  */
32
32
  export declare function isSelfTrustedContractCaller(userContext: UserContext, remoteIdentity: ContractRemoteIdentity): Promise<boolean>;
33
+ /**
34
+ * Create a provider router for one authenticated UI-to-local-host session.
35
+ *
36
+ * The request listener is registered synchronously while user-context loading is
37
+ * deferred until each call. This prevents renderer startup from racing provider
38
+ * registration. Calls may target only the local user's personal context or a
39
+ * currently known group context; arbitrary valid IDs are rejected before
40
+ * `UserContext.getDataContext` can create a new context.
41
+ *
42
+ * This helper trusts the host transport's session authentication. It does not
43
+ * infer package-level authority from renderer-supplied data.
44
+ *
45
+ * @param transport Contract transport backed by an authenticated local session.
46
+ * @param opts.getUserContext Lazy accessor for the host's loaded user context.
47
+ * @param opts.allowedContractIds Optional contract allowlist for this session.
48
+ */
49
+ export declare function createLocalUserContextContractProviderRouter(transport: IContractTransport, opts: {
50
+ getUserContext: () => Promise<UserContext>;
51
+ allowedContractIds?: ReadonlySet<string>;
52
+ }): IContractProviderRouter;
33
53
  /**
34
54
  * Create the local-object provider router for one verified device connection.
35
55
  *
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerContractResolver = registerContractResolver;
4
4
  exports.getContractResolver = getContractResolver;
5
5
  exports.isSelfTrustedContractCaller = isSelfTrustedContractCaller;
6
+ exports.createLocalUserContextContractProviderRouter = createLocalUserContextContractProviderRouter;
6
7
  exports.createUserContextContractProviderRouter = createUserContextContractProviderRouter;
7
8
  exports.handleContractCall = handleContractCall;
8
9
  const user_permissions_1 = require("../data/user-permissions");
@@ -74,6 +75,62 @@ async function authorizeUserContextCall(call, userContext, remoteIdentity) {
74
75
  context,
75
76
  };
76
77
  }
78
+ function getAuthorizedLocalDataContext(userContext, requestedId) {
79
+ const dataContextId = requestedId || userContext.userId;
80
+ if (dataContextId === userContext.userId) {
81
+ return userContext.userDataContext;
82
+ }
83
+ if (!userContext.groupIds().includes(dataContextId)) {
84
+ throw new Error(`Permission denied: data context '${dataContextId}' is not available locally`);
85
+ }
86
+ return userContext.getDataContext(dataContextId);
87
+ }
88
+ /**
89
+ * Create a provider router for one authenticated UI-to-local-host session.
90
+ *
91
+ * The request listener is registered synchronously while user-context loading is
92
+ * deferred until each call. This prevents renderer startup from racing provider
93
+ * registration. Calls may target only the local user's personal context or a
94
+ * currently known group context; arbitrary valid IDs are rejected before
95
+ * `UserContext.getDataContext` can create a new context.
96
+ *
97
+ * This helper trusts the host transport's session authentication. It does not
98
+ * infer package-level authority from renderer-supplied data.
99
+ *
100
+ * @param transport Contract transport backed by an authenticated local session.
101
+ * @param opts.getUserContext Lazy accessor for the host's loaded user context.
102
+ * @param opts.allowedContractIds Optional contract allowlist for this session.
103
+ */
104
+ function createLocalUserContextContractProviderRouter(transport, opts) {
105
+ const { getUserContext, allowedContractIds } = opts;
106
+ return (0, contract_provider_router_1.createContractProviderRouter)(transport, {
107
+ authorizeCall: async (call) => {
108
+ if (allowedContractIds && !allowedContractIds.has(call.contractId)) {
109
+ throw new Error(`Permission denied: contract ${call.contractId} is not available locally`);
110
+ }
111
+ const userContext = await getUserContext();
112
+ const dataContext = getAuthorizedLocalDataContext(userContext, call.dataContextId);
113
+ const context = {
114
+ callerUserId: userContext.userId,
115
+ localUserId: userContext.userId,
116
+ };
117
+ return {
118
+ dataContextId: dataContext.dataContextId,
119
+ context,
120
+ };
121
+ },
122
+ resolveEndpoint: async ({ contractId, version, dataContextId, context, notify }) => {
123
+ const userContext = await getUserContext();
124
+ const resolver = getContractResolver(contractId, version);
125
+ if (!resolver) {
126
+ throw new Error(`No contract provider registered for ${contractId} v${version}`);
127
+ }
128
+ const dataContext = getAuthorizedLocalDataContext(userContext, dataContextId);
129
+ const resolution = await resolver({ dataContext });
130
+ return (0, contract_proxy_1.createContractProviderEndpoint)(resolution, { context, notify });
131
+ },
132
+ });
133
+ }
77
134
  /**
78
135
  * Create the local-object provider router for one verified device connection.
79
136
  *
@@ -0,0 +1,12 @@
1
+ import { type IContractConsumer, type IContractResolution } from "./contract-proxy";
2
+ import type { IContractDefinition } from "./types";
3
+ /**
4
+ * Build a same-process contract consumer wired to a live provider resolution.
5
+ *
6
+ * Creates an {@link inProcessTransportPair}, attaches a provider session on one
7
+ * end and a consumer proxy on the other. Intended for package-loader settlement
8
+ * of `consumes` handles when the provider runs in the same process.
9
+ */
10
+ export declare function createLocalContractConsumer(definition: IContractDefinition, resolution: IContractResolution, opts?: {
11
+ dataContextId?: string;
12
+ }): IContractConsumer;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLocalContractConsumer = createLocalContractConsumer;
4
+ const contract_proxy_1 = require("./contract-proxy");
5
+ const contract_transport_1 = require("./contract-transport");
6
+ /**
7
+ * Build a same-process contract consumer wired to a live provider resolution.
8
+ *
9
+ * Creates an {@link inProcessTransportPair}, attaches a provider session on one
10
+ * end and a consumer proxy on the other. Intended for package-loader settlement
11
+ * of `consumes` handles when the provider runs in the same process.
12
+ */
13
+ function createLocalContractConsumer(definition, resolution, opts) {
14
+ const [consumerTransport, providerTransport] = (0, contract_transport_1.inProcessTransportPair)();
15
+ (0, contract_proxy_1.createContractProviderSession)(resolution, providerTransport);
16
+ return (0, contract_proxy_1.createContractConsumer)(definition, consumerTransport, {
17
+ dataContextId: opts?.dataContextId,
18
+ });
19
+ }
@@ -0,0 +1,38 @@
1
+ import type { IContractTransport } from "./contract-transport";
2
+ /** Listener notified whenever the active UI-to-host contract transport changes. */
3
+ export type HostContractTransportListener = (transport: IContractTransport | undefined) => void;
4
+ /**
5
+ * Register the transport used by renderer code to call its trusted local host.
6
+ *
7
+ * A newer registration replaces the previous active transport. The returned
8
+ * disposer clears only its own registration, so disposing a stale Electron
9
+ * connection cannot remove a transport installed by a later reconnect.
10
+ *
11
+ * @param transport UI-side transport connected to the local host provider router.
12
+ * @returns A disposer for this exact registration.
13
+ */
14
+ export declare function registerHostContractTransport(transport: IContractTransport): () => void;
15
+ /** Return the currently registered UI-to-host contract transport, if ready. */
16
+ export declare function getHostContractTransport(): IContractTransport | undefined;
17
+ /**
18
+ * Subscribe to UI-to-host contract transport lifecycle changes.
19
+ *
20
+ * The current value is delivered synchronously by default so a consumer owner
21
+ * can create or dispose its proxy immediately.
22
+ *
23
+ * @param listener Callback receiving the active transport or `undefined`.
24
+ * @param opts.emitCurrent Whether to deliver the current value immediately.
25
+ * @returns An idempotent unsubscribe function.
26
+ */
27
+ export declare function subscribeHostContractTransport(listener: HostContractTransportListener, opts?: {
28
+ emitCurrent?: boolean;
29
+ }): () => void;
30
+ /**
31
+ * Wait for the next available UI-to-host contract transport.
32
+ *
33
+ * @param opts.timeoutMs Optional deadline; rejects if no transport registers in time.
34
+ * @returns The current transport immediately, or the next registered transport.
35
+ */
36
+ export declare function waitForHostContractTransport(opts?: {
37
+ timeoutMs?: number;
38
+ }): Promise<IContractTransport>;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerHostContractTransport = registerHostContractTransport;
4
+ exports.getHostContractTransport = getHostContractTransport;
5
+ exports.subscribeHostContractTransport = subscribeHostContractTransport;
6
+ exports.waitForHostContractTransport = waitForHostContractTransport;
7
+ let activeRegistration;
8
+ const listeners = new Set();
9
+ function notifyListeners() {
10
+ const transport = activeRegistration?.transport;
11
+ for (const listener of [...listeners]) {
12
+ listener(transport);
13
+ }
14
+ }
15
+ /**
16
+ * Register the transport used by renderer code to call its trusted local host.
17
+ *
18
+ * A newer registration replaces the previous active transport. The returned
19
+ * disposer clears only its own registration, so disposing a stale Electron
20
+ * connection cannot remove a transport installed by a later reconnect.
21
+ *
22
+ * @param transport UI-side transport connected to the local host provider router.
23
+ * @returns A disposer for this exact registration.
24
+ */
25
+ function registerHostContractTransport(transport) {
26
+ const registration = { id: Symbol("host-contract-transport"), transport };
27
+ activeRegistration = registration;
28
+ notifyListeners();
29
+ let disposed = false;
30
+ return () => {
31
+ if (disposed) {
32
+ return;
33
+ }
34
+ disposed = true;
35
+ if (activeRegistration?.id === registration.id) {
36
+ activeRegistration = undefined;
37
+ notifyListeners();
38
+ }
39
+ };
40
+ }
41
+ /** Return the currently registered UI-to-host contract transport, if ready. */
42
+ function getHostContractTransport() {
43
+ return activeRegistration?.transport;
44
+ }
45
+ /**
46
+ * Subscribe to UI-to-host contract transport lifecycle changes.
47
+ *
48
+ * The current value is delivered synchronously by default so a consumer owner
49
+ * can create or dispose its proxy immediately.
50
+ *
51
+ * @param listener Callback receiving the active transport or `undefined`.
52
+ * @param opts.emitCurrent Whether to deliver the current value immediately.
53
+ * @returns An idempotent unsubscribe function.
54
+ */
55
+ function subscribeHostContractTransport(listener, opts = {}) {
56
+ listeners.add(listener);
57
+ if (opts.emitCurrent !== false) {
58
+ listener(activeRegistration?.transport);
59
+ }
60
+ let subscribed = true;
61
+ return () => {
62
+ if (!subscribed) {
63
+ return;
64
+ }
65
+ subscribed = false;
66
+ listeners.delete(listener);
67
+ };
68
+ }
69
+ /**
70
+ * Wait for the next available UI-to-host contract transport.
71
+ *
72
+ * @param opts.timeoutMs Optional deadline; rejects if no transport registers in time.
73
+ * @returns The current transport immediately, or the next registered transport.
74
+ */
75
+ function waitForHostContractTransport(opts = {}) {
76
+ const current = getHostContractTransport();
77
+ if (current) {
78
+ return Promise.resolve(current);
79
+ }
80
+ const { timeoutMs } = opts;
81
+ return new Promise((resolve, reject) => {
82
+ let settled = false;
83
+ let timer;
84
+ const finish = (action) => {
85
+ if (settled) {
86
+ return;
87
+ }
88
+ settled = true;
89
+ if (timer !== undefined) {
90
+ clearTimeout(timer);
91
+ }
92
+ unsubscribe();
93
+ action();
94
+ };
95
+ const unsubscribe = subscribeHostContractTransport((transport) => {
96
+ if (!transport) {
97
+ return;
98
+ }
99
+ finish(() => resolve(transport));
100
+ }, { emitCurrent: false });
101
+ if (timeoutMs !== undefined) {
102
+ timer = setTimeout(() => {
103
+ finish(() => reject(new Error(`Timed out waiting for host contract transport after ${timeoutMs}ms`)));
104
+ }, timeoutMs);
105
+ }
106
+ });
107
+ }
@@ -1,15 +1,19 @@
1
1
  export { ContractBuilder, definePackage, PackageBuilder } from "./builder";
2
2
  export { type ContractCallAuthorizer, type ContractProviderEndpointResolver, 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 IContractNotification, type IContractProviderEndpoint, type IContractProviderEndpointOptions, type IContractProviderSession, type IContractProviderSessionOptions, type IContractResolution, sameUserContractPermissionCheck, } from "./contract-proxy";
5
- export { type ContractRemoteIdentity, type ContractResolver, createUserContextContractProviderRouter, getContractResolver, handleContractCall, isSelfTrustedContractCaller, registerContractResolver, } from "./contract-resolvers";
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 ITableProxy, sameUserContractPermissionCheck, } from "./contract-proxy";
5
+ export { type ContractRemoteIdentity, type ContractResolver, createLocalUserContextContractProviderRouter, createUserContextContractProviderRouter, getContractResolver, handleContractCall, isSelfTrustedContractCaller, registerContractResolver, } 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
+ export { createLocalContractConsumer } from "./create-local-consumer";
8
9
  export { extractTableShape, extractToolShape, type IExtractableTableDef, type IExtractableToolInstance, setSchemaToFieldsFn, } from "./extract";
10
+ export { getHostContractTransport, type HostContractTransportListener, registerHostContractTransport, subscribeHostContractTransport, waitForHostContractTransport, } from "./host-contract-transport";
9
11
  export { PersistentContractRegistry } from "./persistent-registry";
10
12
  export { ContractRegistry } from "./registry";
11
13
  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";
12
- export { getLogsContractDefinition, LOGS_CONTRACT_VERSION, resolveLogsContract, } from "./system/logs-contract";
13
- export type { IAlsoImplementsDeclaration, IConsumedContract, IContractDefinition, IContractEvent, IContractObservable, IContractTable, IContractTool, IPackageDefinitionResult, IResolvedContract, IValidationError, IValidationResult, } from "./types";
14
+ export { getLogsContractDefinition, type ILogsConsumer, LOGS_CONTRACT_VERSION, resolveLogsContract, } from "./system/logs-contract";
15
+ export * from "./system/network-contracts";
16
+ export { type ISystemContractRegistration, installSystemContracts, listSystemContracts, registerSystemContract, } from "./system-contracts";
17
+ export type { IAlsoImplementsDeclaration, IConsumedContract, IConsumedContractHandle, IConsumedContractOptions, IContractDefinition, IContractEvent, IContractObservable, IContractTable, IContractTool, IPackageDefinitionResult, IResolvedContract, IValidationError, IValidationResult, } from "./types";
14
18
  export { contractKey } from "./types";
15
19
  export { validateAlsoImplements, validateImmutability, validateProviderSatisfiesContract, } from "./validate";
@@ -1,6 +1,21 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateProviderSatisfiesContract = exports.validateImmutability = exports.validateAlsoImplements = exports.contractKey = exports.resolveLogsContract = exports.LOGS_CONTRACT_VERSION = exports.getLogsContractDefinition = exports.getDeviceOperationsContractDefinition = exports.deviceOperationsToolIds = exports.deviceOperationsProviderPackageId = 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.ContractRegistry = exports.PersistentContractRegistry = exports.setSchemaToFieldsFn = exports.extractToolShape = exports.extractTableShape = exports.contractsSchema = exports.contractsMetaData = exports.ContractsTable = exports.Contracts = exports.inProcessTransportPair = exports.connectionContractTransport = exports.CONTRACT_REQUEST_CHANNEL = exports.CONTRACT_NOTIFY_CHANNEL = exports.registerContractResolver = exports.isSelfTrustedContractCaller = exports.handleContractCall = exports.getContractResolver = exports.createUserContextContractProviderRouter = exports.sameUserContractPermissionCheck = 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;
17
+ exports.installSystemContracts = exports.resolveLogsContract = exports.LOGS_CONTRACT_VERSION = exports.getLogsContractDefinition = exports.getDeviceOperationsContractDefinition = exports.deviceOperationsToolIds = exports.deviceOperationsProviderPackageId = 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.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.registerContractResolver = exports.isSelfTrustedContractCaller = exports.handleContractCall = exports.getContractResolver = exports.createUserContextContractProviderRouter = exports.createLocalUserContextContractProviderRouter = exports.sameUserContractPermissionCheck = 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 = void 0;
4
19
  var builder_1 = require("./builder");
5
20
  Object.defineProperty(exports, "ContractBuilder", { enumerable: true, get: function () { return builder_1.ContractBuilder; } });
6
21
  Object.defineProperty(exports, "definePackage", { enumerable: true, get: function () { return builder_1.definePackage; } });
@@ -20,6 +35,7 @@ Object.defineProperty(exports, "createContractProviderEndpoint", { enumerable: t
20
35
  Object.defineProperty(exports, "createContractProviderSession", { enumerable: true, get: function () { return contract_proxy_1.createContractProviderSession; } });
21
36
  Object.defineProperty(exports, "sameUserContractPermissionCheck", { enumerable: true, get: function () { return contract_proxy_1.sameUserContractPermissionCheck; } });
22
37
  var contract_resolvers_1 = require("./contract-resolvers");
38
+ Object.defineProperty(exports, "createLocalUserContextContractProviderRouter", { enumerable: true, get: function () { return contract_resolvers_1.createLocalUserContextContractProviderRouter; } });
23
39
  Object.defineProperty(exports, "createUserContextContractProviderRouter", { enumerable: true, get: function () { return contract_resolvers_1.createUserContextContractProviderRouter; } });
24
40
  Object.defineProperty(exports, "getContractResolver", { enumerable: true, get: function () { return contract_resolvers_1.getContractResolver; } });
25
41
  Object.defineProperty(exports, "handleContractCall", { enumerable: true, get: function () { return contract_resolvers_1.handleContractCall; } });
@@ -35,10 +51,17 @@ Object.defineProperty(exports, "Contracts", { enumerable: true, get: function ()
35
51
  Object.defineProperty(exports, "ContractsTable", { enumerable: true, get: function () { return contracts_table_1.ContractsTable; } });
36
52
  Object.defineProperty(exports, "contractsMetaData", { enumerable: true, get: function () { return contracts_table_1.contractsMetaData; } });
37
53
  Object.defineProperty(exports, "contractsSchema", { enumerable: true, get: function () { return contracts_table_1.contractsSchema; } });
54
+ var create_local_consumer_1 = require("./create-local-consumer");
55
+ Object.defineProperty(exports, "createLocalContractConsumer", { enumerable: true, get: function () { return create_local_consumer_1.createLocalContractConsumer; } });
38
56
  var extract_1 = require("./extract");
39
57
  Object.defineProperty(exports, "extractTableShape", { enumerable: true, get: function () { return extract_1.extractTableShape; } });
40
58
  Object.defineProperty(exports, "extractToolShape", { enumerable: true, get: function () { return extract_1.extractToolShape; } });
41
59
  Object.defineProperty(exports, "setSchemaToFieldsFn", { enumerable: true, get: function () { return extract_1.setSchemaToFieldsFn; } });
60
+ var host_contract_transport_1 = require("./host-contract-transport");
61
+ Object.defineProperty(exports, "getHostContractTransport", { enumerable: true, get: function () { return host_contract_transport_1.getHostContractTransport; } });
62
+ Object.defineProperty(exports, "registerHostContractTransport", { enumerable: true, get: function () { return host_contract_transport_1.registerHostContractTransport; } });
63
+ Object.defineProperty(exports, "subscribeHostContractTransport", { enumerable: true, get: function () { return host_contract_transport_1.subscribeHostContractTransport; } });
64
+ Object.defineProperty(exports, "waitForHostContractTransport", { enumerable: true, get: function () { return host_contract_transport_1.waitForHostContractTransport; } });
42
65
  var persistent_registry_1 = require("./persistent-registry");
43
66
  Object.defineProperty(exports, "PersistentContractRegistry", { enumerable: true, get: function () { return persistent_registry_1.PersistentContractRegistry; } });
44
67
  var registry_1 = require("./registry");
@@ -56,6 +79,11 @@ var logs_contract_1 = require("./system/logs-contract");
56
79
  Object.defineProperty(exports, "getLogsContractDefinition", { enumerable: true, get: function () { return logs_contract_1.getLogsContractDefinition; } });
57
80
  Object.defineProperty(exports, "LOGS_CONTRACT_VERSION", { enumerable: true, get: function () { return logs_contract_1.LOGS_CONTRACT_VERSION; } });
58
81
  Object.defineProperty(exports, "resolveLogsContract", { enumerable: true, get: function () { return logs_contract_1.resolveLogsContract; } });
82
+ __exportStar(require("./system/network-contracts"), exports);
83
+ var system_contracts_1 = require("./system-contracts");
84
+ Object.defineProperty(exports, "installSystemContracts", { enumerable: true, get: function () { return system_contracts_1.installSystemContracts; } });
85
+ Object.defineProperty(exports, "listSystemContracts", { enumerable: true, get: function () { return system_contracts_1.listSystemContracts; } });
86
+ Object.defineProperty(exports, "registerSystemContract", { enumerable: true, get: function () { return system_contracts_1.registerSystemContract; } });
59
87
  var types_1 = require("./types");
60
88
  Object.defineProperty(exports, "contractKey", { enumerable: true, get: function () { return types_1.contractKey; } });
61
89
  var validate_1 = require("./validate");
@@ -39,6 +39,23 @@ export declare class ContractRegistry {
39
39
  resolve(contractId: string, version: number): IContractDefinition | undefined;
40
40
  /** Get the active provider's package ID for a contract. */
41
41
  getProviderPackageId(contractId: string, version: number): string | undefined;
42
+ /**
43
+ * Package IDs registered as providers for a contract version (registration order).
44
+ * Includes inactive providers.
45
+ */
46
+ getRegisteredProviderIds(contractId: string, version: number): string[];
47
+ /**
48
+ * Pick a provider for a consumed-contract declaration.
49
+ *
50
+ * - No `providerPackageIds` → active provider
51
+ * - With `providerPackageIds` → first listed id that is registered
52
+ * - If none match and `fallbackToDefaultProvider === true` → active provider
53
+ * - Otherwise → `undefined` (missing)
54
+ */
55
+ selectProvider(dep: IConsumedContract): {
56
+ providerPackageId: string;
57
+ definition: IContractDefinition;
58
+ } | undefined;
42
59
  /** Get the stored contract definition (regardless of active provider). */
43
60
  getDefinition(contractId: string, version: number): IContractDefinition | undefined;
44
61
  /** Replace the stored definition for a contract (e.g. to freeze a dev contract). */
@@ -98,6 +98,42 @@ class ContractRegistry {
98
98
  const key = (0, types_1.contractKey)(contractId, version);
99
99
  return this.activeProviders.get(key)?.providerPackageId;
100
100
  }
101
+ /**
102
+ * Package IDs registered as providers for a contract version (registration order).
103
+ * Includes inactive providers.
104
+ */
105
+ getRegisteredProviderIds(contractId, version) {
106
+ const key = (0, types_1.contractKey)(contractId, version);
107
+ return (this.allProviders.get(key) ?? []).map((p) => p.providerPackageId);
108
+ }
109
+ /**
110
+ * Pick a provider for a consumed-contract declaration.
111
+ *
112
+ * - No `providerPackageIds` → active provider
113
+ * - With `providerPackageIds` → first listed id that is registered
114
+ * - If none match and `fallbackToDefaultProvider === true` → active provider
115
+ * - Otherwise → `undefined` (missing)
116
+ */
117
+ selectProvider(dep) {
118
+ const key = (0, types_1.contractKey)(dep.contractId, dep.version);
119
+ const providers = this.allProviders.get(key) ?? [];
120
+ const active = this.activeProviders.get(key);
121
+ if (!dep.providerPackageIds || dep.providerPackageIds.length === 0) {
122
+ return active
123
+ ? { providerPackageId: active.providerPackageId, definition: active.definition }
124
+ : undefined;
125
+ }
126
+ for (const preferredId of dep.providerPackageIds) {
127
+ const match = providers.find((p) => p.providerPackageId === preferredId);
128
+ if (match) {
129
+ return { providerPackageId: match.providerPackageId, definition: match.definition };
130
+ }
131
+ }
132
+ if (dep.fallbackToDefaultProvider === true && active) {
133
+ return { providerPackageId: active.providerPackageId, definition: active.definition };
134
+ }
135
+ return undefined;
136
+ }
101
137
  /** Get the stored contract definition (regardless of active provider). */
102
138
  getDefinition(contractId, version) {
103
139
  return this.definitions.get((0, types_1.contractKey)(contractId, version));
@@ -4,6 +4,7 @@ exports.deviceOperationsProviderPackageId = exports.deviceOperationsToolIds = ex
4
4
  exports.getDeviceOperationsContractDefinition = getDeviceOperationsContractDefinition;
5
5
  const system_ids_1 = require("../../system-ids");
6
6
  const field_type_1 = require("../../types/field-type");
7
+ const system_contracts_1 = require("../system-contracts");
7
8
  /** Version of the built-in System Device Operations contract. */
8
9
  exports.DEVICE_OPERATIONS_CONTRACT_VERSION = 1;
9
10
  /** Maximum SQL text accepted by the remote database operation. */
@@ -108,3 +109,9 @@ function getDeviceOperationsContractDefinition() {
108
109
  }
109
110
  /** Package ID used by live System Device Operations tool instances. */
110
111
  exports.deviceOperationsProviderPackageId = system_ids_1.peersSystemPackageId;
112
+ (0, system_contracts_1.registerSystemContract)({
113
+ providerPackageId: system_ids_1.peersSystemPackageId,
114
+ contractId: system_ids_1.deviceOperationsContractId,
115
+ version: exports.DEVICE_OPERATIONS_CONTRACT_VERSION,
116
+ getDefinition: getDeviceOperationsContractDefinition,
117
+ });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Built-in system contracts. Importing this barrel runs each module's
3
+ * {@link registerSystemContract} side effect so the catalog is populated.
4
+ */
5
+ import "./device-operations-contract";
6
+ import "./logs-contract";
7
+ import "./network-contracts";
8
+ 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 "./device-operations-contract";
9
+ export { getLogsContractDefinition, type ILogsConsumer, LOGS_CONTRACT_VERSION, resolveLogsContract, } from "./logs-contract";
10
+ export * from "./network-contracts";
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.resolveLogsContract = exports.LOGS_CONTRACT_VERSION = exports.getLogsContractDefinition = exports.getDeviceOperationsContractDefinition = exports.deviceOperationsToolIds = exports.deviceOperationsProviderPackageId = 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 = void 0;
18
+ /**
19
+ * Built-in system contracts. Importing this barrel runs each module's
20
+ * {@link registerSystemContract} side effect so the catalog is populated.
21
+ */
22
+ require("./device-operations-contract");
23
+ require("./logs-contract");
24
+ require("./network-contracts");
25
+ var device_operations_contract_1 = require("./device-operations-contract");
26
+ Object.defineProperty(exports, "DEVICE_OPERATIONS_CONTRACT_VERSION", { enumerable: true, get: function () { return device_operations_contract_1.DEVICE_OPERATIONS_CONTRACT_VERSION; } });
27
+ Object.defineProperty(exports, "DEVICE_OPERATIONS_MAX_QUERY_LENGTH", { enumerable: true, get: function () { return device_operations_contract_1.DEVICE_OPERATIONS_MAX_QUERY_LENGTH; } });
28
+ Object.defineProperty(exports, "DEVICE_OPERATIONS_MAX_RESULT_BYTES", { enumerable: true, get: function () { return device_operations_contract_1.DEVICE_OPERATIONS_MAX_RESULT_BYTES; } });
29
+ Object.defineProperty(exports, "DEVICE_OPERATIONS_MAX_ROWS", { enumerable: true, get: function () { return device_operations_contract_1.DEVICE_OPERATIONS_MAX_ROWS; } });
30
+ Object.defineProperty(exports, "DEVICE_OPERATIONS_MAX_TOOLS", { enumerable: true, get: function () { return device_operations_contract_1.DEVICE_OPERATIONS_MAX_TOOLS; } });
31
+ Object.defineProperty(exports, "deviceOperationsProviderPackageId", { enumerable: true, get: function () { return device_operations_contract_1.deviceOperationsProviderPackageId; } });
32
+ Object.defineProperty(exports, "deviceOperationsToolIds", { enumerable: true, get: function () { return device_operations_contract_1.deviceOperationsToolIds; } });
33
+ Object.defineProperty(exports, "getDeviceOperationsContractDefinition", { enumerable: true, get: function () { return device_operations_contract_1.getDeviceOperationsContractDefinition; } });
34
+ var logs_contract_1 = require("./logs-contract");
35
+ Object.defineProperty(exports, "getLogsContractDefinition", { enumerable: true, get: function () { return logs_contract_1.getLogsContractDefinition; } });
36
+ Object.defineProperty(exports, "LOGS_CONTRACT_VERSION", { enumerable: true, get: function () { return logs_contract_1.LOGS_CONTRACT_VERSION; } });
37
+ Object.defineProperty(exports, "resolveLogsContract", { enumerable: true, get: function () { return logs_contract_1.resolveLogsContract; } });
38
+ __exportStar(require("./network-contracts"), exports);