nervur 0.21.5 → 0.22.0

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 (334) hide show
  1. package/README.md +215 -158
  2. package/dist/browser.js +4 -3
  3. package/dist/cli.js +16 -0
  4. package/dist/{being → core/being}/being.js +10 -0
  5. package/dist/{being → core/being}/faculty.js +5 -2
  6. package/dist/{being → core/being}/index.d.ts +1 -1
  7. package/dist/{being → core/being}/index.js +1 -1
  8. package/dist/{being → core/being}/kind.d.ts +2 -0
  9. package/dist/{being → core/being}/kind.js +6 -0
  10. package/dist/{being → core/being}/types.js +1 -1
  11. package/dist/{browser → core/browser}/index.d.ts +6 -5
  12. package/dist/{browser → core/browser}/index.js +10 -10
  13. package/dist/{browser → core/browser}/worker.d.ts +2 -3
  14. package/dist/{browser → core/browser}/worker.js +8 -11
  15. package/dist/{cli → core/cli}/command.d.ts +4 -4
  16. package/dist/{cli → core/cli}/command.js +116 -66
  17. package/dist/{cli → core/cli}/edge.js +4 -2
  18. package/dist/core/cli/harbor.d.ts +25 -0
  19. package/dist/{cli → core/cli}/harbor.js +45 -33
  20. package/dist/{contract → core/contract}/index.d.ts +6 -5
  21. package/dist/{contract → core/contract}/index.js +8 -9
  22. package/dist/core/contract/link.d.ts +4 -0
  23. package/dist/core/contract/link.js +45 -0
  24. package/dist/core/edge/index.d.ts +164 -0
  25. package/dist/core/edge/index.js +739 -0
  26. package/dist/core/edge/kit.d.ts +2 -0
  27. package/dist/core/edge/kit.js +2 -0
  28. package/dist/core/git/http.d.ts +6 -0
  29. package/dist/core/git/http.js +102 -0
  30. package/dist/core/git/index.d.ts +5 -0
  31. package/dist/core/git/index.js +10 -0
  32. package/dist/core/git/object.d.ts +40 -0
  33. package/dist/core/git/object.js +103 -0
  34. package/dist/core/git/pack.d.ts +9 -0
  35. package/dist/core/git/pack.js +171 -0
  36. package/dist/core/git/store.d.ts +23 -0
  37. package/dist/core/git/store.js +120 -0
  38. package/dist/core/git/zlib.d.ts +6 -0
  39. package/dist/core/git/zlib.js +210 -0
  40. package/dist/core/harbor/carrying.d.ts +51 -0
  41. package/dist/core/harbor/carrying.js +69 -0
  42. package/dist/core/harbor/catalogue.d.ts +33 -0
  43. package/dist/core/harbor/catalogue.js +365 -0
  44. package/dist/core/harbor/dna.d.ts +13 -0
  45. package/dist/core/harbor/dna.js +120 -0
  46. package/dist/{harbor → core/harbor}/dock.d.ts +22 -13
  47. package/dist/core/harbor/dock.js +381 -0
  48. package/dist/core/harbor/harbor.d.ts +16 -0
  49. package/dist/core/harbor/harbor.js +438 -0
  50. package/dist/core/harbor/index.d.ts +11 -0
  51. package/dist/{harbor → core/harbor}/index.js +5 -5
  52. package/dist/core/harbor/memory.d.ts +10 -0
  53. package/dist/core/harbor/memory.js +25 -0
  54. package/dist/{harbor → core/harbor}/package.d.ts +0 -1
  55. package/dist/{harbor → core/harbor}/package.js +9 -9
  56. package/dist/core/harbor/probe.d.ts +22 -0
  57. package/dist/core/harbor/probe.js +15 -0
  58. package/dist/core/harbor/registry.d.ts +15 -0
  59. package/dist/{harbor → core/harbor}/registry.js +26 -10
  60. package/dist/core/harbor/root-line.d.ts +7 -0
  61. package/dist/core/harbor/root-line.js +9 -0
  62. package/dist/{harbor → core/harbor}/terrain.d.ts +9 -6
  63. package/dist/{harbor → core/harbor}/terrain.js +5 -4
  64. package/dist/core/http/index.d.ts +2 -0
  65. package/dist/{http → core/http}/index.js +3 -5
  66. package/dist/{line → core/line}/answer.d.ts +2 -2
  67. package/dist/{line → core/line}/frame.d.ts +0 -5
  68. package/dist/{line → core/line}/frame.js +0 -4
  69. package/dist/core/line/ground.js +7 -0
  70. package/dist/core/line/index.d.ts +4 -0
  71. package/dist/core/line/index.js +8 -0
  72. package/dist/core/line/web.d.ts +12 -0
  73. package/dist/{line → core/line}/web.js +13 -77
  74. package/dist/{node → core/node}/index.d.ts +2 -15
  75. package/dist/core/node/index.js +124 -0
  76. package/dist/{pointer → core/pointer}/bodies.d.ts +7 -5
  77. package/dist/core/pointer/bodies.js +118 -0
  78. package/dist/core/pointer/index.d.ts +2 -0
  79. package/dist/{pointer → core/pointer}/index.js +1 -1
  80. package/dist/{pointer → core/pointer}/world.d.ts +13 -9
  81. package/dist/{pointer → core/pointer}/world.js +31 -16
  82. package/dist/{proof → core/proof}/contracts.d.ts +6 -2
  83. package/dist/{proof → core/proof}/contracts.js +11 -10
  84. package/dist/core/proof/index.d.ts +3 -0
  85. package/dist/{proof → core/proof}/index.js +2 -2
  86. package/dist/core/proof/law.d.ts +25 -0
  87. package/dist/core/proof/law.js +715 -0
  88. package/dist/{tcp → core/tcp}/index.d.ts +7 -4
  89. package/dist/{tcp → core/tcp}/index.js +11 -62
  90. package/dist/{ward/ward.d.ts → core/ward/house.d.ts} +24 -10
  91. package/dist/core/ward/house.js +473 -0
  92. package/dist/core/ward/index.d.ts +5 -0
  93. package/dist/core/ward/index.js +7 -0
  94. package/dist/{ward → core/ward}/partition.d.ts +1 -0
  95. package/dist/{ward → core/ward}/stance.d.ts +2 -2
  96. package/dist/{ward → core/ward}/stance.js +5 -2
  97. package/dist/{ward/ward-being.d.ts → core/ward/ward.d.ts} +14 -6
  98. package/dist/core/ward/ward.js +140 -0
  99. package/dist/core.d.ts +10 -0
  100. package/dist/core.js +19 -0
  101. package/dist/defaults/dock/index.d.ts +4 -0
  102. package/dist/defaults/dock/index.js +11 -0
  103. package/dist/defaults/index.d.ts +5 -0
  104. package/dist/defaults/index.js +10 -0
  105. package/dist/defaults/memory/index.d.ts +12 -0
  106. package/dist/defaults/memory/index.js +39 -0
  107. package/dist/defaults/tcp/index.d.ts +16 -0
  108. package/dist/defaults/tcp/index.js +82 -0
  109. package/dist/defaults/ward/index.d.ts +4 -0
  110. package/dist/defaults/ward/index.js +11 -0
  111. package/dist/defaults/web/index.d.ts +15 -0
  112. package/dist/defaults/web/index.js +90 -0
  113. package/dist/edge.js +4 -3
  114. package/dist/index.d.ts +1 -8
  115. package/dist/index.js +13 -18
  116. package/dist/kit.d.ts +4 -0
  117. package/dist/kit.js +12 -0
  118. package/dist/node.js +4 -3
  119. package/package.json +22 -18
  120. package/src/browser.ts +4 -3
  121. package/src/cli.ts +15 -0
  122. package/src/{being → core/being}/being.ts +4 -0
  123. package/src/{being → core/being}/faculty.ts +5 -2
  124. package/src/{being → core/being}/index.ts +1 -1
  125. package/src/{being → core/being}/kind.ts +7 -0
  126. package/src/{being → core/being}/types.ts +1 -1
  127. package/src/{browser → core/browser}/index.ts +16 -13
  128. package/src/{browser → core/browser}/worker.ts +11 -14
  129. package/src/{cli → core/cli}/command.ts +113 -66
  130. package/src/{cli → core/cli}/edge.ts +4 -2
  131. package/src/{cli → core/cli}/harbor.ts +48 -31
  132. package/src/{contract → core/contract}/index.ts +14 -14
  133. package/src/core/contract/link.ts +58 -0
  134. package/src/core/edge/index.ts +865 -0
  135. package/src/core/git/http.ts +103 -0
  136. package/src/core/git/index.ts +10 -0
  137. package/src/core/git/object.ts +116 -0
  138. package/src/core/git/pack.ts +147 -0
  139. package/src/core/git/store.ts +122 -0
  140. package/src/core/git/zlib.ts +197 -0
  141. package/src/core/harbor/carrying.ts +124 -0
  142. package/src/core/harbor/catalogue.ts +386 -0
  143. package/src/core/harbor/dna.ts +116 -0
  144. package/src/core/harbor/dock.ts +420 -0
  145. package/src/core/harbor/harbor.ts +433 -0
  146. package/src/core/harbor/index.ts +14 -0
  147. package/src/core/harbor/memory.ts +31 -0
  148. package/src/{harbor → core/harbor}/package.ts +15 -15
  149. package/src/core/harbor/probe.ts +39 -0
  150. package/src/{harbor → core/harbor}/registry.ts +28 -11
  151. package/src/core/harbor/root-line.ts +19 -0
  152. package/src/{harbor → core/harbor}/terrain.ts +14 -7
  153. package/src/{http → core/http}/index.ts +5 -8
  154. package/src/{line → core/line}/answer.ts +3 -2
  155. package/src/{line → core/line}/frame.ts +0 -5
  156. package/src/core/line/ground.ts +18 -0
  157. package/src/core/line/index.ts +8 -0
  158. package/src/{line → core/line}/web.ts +1 -105
  159. package/src/core/node/index.ts +139 -0
  160. package/src/core/pointer/bodies.ts +122 -0
  161. package/src/core/pointer/index.ts +4 -0
  162. package/src/{pointer → core/pointer}/world.ts +45 -21
  163. package/src/{proof → core/proof}/contracts.ts +18 -13
  164. package/src/{proof → core/proof}/index.ts +3 -3
  165. package/src/core/proof/law.ts +742 -0
  166. package/src/{stand → core/stand}/stand.ts +2 -2
  167. package/src/{tcp → core/tcp}/index.ts +17 -74
  168. package/src/core/ward/house.ts +524 -0
  169. package/src/core/ward/index.ts +7 -0
  170. package/src/{ward → core/ward}/partition.ts +5 -1
  171. package/src/{ward → core/ward}/stance.ts +5 -2
  172. package/src/core/ward/ward.ts +166 -0
  173. package/src/core.ts +55 -0
  174. package/src/defaults/dock/index.ts +12 -0
  175. package/src/defaults/index.ts +10 -0
  176. package/src/defaults/memory/index.ts +50 -0
  177. package/src/defaults/tcp/index.ts +89 -0
  178. package/src/defaults/ward/index.ts +12 -0
  179. package/src/defaults/web/index.ts +97 -0
  180. package/src/edge.ts +4 -3
  181. package/src/index.ts +13 -50
  182. package/src/kit.ts +15 -0
  183. package/src/node.ts +4 -3
  184. package/dist/cli/harbor.d.ts +0 -16
  185. package/dist/cli/main.js +0 -14
  186. package/dist/edge/index.d.ts +0 -81
  187. package/dist/edge/index.js +0 -400
  188. package/dist/harbor/carrying.d.ts +0 -17
  189. package/dist/harbor/carrying.js +0 -38
  190. package/dist/harbor/catalogue.d.ts +0 -28
  191. package/dist/harbor/catalogue.js +0 -109
  192. package/dist/harbor/dock.js +0 -236
  193. package/dist/harbor/harbor.d.ts +0 -45
  194. package/dist/harbor/harbor.js +0 -347
  195. package/dist/harbor/index.d.ts +0 -11
  196. package/dist/harbor/probe.d.ts +0 -18
  197. package/dist/harbor/probe.js +0 -15
  198. package/dist/harbor/registry.d.ts +0 -10
  199. package/dist/harbor/relay.d.ts +0 -15
  200. package/dist/harbor/relay.js +0 -406
  201. package/dist/harbor/root-line.d.ts +0 -9
  202. package/dist/harbor/root-line.js +0 -38
  203. package/dist/harbor/store.d.ts +0 -13
  204. package/dist/harbor/store.js +0 -53
  205. package/dist/http/index.d.ts +0 -4
  206. package/dist/line/ground.js +0 -9
  207. package/dist/line/index.d.ts +0 -5
  208. package/dist/line/index.js +0 -9
  209. package/dist/line/push.d.ts +0 -7
  210. package/dist/line/push.js +0 -92
  211. package/dist/line/web.d.ts +0 -30
  212. package/dist/node/index.js +0 -236
  213. package/dist/pointer/bodies.js +0 -80
  214. package/dist/pointer/index.d.ts +0 -2
  215. package/dist/proof/index.d.ts +0 -3
  216. package/dist/proof/law.d.ts +0 -90
  217. package/dist/proof/law.js +0 -591
  218. package/dist/tcp/frame.d.ts +0 -25
  219. package/dist/tcp/frame.js +0 -64
  220. package/dist/ward/index.d.ts +0 -6
  221. package/dist/ward/index.js +0 -8
  222. package/dist/ward/pilot.d.ts +0 -8
  223. package/dist/ward/pilot.js +0 -50
  224. package/dist/ward/ward-being.js +0 -82
  225. package/dist/ward/ward.js +0 -290
  226. package/src/cli/main.ts +0 -13
  227. package/src/edge/index.ts +0 -490
  228. package/src/harbor/carrying.ts +0 -56
  229. package/src/harbor/catalogue.ts +0 -134
  230. package/src/harbor/dock.ts +0 -265
  231. package/src/harbor/harbor.ts +0 -381
  232. package/src/harbor/index.ts +0 -14
  233. package/src/harbor/probe.ts +0 -34
  234. package/src/harbor/relay.ts +0 -418
  235. package/src/harbor/root-line.ts +0 -39
  236. package/src/harbor/store.ts +0 -69
  237. package/src/line/ground.ts +0 -19
  238. package/src/line/index.ts +0 -9
  239. package/src/line/push.ts +0 -112
  240. package/src/node/index.ts +0 -241
  241. package/src/pointer/bodies.ts +0 -82
  242. package/src/pointer/index.ts +0 -4
  243. package/src/proof/law.ts +0 -591
  244. package/src/ward/index.ts +0 -8
  245. package/src/ward/pilot.ts +0 -50
  246. package/src/ward/ward-being.ts +0 -103
  247. package/src/ward/ward.ts +0 -328
  248. /package/dist/{cli/main.d.ts → cli.d.ts} +0 -0
  249. /package/dist/{being → core/being}/being.d.ts +0 -0
  250. /package/dist/{being → core/being}/digest.d.ts +0 -0
  251. /package/dist/{being → core/being}/digest.js +0 -0
  252. /package/dist/{being → core/being}/faculty.d.ts +0 -0
  253. /package/dist/{being → core/being}/types.d.ts +0 -0
  254. /package/dist/{being → core/being}/words.d.ts +0 -0
  255. /package/dist/{being → core/being}/words.js +0 -0
  256. /package/dist/{cli → core/cli}/edge.d.ts +0 -0
  257. /package/dist/{crypto → core/crypto}/aes.d.ts +0 -0
  258. /package/dist/{crypto → core/crypto}/aes.js +0 -0
  259. /package/dist/{crypto → core/crypto}/bytes.d.ts +0 -0
  260. /package/dist/{crypto → core/crypto}/bytes.js +0 -0
  261. /package/dist/{crypto → core/crypto}/ed25519.d.ts +0 -0
  262. /package/dist/{crypto → core/crypto}/ed25519.js +0 -0
  263. /package/dist/{crypto → core/crypto}/hash.d.ts +0 -0
  264. /package/dist/{crypto → core/crypto}/hash.js +0 -0
  265. /package/dist/{crypto → core/crypto}/index.d.ts +0 -0
  266. /package/dist/{crypto → core/crypto}/index.js +0 -0
  267. /package/dist/{crypto → core/crypto}/json.d.ts +0 -0
  268. /package/dist/{crypto → core/crypto}/json.js +0 -0
  269. /package/dist/{crypto → core/crypto}/mlkem.d.ts +0 -0
  270. /package/dist/{crypto → core/crypto}/mlkem.js +0 -0
  271. /package/dist/{crypto → core/crypto}/subtle.d.ts +0 -0
  272. /package/dist/{crypto → core/crypto}/subtle.js +0 -0
  273. /package/dist/{crypto → core/crypto}/x25519.d.ts +0 -0
  274. /package/dist/{crypto → core/crypto}/x25519.js +0 -0
  275. /package/dist/{folder → core/folder}/index.d.ts +0 -0
  276. /package/dist/{folder → core/folder}/index.js +0 -0
  277. /package/dist/{http → core/http}/websocket.d.ts +0 -0
  278. /package/dist/{http → core/http}/websocket.js +0 -0
  279. /package/dist/{line → core/line}/answer.js +0 -0
  280. /package/dist/{line → core/line}/ground.d.ts +0 -0
  281. /package/dist/{proof → core/proof}/expect.d.ts +0 -0
  282. /package/dist/{proof → core/proof}/expect.js +0 -0
  283. /package/dist/{quo → core/quo}/address.d.ts +0 -0
  284. /package/dist/{quo → core/quo}/address.js +0 -0
  285. /package/dist/{quo → core/quo}/door.d.ts +0 -0
  286. /package/dist/{quo → core/quo}/door.js +0 -0
  287. /package/dist/{quo → core/quo}/index.d.ts +0 -0
  288. /package/dist/{quo → core/quo}/index.js +0 -0
  289. /package/dist/{quo → core/quo}/invitation.d.ts +0 -0
  290. /package/dist/{quo → core/quo}/invitation.js +0 -0
  291. /package/dist/{quo → core/quo}/keys.d.ts +0 -0
  292. /package/dist/{quo → core/quo}/keys.js +0 -0
  293. /package/dist/{quo → core/quo}/payload.d.ts +0 -0
  294. /package/dist/{quo → core/quo}/payload.js +0 -0
  295. /package/dist/{quo → core/quo}/relations.d.ts +0 -0
  296. /package/dist/{quo → core/quo}/relations.js +0 -0
  297. /package/dist/{quo → core/quo}/reply.d.ts +0 -0
  298. /package/dist/{quo → core/quo}/reply.js +0 -0
  299. /package/dist/{quo → core/quo}/seal.d.ts +0 -0
  300. /package/dist/{quo → core/quo}/seal.js +0 -0
  301. /package/dist/{quo → core/quo}/standing.d.ts +0 -0
  302. /package/dist/{quo → core/quo}/standing.js +0 -0
  303. /package/dist/{ward → core/ward}/allowance.d.ts +0 -0
  304. /package/dist/{ward → core/ward}/allowance.js +0 -0
  305. /package/dist/{ward → core/ward}/cells.d.ts +0 -0
  306. /package/dist/{ward → core/ward}/cells.js +0 -0
  307. /package/dist/{ward → core/ward}/partition.js +0 -0
  308. /package/src/{being → core/being}/digest.ts +0 -0
  309. /package/src/{being → core/being}/words.ts +0 -0
  310. /package/src/{crypto → core/crypto}/aes.ts +0 -0
  311. /package/src/{crypto → core/crypto}/bytes.ts +0 -0
  312. /package/src/{crypto → core/crypto}/ed25519.ts +0 -0
  313. /package/src/{crypto → core/crypto}/hash.ts +0 -0
  314. /package/src/{crypto → core/crypto}/index.ts +0 -0
  315. /package/src/{crypto → core/crypto}/json.ts +0 -0
  316. /package/src/{crypto → core/crypto}/mlkem.ts +0 -0
  317. /package/src/{crypto → core/crypto}/subtle.ts +0 -0
  318. /package/src/{crypto → core/crypto}/x25519.ts +0 -0
  319. /package/src/{folder → core/folder}/index.ts +0 -0
  320. /package/src/{http → core/http}/websocket.ts +0 -0
  321. /package/src/{proof → core/proof}/expect.ts +0 -0
  322. /package/src/{quo → core/quo}/address.ts +0 -0
  323. /package/src/{quo → core/quo}/door.ts +0 -0
  324. /package/src/{quo → core/quo}/index.ts +0 -0
  325. /package/src/{quo → core/quo}/invitation.ts +0 -0
  326. /package/src/{quo → core/quo}/keys.ts +0 -0
  327. /package/src/{quo → core/quo}/payload.ts +0 -0
  328. /package/src/{quo → core/quo}/relations.ts +0 -0
  329. /package/src/{quo → core/quo}/reply.ts +0 -0
  330. /package/src/{quo → core/quo}/seal.ts +0 -0
  331. /package/src/{quo → core/quo}/standing.ts +0 -0
  332. /package/src/{stand → core/stand}/main.ts +0 -0
  333. /package/src/{ward → core/ward}/allowance.ts +0 -0
  334. /package/src/{ward → core/ward}/cells.ts +0 -0
