@peers-app/peers-sdk 0.27.3 → 0.27.5

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 (272) hide show
  1. package/dist/contracts/contract-proxy.d.ts +7 -0
  2. package/dist/contracts/contract-proxy.js +19 -2
  3. package/dist/contracts/contract-transport.d.ts +2 -1
  4. package/dist/contracts/contract-transport.js +24 -2
  5. package/dist/contracts/create-local-consumer.js +16 -1
  6. package/dist/contracts/index.d.ts +2 -0
  7. package/dist/contracts/index.js +2 -0
  8. package/dist/contracts/system/index.d.ts +2 -0
  9. package/dist/contracts/system/index.js +2 -0
  10. package/dist/contracts/system/invites-contract.js +2 -1
  11. package/dist/contracts/system/sync-check-contract.d.ts +97 -0
  12. package/dist/contracts/system/sync-check-contract.js +115 -0
  13. package/dist/contracts/tool-arguments.d.ts +15 -0
  14. package/dist/contracts/tool-arguments.js +41 -0
  15. package/dist/contracts/tool-catalog-service.js +2 -12
  16. package/dist/contracts/tool-catalog.js +6 -2
  17. package/dist/data/change-tracking.d.ts +40 -0
  18. package/dist/data/change-tracking.js +89 -0
  19. package/dist/data/orm/types.d.ts +24 -7
  20. package/dist/data/orm/types.js +97 -24
  21. package/dist/define/manifest.js +6 -34
  22. package/dist/device/binary-peer-connection-v2.d.ts +7 -15
  23. package/dist/device/binary-peer-connection-v2.js +14 -30
  24. package/dist/device/connection.d.ts +34 -43
  25. package/dist/device/connection.js +188 -186
  26. package/dist/device/device.d.ts +1 -8
  27. package/dist/device/device.js +1 -30
  28. package/dist/device/socket.type.d.ts +6 -12
  29. package/dist/package-loader/package-loader.js +27 -22
  30. package/dist/system-ids.d.ts +5 -0
  31. package/dist/system-ids.js +6 -1
  32. package/package.json +4 -2
  33. package/dist/context/user-context-identity.test.d.ts +0 -1
  34. package/dist/context/user-context-identity.test.js +0 -220
  35. package/dist/contracts/__tests__/action-dispatch.test.d.ts +0 -1
  36. package/dist/contracts/__tests__/action-dispatch.test.js +0 -319
  37. package/dist/contracts/__tests__/also-implements.test.d.ts +0 -1
  38. package/dist/contracts/__tests__/also-implements.test.js +0 -110
  39. package/dist/contracts/__tests__/builder.test.d.ts +0 -1
  40. package/dist/contracts/__tests__/builder.test.js +0 -669
  41. package/dist/contracts/__tests__/contract-events.test.d.ts +0 -1
  42. package/dist/contracts/__tests__/contract-events.test.js +0 -199
  43. package/dist/contracts/__tests__/contract-observables.test.d.ts +0 -1
  44. package/dist/contracts/__tests__/contract-observables.test.js +0 -290
  45. package/dist/contracts/__tests__/contract-provider-router.test.d.ts +0 -1
  46. package/dist/contracts/__tests__/contract-provider-router.test.js +0 -315
  47. package/dist/contracts/__tests__/contract-proxy.test.d.ts +0 -1
  48. package/dist/contracts/__tests__/contract-proxy.test.js +0 -657
  49. package/dist/contracts/__tests__/contract-resolvers.test.d.ts +0 -1
  50. package/dist/contracts/__tests__/contract-resolvers.test.js +0 -758
  51. package/dist/contracts/__tests__/contract-subscription-lifecycle.test.d.ts +0 -1
  52. package/dist/contracts/__tests__/contract-subscription-lifecycle.test.js +0 -353
  53. package/dist/contracts/__tests__/contract-table-events.test.d.ts +0 -1
  54. package/dist/contracts/__tests__/contract-table-events.test.js +0 -209
  55. package/dist/contracts/__tests__/contract-transport.test.d.ts +0 -1
  56. package/dist/contracts/__tests__/contract-transport.test.js +0 -163
  57. package/dist/contracts/__tests__/extract.test.d.ts +0 -1
  58. package/dist/contracts/__tests__/extract.test.js +0 -145
  59. package/dist/contracts/__tests__/frozen-contracts.test.d.ts +0 -1
  60. package/dist/contracts/__tests__/frozen-contracts.test.js +0 -191
  61. package/dist/contracts/__tests__/generic-tool-dispatch.test.d.ts +0 -1
  62. package/dist/contracts/__tests__/generic-tool-dispatch.test.js +0 -130
  63. package/dist/contracts/__tests__/host-contract-client.test.d.ts +0 -1
  64. package/dist/contracts/__tests__/host-contract-client.test.js +0 -793
  65. package/dist/contracts/__tests__/host-contract-consumer.test.d.ts +0 -1
  66. package/dist/contracts/__tests__/host-contract-consumer.test.js +0 -163
  67. package/dist/contracts/__tests__/host-contract-transport.test.d.ts +0 -1
  68. package/dist/contracts/__tests__/host-contract-transport.test.js +0 -66
  69. package/dist/contracts/__tests__/integration.test.d.ts +0 -1
  70. package/dist/contracts/__tests__/integration.test.js +0 -348
  71. package/dist/contracts/__tests__/legacy-removal.test.d.ts +0 -1
  72. package/dist/contracts/__tests__/legacy-removal.test.js +0 -128
  73. package/dist/contracts/__tests__/persistent-registry.test.d.ts +0 -1
  74. package/dist/contracts/__tests__/persistent-registry.test.js +0 -109
  75. package/dist/contracts/__tests__/playground.test.d.ts +0 -1
  76. package/dist/contracts/__tests__/playground.test.js +0 -216
  77. package/dist/contracts/__tests__/registry.test.d.ts +0 -1
  78. package/dist/contracts/__tests__/registry.test.js +0 -238
  79. package/dist/contracts/__tests__/remote-contract-transport.test.d.ts +0 -1
  80. package/dist/contracts/__tests__/remote-contract-transport.test.js +0 -119
  81. package/dist/contracts/__tests__/system-contracts.test.d.ts +0 -1
  82. package/dist/contracts/__tests__/system-contracts.test.js +0 -247
  83. package/dist/contracts/__tests__/target-dispatch.d.ts +0 -11
  84. package/dist/contracts/__tests__/target-dispatch.js +0 -24
  85. package/dist/contracts/__tests__/tool-catalog-inventory.test.d.ts +0 -1
  86. package/dist/contracts/__tests__/tool-catalog-inventory.test.js +0 -44
  87. package/dist/contracts/__tests__/tool-catalog-service.test.d.ts +0 -1
  88. package/dist/contracts/__tests__/tool-catalog-service.test.js +0 -482
  89. package/dist/contracts/__tests__/tool-catalog.test.d.ts +0 -1
  90. package/dist/contracts/__tests__/tool-catalog.test.js +0 -1199
  91. package/dist/contracts/__tests__/validate.test.d.ts +0 -1
  92. package/dist/contracts/__tests__/validate.test.js +0 -991
  93. package/dist/contracts/__tests__/workflow-context.test.d.ts +0 -1
  94. package/dist/contracts/__tests__/workflow-context.test.js +0 -50
  95. package/dist/data/access-level.test.d.ts +0 -1
  96. package/dist/data/access-level.test.js +0 -53
  97. package/dist/data/change-tracking.test.d.ts +0 -1
  98. package/dist/data/change-tracking.test.js +0 -62
  99. package/dist/data/files/files.test.d.ts +0 -1
  100. package/dist/data/files/files.test.js +0 -770
  101. package/dist/data/group-members.test.d.ts +0 -1
  102. package/dist/data/group-members.test.js +0 -336
  103. package/dist/data/group-share.test.d.ts +0 -1
  104. package/dist/data/group-share.test.js +0 -110
  105. package/dist/data/groups.test.d.ts +0 -1
  106. package/dist/data/groups.test.js +0 -153
  107. package/dist/data/orm/cursor.test.d.ts +0 -1
  108. package/dist/data/orm/cursor.test.js +0 -314
  109. package/dist/data/orm/data-query.mongo.test.d.ts +0 -1
  110. package/dist/data/orm/data-query.mongo.test.js +0 -367
  111. package/dist/data/orm/data-query.sqlite.test.d.ts +0 -1
  112. package/dist/data/orm/data-query.sqlite.test.js +0 -365
  113. package/dist/data/orm/data-query.test.d.ts +0 -1
  114. package/dist/data/orm/data-query.test.js +0 -545
  115. package/dist/data/orm/dependency-injection.test.d.ts +0 -1
  116. package/dist/data/orm/dependency-injection.test.js +0 -171
  117. package/dist/data/orm/event-registry.test.d.ts +0 -1
  118. package/dist/data/orm/event-registry.test.js +0 -44
  119. package/dist/data/orm/multi-cursors.test.d.ts +0 -1
  120. package/dist/data/orm/multi-cursors.test.js +0 -463
  121. package/dist/data/orm/sql.data-source.test.d.ts +0 -1
  122. package/dist/data/orm/sql.data-source.test.js +0 -731
  123. package/dist/data/orm/table-container-events.test.d.ts +0 -1
  124. package/dist/data/orm/table-container-events.test.js +0 -101
  125. package/dist/data/orm/table-container.test.d.ts +0 -1
  126. package/dist/data/orm/table-container.test.js +0 -273
  127. package/dist/data/orm/table.event-source.test.d.ts +0 -1
  128. package/dist/data/orm/table.event-source.test.js +0 -331
  129. package/dist/data/orm/types.test.d.ts +0 -1
  130. package/dist/data/orm/types.test.js +0 -409
  131. package/dist/data/package-table-identity.test.d.ts +0 -1
  132. package/dist/data/package-table-identity.test.js +0 -46
  133. package/dist/data/package-version-permissions.test.d.ts +0 -1
  134. package/dist/data/package-version-permissions.test.js +0 -107
  135. package/dist/data/package-version-resolver.test.d.ts +0 -4
  136. package/dist/data/package-version-resolver.test.js +0 -543
  137. package/dist/data/package-versions.test.d.ts +0 -1
  138. package/dist/data/package-versions.test.js +0 -227
  139. package/dist/data/persistent-vars.conflict.test.d.ts +0 -1
  140. package/dist/data/persistent-vars.conflict.test.js +0 -126
  141. package/dist/data/persistent-vars.migration.test.d.ts +0 -1
  142. package/dist/data/persistent-vars.migration.test.js +0 -133
  143. package/dist/data/persistent-vars.package-scope.test.d.ts +0 -1
  144. package/dist/data/persistent-vars.package-scope.test.js +0 -27
  145. package/dist/data/sync-recovery-queue.test.d.ts +0 -1
  146. package/dist/data/sync-recovery-queue.test.js +0 -215
  147. package/dist/data/table-signing.test.d.ts +0 -1
  148. package/dist/data/table-signing.test.js +0 -118
  149. package/dist/data/tool-access.test.d.ts +0 -1
  150. package/dist/data/tool-access.test.js +0 -166
  151. package/dist/data/user-permissions.test.d.ts +0 -1
  152. package/dist/data/user-permissions.test.js +0 -305
  153. package/dist/data/user-trust-levels.test.d.ts +0 -1
  154. package/dist/data/user-trust-levels.test.js +0 -37
  155. package/dist/define/also-implements.test.d.ts +0 -1
  156. package/dist/define/also-implements.test.js +0 -123
  157. package/dist/define/declare-contract.test.d.ts +0 -1
  158. package/dist/define/declare-contract.test.js +0 -573
  159. package/dist/define/define.test.d.ts +0 -1
  160. package/dist/define/define.test.js +0 -1010
  161. package/dist/define/empty-fields.test.d.ts +0 -1
  162. package/dist/define/empty-fields.test.js +0 -55
  163. package/dist/define/events-observables.test.d.ts +0 -1
  164. package/dist/define/events-observables.test.js +0 -1013
  165. package/dist/define/serve-members.test.d.ts +0 -1
  166. package/dist/define/serve-members.test.js +0 -630
  167. package/dist/define/vars.test.d.ts +0 -1
  168. package/dist/define/vars.test.js +0 -39
  169. package/dist/device/binary-peer-connection-v2.test.d.ts +0 -1
  170. package/dist/device/binary-peer-connection-v2.test.js +0 -730
  171. package/dist/device/binary-peer-connection.d.ts +0 -58
  172. package/dist/device/binary-peer-connection.js +0 -516
  173. package/dist/device/binary-peer-connection.test.d.ts +0 -1
  174. package/dist/device/binary-peer-connection.test.js +0 -184
  175. package/dist/device/connection.test.d.ts +0 -1
  176. package/dist/device/connection.test.js +0 -613
  177. package/dist/device/device-election.test.d.ts +0 -1
  178. package/dist/device/device-election.test.js +0 -516
  179. package/dist/device/device.test.d.ts +0 -1
  180. package/dist/device/device.test.js +0 -243
  181. package/dist/device/frame-cipher.test.d.ts +0 -1
  182. package/dist/device/frame-cipher.test.js +0 -219
  183. package/dist/device/get-trust-level-fn.test.d.ts +0 -1
  184. package/dist/device/get-trust-level-fn.test.js +0 -685
  185. package/dist/device/streamed-socket.d.ts +0 -23
  186. package/dist/device/streamed-socket.js +0 -255
  187. package/dist/device/streamed-socket.test.d.ts +0 -1
  188. package/dist/device/streamed-socket.test.js +0 -216
  189. package/dist/device/tx-encoding.test.d.ts +0 -1
  190. package/dist/device/tx-encoding.test.js +0 -295
  191. package/dist/device-pairing/cpace.test.d.ts +0 -1
  192. package/dist/device-pairing/cpace.test.js +0 -116
  193. package/dist/device-pairing/device-pairing.test.d.ts +0 -1
  194. package/dist/device-pairing/device-pairing.test.js +0 -211
  195. package/dist/hlc.test.d.ts +0 -1
  196. package/dist/hlc.test.js +0 -45
  197. package/dist/host-credentials.test.d.ts +0 -1
  198. package/dist/host-credentials.test.js +0 -88
  199. package/dist/identity/account-email.test.d.ts +0 -1
  200. package/dist/identity/account-email.test.js +0 -59
  201. package/dist/identity/anchor-document.test.d.ts +0 -1
  202. package/dist/identity/anchor-document.test.js +0 -16
  203. package/dist/identity/anchor-resolution.test.d.ts +0 -1
  204. package/dist/identity/anchor-resolution.test.js +0 -130
  205. package/dist/identity/key-change.test.d.ts +0 -1
  206. package/dist/identity/key-change.test.js +0 -811
  207. package/dist/invites/group-approval.test.d.ts +0 -1
  208. package/dist/invites/group-approval.test.js +0 -223
  209. package/dist/invites/invite-token.test.d.ts +0 -1
  210. package/dist/invites/invite-token.test.js +0 -123
  211. package/dist/keys.test.d.ts +0 -1
  212. package/dist/keys.test.js +0 -336
  213. package/dist/logging/console-logger.test.d.ts +0 -1
  214. package/dist/logging/console-logger.test.js +0 -300
  215. package/dist/logging/console-logs.table.test.d.ts +0 -1
  216. package/dist/logging/console-logs.table.test.js +0 -156
  217. package/dist/observable.test.d.ts +0 -1
  218. package/dist/observable.test.js +0 -309
  219. package/dist/package-build/build-package.test.d.ts +0 -1
  220. package/dist/package-build/build-package.test.js +0 -204
  221. package/dist/package-build/contract-add.test.d.ts +0 -1
  222. package/dist/package-build/contract-add.test.js +0 -467
  223. package/dist/package-build/freeze-contracts.test.d.ts +0 -1
  224. package/dist/package-build/freeze-contracts.test.js +0 -355
  225. package/dist/package-installer/package-author-signing.test.d.ts +0 -1
  226. package/dist/package-installer/package-author-signing.test.js +0 -200
  227. package/dist/package-installer/package-cloner.test.d.ts +0 -1
  228. package/dist/package-installer/package-cloner.test.js +0 -278
  229. package/dist/package-installer/package-creator.test.d.ts +0 -1
  230. package/dist/package-installer/package-creator.test.js +0 -908
  231. package/dist/package-installer/package-dev-tools.test.d.ts +0 -1
  232. package/dist/package-installer/package-dev-tools.test.js +0 -64
  233. package/dist/package-installer/package-installer.test.d.ts +0 -1
  234. package/dist/package-installer/package-installer.test.js +0 -882
  235. package/dist/package-installer/package-propagation.test.d.ts +0 -1
  236. package/dist/package-installer/package-propagation.test.js +0 -1269
  237. package/dist/package-installer/package-publisher.test.d.ts +0 -1
  238. package/dist/package-installer/package-publisher.test.js +0 -153
  239. package/dist/package-installer/package-remote-checker.test.d.ts +0 -1
  240. package/dist/package-installer/package-remote-checker.test.js +0 -334
  241. package/dist/package-installer/package-seed-installer.test.d.ts +0 -1
  242. package/dist/package-installer/package-seed-installer.test.js +0 -123
  243. package/dist/package-installer/package-tarball.test.d.ts +0 -1
  244. package/dist/package-installer/package-tarball.test.js +0 -75
  245. package/dist/package-installer/peers-core-installer.test.d.ts +0 -1
  246. package/dist/package-installer/peers-core-installer.test.js +0 -49
  247. package/dist/package-installer/peers-core-trust-anchor.test.d.ts +0 -1
  248. package/dist/package-installer/peers-core-trust-anchor.test.js +0 -155
  249. package/dist/package-loader/contract-package-loader.test.d.ts +0 -1
  250. package/dist/package-loader/contract-package-loader.test.js +0 -274
  251. package/dist/package-loader/host-authority-loading.test.d.ts +0 -1
  252. package/dist/package-loader/host-authority-loading.test.js +0 -104
  253. package/dist/package-loader/host-dispatch-policy.test.d.ts +0 -1
  254. package/dist/package-loader/host-dispatch-policy.test.js +0 -56
  255. package/dist/package-loader/isolated-artifact.test.d.ts +0 -1
  256. package/dist/package-loader/isolated-artifact.test.js +0 -688
  257. package/dist/package-loader/isolated-persistent-var-gateway.test.d.ts +0 -1
  258. package/dist/package-loader/isolated-persistent-var-gateway.test.js +0 -56
  259. package/dist/package-loader/isolated-table-gateway.test.d.ts +0 -1
  260. package/dist/package-loader/isolated-table-gateway.test.js +0 -633
  261. package/dist/package-loader/package-loader.test.d.ts +0 -1
  262. package/dist/package-loader/package-loader.test.js +0 -1764
  263. package/dist/package-loader/resolve-consumed-contracts.test.d.ts +0 -1
  264. package/dist/package-loader/resolve-consumed-contracts.test.js +0 -166
  265. package/dist/serial-json.compat.test.d.ts +0 -1
  266. package/dist/serial-json.compat.test.js +0 -369
  267. package/dist/serial-json.test.d.ts +0 -1
  268. package/dist/serial-json.test.js +0 -401
  269. package/dist/testing/mock-host-contract.test.d.ts +0 -1
  270. package/dist/testing/mock-host-contract.test.js +0 -782
  271. package/dist/utils.test.d.ts +0 -1
  272. package/dist/utils.test.js +0 -232