package/README.md CHANGED
@@ -21,42 +21,62 @@ a disk and needs Node's file system.
21
21
  ## A harbor where you run
22
22
 
23
23
  ```js
24
+ import { readFile } from 'node:fs/promises';
24
25
  import { Harbor } from 'nervur';
25
- import * as greetings from './greetings.js';
26
26
 
27
- const harbor = await Harbor.open({ modules: [greetings] });
27
+ const harbor = await Harbor.open();
28
+ await harbor.ask({ method: 'stand' });
29
+ const source = await readFile('./greetings.js', 'utf8');
30
+ await harbor.ask({ method: 'ask', args: { being: 'catalogue', method: 'add', args: { source } } });
28
31
  ```
29
32
 
33
+ A harbor is asked and nothing else. `harbor.ask` takes one root request,
34
+ `{ ward?, method?, args? }`, asks the box ward, or the hosted ward named,
35
+ as its root, and answers one plain JSON value. `arrive`, `holds` and
36
+ `close` are the rest of what a program holds of a harbor.
37
+
30
38
  With no terrain, the harbor picks its ground's bodies itself. In Node it
31
39
  keeps itself in a folder, `where` if you name one, else `$NERVUR_DIR`,
32
- else `~/.nervur`, speaks TCP and, where you open them, the web and Web
33
- Push, and serves its root line, so the `nervur` command below asks it
34
- while it stands. A folder opens in one run at a time. Bundled for a
35
- browser, in a page or a worker, it keeps itself in the IndexedDB
36
- database `where` names, else `nervur`, its seed sealed under a key the
37
- browser never hands out, speaks the web, and opens in one run at a time.
40
+ else `~/.nervur`, speaks TCP and the web where you open them,
41
+ and serves its root line, so the `nervur` command below asks it while it
42
+ stands. A folder opens in one run at a time. Bundled for a browser, in a
43
+ page or a worker, it keeps itself in the IndexedDB database `where`
44
+ names, else `nervur`, its seed sealed under a key the browser never hands
45
+ out, speaks the web where you open it, and opens in one run at a time.
38
46
  On Cloudflare Workers it is one Durable Object of many a worker carries,
47
+ running in a child worker the object loads for the commit `live` names,
39
48
  answering Quo at `/<name>/quo` on whatever host reaches it, and asking
40
- over TCP and the web. Anywhere
41
- else it lives as long as its process and speaks the web. Hand in a
42
- terrain, as below, and that one is used.
49
+ over TCP and the web. Anywhere else it lives as long as its process and
50
+ speaks the web where you open it. Hand in a terrain, as below, and that
51
+ one is used.
52
+
53
+ Nothing enters a harbor unasked. A new harbor holds its catalogue alone,
54
+ and a carrier stands only once the root opens it:
55
+
56
+ ```js
57
+ await harbor.ask({ method: 'open', args: { key: 'web', class: 'org.nervur.web' } });
58
+ ```
43
59
 
44
60
  ## A harbor on the edge
45
61
 
46
62
  An edge harbor is born on your machine and carried there, so you pilot it
47
- from your own harbor, as you pilot one on a server. One worker carries as
48
- many harbors as you pack into it, each a Durable Object by its name,
49
- answering at `/<name>/quo`. The worker is a folder of its own, an ES
50
- module project (`"type": "module"` in its `package.json`), holding the
51
- worker and its `wrangler.toml`:
63
+ from your own harbor, as you pilot one on a server, and you move its code
64
+ the same way, with no deploy. One worker carries as many harbors as you
65
+ pack into it, each a Durable Object by its name, answering at
66
+ `/<name>/quo`. The worker is a shell: it keeps each harbor's storage and
67
+ its web door, and runs the harbor, the kit and the modules its `live`
68
+ commit holds, in a child worker Cloudflare's Worker Loader makes of them.
69
+ The worker is a folder of its own, an ES module project (`"type":
70
+ "module"` in its `package.json`), holding the worker and its
71
+ `wrangler.toml`:
52
72
 