@@ -1,573 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const isolated_artifact_1 = require("../package-loader/isolated-artifact");
4
- const peer_id_1 = require("../peer-id");
5
- const index_1 = require("./index");
6
- const manifest_1 = require("./manifest");
7
- const observables_1 = require("./observables");
8
- const serve_members_1 = require("./serve-members");
9
- /** A ctx whose host calls are recorded and answered by `answer`. */
10
- function fakeContext(answer = () => null) {
11
- const calls = [];
12
- const ctx = new Proxy({}, {
13
- get(_target, method) {
14
- return async (...args) => {
15
- calls.push([method, ...args]);
16
- return answer(method, args);
17
- };
18
- },
19
- });
20
- return { ctx, calls };
21
- }
22
- const contractId = (0, peer_id_1.newid)();
23
- const invokeInput = index_1.z.object({
24
- tool: index_1.z.string().describe("Catalog tool name."),
25
- args: index_1.z.object({}).passthrough().optional().describe("Arguments for that tool."),
26
- });
27
- const invokeOutput = index_1.z.object({
28
- result: index_1.z.unknown().optional(),
29
- speech: index_1.z.string().optional(),
30
- });
31
- const catalogSchema = index_1.z.object({ name: index_1.z.string(), slug: index_1.z.string() });
32
- const alert = (0, index_1.defineEvent)({
33
- name: "alert",
34
- description: "Something needs attention.",
35
- payloadSchema: index_1.z.object({ title: index_1.z.string(), detail: index_1.z.string().optional() }),
36
- });
37
- const Notes = (0, index_1.defineTable)({
38
- name: "Notes",
39
- description: "Notes.",
40
- primaryKeyName: "noteId",
41
- schema: index_1.z.object({ noteId: index_1.zodPeerId, text: index_1.z.string() }),
42
- });
43
- const invokeShape = {
44
- name: "invoke",
45
- usageDescription: "Run one catalog tool.",
46
- accessLevel: index_1.AccessLevel.Reader,
47
- authorityPropagation: "preserve",
48
- inputSchema: invokeInput,
49
- outputSchema: invokeOutput,
50
- };
51
- const Skill = (0, index_1.declareContract)({
52
- contractId,
53
- version: 1,
54
- name: "Skill",
55
- description: "A skill.",
56
- tables: [Notes],
57
- tools: [(0, index_1.declareTool)(invokeShape)],
58
- observables: [
59
- (0, index_1.declareObservable)({ name: "skill", description: "The catalog.", schema: catalogSchema }),
60
- ],
61
- events: [alert],
62
- });
63
- const catalog = (0, index_1.deviceVar)(`skill-${(0, peer_id_1.newid)()}`, { defaultValue: { name: "Timers", slug: "timers" } });
64
- const handler = async ({ tool }) => ({ speech: tool });
65
- const packageId = (0, peer_id_1.newid)();
66
- function manifestOf(contract) {
67
- return (0, manifest_1.buildPackageManifest)((0, index_1.definePackage)((pkg) => {
68
- pkg.packageId = packageId;
69
- pkg.version = "1.0.0";
70
- pkg.provides(contract);
71
- }));
72
- }
73
- describe("declareContract", () => {
74
- test("the declaration is a typed reference that can pick a provider", async () => {
75
- const { ctx, calls } = fakeContext((method) => method === "callConsumedTool" ? { speech: "ok" } : { name: "Timers", slug: "timers" });
76
- const result = await Skill(ctx, { providerPackageId: "p1" }).tools.invoke({ tool: "list" });
77
- const speech = result.speech;
78
- expect(speech).toBe("ok");
79
- const value = await Skill(ctx).observables.skill.get();
80
- expect(value?.slug).toBe("timers");
81
- await Skill(ctx, { providerPackageId: "p2" }).observables.skill.get();
82
- expect(calls).toStrictEqual([
83
- ["callConsumedTool", contractId, 1, "invoke", { tool: "list" }, { providerPackageId: "p1" }],
84
- ["getConsumedObservable", contractId, 1, "skill"],
85
- ["getConsumedObservable", contractId, 1, "skill", { providerPackageId: "p2" }],
86
- ]);
87
- await expect(Skill(ctx, { providerPackageId: "p1" }).tables.Notes.list()).rejects.toThrow(/can't pick a provider/);
88
- expect(() => Skill(ctx, { providerPackageId: 3 })).toThrow(/package id/);
89
- for (const providerPackageId of ["", " "]) {
90
- expect(() => Skill(ctx, { providerPackageId })).toThrow(/non-empty package id/);
91
- }
92
- // @ts-expect-error the skill observable is read-only
93
- expect(typeof Skill(ctx).observables.skill.set).toBe("function");
94
- // @ts-expect-error invoke needs a tool name
95
- void Skill(ctx).tools.invoke({});
96
- expect((0, index_1.isContractDeclaration)(Skill)).toBe(true);
97
- expect(Skill.declaration.tools.map((tool) => tool.definition.name)).toEqual(["invoke"]);
98
- });
99
- test("type-only references and implementation helpers accept the declaration's type", async () => {
100
- const Literal = (0, index_1.declareContract)({
101
- contractId: "00muxgugn6xvs8f2r80ru205t",
102
- version: 3,
103
- name: "Literal",
104
- });
105
- (0, index_1.contractRef)(Literal.contractId, Literal.version);
106
- // @ts-expect-error the declared id is preserved
107
- (0, index_1.contractRef)("00mvhostclient00000000001", 3);
108
- // @ts-expect-error the declared version is preserved
109
- (0, index_1.contractRef)(Literal.contractId, 4);
110
- const implementation = {
111
- tools: { invoke: ({ tool }) => ({ speech: tool }) },
112
- observables: { skill: catalog },
113
- };
114
- const implemented = (0, index_1.implementContract)(Skill, implementation);
115
- expect(implemented.tools[0].definition.name).toBe("invoke");
116
- const Ref = (0, index_1.contractRef)(contractId, 1);
117
- const { ctx } = fakeContext(() => ({ speech: "typed" }));
118
- const result = await Ref(ctx).tools.invoke({ tool: "list" });
119
- const speech = result.speech;
120
- expect(speech).toBe("typed");
121
- // @ts-expect-error the declared version is 1
122
- (0, index_1.contractRef)(contractId, 2);
123
- // @ts-expect-error a type-only reference still requires the tool's input
124
- void Ref(ctx).tools.invoke({});
125
- // @ts-expect-error the observable remains read-only through a type-only reference
126
- void Ref(ctx).observables.skill.set;
127
- const values = {
128
- skill: { name: "Timers", slug: "timers" },
129
- };
130
- const writable = { skill: false };
131
- const rows = { Notes: { noteId: (0, peer_id_1.newid)(), text: "typed" } };
132
- const inputs = rows;
133
- const payloads = { alert: { title: "typed" } };
134
- expect([values.skill.slug, writable.skill, inputs.Notes.text, payloads.alert.title]).toEqual([
135
- "timers",
136
- false,
137
- "typed",
138
- "typed",
139
- ]);
140
- });
141
- test("members written inline in the lists keep their names, types, and writability", async () => {
142
- const tool = (name, inputSchema) => ({
143
- name,
144
- usageDescription: "A tool.",
145
- accessLevel: index_1.AccessLevel.Reader,
146
- inputSchema,
147
- outputSchema: index_1.z.object({ ok: index_1.z.boolean() }),
148
- });
149
- const Inline = (0, index_1.declareContract)({
150
- contractId: (0, peer_id_1.newid)(),
151
- version: 1,
152
- name: "Inline",
153
- tools: [
154
- (0, index_1.declareTool)(tool("count", index_1.z.object({ n: index_1.z.number() }))),
155
- (0, index_1.declareTool)(tool("label", index_1.z.object({ text: index_1.z.string() }))),
156
- ],
157
- observables: [
158
- (0, index_1.declareObservable)({
159
- name: "level",
160
- description: "Level.",
161
- schema: index_1.z.number(),
162
- writable: true,
163
- }),
164
- (0, index_1.declareObservable)({ name: "mode", description: "Mode.", schema: index_1.z.string() }),
165
- ],
166
- events: [
167
- (0, index_1.defineEvent)({
168
- name: "counted",
169
- description: "C.",
170
- payloadSchema: index_1.z.object({ n: index_1.z.number() }),
171
- }),
172
- (0, index_1.defineEvent)({
173
- name: "labeled",
174
- description: "L.",
175
- payloadSchema: index_1.z.object({ t: index_1.z.string() }),
176
- }),
177
- ],
178
- });
179
- const { ctx } = fakeContext(() => ({ ok: true }));
180
- await Inline(ctx).tools.label({ text: "a" });
181
- // @ts-expect-error each tool keeps its own input
182
- void Inline(ctx).tools.label({ n: 1 });
183
- // @ts-expect-error a name the contract doesn't declare
184
- void Inline(ctx).tools.other;
185
- // @ts-expect-error a read-only observable stays read-only beside a writable one
186
- void Inline(ctx).observables.mode.set;
187
- const values = { level: 1, mode: "on" };
188
- // @ts-expect-error each observable keeps its own value type
189
- values.mode = 1;
190
- const payloads = {
191
- counted: { n: 1 },
192
- labeled: { t: "a" },
193
- };
194
- // @ts-expect-error each event keeps its own payload
195
- payloads.labeled = { n: 1 };
196
- // Handlers are typed per tool, and a read-only source may sit beside a writable one.
197
- const implemented = (0, index_1.implementContract)(Inline, {
198
- tools: {
199
- count: ({ n }) => ({ ok: n > 0 }),
200
- label: ({ text }) => ({ ok: text.length > 0 }),
201
- },
202
- observables: { level: (0, index_1.observable)(0), mode: (0, index_1.observable)("on") },
203
- });
204
- expect(implemented.tools.map((member) => member.definition.name)).toEqual(["count", "label"]);
205
- const Defined = (0, index_1.defineContract)({
206
- contractId: (0, peer_id_1.newid)(),
207
- version: 1,
208
- name: "Defined",
209
- tools: [
210
- (0, index_1.defineTool)({
211
- ...tool("count", index_1.z.object({ n: index_1.z.number() })),
212
- handler: ({ n }) => ({ ok: n > 0 }),
213
- }),
214
- ],
215
- observables: [
216
- (0, index_1.defineObservable)({
217
- name: "level",
218
- description: "Level.",
219
- schema: index_1.z.number(),
220
- writable: true,
221
- source: (0, index_1.observable)(0),
222
- }),
223
- (0, index_1.defineObservable)({
224
- name: "mode",
225
- description: "Mode.",
226
- schema: index_1.z.string(),
227
- source: (0, index_1.observable)("on"),
228
- }),
229
- ],
230
- });
231
- const Ref = (0, index_1.contractRef)(Defined.contractId, 1);
232
- // @ts-expect-error defineContract's inline members keep their names too
233
- void Ref(ctx).tools.other;
234
- // @ts-expect-error and their writability
235
- void Ref(ctx).observables.mode.set;
236
- });
237
- test("a tools-only reference can still have a tool named declaration", async () => {
238
- const Ref = (0, index_1.contractRef)(contractId, 1);
239
- const { ctx } = fakeContext(() => ({ speech: "done" }));
240
- const { speech } = await Ref(ctx).tools.declaration({ label: "ready" });
241
- const value = speech;
242
- expect(value).toBe("done");
243
- });
244
- test("observable writes forward the provider and snapshot values, with no options by default", async () => {
245
- const State = (0, index_1.declareContract)({
246
- contractId: (0, peer_id_1.newid)(),
247
- version: 1,
248
- name: "State",
249
- observables: [
250
- (0, index_1.declareObservable)({
251
- name: "value",
252
- description: "Writable state.",
253
- schema: index_1.z.object({ label: index_1.z.string(), detail: index_1.z.string().optional() }),
254
- writable: true,
255
- }),
256
- ],
257
- });
258
- const { ctx, calls } = fakeContext((_method, args) => args[3]);
259
- const value = { label: "ready", detail: undefined };
260
- await State(ctx).observables.value.set(value);
261
- await State(ctx, { providerPackageId: "p1" }).observables.value.set(value);
262
- expect(calls).toEqual([
263
- ["setConsumedObservable", State.contractId, 1, "value", { label: "ready" }],
264
- [
265
- "setConsumedObservable",
266
- State.contractId,
267
- 1,
268
- "value",
269
- { label: "ready" },
270
- { providerPackageId: "p1" },
271
- ],
272
- ]);
273
- expect(Object.hasOwn(value, "detail")).toBe(true);
274
- });
275
- test("an empty whole observable value is null on the bridge, including a write's reply", async () => {
276
- const State = (0, index_1.declareContract)({
277
- contractId: (0, peer_id_1.newid)(),
278
- version: 1,
279
- name: "State",
280
- observables: [
281
- (0, index_1.declareObservable)({
282
- name: "value",
283
- description: "Optional state.",
284
- schema: index_1.z.string().optional(),
285
- writable: true,
286
- }),
287
- ],
288
- });
289
- const source = (0, index_1.observable)();
290
- const Implemented = (0, index_1.implementContract)(State, { observables: { value: source } });
291
- const handlers = [];
292
- (0, serve_members_1.serveContractMembers)(Implemented, (_name, handler) => handlers.push(handler));
293
- const { ctx } = fakeContext((method, args) => handlers[0]({
294
- member: "observable",
295
- name: "value",
296
- operation: method === "getConsumedObservable" ? "get" : "set",
297
- args: method === "getConsumedObservable" ? [] : [args[3] ?? null],
298
- }, ctx));
299
- await (0, index_1.startPackage)((0, index_1.definePackage)((pkg) => {
300
- pkg.packageId = (0, peer_id_1.newid)();
301
- pkg.version = "1.0.0";
302
- pkg.provides(Implemented);
303
- }), fakeContext().ctx);
304
- const read = await State(ctx).observables.value.get();
305
- // The type must allow what the provider's member handler actually returns.
306
- const emptyRead = null;
307
- expect(read).toBe(emptyRead);
308
- // A provider's subscribers can adjust the value before it replies to the write.
309
- source.subscribe(() => source(undefined));
310
- const written = await State(ctx).observables.value.set("clear");
311
- const emptyWrite = null;
312
- expect(written).toBe(emptyWrite);
313
- // @ts-expect-error undefined crosses the bridge as null, which this schema refuses
314
- const missingWrite = State(ctx).observables.value.set(undefined);
315
- await expect(missingWrite).rejects.toThrow(/null/);
316
- });
317
- test("a consumer lists the declaration itself", () => {
318
- const manifest = (0, manifest_1.buildPackageManifest)((0, index_1.definePackage)((pkg) => {
319
- pkg.packageId = (0, peer_id_1.newid)();
320
- pkg.version = "1.0.0";
321
- pkg.consumes(Skill, { optional: true });
322
- }));
323
- expect(manifest.consumes).toEqual([{ contractId, version: 1, optional: true }]);
324
- });
325
- test("refuses members that carry an implementation", () => {
326
- const base = { contractId, version: 1, name: "Bad" };
327
- expect(() => (0, index_1.declareContract)({ ...base, tools: [(0, index_1.defineTool)({ ...invokeShape, handler })] })).toThrow('tool "invoke" has a handler');
328
- expect(() => (0, index_1.declareContract)({
329
- ...base,
330
- observables: [
331
- (0, index_1.defineObservable)({
332
- name: "skill",
333
- description: "The catalog.",
334
- schema: catalogSchema,
335
- source: (0, index_1.observable)({ name: "a", slug: "a" }),
336
- }),
337
- ],
338
- })).toThrow('observable "skill" has a source');
339
- class NotesTable extends index_1.PackageTable {
340
- }
341
- expect(() => (0, index_1.declareContract)({
342
- ...base,
343
- tables: [(0, index_1.defineTable)({ ...Notes.definition, tableClass: NotesTable })],
344
- })).toThrow('table "Notes" has a tableClass');
345
- expect(() => (0, index_1.declareContract)({ ...base, contractId: "short" })).toThrow(/25-character/);
346
- expect(() => (0, index_1.declareContract)({ ...base, tools: [(0, index_1.declareTool)(invokeShape), (0, index_1.declareTool)(invokeShape)] })).toThrow(/twice/);
347
- expect(() => (0, index_1.declareTool)({ ...invokeShape, handler })).toThrow(/takes no handler/);
348
- expect(() => (0, index_1.declareObservable)({
349
- name: "skill",
350
- description: "The catalog.",
351
- schema: catalogSchema,
352
- source: (0, index_1.observable)(null),
353
- })).toThrow(/takes no source/);
354
- });
355
- test("recognizing an observable declaration does not claim it has a source", () => {
356
- const declared = (0, index_1.declareObservable)({
357
- name: "value",
358
- description: "Value.",
359
- schema: index_1.z.number(),
360
- });
361
- expect((0, observables_1.isPackageObservable)(declared)).toBe(true);
362
- expect((0, observables_1.isImplementedObservable)(declared)).toBe(false);
363
- if ((0, observables_1.isPackageObservable)(declared)) {
364
- // @ts-expect-error recognizing the observable kind does not add an implementation
365
- void declared.definition.source;
366
- }
367
- const implemented = (0, index_1.defineObservable)({
368
- name: "value",
369
- description: "Value.",
370
- schema: index_1.z.number(),
371
- source: (0, index_1.observable)(0),
372
- });
373
- expect((0, observables_1.isImplementedObservable)(implemented)).toBe(true);
374
- });
375
- });
376
- describe("implementContract", () => {
377
- test("only read-only declarations accept a source with a narrower value type", () => {
378
- const shape = {
379
- name: "mode",
380
- description: "The mode.",
381
- schema: index_1.z.enum(["on", "off"]),
382
- };
383
- const ReadOnly = (0, index_1.declareContract)({
384
- contractId: (0, peer_id_1.newid)(),
385
- version: 1,
386
- name: "Read-only mode",
387
- observables: [(0, index_1.declareObservable)(shape)],
388
- });
389
- const Writable = (0, index_1.declareContract)({
390
- contractId: (0, peer_id_1.newid)(),
391
- version: 1,
392
- name: "Writable mode",
393
- observables: [(0, index_1.declareObservable)({ ...shape, writable: true })],
394
- });
395
- const narrow = (0, index_1.observable)("on");
396
- // Read-only consumers can't give the narrower source a value outside its own type.
397
- (0, index_1.implementContract)(ReadOnly, { observables: { mode: narrow } });
398
- (0, index_1.implementContract)(Writable, {
399
- // @ts-expect-error this source's subscribers only accept "on", but consumers can write "off"
400
- observables: { mode: narrow },
401
- });
402
- (0, index_1.implementContract)(Writable, {
403
- // @ts-expect-error explicit type arguments must also reject a narrower writable source
404
- observables: { mode: narrow },
405
- });
406
- const invalid = {
407
- // @ts-expect-error a typed implementation must reject a narrower writable source too
408
- observables: { mode: narrow },
409
- };
410
- // Read-only sources keep their covariance even in a typed implementation.
411
- const readOnly = { observables: { mode: narrow } };
412
- (0, index_1.implementContract)(ReadOnly, readOnly);
413
- void invalid;
414
- const source = (0, index_1.observable)("on");
415
- const implemented = (0, index_1.implementContract)(Writable, { observables: { mode: source } });
416
- expect(implemented.observables[0].definition.source).toBe(source);
417
- // Explicit declaration type arguments keep valid implementations working too.
418
- (0, index_1.implementContract)(Writable, { observables: { mode: source } });
419
- expect(() => (0, index_1.implementContract)(Writable, {
420
- // @ts-expect-error the source map must still refuse undeclared names
421
- observables: { mode: source, extra: source },
422
- })).toThrow('declares no observable "extra"');
423
- });
424
- test("the manifest is the declared shape with the provider's handler and source", async () => {
425
- const Implemented = (0, index_1.implementContract)(Skill, {
426
- tools: { invoke: { handler, timeoutMs: 90_000 } },
427
- observables: { skill: catalog },
428
- });
429
- const [declaredTool] = Skill.declaration.tools;
430
- const [declaredObservable] = Skill.declaration.observables;
431
- const Same = (0, index_1.defineContract)({
432
- contractId,
433
- version: 1,
434
- name: "Skill",
435
- description: "A skill.",
436
- tables: [Notes],
437
- tools: [(0, index_1.defineTool)({ ...declaredTool.definition, timeoutMs: 90_000, handler })],
438
- observables: [
439
- (0, index_1.defineObservable)({ ...declaredObservable.definition, source: catalog }),
440
- ],
441
- events: [alert],
442
- });
443
- const manifest = manifestOf(Implemented);
444
- expect(manifest).toEqual(manifestOf(Same));
445
- const [tool] = manifest.provides[0].tools;
446
- expect(tool).toMatchObject({
447
- name: "invoke",
448
- suggestedAccessLevel: index_1.AccessLevel.Reader,
449
- authorityPropagation: "preserve",
450
- timeoutMs: 90_000,
451
- });
452
- expect(manifest.provides[0].observables?.[0].persistentVar).toMatchObject({
453
- scope: "device",
454
- defaultValue: { name: "Timers", slug: "timers" },
455
- });
456
- expect(() => (0, isolated_artifact_1.validateIsolatedPackageArtifact)({ manifest, providerSource: "void 0;" }, { strict: true })).not.toThrow();
457
- const { ctx } = fakeContext();
458
- // The declared schema parses the input, empty optional fields left out.
459
- await expect((0, index_1.runPackageTool)(Implemented.tools[0], { tool: "list", args: null }, ctx)).resolves.toEqual({ speech: "list" });
460
- });
461
- test("the declaration's event goes out on the implemented contract", async () => {
462
- const Implemented = (0, index_1.implementContract)(Skill, {
463
- tools: { invoke: handler },
464
- observables: { skill: catalog },
465
- });
466
- const calls = [];
467
- const ctx = {
468
- emitContractEvent: async (...args) => {
469
- calls.push(args);
470
- return null;
471
- },
472
- getOwnedPersistentVar: async () => null,
473
- watchOwnedPersistentVar: async () => () => undefined,
474
- };
475
- await (0, index_1.startPackage)((0, index_1.definePackage)((pkg) => {
476
- pkg.packageId = (0, peer_id_1.newid)();
477
- pkg.version = "1.0.0";
478
- pkg.provides(Implemented);
479
- }), ctx);
480
- await alert.emit({ title: "Done" });
481
- expect(calls).toEqual([[contractId, 1, "alert", { title: "Done" }]]);
482
- });
483
- test("refuses a missing, extra, or unknown member", () => {
484
- const observables = { skill: catalog };
485
- expect(() => (0, index_1.implementContract)(Skill, { tools: {}, observables })).toThrow('implement tool "invoke" with a handler');
486
- expect(() => (0, index_1.implementContract)(Skill, {
487
- tools: { invoke: handler, other: handler },
488
- observables,
489
- })).toThrow('declares no tool "other"');
490
- expect(() => (0, index_1.implementContract)(Skill, { tools: { invoke: handler }, observables: {} })).toThrow('implement observable "skill" with a source');
491
- expect(() => (0, index_1.implementContract)(Skill, {
492
- tools: { invoke: { handler, accessLevel: 0 } },
493
- observables,
494
- })).toThrow(/handler and timeoutMs only, not accessLevel/);
495
- expect(() => (0, index_1.implementContract)(Skill, {
496
- tools: { invoke: handler },
497
- observables,
498
- tables: {},
499
- })).toThrow(/tools, observables, exposes, and alsoImplements, not tables/);
500
- expect(() => (0, index_1.implementContract)((0, index_1.defineContract)({ contractId, version: 1, name: "X" }), {})).toThrow(/takes a declaration/);
501
- // Types follow the declaration.
502
- (0, index_1.implementContract)(Skill, {
503
- // @ts-expect-error speech is a string
504
- tools: { invoke: () => ({ speech: 1 }) },
505
- observables,
506
- });
507
- (0, index_1.implementContract)(Skill, {
508
- tools: { invoke: handler },
509
- // @ts-expect-error the source must hold the declared value
510
- observables: { skill: (0, index_1.observable)(3) },
511
- });
512
- });
513
- test("exposes other contracts the package provides, outside the contract's shape", () => {
514
- const News = (0, index_1.defineContract)({
515
- contractId: (0, peer_id_1.newid)(),
516
- version: 1,
517
- name: "News",
518
- tools: [
519
- (0, index_1.defineTool)({
520
- name: "headlines",
521
- usageDescription: "Recent headlines.",
522
- accessLevel: index_1.AccessLevel.Reader,
523
- inputSchema: index_1.z.object({}),
524
- outputSchema: index_1.z.object({}),
525
- handler: async () => ({}),
526
- }),
527
- ],
528
- });
529
- const members = { tools: { invoke: handler }, observables: { skill: catalog } };
530
- const Implemented = (0, index_1.implementContract)(Skill, { ...members, exposes: [News] });
531
- expect(Implemented.exposes).toEqual([{ contractId: News.contractId, version: 1 }]);
532
- // A reference names the contract as well as the contract itself does.
533
- expect((0, index_1.implementContract)(Skill, { ...members, exposes: [(0, index_1.contractRef)(News.contractId, 1)] }).exposes).toEqual(Implemented.exposes);
534
- const manifest = (0, manifest_1.buildPackageManifest)((0, index_1.definePackage)((pkg) => {
535
- pkg.packageId = packageId;
536
- pkg.version = "1.0.0";
537
- pkg.provides(News);
538
- pkg.provides(Implemented);
539
- }));
540
- expect(manifest.provides[1].exposes).toEqual([{ contractId: News.contractId, version: 1 }]);
541
- expect(manifest.provides[0]).not.toHaveProperty("exposes");
542
- // The validator fills in defaults, so it checks a copy.
543
- expect(() => (0, isolated_artifact_1.validateIsolatedPackageArtifact)({ manifest: JSON.parse(JSON.stringify(manifest)), providerSource: "void 0;" }, { strict: true })).not.toThrow();
544
- // Everything but `exposes` is the contract as implemented without it.
545
- const { exposes: _exposes, ...shape } = manifest.provides[1];
546
- expect(shape).toEqual(manifestOf((0, index_1.implementContract)(Skill, members)).provides[0]);
547
- // An implementation without `exposes` carries none.
548
- expect((0, index_1.implementContract)(Skill, members)).not.toHaveProperty("exposes");
549
- });
550
- test("refuses exposing itself, a contract twice, or one the package doesn't provide", () => {
551
- const members = { tools: { invoke: handler }, observables: { skill: catalog } };
552
- const other = { contractId: (0, peer_id_1.newid)(), version: 1 };
553
- expect(() => (0, index_1.implementContract)(Skill, { ...members, exposes: [Skill] })).toThrow(/can't expose itself/);
554
- expect(() => (0, index_1.implementContract)(Skill, { ...members, exposes: [other, other] })).toThrow(/exposes .* twice/);
555
- expect(() => (0, index_1.implementContract)(Skill, { ...members, exposes: other })).toThrow(/exposes must be a list of contracts/);
556
- expect(() => (0, index_1.implementContract)(Skill, { ...members, exposes: [{ contractId: "x", version: 1 }] })).toThrow(/with an id and version/);
557
- expect(() => (0, index_1.definePackage)((pkg) => {
558
- pkg.packageId = (0, peer_id_1.newid)();
559
- pkg.version = "1.0.0";
560
- pkg.provides((0, index_1.implementContract)(Skill, { ...members, exposes: [other] }));
561
- })).toThrow(/exposes .*, which the package doesn't provide; add it with pkg.provides/);
562
- });
563
- test("defineContract and pkg.provides refuse what isn't implemented", () => {
564
- const base = { contractId, version: 1, name: "X" };
565
- expect(() => (0, index_1.defineContract)({ ...base, tools: [Skill.declaration.tools[0]] })).toThrow(/has no handler; .*declareContract and implementContract/);
566
- expect(() => (0, index_1.defineContract)({ ...base, observables: [Skill.declaration.observables[0]] })).toThrow(/has no source/);
567
- expect(() => (0, index_1.definePackage)((pkg) => {
568
- pkg.packageId = (0, peer_id_1.newid)();
569
- pkg.version = "1.0.0";
570
- pkg.provides(Skill);
571
- })).toThrow(/implementContract first/);
572
- });
573
- });
@@ -1 +0,0 @@
1
- export {};