53
73
  ```js
54
74
  // worker.js
55
- import { harborObject, harborWorker } from 'nervur/edge';
75
+ import { harborShell, harborWorker } from 'nervur/edge';
76
+ import kit from 'nervur/edge/kit';
56
77
  import pack from './pack.edge.json';
57
- import * as greetings from './greetings.js';
58
78
 
59
- export const Harbor = harborObject({ modules: [greetings], pack });
79
+ export const Harbor = harborShell({ kit, pack });
60
80
  export default harborWorker();
61
81
  ```
62
82
 
@@ -73,8 +93,14 @@ class_name = "Harbor"
73
93
  [[migrations]]
74
94
  tag = "v1"
75
95
  new_sqlite_classes = ["Harbor"]
96
+
97
+ [[worker_loaders]]
98
+ binding = "LOADER"
76
99
  ```
77
100
 
101
+ The Worker Loader is in beta, and on Cloudflare it needs the Workers Paid
102
+ plan. `wrangler dev` runs it on your machine at no cost.
103
+
78
104
  Make the harbor and set it up with the command, from that folder, naming
79
105
  where the edge will reach it:
80
106
 
@@ -95,44 +121,43 @@ nervur edge dev ./pack.edge.json main --dir ./harbor
95
121
  `edge dev` packs the harbor as `main` into `pack.edge.json`, beside any
96
122
  harbor packed there before, and runs your `wrangler dev`, keeping the
97
123
  objects' storage and a secret of its own in `.nervur-edge`, so the
98
- harbor stands again each time you run it. The first time its object
99
- starts, the harbor lands in its storage; after that the storage is the
100
- harbor, and a new deploy leaves it be. Then, from your own harbor:
124
+ harbor stands again each time you run it. The harbor's code travels in
125
+ its package, as its DNA. The first time its object starts, the harbor
126
+ lands in its storage; after that the storage is the harbor, and a new
127
+ deploy leaves it be. Then, from your own harbor:
101
128
 
102
129
  ```sh
103
130
  nervur pilot edge '<the owner invitation>' --dir ./mine
104
131
  nervur host shop --via edge --dir ./mine
132
+ nervur module add ./greetings.js --via edge --dir ./mine
105
133
  ```
106
134
 
135
+ A module added, or `live` moved back, runs on the edge at once: the
136
+ worker loads the next child for the commit `live` names, with no deploy.
137
+ A module that does not load there is refused with its reason, and `live`
138
+ stays where it was.
139
+
107
140
  For Cloudflare, keep one secret for the worker, `wrangler secret put
108
141
  NERVUR_SECRET`, and hold the same one as `NERVUR_SECRET` in your shell.
109
142
  Name each harbor's address with `reach`, pack each with
110
143
  `nervur edge pack ./pack.edge.json <name> --dir <its folder>`, and
111
144
  `wrangler deploy`. A pack holds every seed sealed under that secret, so
112
145
  it ships in the bundle and opens nowhere else, and a new harbor is a new
113
- deploy, never a new secret.
114
-
115
- `pilot` opens the web carrier where the invitation names a web address.
116
- A harbor may also be born on the edge, under a name `born` allows, with
117
- a seed of its own sealed the same way, and `stood` runs the worker's own
118
- code on it as root. A name the pack does not hold and `born` does not
119
- allow answers 404, so a stranger's request mints nothing:
120
-
121
- ```js
122
- export const Harbor = harborObject({
123
- modules: [greetings],
124
- pack,
125
- born: (name) => name === 'shop',
126
- stood: async (harbor, name) => {
127
- // runs once the harbor stands
128
- },
129
- });
130
- ```
146
+ deploy, never a new secret. `pilot` opens the web carrier where the
147
+ invitation names a web address. A name the pack does not hold answers
148
+ 404, so a stranger's request mints nothing.
131
149
 
132
150
  ## A world in one process
133
151
 
152
+ A module is one file of JavaScript that imports nothing but `nervur`:
153
+
134
154
  ```js
135
- import { Being, Faculty, World } from 'nervur';
155
+ // greetings.js
156
+ import { Being, Faculty } from 'nervur';
157
+
158
+ // Its name, as a kind is named, and its version.
159
+ export const module = 'org.example.greetings';
160
+ export const version = '1.0.0';
136
161
 
137
162
  // A contract, and a faculty that fulfils it. Every class names its kind.
138
163
  class Clock extends Faculty {
@@ -157,16 +182,22 @@ class Greeter extends Being {
157
182
  }
158
183
  }
159
184
 
160
- // The module these classes are: its name, its version, its classes.
161
- const greetings = { module: 'org.example.greetings', version: '1.0.0', classes: [SystemTime, Greeter] };
185
+ export const classes = [SystemTime, Greeter];
186
+ ```
162
187
 
163
- // A harbor whose terrain can load that module, and whose catalogue runs it.
164
- const world = new World();
165
- const harbor = await world.harbor('home', [greetings]);
166
- await harbor.root('ask', { being: 'catalogue', method: 'add', args: { from: 'org.example.greetings' } });
167
- await harbor.root('open', { key: 'clock', class: 'org.example.system-time' });
168
- await harbor.root('host', { ward: 'alice' });
169
- await harbor.ward('alice').root('boot', { key: 'greeter', class: 'org.example.greeter' });
188
+ A harbor's catalogue takes its source, commits it, and runs it:
189
+
190
+ ```js
191
+ import { readFile } from 'node:fs/promises';
192
+ import { DEFAULTS, World } from 'nervur';
193
+
194
+ const world = new World(DEFAULTS);
195
+ const harbor = await world.harbor('home');
196
+ const source = await readFile('./greetings.js', 'utf8');
197
+ await harbor.ask({ method: 'ask', args: { being: 'catalogue', method: 'add', args: { source } } });
198
+ await harbor.ask({ method: 'open', args: { key: 'clock', class: 'org.example.system-time' } });
199
+ await harbor.ask({ method: 'host', args: { ward: 'alice' } });
200
+ await harbor.ask({ ward: 'alice', method: 'boot', args: { key: 'greeter', class: 'org.example.greeter' } });
170
201
  ```
171
202
 
172
203
  A second harbor in the same world takes an invitation on the greeter and
@@ -187,57 +218,117 @@ domain: `com.acme.shop` stands `com.acme.*` kinds. A harbor refuses a
187
218
  module in which one kind names two classes or two contracts, or names a
188
219
  class and a contract.
189
220
 
190
- ## Modules
191
-
192
- Your classes come in modules: `{ module, version, classes }`, a module
193
- named as a kind is. A harbor's catalogue is a faculty of its own, and her
194
- cells name the modules the harbor runs. `add { from }` runs the module
195
- the terrain's loader finds there, and `remove { module }` stops one no
196
- being stands on. A restart loads every module she names and refuses to
197
- stand when one is missing. A module found at a new version wakes, and
198
- `modules` shows the version kept and the version running.
221
+ ## The DNA
222
+
223
+ Your classes come in modules, each one file exporting `module`, `version`
224
+ and `classes`, a module named as a kind is. A harbor's catalogue keeps
225
+ its code as a git repository, its DNA, from its first moment: a commit
226
+ holds `modules/<module>.js` for every module the harbor runs, and `live`
227
+ names the commit that stands. Her asks, the root's and an owner's:
228
+
229
+ - `add { source, name? }` commits a module's source on `live` and moves
230
+ `live` to it; the same module again takes its new version.
231
+ - `remove { module }` commits its file away, refused while a being or a
232
+ ward stands on its kinds.
233
+ - `live { commit? }` moves `live` to a commit or a fetched ref, or, with
234
+ none, names the commit that stands. Moving `live` back is a rollback.
235
+ - `log` walks back from `live`. `modules` shows what `live` runs, and why
236
+ a module does not.
237
+ - `origin { url }` names a git repository over HTTP, and `fetch` reads
238
+ every ref it has and all they reach into the harbor, touching nothing
239
+ there.
240
+
241
+ Moving `live` runs the commit's modules together, or refuses them with
242
+ the reason and leaves `live` where it was. Once they run, every being a
243
+ new class resolves is born again of it, on the cells she keeps. A
244
+ restart stands `live` from what the harbor keeps, with no network. The
245
+ objects live in the harbor's memory, sealed as everything else is, so a
246
+ harbor carried to another ground carries its DNA. Real `git` reads a
247
+ harbor's objects, and a harbor reads what `git` serves.
199
248
 
200
249
  ## The onion
201
250
 
202
251
  A harbor is one package. Only the seed and the terrain's bodies, its
203
- loader among them, stand outside it.
252
+ loader among them, stand outside it. It stands in three levels, and each
253
+ level stands the next and leaves it alone.
254
+
255
+ 1. **The boot**, the harbor's own, from the library's core alone. The
256
+ terrain gives the seed, which opens its memory; the terrain keeps that
257
+ memory as sealed bytes and reads none of it. The box ward unpacks, the
258
+ catalogue stands and runs every module `live` holds, every registry the
259
+ catalogue resolves stands, and then the dock, of her class. The door is
260
+ hers from here, and `Harbor.open()` returns. It is one call, and no ask
261
+ makes it.
262
+ 2. **The dock's**, on her `stand` ask. She stands every other faculty,
263
+ registries first, then memory faculties, then the rest; hands her
264
+ routes to the carrier; and stands every ward she hosts, under the seed
265
+ she keeps for it.
266
+ 3. **Each ward's beings**, stood by nothing. A being's cells, occupants
267
+ and standings are her ward's rows, so she is born from her row when an
268
+ ask reaches her, once for the asks in flight on her, and dropped after.
269
+ A harbor holds in memory its faculties, its wards and the beings
270
+ answering now.
271
+
272
+ After the boot a harbor takes asks alone. Whoever holds it asks `stand`:
273
+
274
+ ```js
275
+ const harbor = await Harbor.open();
276
+ await harbor.ask({ method: 'stand' });
277
+ ```
204
278
 
205
- 1. The terrain gives the harbor's seed, which opens its memory. The
206
- terrain keeps that memory as sealed bytes and reads none of it.
207
- 2. The box ward unpacks under the seed, its ward-being the dock.
208
- 3. The catalogue wakes, and loads every module she names.
209
- 4. The other faculties are born from their rows.
210
- 5. The routes the dock keeps are handed to the carrier.
211
- 6. Every ward the dock hosts unpacks, under the seed the dock keeps for it.
212
- 7. In every ward, the ward-being first, then each being from her row.
279
+ `stand` answers what stood, or silence where everything already stands.
280
+ The command asks it of every harbor it opens.
213
281
 
214
282
  Cells decide what stands. The modules only resolve a kind a row keeps.
215
- Opening a harbor on empty memory is its genesis: the dock stands the
216
- catalogue, and the root's asks write the rest: `add` on the catalogue,
217
- `open`, `host`, `route`, and `boot` on a ward. `host { ward, seed? }`
218
- stands a ward under a seed you name, or a drawn one.
219
-
220
- A ward's place is kept by the root memory unless you name a store.
221
- `open { key: 'vault', class: 'org.nervur.ground-store' }` opens the
222
- store every ground ships, and `host { ward, store: 'vault' }` keeps the
223
- ward there. A class of yours extending `Store` keeps a ward in a bucket
224
- or a database the same way, and `move { ward, store }` carries a ward
225
- between keepers whole.
283
+ Opening a harbor on empty memory is its genesis: the harbor writes the
284
+ catalogue and the default dock, and the root's asks write the rest: `add`
285
+ on the catalogue, `open`, `host`, `route`, and `boot` on a ward.
286
+ `host { ward, seed? }` stands a ward under a seed you name, or a drawn
287
+ one.
288
+
289
+ A ward is a being too, and her row keeps her class's kind. `Ward` and
290
+ `Dock` are contracts, and `DefaultWard` and `DefaultDock` the library's
291
+ defaults of them. A class of yours extending either, in a module the
292
+ catalogue runs, is a ward of your own: `host { ward, class }` stands a
293
+ hosted ward of it, and `become { class }` on any ward, the box ward's
294
+ dock among them, has her born again of it on the same cells and
295
+ relations. A dock of yours stands on every open, since she stands once
296
+ the catalogue runs.
297
+
298
+ Every class comes from a registry. The catalogue is the library's, and a
299
+ class of yours extending `RegistryFaculty` is another: open it as any
300
+ faculty, and name it where a class is named. `open { key, class,
301
+ registry }` stands a faculty through it, `host { ward, registry }` stands
302
+ a ward and every class of it through it, and `become { class, registry }`
303
+ stands the dock through it, where the catalogue stands that registry. A
304
+ registry may stand through another.
305
+
306
+ A ward's place is kept by the root memory unless you name a memory
307
+ faculty. `open { key: 'vault', class: 'org.nervur.ground-memory' }` opens
308
+ the memory faculty every ground ships, and `host { ward, memory: 'vault' }`
309
+ keeps the ward there. A class of yours extending `MemoryFaculty` keeps a
310
+ ward in a bucket or a database the same way, and `move { ward, memory }`
311
+ carries a ward between keepers whole.
226
312
 
227
313
  ## What it holds
228
314
 
229
- - **Being, Faculty.** What you extend. A faculty's contract is its class
230
- and every class between it and `Faculty`.
315
+ - **Being, Faculty, Ward, Dock.** What you extend, each a contract.
316
+ A faculty's contract is its class and every class between it and
317
+ `Faculty`. `DefaultWard` and `DefaultDock` are the kit's ward and dock.
231
318
  - **Entropy, Clock, Custody, Memory, Carrier, Loader.** The contracts a
232
319
  terrain fulfils. Each has one suite, and every body that fulfils it
233
320
  passes it. `nervur/proof` hands you those suites and the unpacking
234
321
  law's as scenes, a title and a function each, so a body of your own,
235
- a store in a cloud or a secret of your platform's, runs them under
322
+ a memory in a cloud or a secret of your platform's, runs them under
236
323
  your own runner: `for (const [title, scene] of memoryScenes('Mine',
237
324
  make, expect)) test(title, scene)`. `@nervur-org/s3` is one such body.
238
- - **Harbor, Terrain, Dock, Catalogue, Registry, WardBeing.** The onion.
239
- - **World, PointerTerrain** and the pointer bodies, `HeldLoader` among
240
- them. A whole world with this package alone.
325
+ - **Harbor, Terrain, Catalogue, Registry.** The onion.
326
+ - **World, PointerTerrain** and the pointer bodies. A whole world with
327
+ this package alone.
328
+ - **SourceLoader, BundleLoader.** A module's source run by the engine's
329
+ own import, its `nervur` linked to the kit running, and the modules a
330
+ bundle carries, found by their git blob, for a service worker, which
331
+ imports nothing once it runs.
241
332
  - **addGround, grounds**: the grounds `Harbor.open()` tries, and a way to
242
333
  add your own.
243
334
  - **NodeTerrain**, from `nervur/node`: the Node ground's terrain, for a
@@ -246,24 +337,26 @@ between keepers whole.
246
337
  browser ground's terrain and bodies. `serveWorker(Harbor.open())` at
247
338
  the top of a shared or service worker holds one harbor for every tab,
248
339
  each tab asks it with `rootOf(worker)`, and a push the service worker
249
- hears makes every relay client `ring`.
340
+ hears is the dock's `heard`, told to every carrier.
341
+ - **harborShell, harborWorker, EdgeMemory, EdgeCustody, EdgeLoader**,
342
+ from `nervur/edge`, and the kit as one module's text, from
343
+ `nervur/edge/kit`: the edge's shell and the bodies its children stand
344
+ on.
250
345
  - **FolderMemory, FolderCustody**, from `nervur/folder`.
251
- - **TcpCarrier, TcpListener**, from `nervur/tcp`: Quo over TCP. Route a
252
- ward pk to its `tcp://host:port` addresses on the carrier, hand the
253
- listener your harbor, and harbors in two processes, or a harbor and
254
- another kit, speak. `tcpFaculty` is the same carrier as a faculty of a
255
- harbor.
256
- - **WebDialer, webFaculty**: Quo over the web, a post to `https://` or a
346
+ - **TcpCarrier, TcpListener, NodeSockets**, from `nervur/tcp`: Quo over
347
+ TCP. Route a ward pk to its `tcp://host:port` addresses on the carrier,
348
+ hand the listener your harbor, and harbors in two processes, or a
349
+ harbor and another kit, speak. `TcpFaculty` is the same carrier as a
350
+ faculty of a harbor, on the sockets its terrain hands it:
351
+ `NodeSockets` on Node, a worker's own on the edge.
352
+ - **WebDialer, WebFaculty**: Quo over the web, a post to `https://` or a
257
353
  held line to `wss://`, in any engine with `fetch` and WebSocket.
258
- `webServe` and `webGround`, from `nervur/http`, listen for it on Node.
259
- `answerPost(harbor, listen, request)` answers one post and nothing
260
- more, for a function that opens a harbor per request and closes it.
261
-
262
- - **The relay**, `org.nervur.relay` and `org.nervur.relay-client`, in
263
- every harbor: a harbor nobody can dial is reached through one that
264
- can, by relations alone. See "A harbor nobody dials" below.
265
- - **Push, webPush**: a ring with no content, as Web Push sends it,
266
- signed with VAPID, on fetch and Web Crypto.
354
+ `webServe`, from `nervur/http`, is the listener a Node terrain hands
355
+ the web carrier. `answerPost(harbor, listen, request)` answers one post
356
+ and nothing more, for a function that opens a harbor per request and
357
+ closes it.
358
+ - **DEFAULTS**: the one list of beings and faculties every ground runs
359
+ where you write none, handed to a terrain as `defaults`.
267
360
 
268
361
  Quo crosses two carriers, TCP and the web, and no third. MCP, an HTTP API
269
362
  and every other outside protocol are gateway faculties: classes that
@@ -281,7 +374,7 @@ folder, Quo over TCP as its carrier. A module is a file that exports
281
374
 
282
375
  ```sh
283
376
  nervur init --dir ./harbor
284
- nervur module add ./greetings.js --dir ./harbor # or @acme/greetings, or its id
377
+ nervur module add ./greetings.js --dir ./harbor
285
378
  nervur serve --dir ./harbor --port 7000
286
379
  nervur reach tcp://harbor.example:7000 --dir ./harbor
287
380
  nervur open web org.nervur.web --dir ./harbor
@@ -300,18 +393,20 @@ so nobody routes it by hand. Where an invitation carries no `at`,
300
393
  `nervur route <ward pk> tcp://host:port` names the route, and a route
301
394
  named this way is trusted first.
302
395
 
303
- `init` makes the harbor and prints its pk and an owner invitation. `serve`
304
- listens for Quo on TCP and for the root's asks on a local socket, open to
305
- you alone. Every other command is one root ask, sent to the served
396
+ `init` makes the harbor, opens its TCP carrier unless you pass
397
+ `--no-tcp`, and prints its pk and an owner invitation. `serve` listens for
398
+ Quo on that carrier and for the root's asks on a local socket, open to
399
+ you alone, and adds nothing to the harbor: one with no TCP carrier is not
400
+ served. Every other command is one root ask, sent to the served
306
401
  harbor, or answered from the folder when none is served. Each prints one
307
402
  JSON line. `--dir` defaults to `$NERVUR_DIR`, then `~/.nervur`.
308
- `module add` takes a file, an installed package, or a module's id, and
309
- the catalogue keeps the id the module declares, so the same harbor finds
310
- its code on any ground: on this machine through `modules.json` beside
311
- the harbor, which remembers where each id was found, and on an edge or
312
- in a browser in the bundle. Routes live in the harbor like everything
313
- else, so a restart finds both. `nervur
314
- modules` shows what runs, and `nervur module remove <module>` stops one.
403
+ `module add` reads the file and commits its text into the harbor's DNA,
404
+ so the harbor holds its own code on any ground. Routes live in the
405
+ harbor like everything else, so a restart finds both. `nervur modules`
406
+ shows what runs, `nervur module remove <module>` stops one, `nervur log`
407
+ walks the commits, `nervur live <commit>` moves `live`, and `nervur
408
+ origin <url>` with `nervur fetch` reads a git repository into the
409
+ harbor.
315
410
 
316
411
  A harbor elsewhere is piloted with the owner invitation its `init`
317
412
  printed, from a harbor of your own:
@@ -321,56 +416,18 @@ nervur pilot far '<owner invitation>' --dir ./mine
321
416
  nervur host shop --via far --dir ./mine
322
417
  ```
323
418
 
324
- `pilot` boots an `org.nervur.pilot` being in your harbor that holds the
325
- invitation as an ordinary Quo relation, kept in your harbor's memory, and
419
+ `pilot` is your dock's `hold`: it keeps the invitation under the name
420
+ `far` as an ordinary Quo relation, kept in your harbor's memory, and
326
421
  reaches the far harbor where its invitation's `at` says; where it says
327
422
  nothing, name the address after the invitation. With
328
423
  `--via far`, any command is asked of the far harbor as its owner, sealed
329
- over TCP, except `own` and `disown`, which stay the far root's.
330
- `nervur unboot far` lets it go.
331
-
332
- `rootLine(harbor, request)` is the same request in code, for any other
333
- front: `{ ward?, method?, args? }` in, one JSON answer out.
334
-
335
- ## A harbor nobody dials
336
-
337
- A device behind a home router listens nowhere a caller can reach. A
338
- served harbor that can be reached relays for it. On the relay's harbor:
339
-
340
- ```sh
341
- nervur open relay org.nervur.relay --dir ./relay
342
- nervur ask relay invite '{"id":"house","wards":["<camera ward pk>"]}' --dir ./relay
343
- ```
344
-
345
- On the device, with the relay's address as its own reach:
346
-
347
- ```sh
348
- nervur open client org.nervur.relay-client --dir ./house
349
- nervur ask client hold '{"invitation":<the invitation>,"line":true}' --dir ./house
350
- nervur reach tcp://relay.example:7000 --dir ./house
351
- nervur serve --dir ./house
352
- ```
353
-
354
- Every invitation the device gives now sends callers to the relay. The
355
- relay holds each sealed box, the client collects it by an ordinary ask,
356
- hands it to the device's door, and returns the sealed reply in its next
357
- ask. Nothing is opened on the way. `line` keeps collecting, for a
358
- camera. Without it the client is a doorbell: `ring` collects what waits,
359
- and `"every": 60000` rings on a schedule, for a garage door.
360
-
361
- A doorbell can also be rung by a push with nothing in it. The relay's
362
- harbor opens Web Push and names who it is:
363
-
364
- ```sh
365
- nervur open push org.nervur.web-push --dir ./relay
366
- nervur ask push subject '{"subject":"mailto:ops@example.org"}' --dir ./relay
367
- ```
424
+ over TCP, except `own` and `disown`, which stay the far root's. Every ward
425
+ holds far beings this way, a ward or any other being whose invitation
426
+ carries the notes `{ owner: true }`, each under a name, asked with
427
+ `pilot { name, method, args }` and let go with `drop { name }`.
368
428
 
369
- The device asks its client for the key (`nervur ask client key`),
370
- subscribes to pushes with it, and hands the subscription's endpoint to
371
- `nervur ask client bell '{"endpoint":"https://..."}'`. When a box waits
372
- and no line collects, the relay rings that endpoint once. Whatever hears
373
- the push on the device asks the client's `ring`.
429
+ `harbor.ask(request)` is the same request in code, for any other front:
430
+ `{ ward?, method?, args? }` in, one JSON answer out.
374
431
 
375
432
  ## Moving a harbor
376
433
 
package/dist/browser.js CHANGED
@@ -1,7 +1,8 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // `nervur` as a browser bundle reads it: the main entry, with the browser
3
3
  // ground added, so `Harbor.open()` keeps a harbor in IndexedDB.
4
- import { browserGround } from './browser/index.js';
5
- import { addGround } from './harbor/index.js';
4
+ import { browserGround } from './core/browser/index.js';
5
+ import { addGround } from './core/harbor/index.js';
6
+ import { DEFAULTS } from './index.js';
6
7
  export * from './index.js';
7
- addGround(browserGround);
8
+ addGround(browserGround, DEFAULTS);
package/dist/cli.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // The `nervur` program: `core/cli/command.ts` over this process's
4
+ // arguments, its harbors running the defaults of the Node entry. A command
5
+ // that cannot run exits 2 and says why on stderr.
6
+ import { main, SERVING } from './core/cli/command.js';
7
+ import { DEFAULTS } from './node.js';
8
+ try {
9
+ const code = await main(process.argv.slice(2), process.env, (line) => process.stdout.write(`${line}\n`), DEFAULTS);
10
+ if (code !== SERVING)
11
+ process.exitCode = code;
12
+ }
13
+ catch (e) {
14
+ process.stderr.write(`nervur: ${e.message}\n`);
15
+ process.exitCode = 2;
16
+ }
@@ -1,3 +1,10 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // The base class most beings extend. It writes `answer`: the empty ask is
3
+ // her blueprint for this asker, a named ask calls her method of that name,
4
+ // and an ask she did not declare, or hides from this asker, is an error
5
+ // object. A class that writes `answer` by hand is a being just the same.
6
+ // What she acts through is `this.stance`.
7
+ import { ships } from './kind.js';
1
8
  // Names a subclass may not declare as an ask, because they are the base's.
2
9
  const RESERVED = new Set(['answer', 'describe', 'stance', 'cells', 'notes', 'constructor']);
3
10
  // Whether she wrote a method of that name, below Object's prototype.
@@ -15,6 +22,9 @@ export class Being {
15
22
  // The name her row keeps for this class. Every class that stands declares
16
23
  // its own.
17
24
  static kind = 'org.nervur.being';
25
+ static {
26
+ ships(this);
27
+ }
18
28
  // Her cells' defaults, written at birth only where a key is missing.
19
29
  static cells = {};
20
30
  static asks = {};
@@ -10,14 +10,17 @@
10
10
  // A being lends by the contract's kind and never learns the class. Every
11
11
  // class between the faculty and `Faculty` is a contract and declares its
12
12
  // own kind, and a faculty fulfils each of them and her own. Two asks are the
13
- // faculty's own and answered to the ward-being that opened her alone:
13
+ // faculty's own and answered to the ward that opened her alone:
14
14
  // `offer`, an invitation on herself for a ward the dock vouches for, and
15
15
  // `retract`, an offer that was not taken.
16
16
  import { Being } from './being.js';
17
- import { kindOf } from './kind.js';
17
+ import { kindOf, ships } from './kind.js';
18
18
  import { WARD } from './types.js';
19
19
  export class Faculty extends Being {
20
20
  static kind = 'org.nervur.faculty';
21
+ static {
22
+ ships(this);
23
+ }
21
24
  // The contracts a class fulfils: itself and every class between it and
22
25
  // `Faculty`, by kind. A class among them with no kind of its own throws.
23
26
  static contracts(C) {
@@ -1,6 +1,6 @@
1
1
  export { Being, type AskSpec } from './being.ts';
2
2
  export { canonical, digest } from './digest.ts';
3
3
  export { Faculty } from './faculty.ts';
4
- export { isKind, KIT, kindOf, ownKind } from './kind.ts';
4
+ export { isKind, KIT, kindOf, ownKind, shipped, ships } from './kind.ts';
5
5
  export { OWNER, WARD, type Answer, type Ask, type Asker, type BeingClass, type BeingLike, type Blueprint, type Invitation, type Json, type JsonObject, type Occupants, type Reply, type Schema, type Stance, type Standing, type Standings, type Wanted } from './types.ts';
6
6
  export { isSilence, isWord, silence, told, word, type Silence, type Word, type WordName } from './words.ts';
@@ -3,6 +3,6 @@
3
3
  export { Being } from './being.js';
4
4
  export { canonical, digest } from './digest.js';
5
5
  export { Faculty } from './faculty.js';
6
- export { isKind, KIT, kindOf, ownKind } from './kind.js';
6
+ export { isKind, KIT, kindOf, ownKind, shipped, ships } from './kind.js';
7
7
  export { OWNER, WARD } from './types.js';
8
8
  export { isSilence, isWord, silence, told, word } from './words.js';
@@ -1,4 +1,6 @@
1
1
  export declare const KIT = "org.nervur.";
2
2
  export declare const isKind: (text: unknown) => text is string;
3
3
  export declare const ownKind: (C: unknown) => string | undefined;
4
+ export declare const ships: (C: object) => void;
5
+ export declare const shipped: (C: unknown) => boolean;
4
6
  export declare const kindOf: (C: unknown) => string;
@@ -19,6 +19,12 @@ export const ownKind = (C) => {
19
19
  const kind = C.kind;
20
20
  return isKind(kind) ? kind : undefined;
21
21
  };
22
+ // The classes the kit ships. Each is marked on itself as it is declared,
23
+ // under a registered symbol, so the mark holds for a class of any copy of
24
+ // the kit a module was built against, and a subclass inherits no mark.
25
+ const SHIPS = Symbol.for('org.nervur.ships');
26
+ export const ships = (C) => void Object.defineProperty(C, SHIPS, { value: true });
27
+ export const shipped = (C) => typeof C === 'function' && Object.hasOwn(C, SHIPS);
22
28
  // The kind a class declares on itself, or a throw naming the class.
23
29
  export const kindOf = (C) => {
24
30
  const kind = ownKind(C);
@@ -1,4 +1,4 @@
1
1
  export const OWNER = 'OWNER';
2
- // The ward-being's key in her ward, and so the id every being she makes
2
+ // The ward's key in her house, and so the id every being she makes
3
3
  // knows her by.
4
4
  export const WARD = 'ward';