@ibgib/core-gib 0.0.4

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 (330) hide show
  1. package/.vscode/core-gib-snippets.code-snippets +189 -0
  2. package/.vscode/launch.json +24 -0
  3. package/.vscode/settings.json +56 -0
  4. package/.vscode/tasks.json +37 -0
  5. package/CHANGELOG.md +11 -0
  6. package/README.md +215 -0
  7. package/dist/common/aws-constants.d.mts +7 -0
  8. package/dist/common/aws-constants.d.mts.map +1 -0
  9. package/dist/common/aws-constants.mjs +7 -0
  10. package/dist/common/aws-constants.mjs.map +1 -0
  11. package/dist/common/bin/bin-types.d.mts +17 -0
  12. package/dist/common/bin/bin-types.d.mts.map +1 -0
  13. package/dist/common/bin/bin-types.mjs +3 -0
  14. package/dist/common/bin/bin-types.mjs.map +1 -0
  15. package/dist/common/cache/cache-types.d.mts +57 -0
  16. package/dist/common/cache/cache-types.d.mts.map +1 -0
  17. package/dist/common/cache/cache-types.mjs +2 -0
  18. package/dist/common/cache/cache-types.mjs.map +1 -0
  19. package/dist/common/comment/comment-constants.d.mts +11 -0
  20. package/dist/common/comment/comment-constants.d.mts.map +1 -0
  21. package/dist/common/comment/comment-constants.mjs +11 -0
  22. package/dist/common/comment/comment-constants.mjs.map +1 -0
  23. package/dist/common/comment/comment-helper.d.mts +59 -0
  24. package/dist/common/comment/comment-helper.d.mts.map +1 -0
  25. package/dist/common/comment/comment-helper.mjs +173 -0
  26. package/dist/common/comment/comment-helper.mjs.map +1 -0
  27. package/dist/common/comment/comment-types.d.mts +16 -0
  28. package/dist/common/comment/comment-types.d.mts.map +1 -0
  29. package/dist/common/comment/comment-types.mjs +2 -0
  30. package/dist/common/comment/comment-types.mjs.map +1 -0
  31. package/dist/common/display/display-helper.d.mts +19 -0
  32. package/dist/common/display/display-helper.d.mts.map +1 -0
  33. package/dist/common/display/display-helper.mjs +68 -0
  34. package/dist/common/display/display-helper.mjs.map +1 -0
  35. package/dist/common/display/display-types.d.mts +97 -0
  36. package/dist/common/display/display-types.d.mts.map +1 -0
  37. package/dist/common/display/display-types.mjs +37 -0
  38. package/dist/common/display/display-types.mjs.map +1 -0
  39. package/dist/common/encrypt/encrypt-constants.d.mts +27 -0
  40. package/dist/common/encrypt/encrypt-constants.d.mts.map +1 -0
  41. package/dist/common/encrypt/encrypt-constants.mjs +27 -0
  42. package/dist/common/encrypt/encrypt-constants.mjs.map +1 -0
  43. package/dist/common/encrypt/encrypt-types.d.mts +116 -0
  44. package/dist/common/encrypt/encrypt-types.d.mts.map +1 -0
  45. package/dist/common/encrypt/encrypt-types.mjs +9 -0
  46. package/dist/common/encrypt/encrypt-types.mjs.map +1 -0
  47. package/dist/common/error/error-constants.d.mts +9 -0
  48. package/dist/common/error/error-constants.d.mts.map +1 -0
  49. package/dist/common/error/error-constants.mjs +9 -0
  50. package/dist/common/error/error-constants.mjs.map +1 -0
  51. package/dist/common/error/error-helper.d.mts +43 -0
  52. package/dist/common/error/error-helper.d.mts.map +1 -0
  53. package/dist/common/error/error-helper.mjs +167 -0
  54. package/dist/common/error/error-helper.mjs.map +1 -0
  55. package/dist/common/error/error-types.d.mts +58 -0
  56. package/dist/common/error/error-types.d.mts.map +1 -0
  57. package/dist/common/error/error-types.mjs +2 -0
  58. package/dist/common/error/error-types.mjs.map +1 -0
  59. package/dist/common/form/form-helper.d.mts +97 -0
  60. package/dist/common/form/form-helper.d.mts.map +1 -0
  61. package/dist/common/form/form-helper.mjs +185 -0
  62. package/dist/common/form/form-helper.mjs.map +1 -0
  63. package/dist/common/form/form-items.d.mts +229 -0
  64. package/dist/common/form/form-items.d.mts.map +1 -0
  65. package/dist/common/form/form-items.mjs +63 -0
  66. package/dist/common/form/form-items.mjs.map +1 -0
  67. package/dist/common/import-export/import-export-types.d.mts +18 -0
  68. package/dist/common/import-export/import-export-types.d.mts.map +1 -0
  69. package/dist/common/import-export/import-export-types.mjs +2 -0
  70. package/dist/common/import-export/import-export-types.mjs.map +1 -0
  71. package/dist/common/legacy/legacy-types.d.mts +2 -0
  72. package/dist/common/legacy/legacy-types.d.mts.map +1 -0
  73. package/dist/common/legacy/legacy-types.mjs +2 -0
  74. package/dist/common/legacy/legacy-types.mjs.map +1 -0
  75. package/dist/common/link/link-constants.d.mts +2 -0
  76. package/dist/common/link/link-constants.d.mts.map +1 -0
  77. package/dist/common/link/link-constants.mjs +2 -0
  78. package/dist/common/link/link-constants.mjs.map +1 -0
  79. package/dist/common/link/link-helper.d.mts +37 -0
  80. package/dist/common/link/link-helper.d.mts.map +1 -0
  81. package/dist/common/link/link-helper.mjs +143 -0
  82. package/dist/common/link/link-helper.mjs.map +1 -0
  83. package/dist/common/link/link-types.d.mts +14 -0
  84. package/dist/common/link/link-types.d.mts.map +1 -0
  85. package/dist/common/link/link-types.mjs +2 -0
  86. package/dist/common/link/link-types.mjs.map +1 -0
  87. package/dist/common/other/graph-helper.d.mts +166 -0
  88. package/dist/common/other/graph-helper.d.mts.map +1 -0
  89. package/dist/common/other/graph-helper.mjs +710 -0
  90. package/dist/common/other/graph-helper.mjs.map +1 -0
  91. package/dist/common/other/ibgib-helper.d.mts +245 -0
  92. package/dist/common/other/ibgib-helper.d.mts.map +1 -0
  93. package/dist/common/other/ibgib-helper.mjs +641 -0
  94. package/dist/common/other/ibgib-helper.mjs.map +1 -0
  95. package/dist/common/other/other-constants.d.mts +53 -0
  96. package/dist/common/other/other-constants.d.mts.map +1 -0
  97. package/dist/common/other/other-constants.mjs +67 -0
  98. package/dist/common/other/other-constants.mjs.map +1 -0
  99. package/dist/common/other/other-types.d.mts +166 -0
  100. package/dist/common/other/other-types.d.mts.map +1 -0
  101. package/dist/common/other/other-types.mjs +30 -0
  102. package/dist/common/other/other-types.mjs.map +1 -0
  103. package/dist/common/other/svg-constants.d.mts +2 -0
  104. package/dist/common/other/svg-constants.d.mts.map +1 -0
  105. package/dist/common/other/svg-constants.mjs +2 -0
  106. package/dist/common/other/svg-constants.mjs.map +1 -0
  107. package/dist/common/other/svg-helper.d.mts +54 -0
  108. package/dist/common/other/svg-helper.d.mts.map +1 -0
  109. package/dist/common/other/svg-helper.mjs +170 -0
  110. package/dist/common/other/svg-helper.mjs.map +1 -0
  111. package/dist/common/pic/pic-constants.d.mts +13 -0
  112. package/dist/common/pic/pic-constants.d.mts.map +1 -0
  113. package/dist/common/pic/pic-constants.mjs +13 -0
  114. package/dist/common/pic/pic-constants.mjs.map +1 -0
  115. package/dist/common/pic/pic-helper.d.mts +70 -0
  116. package/dist/common/pic/pic-helper.d.mts.map +1 -0
  117. package/dist/common/pic/pic-helper.mjs +235 -0
  118. package/dist/common/pic/pic-helper.mjs.map +1 -0
  119. package/dist/common/pic/pic-types.d.mts +23 -0
  120. package/dist/common/pic/pic-types.d.mts.map +1 -0
  121. package/dist/common/pic/pic-types.mjs +2 -0
  122. package/dist/common/pic/pic-types.mjs.map +1 -0
  123. package/dist/common/root/root-constants.d.mts +40 -0
  124. package/dist/common/root/root-constants.d.mts.map +1 -0
  125. package/dist/common/root/root-constants.mjs +40 -0
  126. package/dist/common/root/root-constants.mjs.map +1 -0
  127. package/dist/common/root/root-types.d.mts +9 -0
  128. package/dist/common/root/root-types.d.mts.map +1 -0
  129. package/dist/common/root/root-types.mjs +2 -0
  130. package/dist/common/root/root-types.mjs.map +1 -0
  131. package/dist/common/tag/tag-constants.d.mts +21 -0
  132. package/dist/common/tag/tag-constants.d.mts.map +1 -0
  133. package/dist/common/tag/tag-constants.mjs +28 -0
  134. package/dist/common/tag/tag-constants.mjs.map +1 -0
  135. package/dist/common/tag/tag-types.d.mts +14 -0
  136. package/dist/common/tag/tag-types.d.mts.map +1 -0
  137. package/dist/common/tag/tag-types.mjs +2 -0
  138. package/dist/common/tag/tag-types.mjs.map +1 -0
  139. package/dist/core-constants.d.mts +89 -0
  140. package/dist/core-constants.d.mts.map +1 -0
  141. package/dist/core-constants.mjs +484 -0
  142. package/dist/core-constants.mjs.map +1 -0
  143. package/dist/core-helper.d.mts +6 -0
  144. package/dist/core-helper.d.mts.map +1 -0
  145. package/dist/core-helper.mjs +28 -0
  146. package/dist/core-helper.mjs.map +1 -0
  147. package/dist/core-types.d.mts +520 -0
  148. package/dist/core-types.d.mts.map +1 -0
  149. package/dist/core-types.mjs +2 -0
  150. package/dist/core-types.mjs.map +1 -0
  151. package/dist/index.d.mts +2 -0
  152. package/dist/index.d.mts.map +1 -0
  153. package/dist/index.mjs +3 -0
  154. package/dist/index.mjs.map +1 -0
  155. package/dist/witness/app/app-base-v1.d.mts +130 -0
  156. package/dist/witness/app/app-base-v1.d.mts.map +1 -0
  157. package/dist/witness/app/app-base-v1.mjs +462 -0
  158. package/dist/witness/app/app-base-v1.mjs.map +1 -0
  159. package/dist/witness/app/app-constants.d.mts +10 -0
  160. package/dist/witness/app/app-constants.d.mts.map +1 -0
  161. package/dist/witness/app/app-constants.mjs +13 -0
  162. package/dist/witness/app/app-constants.mjs.map +1 -0
  163. package/dist/witness/app/app-helper.d.mts +85 -0
  164. package/dist/witness/app/app-helper.d.mts.map +1 -0
  165. package/dist/witness/app/app-helper.mjs +258 -0
  166. package/dist/witness/app/app-helper.mjs.map +1 -0
  167. package/dist/witness/app/app-types.d.mts +211 -0
  168. package/dist/witness/app/app-types.d.mts.map +1 -0
  169. package/dist/witness/app/app-types.mjs +49 -0
  170. package/dist/witness/app/app-types.mjs.map +1 -0
  171. package/dist/witness/app/chat-app/chat-app-types.d.mts +18 -0
  172. package/dist/witness/app/chat-app/chat-app-types.d.mts.map +1 -0
  173. package/dist/witness/app/chat-app/chat-app-types.mjs +25 -0
  174. package/dist/witness/app/chat-app/chat-app-types.mjs.map +1 -0
  175. package/dist/witness/app/flash-app/flash-app-types.d.mts +16 -0
  176. package/dist/witness/app/flash-app/flash-app-types.d.mts.map +1 -0
  177. package/dist/witness/app/flash-app/flash-app-types.mjs +23 -0
  178. package/dist/witness/app/flash-app/flash-app-types.mjs.map +1 -0
  179. package/dist/witness/app/raw-app/raw-app-types.d.mts +18 -0
  180. package/dist/witness/app/raw-app/raw-app-types.d.mts.map +1 -0
  181. package/dist/witness/app/raw-app/raw-app-types.mjs +25 -0
  182. package/dist/witness/app/raw-app/raw-app-types.mjs.map +1 -0
  183. package/dist/witness/app/todo-app/todo-app-types.d.ts +33 -0
  184. package/dist/witness/app/todo-app/todo-app-types.d.ts.map +1 -0
  185. package/dist/witness/app/todo-app/todo-app-types.js +31 -0
  186. package/dist/witness/app/todo-app/todo-app-types.js.map +1 -0
  187. package/dist/witness/robbot/robbot-base-v1.d.ts +432 -0
  188. package/dist/witness/robbot/robbot-base-v1.d.ts.map +1 -0
  189. package/dist/witness/robbot/robbot-base-v1.js +1407 -0
  190. package/dist/witness/robbot/robbot-base-v1.js.map +1 -0
  191. package/dist/witness/robbot/robbot-constants.d.mts +24 -0
  192. package/dist/witness/robbot/robbot-constants.d.mts.map +1 -0
  193. package/dist/witness/robbot/robbot-constants.mjs +24 -0
  194. package/dist/witness/robbot/robbot-constants.mjs.map +1 -0
  195. package/dist/witness/robbot/robbot-helper.d.mts +152 -0
  196. package/dist/witness/robbot/robbot-helper.d.mts.map +1 -0
  197. package/dist/witness/robbot/robbot-helper.mjs +609 -0
  198. package/dist/witness/robbot/robbot-helper.mjs.map +1 -0
  199. package/dist/witness/robbot/robbot-types.d.mts +539 -0
  200. package/dist/witness/robbot/robbot-types.d.mts.map +1 -0
  201. package/dist/witness/robbot/robbot-types.mjs +294 -0
  202. package/dist/witness/robbot/robbot-types.mjs.map +1 -0
  203. package/dist/witness/space/bootstrap/bootstrap-constants.d.mts +14 -0
  204. package/dist/witness/space/bootstrap/bootstrap-constants.d.mts.map +1 -0
  205. package/dist/witness/space/bootstrap/bootstrap-constants.mjs +15 -0
  206. package/dist/witness/space/bootstrap/bootstrap-constants.mjs.map +1 -0
  207. package/dist/witness/space/inner-space-v1.d.ts +63 -0
  208. package/dist/witness/space/inner-space-v1.d.ts.map +1 -0
  209. package/dist/witness/space/inner-space-v1.js +356 -0
  210. package/dist/witness/space/inner-space-v1.js.map +1 -0
  211. package/dist/witness/space/outer-space/outer-space-constants.d.mts +2 -0
  212. package/dist/witness/space/outer-space/outer-space-constants.d.mts.map +1 -0
  213. package/dist/witness/space/outer-space/outer-space-constants.mjs +2 -0
  214. package/dist/witness/space/outer-space/outer-space-constants.mjs.map +1 -0
  215. package/dist/witness/space/outer-space/outer-space-helper.d.mts +28 -0
  216. package/dist/witness/space/outer-space/outer-space-helper.d.mts.map +1 -0
  217. package/dist/witness/space/outer-space/outer-space-helper.mjs +87 -0
  218. package/dist/witness/space/outer-space/outer-space-helper.mjs.map +1 -0
  219. package/dist/witness/space/outer-space/outer-space-types.d.mts +548 -0
  220. package/dist/witness/space/outer-space/outer-space-types.d.mts.map +1 -0
  221. package/dist/witness/space/outer-space/outer-space-types.mjs +118 -0
  222. package/dist/witness/space/outer-space/outer-space-types.mjs.map +1 -0
  223. package/dist/witness/space/space-base-v1.d.mts +147 -0
  224. package/dist/witness/space/space-base-v1.d.mts.map +1 -0
  225. package/dist/witness/space/space-base-v1.mjs +350 -0
  226. package/dist/witness/space/space-base-v1.mjs.map +1 -0
  227. package/dist/witness/space/space-constants.d.mts +181 -0
  228. package/dist/witness/space/space-constants.d.mts.map +1 -0
  229. package/dist/witness/space/space-constants.mjs +192 -0
  230. package/dist/witness/space/space-constants.mjs.map +1 -0
  231. package/dist/witness/space/space-helper.d.mts +666 -0
  232. package/dist/witness/space/space-helper.d.mts.map +1 -0
  233. package/dist/witness/space/space-helper.mjs +2830 -0
  234. package/dist/witness/space/space-helper.mjs.map +1 -0
  235. package/dist/witness/space/space-types.d.mts +422 -0
  236. package/dist/witness/space/space-types.d.mts.map +1 -0
  237. package/dist/witness/space/space-types.mjs +52 -0
  238. package/dist/witness/space/space-types.mjs.map +1 -0
  239. package/dist/witness/witness-base-v1.d.ts +144 -0
  240. package/dist/witness/witness-base-v1.d.ts.map +1 -0
  241. package/dist/witness/witness-base-v1.js +300 -0
  242. package/dist/witness/witness-base-v1.js.map +1 -0
  243. package/dist/witness/witness-constants.d.mts +3 -0
  244. package/dist/witness/witness-constants.d.mts.map +1 -0
  245. package/dist/witness/witness-constants.mjs +3 -0
  246. package/dist/witness/witness-constants.mjs.map +1 -0
  247. package/dist/witness/witness-form-builder.d.mts +45 -0
  248. package/dist/witness/witness-form-builder.d.mts.map +1 -0
  249. package/dist/witness/witness-form-builder.mjs +95 -0
  250. package/dist/witness/witness-form-builder.mjs.map +1 -0
  251. package/dist/witness/witness-helper.d.mts +89 -0
  252. package/dist/witness/witness-helper.d.mts.map +1 -0
  253. package/dist/witness/witness-helper.mjs +229 -0
  254. package/dist/witness/witness-helper.mjs.map +1 -0
  255. package/dist/witness/witness-types.d.mts +211 -0
  256. package/dist/witness/witness-types.d.mts.map +1 -0
  257. package/dist/witness/witness-types.mjs +2 -0
  258. package/dist/witness/witness-types.mjs.map +1 -0
  259. package/jasmine-browser.json +18 -0
  260. package/jasmine.json +6 -0
  261. package/package.json +67 -0
  262. package/src/assumptions.spec.mts +45 -0
  263. package/src/common/aws-constants.mts +5 -0
  264. package/src/common/bin/bin-types.mts +17 -0
  265. package/src/common/cache/cache-types.mts +53 -0
  266. package/src/common/comment/comment-constants.mts +10 -0
  267. package/src/common/comment/comment-helper.mts +211 -0
  268. package/src/common/comment/comment-types.mts +19 -0
  269. package/src/common/display/display-helper.mts +88 -0
  270. package/src/common/display/display-types.mts +108 -0
  271. package/src/common/encrypt/encrypt-constants.mts +28 -0
  272. package/src/common/encrypt/encrypt-types.mts +130 -0
  273. package/src/common/error/error-constants.mts +8 -0
  274. package/src/common/error/error-helper.mts +155 -0
  275. package/src/common/error/error-types.mts +62 -0
  276. package/src/common/form/form-helper.mts +253 -0
  277. package/src/common/form/form-items.mts +236 -0
  278. package/src/common/import-export/import-export-types.mts +18 -0
  279. package/src/common/legacy/about-legacy.md +0 -0
  280. package/src/common/legacy/legacy-types.mts +0 -0
  281. package/src/common/link/link-constants.mts +1 -0
  282. package/src/common/link/link-helper.mts +155 -0
  283. package/src/common/link/link-types.mts +16 -0
  284. package/src/common/other/graph-helper.mts +853 -0
  285. package/src/common/other/ibgib-helper.mts +671 -0
  286. package/src/common/other/other-constants.mts +76 -0
  287. package/src/common/other/other-types.mts +186 -0
  288. package/src/common/other/svg-constants.mts +1 -0
  289. package/src/common/other/svg-helper.mts +238 -0
  290. package/src/common/pic/pic-constants.mts +13 -0
  291. package/src/common/pic/pic-helper.mts +295 -0
  292. package/src/common/pic/pic-types.mts +29 -0
  293. package/src/common/root/root-constants.mts +41 -0
  294. package/src/common/root/root-types.mts +8 -0
  295. package/src/common/tag/tag-constants.mts +34 -0
  296. package/src/common/tag/tag-types.mts +19 -0
  297. package/src/core-constants.mts +506 -0
  298. package/src/core-helper.mts +33 -0
  299. package/src/core-types.mts +519 -0
  300. package/src/helper.spec.mts +64 -0
  301. package/src/index.mts +1 -0
  302. package/src/witness/app/app-base-v1.mts +584 -0
  303. package/src/witness/app/app-constants.mts +16 -0
  304. package/src/witness/app/app-helper.mts +322 -0
  305. package/src/witness/app/app-types.mts +252 -0
  306. package/src/witness/app/chat-app/chat-app-types.mts +40 -0
  307. package/src/witness/app/flash-app/flash-app-types.mts +38 -0
  308. package/src/witness/app/raw-app/raw-app-types.mts +40 -0
  309. package/src/witness/app/todo-app/todo-app-types.ts +59 -0
  310. package/src/witness/robbot/robbot-base-v1.ts +1531 -0
  311. package/src/witness/robbot/robbot-constants.mts +25 -0
  312. package/src/witness/robbot/robbot-helper.mts +676 -0
  313. package/src/witness/robbot/robbot-helper.spec.mts +135 -0
  314. package/src/witness/robbot/robbot-types.mts +797 -0
  315. package/src/witness/space/bootstrap/bootstrap-constants.mts +15 -0
  316. package/src/witness/space/inner-space-v1.ts +372 -0
  317. package/src/witness/space/outer-space/outer-space-constants.mts +1 -0
  318. package/src/witness/space/outer-space/outer-space-helper.mts +91 -0
  319. package/src/witness/space/outer-space/outer-space-types.mts +627 -0
  320. package/src/witness/space/space-base-v1.mts +414 -0
  321. package/src/witness/space/space-constants.mts +208 -0
  322. package/src/witness/space/space-helper.mts +3242 -0
  323. package/src/witness/space/space-types.mts +476 -0
  324. package/src/witness/witness-base-v1.ts +325 -0
  325. package/src/witness/witness-constants.mts +2 -0
  326. package/src/witness/witness-form-builder.mts +128 -0
  327. package/src/witness/witness-helper.mts +256 -0
  328. package/src/witness/witness-types.mts +249 -0
  329. package/tsconfig.json +15 -0
  330. package/tsconfig.test.json +10 -0
@@ -0,0 +1,2830 @@
1
+ import { clone, delay, getExpirationUTCString, getTimestampInTicks, getUUID, isExpired, pretty } from '@ibgib/helper-gib';
2
+ import { V1, getIbAndGib, getIbGibAddr, } from '@ibgib/ts-gib';
3
+ import { GIB, Rel8n, Factory_V1 as factory, IBGIB_DELIMITER, } from '@ibgib/ts-gib/dist/V1/index.mjs';
4
+ import { getGib, } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';
5
+ import { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
6
+ import { APP_REL8N_NAME, GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
7
+ import { getRootIb, getSpecialConfigKey, getSpecialIbGibIb, getSpecialTypeFromIb, getTjpAddr, isSpecial, isTjp_Naive, tagTextToIb } from '../../common/other/ibgib-helper.mjs';
8
+ import { BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY, BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY, BOOTSTRAP_IBGIB_ADDR } from './bootstrap/bootstrap-constants.mjs';
9
+ import { getAppIb, } from '../app/app-helper.mjs';
10
+ import { DEFAULT_CHAT_APP_DATA_V1, DEFAULT_CHAT_APP_REL8NS_V1 } from '../app/chat-app/chat-app-types.mjs';
11
+ import { DEFAULT_RAW_APP_DATA_V1, DEFAULT_RAW_APP_REL8NS_V1 } from '../app/raw-app/raw-app-types.mjs';
12
+ import { DEFAULT_TODO_APP_DATA_V1, DEFAULT_TODO_APP_REL8NS_V1 } from '../app/todo-app/todo-app-types.js';
13
+ import { DEFAULT_MAX_DELAY_MS_RETRY_LOCK_ACQUIRE, DEFAULT_MAX_DELAY_RETRY_LOCK_ACQUIRE_ATTEMPTS, DEFAULT_SECONDS_VALID_LOCAL, DEFAULT_TX_ID_LENGTH, IBGIB_SPACE_NAME_DEFAULT, SPACE_LOCK_IB_TERM, SYNC_SPACE_REL8N_NAME } from './space-constants.mjs';
14
+ import { DEFAULT_TAG_DESCRIPTION, DEFAULT_TAG_ICON, TAG_REL8N_NAME } from '../../common/tag/tag-constants.mjs';
15
+ import { DEFAULT_ROOT_DESCRIPTION, DEFAULT_ROOT_ICON, DEFAULT_ROOT_REL8N_NAME, DEFAULT_ROOT_TEXT, ROOT_REL8N_NAME } from '../../common/root/root-constants.mjs';
16
+ import { ARCHIVE_REL8N_NAME, TRASH_REL8N_NAME } from '../../common/other/other-constants.mjs';
17
+ const logalot = GLOBAL_LOG_A_LOT || false;
18
+ /**
19
+ * Two spaces can be equivalent if they point to the same area.
20
+ *
21
+ * @returns true if the "same" space
22
+ */
23
+ export function isSameSpace({ a, b, mustHaveSameData, }) {
24
+ const lc = `[${isSameSpace.name}]`;
25
+ if (!a) {
26
+ throw new Error(`${lc} a is falsy`);
27
+ }
28
+ ;
29
+ if (!b) {
30
+ throw new Error(`${lc} b is falsy`);
31
+ }
32
+ ;
33
+ // try by data
34
+ if (a.data && JSON.stringify(a.data) === JSON.stringify(b.data)) {
35
+ return true;
36
+ }
37
+ else if (mustHaveSameData) {
38
+ return false;
39
+ }
40
+ // try by uuid
41
+ if (a.data?.uuid && b.data?.uuid) {
42
+ return a.data.uuid === b.data.uuid;
43
+ }
44
+ // try by tjp
45
+ if (a.rel8ns?.tjp?.length === 1 && b.rel8ns?.tjp?.length === 1) {
46
+ return a.rel8ns.tjp[0] === b.rel8ns.tjp[0];
47
+ }
48
+ // try by gib (last resort), can't both be falsy or primitive (maybe overkill)
49
+ if (!a.gib && !b.gib) {
50
+ throw new Error(`${lc} Invalid spaces. both a.gib and b.gib are falsy, neither has uuid and neither has tjp.`);
51
+ }
52
+ if (a.gib === GIB && b.gib === GIB) {
53
+ throw new Error(`${lc} both a and b are primitives`);
54
+ }
55
+ return a.gib === b.gib;
56
+ }
57
+ /**
58
+ * wrapper for dealing with a space.
59
+ *
60
+ * @returns legacy `GetIbGibResult`
61
+ */
62
+ export async function getFromSpace({ addr, addrs, isMeta, isDna, space, force, }) {
63
+ let lc = `[${getFromSpace.name}]`;
64
+ try {
65
+ if (logalot) {
66
+ console.log(`${lc} starting...`);
67
+ }
68
+ if (!space) {
69
+ throw new Error(`space required. (E: 4d188d6c863246f28aa575753a052304)`);
70
+ }
71
+ if (!addr && (addrs ?? []).length === 0) {
72
+ throw new Error(`addr or addrs required. (E: 1a0b92564ba942f1ba91a089ac1a2125)`);
73
+ }
74
+ if (addr && (addrs?.length ?? 0) > 0) {
75
+ console.warn(`${lc} both addr and addrs provided, but supposed to be used one or the other. (W: 87226c2ac50e4ea28211334a7b58782f)`);
76
+ if (!addrs.includes(addr)) {
77
+ addrs.push(addr);
78
+ }
79
+ }
80
+ addrs = (addrs ?? []).length > 0 ? addrs : [addr];
81
+ const argGet = await space.argy({
82
+ ibMetadata: getSpaceArgMetadata({ space }),
83
+ argData: {
84
+ cmd: 'get',
85
+ ibGibAddrs: addrs,
86
+ isMeta,
87
+ isDna,
88
+ },
89
+ });
90
+ const result = await space.witness(argGet);
91
+ if (result?.data?.success) {
92
+ if (logalot) {
93
+ console.log(`${lc} got.`);
94
+ }
95
+ return {
96
+ success: true,
97
+ ibGibs: result.ibGibs,
98
+ rawResultIbGib: result,
99
+ };
100
+ }
101
+ else {
102
+ if (logalot) {
103
+ console.log(`${lc} didn't get.`);
104
+ }
105
+ return {
106
+ success: false,
107
+ errorMsg: result.data?.errors?.join('|') || `${lc} something went wrong. addrs: ${addrs.join('\n')} (E: b9e9d5ce0cde4122bfb74f7688db85e0)`,
108
+ rawResultIbGib: result,
109
+ };
110
+ }
111
+ }
112
+ catch (error) {
113
+ console.error(`${lc} ${error.message}`);
114
+ return { errorMsg: error.message, };
115
+ }
116
+ }
117
+ /**
118
+ * Wrapper for saving ibgib in a given space.
119
+ *
120
+ * ## warnings
121
+ *
122
+ * The given space doesn't have to work this way.
123
+ * This is a convenience for me ATOW.
124
+ */
125
+ export async function putInSpace({ ibGib, ibGibs, isMeta, isDna, force, space, }) {
126
+ const lc = `[${putInSpace.name}]`;
127
+ try {
128
+ if (!ibGib && (ibGibs ?? []).length === 0) {
129
+ throw new Error(`ibGib or ibGibs required. (E: e59c4de3695f4dd28c8fe82dbb9c4e90)`);
130
+ }
131
+ if (!space) {
132
+ throw new Error(`space required. (E: dd0b7189c67c43c586b905a8ed6f51c9)`);
133
+ }
134
+ if (ibGib && (ibGibs ?? []).length > 0) {
135
+ console.warn(`${lc} Both ibGib and ibGibs is assigned, whereas this is intended to be exclusive one or the other. (W: 4c797835b620445f88e4cba6b5aa3460)`);
136
+ if (!ibGibs.some(x => x.gib === ibGib.gib)) {
137
+ ibGibs = ibGibs.concat([ibGib]);
138
+ }
139
+ }
140
+ ibGibs = ibGibs ?? [ibGib];
141
+ if (logalot) {
142
+ console.log(`${lc} ibGibs.length: ${ibGibs.length}`);
143
+ }
144
+ const argPutIbGibs = await space.argy({
145
+ ibMetadata: getSpaceArgMetadata({ space }),
146
+ argData: {
147
+ cmd: 'put', isMeta, force, isDna,
148
+ ibGibAddrs: ibGibs.map(x => getIbGibAddr({ ibGib: x })),
149
+ },
150
+ ibGibs: ibGibs.concat(),
151
+ });
152
+ const resPutIbGibs = await space.witness(argPutIbGibs);
153
+ if (resPutIbGibs.data?.success) {
154
+ if ((resPutIbGibs.data.warnings ?? []).length > 0) {
155
+ resPutIbGibs.data.warnings.forEach((warning) => console.warn(`${lc} ${warning}`));
156
+ }
157
+ return { success: true };
158
+ }
159
+ else {
160
+ const errorMsg = resPutIbGibs?.data?.errors?.length > 0 ?
161
+ `Error(s) putting in local space:\n${resPutIbGibs.data.errors.join('\n')}` :
162
+ '(UNEXPECTED) unknown error putting ibGibs (E: 3d7426d4527243b79c5e55eb25f3fa73)';
163
+ throw new Error(errorMsg);
164
+ }
165
+ }
166
+ catch (error) {
167
+ console.error(`${lc} ${error.message}`);
168
+ return { errorMsg: error.message, };
169
+ }
170
+ }
171
+ /**
172
+ * Wrapper for removing ibgib from the a given space, else the current space.
173
+ */
174
+ export async function deleteFromSpace({ addr, isMeta, isDna, space, }) {
175
+ let lc = `[${deleteFromSpace.name}]`;
176
+ try {
177
+ if (!space) {
178
+ throw new Error(`space required. (E: 40ab3b51e91c4b5eb4f215baeefbcef0)`);
179
+ }
180
+ if (!space.data) {
181
+ throw new Error(`space.data required. (E: 0d02c8e85ee143b8bd6a1a1db0d9af1b)`);
182
+ }
183
+ lc = `${lc}[${space.data.name || 'noname?'}][${space.data.uuid || 'nouuid?'}]`;
184
+ const argDel = await space.argy({
185
+ ibMetadata: getSpaceArgMetadata({ space }),
186
+ argData: {
187
+ cmd: 'delete',
188
+ ibGibAddrs: [addr],
189
+ isMeta,
190
+ isDna,
191
+ },
192
+ });
193
+ const result = await space.witness(argDel);
194
+ if (result.data?.success) {
195
+ return { success: true, };
196
+ }
197
+ else {
198
+ if (result.data?.warnings?.length > 0) {
199
+ console.warn(`${lc} warnings with delete (${addr}): ${result.data.warnings.join('|')}`);
200
+ }
201
+ if (result.data?.addrs?.length > 0) {
202
+ console.warn(`${lc} partial addrs deleted: ${result.data.addrs.join('|')}`);
203
+ }
204
+ const errorMsg = result.data?.errors?.join('|') || `${lc} something went wrong (E: e397fd09b4a746a3ba3305d6ea0893cb)`;
205
+ if (errorMsg.includes('File does not exist')) {
206
+ if (logalot) {
207
+ console.log(`${lc} tried to delete file that does not exist. (I: cb5d1348ccbc58bf0bfc95f3006f1e22)`);
208
+ }
209
+ }
210
+ return { errorMsg };
211
+ }
212
+ }
213
+ catch (error) {
214
+ console.error(`${lc} ${error.message}`);
215
+ return { errorMsg: error.message };
216
+ }
217
+ }
218
+ /**
219
+ * Convenience function for persisting a transform result, which has
220
+ * a newIbGib and optionally intermediate ibGibs and/or dnas.
221
+ *
222
+ * it persists these ibgibs into the given space, else the current space.
223
+ */
224
+ export async function persistTransformResult({ resTransform, space, isMeta, force, }) {
225
+ const lc = `[${persistTransformResult.name}]`;
226
+ try {
227
+ if (!space) {
228
+ throw new Error(`space required. (E: cf94f1d74f1c4561bb88025a2095965b)`);
229
+ }
230
+ const { newIbGib, intermediateIbGibs, dnas } = resTransform;
231
+ const ibGibs = [newIbGib, ...(intermediateIbGibs || [])];
232
+ const argPutIbGibs = await space.argy({
233
+ ibMetadata: getSpaceArgMetadata({ space }),
234
+ argData: {
235
+ cmd: 'put', isMeta, force,
236
+ ibGibAddrs: ibGibs.map(x => getIbGibAddr({ ibGib: x })),
237
+ },
238
+ ibGibs: ibGibs.concat(),
239
+ });
240
+ const resPutIbGibs = await space.witness(argPutIbGibs);
241
+ if (resPutIbGibs.data?.success) {
242
+ if (resPutIbGibs.data.warnings?.length > 0) {
243
+ resPutIbGibs.data.warnings.forEach((warning) => console.warn(`${lc} ${warning}`));
244
+ }
245
+ }
246
+ else {
247
+ const errorMsg = resPutIbGibs?.data?.errors?.length > 0 ?
248
+ resPutIbGibs.data.errors.join('\n') :
249
+ 'unknown error putting ibGibs';
250
+ throw new Error(errorMsg);
251
+ }
252
+ if (dnas?.length ?? 0 > 0) {
253
+ const argPutDnas = await space.argy({
254
+ ibMetadata: getSpaceArgMetadata({ space }),
255
+ argData: {
256
+ cmd: 'put', isDna: true, force,
257
+ ibGibAddrs: dnas.map(x => getIbGibAddr({ ibGib: x })),
258
+ },
259
+ ibGibs: dnas.concat(),
260
+ });
261
+ const resPutDnas = await space.witness(argPutDnas);
262
+ if (resPutDnas.data?.success) {
263
+ if (resPutDnas.data.warnings?.length > 0) {
264
+ resPutDnas.data.warnings.forEach((warning) => console.warn(`${lc} ${warning}`));
265
+ }
266
+ }
267
+ else {
268
+ const errorMsg = resPutDnas?.data?.errors?.length > 0 ?
269
+ resPutDnas.data.errors.join('\n') :
270
+ 'unknown error putting dna ibGibs';
271
+ throw new Error(errorMsg);
272
+ }
273
+ }
274
+ }
275
+ catch (error) {
276
+ console.error(`${lc} ${error.message}`);
277
+ throw error;
278
+ }
279
+ }
280
+ export async function getSyncSpaces({ space, }) {
281
+ const lc = `[${getSyncSpaces.name}]`;
282
+ try {
283
+ if (!space) {
284
+ throw new Error(`space required. (E: c03f80eca6b045b9a73b0aafa44cdf26)`);
285
+ }
286
+ let syncSpaces = await getSpecialRel8dIbGibs({
287
+ type: "outerspaces",
288
+ rel8nName: SYNC_SPACE_REL8N_NAME,
289
+ space,
290
+ });
291
+ return syncSpaces;
292
+ }
293
+ catch (error) {
294
+ console.error(`${lc} ${error.message}`);
295
+ throw error;
296
+ }
297
+ }
298
+ export async function getSpecialRel8dIbGibs({ type, rel8nName, space, }) {
299
+ const lc = `[${getSpecialRel8dIbGibs.name}]`;
300
+ try {
301
+ if (!space) {
302
+ throw new Error(`space required. (E: f73868a952ac4181a4f90ee6d86cacf3)`);
303
+ }
304
+ let special = await getSpecialIbGib({ type, space });
305
+ if (!special) {
306
+ throw new Error(`couldn't get special (${type})`);
307
+ }
308
+ ;
309
+ const rel8dAddrs = special.rel8ns ? special.rel8ns[rel8nName] || [] : [];
310
+ const rel8dIbgibs = [];
311
+ for (let i = 0; i < rel8dAddrs.length; i++) {
312
+ const addr = rel8dAddrs[i];
313
+ let resGet = await getFromSpace({ addr, space });
314
+ if (resGet.success && resGet.ibGibs?.length === 1) {
315
+ rel8dIbgibs.push(resGet.ibGibs[0]);
316
+ }
317
+ else {
318
+ throw new Error(`couldn't get addr: ${addr}`);
319
+ }
320
+ }
321
+ return rel8dIbgibs;
322
+ }
323
+ catch (error) {
324
+ console.error(`${lc} ${error.message}`);
325
+ throw error;
326
+ }
327
+ }
328
+ /**
329
+ * Gets one of the app's special ibGibs, e.g., TagsIbGib.
330
+ *
331
+ * When initializing tags, this will generate some boilerplate tags.
332
+ * I'm going to be doing roots here also, and who knows what else, but each
333
+ * one will have its own initialize specifics.
334
+ *
335
+ * @param initialize initialize (i.e. create) ONLY IF IbGib not found. Used for initializing app (first run).
336
+ *
337
+ * @see {@link createSpecial}
338
+ * @see {@link createSpecial_Tags}
339
+ */
340
+ export async function getSpecialIbGib({ type, initialize, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, fnGetInitializing, fnSetInitializing, }) {
341
+ const lc = `[${getSpecialIbGib.name}]`;
342
+ try {
343
+ if (!space) {
344
+ throw new Error(`space required. (E: d454b31d58764a9bb9c4e47fb5ef38b5)`);
345
+ }
346
+ let key = getSpecialConfigKey({ type });
347
+ let addr = await getConfigAddr({ key, space });
348
+ if (!addr) {
349
+ if (initialize && (!fnGetInitializing || !fnSetInitializing)) {
350
+ throw new Error(`if initialize, you must provide fnGetInitializeLock & fnSetInitializeLock. (E: 8eb322625d0c4538be089800882487de)`);
351
+ }
352
+ if (initialize && !fnGetInitializing()) {
353
+ fnSetInitializing(true);
354
+ try {
355
+ if (!zeroSpace) {
356
+ throw new Error(`zeroSpace required when 'initialize' truthy (E: 8582c92c637f90c9b2dbe0ec8355b523)`);
357
+ }
358
+ addr = await createSpecial({ type, space, zeroSpace: zeroSpace, fnBroadcast, fnUpdateBootstrap }) ?? undefined;
359
+ }
360
+ catch (error) {
361
+ console.error(`${lc} error initializing: ${error.message}`);
362
+ }
363
+ finally {
364
+ fnSetInitializing(false);
365
+ }
366
+ }
367
+ if (!addr) {
368
+ if (fnGetInitializing && fnGetInitializing()) {
369
+ console.warn(`${lc} couldn't get addr, but we're still initializing...`);
370
+ return null;
371
+ }
372
+ else {
373
+ throw new Error(`Special address not in config and couldn't initialize it either.`);
374
+ }
375
+ }
376
+ }
377
+ if (logalot) {
378
+ console.log(`${lc} getting addr: ${addr}`);
379
+ }
380
+ let resSpecial = await getFromSpace({ addr, isMeta: true, space });
381
+ // I'm putting in this check in case we're getting a meta that wasn't
382
+ // saved into the meta folder.
383
+ if (!resSpecial.success) {
384
+ resSpecial = await getFromSpace({ addr, isMeta: false, space });
385
+ if (resSpecial.success) {
386
+ console.warn(`${lc} special ibgib was not stored in meta folder...putting in meta folder now for the future (W: e6f5571fd98c449bb2809359be5057cc)`);
387
+ const resPutInMeta = await putInSpace({ ibGib: resSpecial.ibGibs[0], isMeta: true, space });
388
+ if (!resPutInMeta.success) {
389
+ console.warn(`${lc} (UNEXPECTED) tried to put special in meta but success was false? (W: b934b53571c24057af172c790e6a7240)`);
390
+ }
391
+ }
392
+ }
393
+ if (!resSpecial.success) {
394
+ throw new Error(resSpecial.errorMsg);
395
+ }
396
+ if (resSpecial.ibGibs?.length !== 1) {
397
+ throw new Error(`no ibGib in result (E: 3a42abdddc3648e292d63dc45c560064)`);
398
+ }
399
+ const specialIbGib = resSpecial.ibGibs[0];
400
+ // I'm putting this check in here because it's bad not to have the
401
+ // latest special associated with a space
402
+ if (type !== 'latest') {
403
+ let resLatest = await getLatestAddrs({ ibGibs: [specialIbGib], space });
404
+ if (resLatest?.data?.success && resLatest.data.addrs?.length === 1) {
405
+ let specialAddr = getIbGibAddr({ ibGib: specialIbGib });
406
+ let latestAddr = resLatest.data.addrs[0];
407
+ if (latestAddr !== specialAddr) {
408
+ console.warn(`${lc} latest addr is not the one associated with the local space.\nspecialAddr: ${specialAddr}\nlatestAddr: ${latestAddr} (W: 141b69dc3c414efc9645bb76fcf12df9)`);
409
+ }
410
+ }
411
+ }
412
+ return specialIbGib;
413
+ }
414
+ catch (error) {
415
+ console.error(`${lc} ${error.message}`);
416
+ return null;
417
+ }
418
+ }
419
+ /**
420
+ * Gets a config addr from the current space via the given key
421
+ * as the space's rel8n name.
422
+ *
423
+ * For example, for `key = tags`, a space may look like:
424
+ *
425
+ * ```json
426
+ * {
427
+ * ib: space xyz,
428
+ * gib: e89ff8a1c4954db28432007615a78952,
429
+ * rel8ns: {
430
+ * past: [space xyz^21cb29cc353f45a491d2b49ff2f130db],
431
+ * ancestor: [space^gib],
432
+ * tags: [tags^99b388355f8f4a979ca30ba284d3a686], // <<< rel8n with name specified by key
433
+ * }
434
+ * }
435
+ * ```
436
+ *
437
+ * @param key config key
438
+ * @returns addr in config if exists, else undefined
439
+ */
440
+ export async function getConfigAddr({ key, space, }) {
441
+ const lc = `[${getConfigAddr.name}](${key})`;
442
+ try {
443
+ if (logalot) {
444
+ console.log(`${lc} getting...`);
445
+ }
446
+ if (!space) {
447
+ throw new Error(`space required. (E: 4f135d4276e64054ba21aeb9c304ecec)`);
448
+ }
449
+ if (!space.rel8ns) {
450
+ console.warn(`${lc} space.rel8ns falsy.`);
451
+ return undefined;
452
+ }
453
+ if (!space.rel8ns[key]) {
454
+ console.warn(`${lc} space.rel8ns[${key}] falsy.`);
455
+ return undefined;
456
+ }
457
+ if (space.rel8ns[key].length === 1) {
458
+ if (logalot) {
459
+ console.log(`${lc} got`);
460
+ }
461
+ return space.rel8ns[key][0];
462
+ }
463
+ else if (space.rel8ns[key].length > 1) {
464
+ console.warn(`${lc} more than one config addr with ${key} rel8n.`);
465
+ return space.rel8ns[key][0];
466
+ }
467
+ else {
468
+ if (logalot) {
469
+ console.log(`${lc} didn't find`);
470
+ }
471
+ // key not found or
472
+ return undefined;
473
+ }
474
+ }
475
+ catch (error) {
476
+ console.error(`${lc} ${error.message}`);
477
+ return undefined;
478
+ }
479
+ }
480
+ export async function setConfigAddr({ key, addr, space, zeroSpace, fnUpdateBootstrap, }) {
481
+ const lc = `[${setConfigAddr.name}]`;
482
+ try {
483
+ if (!space) {
484
+ throw new Error(`space required. (E: c28b663c991d44419aef1026cc689636)`);
485
+ }
486
+ if (!zeroSpace) {
487
+ throw new Error(`zeroSpace required. (E: d3707ae5265d464891ad216f64be6184)`);
488
+ }
489
+ // rel8 the `addr` to the current space via rel8n named `key`
490
+ // note that since we are replacing the pointer, we include the key
491
+ // in `linkedRel8ns` which will keep only the most recent
492
+ const rel8nsToAddByAddr = { [key]: [addr] };
493
+ const resNewSpace = await V1.rel8({
494
+ src: space.toIbGibDto(),
495
+ dna: false,
496
+ linkedRel8ns: ["past", "ancestor", key],
497
+ rel8nsToAddByAddr,
498
+ nCounter: true,
499
+ });
500
+ if (!resNewSpace.newIbGib) {
501
+ throw new Error(`create new space failed.`);
502
+ }
503
+ // persist the new space in both default space and its own space
504
+ // (will actually have the space witness its future self interestingly
505
+ // enough...perhaps should have the new space witness itself instead
506
+ // witness in the default zero space
507
+ // in refactoring, may have to make this optional...hmm
508
+ await persistTransformResult({ isMeta: true, resTransform: resNewSpace, space: zeroSpace });
509
+ // witness in the given space
510
+ await persistTransformResult({ isMeta: true, resTransform: resNewSpace, space });
511
+ // going to update the bootstrap^gib with the new space address, but first...
512
+ const newSpace = resNewSpace.newIbGib;
513
+ // ...must update the original space reference any time we change it.
514
+ // messy atm...
515
+ await space.loadIbGibDto(newSpace);
516
+ // ...now update so the proper space (config) loads on next app start
517
+ if (fnUpdateBootstrap) {
518
+ await fnUpdateBootstrap(newSpace);
519
+ }
520
+ else {
521
+ console.warn(`${lc} fnUpdateBootstrap is falsy. (W: 9fb874de2b19454dac18645e61ac463f)`);
522
+ }
523
+ return newSpace;
524
+ }
525
+ catch (error) {
526
+ console.error(`${lc} ${error.message}`);
527
+ throw error;
528
+ }
529
+ }
530
+ export async function getCurrentRoot({ space, }) {
531
+ const lc = `[${getCurrentRoot.name}]`;
532
+ try {
533
+ if (!space) {
534
+ throw new Error(`space required. (E: f0d546101fba4c169256158114ab3c56)`);
535
+ }
536
+ const roots = await getSpecialIbGib({ type: "roots", space });
537
+ if (!roots) {
538
+ throw new Error(`Roots not initialized. (E: 89b1ba12ed12416aac41cef9fdaf1fc2)`);
539
+ }
540
+ if (!roots.rel8ns) {
541
+ throw new Error(`Roots not initialized properly. No rel8ns. (E: 8513a07cf530484db9521a2a3a27b7f6)`);
542
+ }
543
+ if (!roots.rel8ns.current) {
544
+ throw new Error(`Roots not initialized properly. No current root. (E: 459c3a007a30486d96fb8d83f696e239)`);
545
+ }
546
+ if (roots.rel8ns.current.length === 0) {
547
+ throw new Error(`Invalid Roots: empty current root rel8n. (E: bede5864090440bca01ea7ab7fd107d6)`);
548
+ }
549
+ if (roots.rel8ns.current.length > 1) {
550
+ throw new Error(`Invalid Roots: multiple current roots selected. (E: 97561acbf63a48ecaa037697bd26555a)`);
551
+ }
552
+ const currentRootAddr = roots.rel8ns.current[0];
553
+ const resCurrentRoot = await getFromSpace({ addr: currentRootAddr, isMeta: true, space });
554
+ if (resCurrentRoot.ibGibs?.length === 1) {
555
+ return resCurrentRoot.ibGibs[0];
556
+ }
557
+ else {
558
+ throw new Error(`could not get current root. addr: ${currentRootAddr}`);
559
+ }
560
+ }
561
+ catch (error) {
562
+ console.error(`${lc} ${error.message}`);
563
+ return undefined;
564
+ }
565
+ }
566
+ export async function setCurrentRoot({ root, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
567
+ const lc = `[${setCurrentRoot.name}]`;
568
+ try {
569
+ if (!root) {
570
+ throw new Error(`root required.`);
571
+ }
572
+ if (!space) {
573
+ throw new Error(`space required. (E: 186af2731c5342a78b063a0a4346f3db)`);
574
+ }
575
+ const rootAddr = getIbGibAddr({ ibGib: root });
576
+ // get the roots and update its "current" rel8n
577
+ const roots = await getSpecialIbGib({ type: "roots", space });
578
+ if (!roots) {
579
+ throw new Error(`Roots not initialized.`);
580
+ }
581
+ // we'll rel8 current with a linkedRel8n, thus ensuring a maximum of only
582
+ // one rel8d addr (the one we're adding here)
583
+ const rel8nsToAddByAddr = { current: [rootAddr] };
584
+ const resNewRoots = await V1.rel8({
585
+ src: roots,
586
+ dna: false,
587
+ linkedRel8ns: ["past", "ancestor", "current"],
588
+ rel8nsToAddByAddr,
589
+ nCounter: true,
590
+ });
591
+ await persistTransformResult({ isMeta: true, resTransform: resNewRoots, space });
592
+ const configKey = getSpecialConfigKey({ type: "roots" });
593
+ const newRoots = resNewRoots.newIbGib;
594
+ const newRootsAddr = getIbGibAddr({ ibGib: newRoots });
595
+ await setConfigAddr({ key: configKey, addr: newRootsAddr, space, zeroSpace, fnUpdateBootstrap });
596
+ await registerNewIbGib({ ibGib: newRoots, space, fnBroadcast, zeroSpace, fnUpdateBootstrap });
597
+ // how to let others know roots has changed?
598
+ }
599
+ catch (error) {
600
+ console.error(`${lc} ${error.message}`);
601
+ throw error;
602
+ }
603
+ }
604
+ /**
605
+ * Every tjp should be related to one of the roots in a space.
606
+ *
607
+ * You should NOT relate every ibgib frame of a given ibGib.
608
+ */
609
+ export async function rel8ToCurrentRoot({ ibGib, linked, rel8nName, space, fnBroadcast, zeroSpace, fnUpdateBootstrap, }) {
610
+ const lc = `[${rel8ToCurrentRoot.name}]`;
611
+ try {
612
+ if (!space) {
613
+ throw new Error(`space required. (E: f2758eab3bb844d2b749515672d9e392)`);
614
+ }
615
+ if (!ibGib) {
616
+ throw new Error(`ibGib required (E: f1bfd67754a7271553f4af544d30bc22)`);
617
+ }
618
+ let currentRoot = await getCurrentRoot({ space });
619
+ if (!currentRoot) {
620
+ throw new Error('currentRoot undefined (E: 5c2d84dafc664808866008f6eb535750');
621
+ }
622
+ // only relate the tjp to roots and use the latest special index ibgib to
623
+ // have the reference to the latest ibgib in the space.
624
+ const tjpAddr = getTjpAddr({ ibGib, defaultIfNone: "incomingAddr" });
625
+ const ibGibAddr = getIbGibAddr({ ibGib });
626
+ // check to see if it's already rel8d. If so, we're done.
627
+ if (rel8nName && tjpAddr &&
628
+ currentRoot.rel8ns &&
629
+ currentRoot.rel8ns[rel8nName] &&
630
+ currentRoot.rel8ns[rel8nName].includes(tjpAddr)) {
631
+ // already rel8d
632
+ return;
633
+ }
634
+ rel8nName = rel8nName || DEFAULT_ROOT_REL8N_NAME;
635
+ // we only need to add the ibgib itself to the root, not the tjp
636
+ // and not any dependent ibgibs. ...wakka doodle.
637
+ const resNewRoot = await V1.rel8({
638
+ src: currentRoot,
639
+ dna: false,
640
+ linkedRel8ns: linked ? ["past", "ancestor", rel8nName] : ["past", "ancestor"],
641
+ rel8nsToAddByAddr: { [rel8nName]: [ibGibAddr] },
642
+ nCounter: true,
643
+ });
644
+ await persistTransformResult({ isMeta: true, resTransform: resNewRoot, space });
645
+ const newRoot = resNewRoot.newIbGib;
646
+ const newRootAddr = getIbGibAddr({ ibGib: newRoot });
647
+ if (logalot) {
648
+ console.log(`${lc} updating _currentRoot root. newRootAddr: ${newRootAddr}`);
649
+ }
650
+ await registerNewIbGib({ ibGib: newRoot, space, fnBroadcast, zeroSpace, fnUpdateBootstrap });
651
+ await setCurrentRoot({ root: newRoot, space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
652
+ }
653
+ catch (error) {
654
+ console.error(`${lc} ${error.message}`);
655
+ return;
656
+ }
657
+ }
658
+ /**
659
+ * Used for tracking tjpAddr -> latest ibGibAddr.
660
+ *
661
+ * Call this when you create a new ibGib.
662
+ *
663
+ * Need to put this in another service at some point, but crunch crunch
664
+ * like pacman's lunch.
665
+ */
666
+ export async function registerNewIbGib({ ibGib, space, fnBroadcast, zeroSpace, fnUpdateBootstrap, }) {
667
+ let lc = `[${registerNewIbGib.name}]`;
668
+ try {
669
+ const ibGibAddr = getIbGibAddr({ ibGib });
670
+ lc = `${lc}[${ibGibAddr}]`;
671
+ if (!space) {
672
+ throw new Error(`space required. (E: ea0c03256f8a4062b460aa4de11f1e3e)`);
673
+ }
674
+ if (logalot) {
675
+ console.log(`${lc} starting...`);
676
+ }
677
+ // this is the latest index ibGib. It's just the mapping of tjp -> latestAddr.
678
+ // Other refs to "latest" in this function
679
+ // will refer to the actual/attempted latest of the ibGib arg.
680
+ let specialLatest = await getSpecialIbGib({ type: "latest", space });
681
+ if (!specialLatest) {
682
+ throw new Error(`unable to get specialLatest (E: a24f785753e482085b49b74e367cff23)`);
683
+ }
684
+ if (!specialLatest.rel8ns) {
685
+ specialLatest.rel8ns = {};
686
+ }
687
+ // get the tjp for the rel8nName mapping, and also for some checking logic
688
+ let tjp = await getTjpIbGib({ ibGib, space });
689
+ if (!tjp) {
690
+ console.warn(`${lc} tjp not found for ${ibGibAddr}? Should at least just be the ibGib's address itself.`);
691
+ tjp = ibGib;
692
+ }
693
+ let tjpAddr = getIbGibAddr({ ibGib: tjp });
694
+ // either we're adding the given ibGib, replacing the existing with the ibGib,
695
+ // or doing nothing. We can do this with our current vars in a closure at this point.
696
+ const replaceLatest = async () => {
697
+ if (logalot) {
698
+ console.log(`${lc} adding/replacing latest. tjp: ${tjpAddr}`);
699
+ }
700
+ await rel8ToSpecialIbGib({
701
+ type: "latest",
702
+ rel8nName: tjpAddr,
703
+ ibGibsToRel8: [ibGib],
704
+ linked: true,
705
+ deletePreviousSpecialIbGib: true,
706
+ severPast: true,
707
+ // skipRel8ToRoot: true,
708
+ space,
709
+ zeroSpace,
710
+ fnUpdateBootstrap,
711
+ fnBroadcast,
712
+ });
713
+ if (fnBroadcast) {
714
+ fnBroadcast({ tjpAddr, latestAddr: ibGibAddr, latestIbGib: ibGib });
715
+ }
716
+ };
717
+ let existingMapping = specialLatest.rel8ns[tjpAddr] || [];
718
+ if (existingMapping.length > 0) {
719
+ if (logalot) {
720
+ console.log(`${lc} tjp mapping exists. Checking which is newer.`);
721
+ }
722
+ let existingLatestAddr = existingMapping[0];
723
+ // check to see if ibgib is already the latest
724
+ if (existingLatestAddr === ibGibAddr) {
725
+ if (logalot) {
726
+ console.log(`${lc} Neither is newer because ibGibAddr is already registered as latest, so returning without any further action. (I: 7f5bd5d3391be95919240f0e97976e22)`);
727
+ }
728
+ return; /* <<<< returns early */
729
+ }
730
+ // not the latest or not registered, so get the full existing latest
731
+ // ibgib analyze to see if the incoming ibgib is indeed newer
732
+ let resExistingLatest = await getFromSpace({ addr: existingLatestAddr, space });
733
+ if (!resExistingLatest.success || resExistingLatest.ibGibs?.length !== 1) {
734
+ console.error(`Didn't find existing latest ibGib (${existingLatestAddr}). I haven't implemented more robust multi-node/distributed strategies for this scenario yet. User chose YES to replace.`);
735
+ await replaceLatest();
736
+ return;
737
+ }
738
+ const existingLatest = resExistingLatest.ibGibs[0];
739
+ // if there is an nCounter, then we can go by that. Otherwise, we'll
740
+ // try to brute force "latest" comparison
741
+ const ibGibHasNCounter = ibGib.data?.n &&
742
+ typeof ibGib.data.n === 'number' &&
743
+ ibGib.data.n >= 0;
744
+ if (ibGibHasNCounter) {
745
+ // #region ibGib.data.n counter method
746
+ if (logalot) {
747
+ console.log(`found ibGib.data.n (version counter), using this to determine latest ibGib: ${ibGib.data.n}`);
748
+ }
749
+ const n_ibGib = ibGib.data.n;
750
+ const existingLatestHasNCounter = existingLatest.data?.n &&
751
+ typeof existingLatest.data.n === 'number' &&
752
+ existingLatest.data.n >= 0;
753
+ if (existingLatestHasNCounter) {
754
+ // both have counters, so compare by those.
755
+ const n_existingLatest = existingLatest.data.n;
756
+ if (n_ibGib > n_existingLatest) {
757
+ // is newer
758
+ await replaceLatest();
759
+ }
760
+ else {
761
+ // is not newer, so we don't need to do anything else.
762
+ return;
763
+ }
764
+ }
765
+ else {
766
+ // only the new one has the counter, so that wins by default
767
+ await replaceLatest();
768
+ }
769
+ // #endregion
770
+ }
771
+ else {
772
+ if (logalot) {
773
+ console.log(`${lc} no nCounter found. Trying brute force method.`);
774
+ }
775
+ // #region brute force latest
776
+ let latestAddr = await getLatestAddr_Brute({
777
+ ibGib, ibGibAddr,
778
+ existingLatest, existingLatestAddr,
779
+ tjpAddr,
780
+ space,
781
+ });
782
+ if (latestAddr === ibGibAddr) {
783
+ await replaceLatest();
784
+ }
785
+ else {
786
+ return;
787
+ }
788
+ // #endregion
789
+ }
790
+ }
791
+ else {
792
+ // no existing mapping, so go ahead and add.
793
+ if (logalot) {
794
+ console.log(`${lc} no existing tjp mapping. ${tjpAddr} -> ${ibGibAddr}`);
795
+ }
796
+ await replaceLatest();
797
+ }
798
+ }
799
+ catch (error) {
800
+ console.error(`${lc} ${error.message}`);
801
+ throw error;
802
+ }
803
+ finally {
804
+ if (logalot) {
805
+ console.log(`${lc} complete.`);
806
+ }
807
+ }
808
+ }
809
+ /**
810
+ * Performs a rel8 transform on the special ibgib corresponding to the incoming
811
+ * `type`.
812
+ *
813
+ * ## special ibgibs
814
+ *
815
+ * much metadata configuration is stored via "special" ibgibs. Most of these are
816
+ * tracked in a space's ibgib directly, and the space itself is tracked in the
817
+ * bootstrap. So when storing configuration data, I usually create a new special
818
+ * ibgib. this function performs the plumbing for the rel8 transform related to
819
+ * that special ibgib.
820
+ *
821
+ * ## notes
822
+ *
823
+ * * special ibgib must exist in the space, i.e. previously initialized
824
+ * * i'm using this atm for mainly the local ionic space, but sometimes
825
+ * might be good in sync space, i dunno at this point.
826
+ * * I've migrated a lot of local space behavior into this space-agnostic file.
827
+ *
828
+ * @returns new special ibgib addr
829
+ */
830
+ export async function rel8ToSpecialIbGib({ type, rel8nName, ibGibsToRel8, ibGibsToUnRel8, linked, severPast, deletePreviousSpecialIbGib, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
831
+ const lc = `[${rel8ToSpecialIbGib.name}](type:${type},rel8nName:${rel8nName})`;
832
+ try {
833
+ if (!space) {
834
+ throw new Error(`space required. (E: 956192eea28047eba6dad81620bb96fb)`);
835
+ }
836
+ if ((ibGibsToRel8 ?? []).length === 0 && (ibGibsToUnRel8 ?? []).length === 0) {
837
+ throw new Error(`either ibGibsToRel8 or ibGibsToUnRel8 required. (E: 5add49c8e46a54e2c6b057c22646a822)`);
838
+ }
839
+ const addrsToRel8 = ibGibsToRel8?.map(ibGib => getIbGibAddr({ ibGib }));
840
+ const addrsToUnRel8 = ibGibsToUnRel8?.map(ibGib => getIbGibAddr({ ibGib }));
841
+ // get the special ibgib
842
+ const configKey = getSpecialConfigKey({ type });
843
+ let specialAddr = await getConfigAddr({ key: configKey, space });
844
+ if (!specialAddr) {
845
+ throw new Error(`specialAddr not found`);
846
+ }
847
+ ;
848
+ let resGetSpecial = await getFromSpace({ addr: specialAddr, isMeta: true, space });
849
+ if (!resGetSpecial.success) {
850
+ throw new Error(`couldn't get special`);
851
+ }
852
+ if (!resGetSpecial.ibGibs) {
853
+ throw new Error(`resGetSpecial.ibGibs falsy`);
854
+ }
855
+ if (resGetSpecial.ibGibs.length !== 1) {
856
+ throw new Error(`resGetSpecial.ibGibs count is not 1 (${resGetSpecial.ibGibs.length})`);
857
+ }
858
+ // rel8 the new tag to the special ibgib.
859
+ const resNewSpecial = await V1.rel8({
860
+ src: resGetSpecial.ibGibs[0],
861
+ rel8nsToAddByAddr: addrsToRel8 ? { [rel8nName]: addrsToRel8 } : undefined,
862
+ rel8nsToRemoveByAddr: addrsToUnRel8 ? { [rel8nName]: addrsToUnRel8 } : undefined,
863
+ dna: false,
864
+ linkedRel8ns: linked ? [Rel8n.past, rel8nName] : [Rel8n.past],
865
+ nCounter: true,
866
+ });
867
+ const newSpecialIbGib = resNewSpecial.newIbGib;
868
+ // sever
869
+ if (severPast) {
870
+ if (resNewSpecial.intermediateIbGibs) {
871
+ throw new Error('new special creates intermediate ibgibs. so severing past is harder. (E: b580c0c56253494192e9c62212ee187d)');
872
+ }
873
+ newSpecialIbGib.rel8ns.past = [];
874
+ newSpecialIbGib.gib = await getGib({ ibGib: newSpecialIbGib });
875
+ }
876
+ // persist
877
+ await persistTransformResult({ resTransform: resNewSpecial, isMeta: true, space });
878
+ // return the new special address (not the incoming new ibGib)
879
+ const newSpecialAddr = getIbGibAddr({ ibGib: newSpecialIbGib });
880
+ // const specialTjpAddrs = getTjpAddrs({ ibGibs: [newSpecialIbGib] });
881
+ // const specialTjpAddr = specialTjpAddrs?.length > 0 ? specialTjpAddrs[0] : null;
882
+ const specialTjpAddr = getTjpAddr({ ibGib: newSpecialIbGib });
883
+ // update the space ibgib which contains the special/config information
884
+ await setConfigAddr({ key: configKey, addr: newSpecialAddr, space, zeroSpace, fnUpdateBootstrap });
885
+ // delete if required, only after updating config with the new special addr.
886
+ if (deletePreviousSpecialIbGib) {
887
+ await deleteFromSpace({ addr: specialAddr, isMeta: true, space });
888
+ }
889
+ // I'm thinking we also want to register the special ibgib in the latest index...
890
+ if (type === 'latest') {
891
+ // we're relating somethign to the latest index special ibgib (most
892
+ // likely via registerNewIbgib), and we have a new latest index.
893
+ // we already have updated our reference to space(?) so I'm
894
+ // not sure what the problem is right now...
895
+ }
896
+ else {
897
+ // we're relating something to a special ibgib that is NOT the
898
+ // latest index, so our new special ibgib needs to be registered
899
+ // with that latest index.
900
+ await registerNewIbGib({
901
+ ibGib: newSpecialIbGib,
902
+ zeroSpace,
903
+ fnBroadcast,
904
+ fnUpdateBootstrap,
905
+ space,
906
+ });
907
+ }
908
+ if (fnBroadcast && specialTjpAddr) {
909
+ fnBroadcast({
910
+ tjpAddr: specialTjpAddr,
911
+ latestIbGib: newSpecialIbGib,
912
+ latestAddr: newSpecialAddr,
913
+ });
914
+ }
915
+ return newSpecialAddr;
916
+ }
917
+ catch (error) {
918
+ console.error(`${lc} ${error.message}`);
919
+ throw error;
920
+ }
921
+ }
922
+ export async function getTjpIbGib({ ibGib, naive = true, space, }) {
923
+ const lc = `[${getTjpIbGib.name}]`;
924
+ try {
925
+ if (!space) {
926
+ throw new Error(`space required. (E: 941f973d50e84415b58724af173f52c2)`);
927
+ }
928
+ if (!ibGib) {
929
+ throw new Error('ibGib required.');
930
+ }
931
+ let ibGibAddr = getIbGibAddr({ ibGib });
932
+ const { gib } = getIbAndGib({ ibGibAddr });
933
+ if (gib === GIB) {
934
+ return ibGib;
935
+ }
936
+ let isTjp = await isTjp_Naive({ ibGib, naive });
937
+ if (isTjp) {
938
+ return ibGib;
939
+ }
940
+ // the given ibGib arg isn't itself the tjp
941
+ // if no rel8ns, then there is no tjp ibgib, since this is not
942
+ // intrinsically the tjp and there is no 'tjp' or 'past' rel8n to check
943
+ if (!ibGib.rel8ns) {
944
+ if (logalot) {
945
+ console.log(`${lc} ibgib not tjp in data, and rel8ns is falsy. so tjp is undefined (I: acdadb76a7568807db7a68f6f866de22)`);
946
+ }
947
+ return undefined; // <<<< returns early
948
+ }
949
+ // check explicitly listed tjp in rel8ns
950
+ if (ibGib.rel8ns.tjp && ibGib.rel8ns.tjp.length > 0) {
951
+ let firstTjpAddr = ibGib.rel8ns.tjp[0];
952
+ let resGetTjpIbGib = await getFromSpace({ addr: firstTjpAddr, space });
953
+ if (resGetTjpIbGib.success && resGetTjpIbGib.ibGibs?.length === 1) {
954
+ return resGetTjpIbGib.ibGibs[0];
955
+ }
956
+ else {
957
+ const resErrorMsg = resGetTjpIbGib.errorMsg ?? '[unspecified error in get result]';
958
+ throw new Error(`ibGib references tjp but could not retrieve from space. res error: ${resErrorMsg} (E: 94f0340706ad48c794c6a62c1b235a22)`);
959
+ }
960
+ }
961
+ // couldn't get the tjp from the rel8ns.tjp, so look for manually in past.
962
+ // but we can't just get the earliest in the 'past', because the tjp
963
+ // may be one of the intermediates!
964
+ // So, check the immediate past ibGib recursively.
965
+ const past = ibGib.rel8ns.past || [];
966
+ if (past.length === 0) {
967
+ console.warn(`${lc} past.length === 0, so there is no tjp.`);
968
+ if (logalot) {
969
+ console.log(`${lc} ibgib is not tjp in data, not in tjp rel8n, and past is empty. so tjp is undefined (I: bf06f664917dcf4492fb9c4c106a6222)`);
970
+ }
971
+ return undefined; // <<<< returns early
972
+ }
973
+ const pastIbGibAddr = past[past.length - 1];
974
+ const resGetPastIbGib = await getFromSpace({ addr: pastIbGibAddr, space });
975
+ if (!resGetPastIbGib.success || resGetPastIbGib.ibGibs?.length !== 1) {
976
+ throw new Error(`get past failed. addr: ${pastIbGibAddr}`);
977
+ }
978
+ const pastIbGib = resGetPastIbGib.ibGibs[0];
979
+ // call this method recursively!
980
+ return await getTjpIbGib({ ibGib: pastIbGib, naive, space });
981
+ }
982
+ catch (error) {
983
+ console.error(`${lc} ${error.message}`);
984
+ throw error;
985
+ }
986
+ }
987
+ // #region creates
988
+ /**
989
+ * Routing function to various `create_____` functions.
990
+ *
991
+ * @returns address of newly created special.
992
+ */
993
+ export async function createSpecial({ type, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
994
+ const lc = `[${createSpecial.name}]`;
995
+ try {
996
+ if (!space) {
997
+ throw new Error(`space falsy and localUserSpace not initialized. (E: 66e7d3ff098248f0a5ddda51853c92e6)`);
998
+ }
999
+ switch (type) {
1000
+ case "roots": return createSpecial_Roots({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1001
+ case "tags": return createSpecial_Tags({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1002
+ case "latest": return createSpecial_Latest({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1003
+ case "secrets": return createSpecial_Secrets({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1004
+ case "encryptions": return createSpecial_Encryptions({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1005
+ case "outerspaces": return createSpecial_OuterSpaces({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1006
+ case "autosyncs": return createSpecial_Autosyncs({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1007
+ case "robbots": return createSpecial_Robbots({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1008
+ case "apps": return createSpecial_Apps({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1009
+ default: return createSpecial_Default({ type, space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1010
+ }
1011
+ }
1012
+ catch (error) {
1013
+ console.error(`${lc} ${error.message}`);
1014
+ throw error;
1015
+ }
1016
+ }
1017
+ /**
1018
+ * Creates a new special ibgib, persists it and if not skipped, relates
1019
+ * it to the current root.
1020
+ *
1021
+ * @returns newly created ibgib (not just address)
1022
+ */
1023
+ export async function createSpecialIbGib({ type, skipRel8ToRoot, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1024
+ const lc = `[${createSpecialIbGib.name}][${type || 'falsy type?'}]`;
1025
+ try {
1026
+ if (logalot) {
1027
+ console.log(`${lc} starting...`);
1028
+ }
1029
+ const specialIb = getSpecialIbGibIb({ type });
1030
+ const src = factory.primitive({ ib: specialIb });
1031
+ const resNewSpecial = await V1.fork({
1032
+ src,
1033
+ destIb: specialIb,
1034
+ linkedRel8ns: [Rel8n.past, Rel8n.ancestor],
1035
+ tjp: { uuid: true, timestamp: true },
1036
+ dna: false,
1037
+ nCounter: true,
1038
+ });
1039
+ await persistTransformResult({ resTransform: resNewSpecial, isMeta: true, space });
1040
+ if (type !== 'roots' && !skipRel8ToRoot) {
1041
+ await rel8ToCurrentRoot({
1042
+ ibGib: resNewSpecial.newIbGib,
1043
+ linked: true,
1044
+ space,
1045
+ zeroSpace,
1046
+ fnBroadcast,
1047
+ fnUpdateBootstrap,
1048
+ });
1049
+ }
1050
+ if (logalot) {
1051
+ console.log(`${lc} complete.`);
1052
+ }
1053
+ return resNewSpecial.newIbGib;
1054
+ }
1055
+ catch (error) {
1056
+ console.error(`${lc} ${error.message}`);
1057
+ throw error;
1058
+ }
1059
+ }
1060
+ /**
1061
+ * Creates a new tags^gib instance (unique to current space), as well as
1062
+ * default initial tags, e.g. "home", "favorites", etc., and relates these
1063
+ * individual tags to the tags ibGib itself.
1064
+ *
1065
+ * Stores the tags ibGib's addr in config.
1066
+ */
1067
+ export async function createSpecial_Tags({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1068
+ const lc = `[${createSpecial_Tags.name}]`;
1069
+ try {
1070
+ if (!space) {
1071
+ throw new Error(`space required. (E: 9c05b9bd355943a39ca47afef67a50eb)`);
1072
+ }
1073
+ const configKey = getSpecialConfigKey({ type: "tags" });
1074
+ const special = await createSpecialIbGib({
1075
+ type: "tags",
1076
+ space,
1077
+ zeroSpace,
1078
+ fnBroadcast,
1079
+ fnUpdateBootstrap,
1080
+ });
1081
+ let addr = getIbGibAddr({ ibGib: special });
1082
+ await setConfigAddr({ key: configKey, addr: addr, space, zeroSpace, fnUpdateBootstrap });
1083
+ // at this point, our tags ibGib has no associated tag ibGibs.
1084
+ // add home, favorite tags
1085
+ const initialTagDatas = [
1086
+ { text: 'home', icon: 'home-outline' },
1087
+ { text: 'favorite', icon: 'heart-outline' },
1088
+ ];
1089
+ for (const data of initialTagDatas) {
1090
+ const resCreate = await createTagIbGibAndSundry({ ...data, space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1091
+ addr = resCreate.newTagsAddr;
1092
+ await setConfigAddr({ key: configKey, addr: addr, space, zeroSpace, fnUpdateBootstrap });
1093
+ }
1094
+ return addr;
1095
+ }
1096
+ catch (error) {
1097
+ console.error(`${lc} ${error.message}`);
1098
+ return null;
1099
+ }
1100
+ }
1101
+ /**
1102
+ * 1. Creates a new tag ibgib with the given properties.
1103
+ * 2. Persists graph in given {@link space}
1104
+ * 3. Registers the new tag ibgib in that space, using the given
1105
+ * {@link fnUpdateBootstrap} and {@link fnBroadcast} functions.
1106
+ * 4. Relates the new tag to the special tags ibgib.
1107
+ *
1108
+ * @returns the new tag ibgib and new tags address.
1109
+ */
1110
+ export async function createTagIbGibAndSundry({ text, icon, description, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1111
+ const lc = `[${createTagIbGibAndSundry.name}]`;
1112
+ try {
1113
+ if (logalot) {
1114
+ console.log(`${lc} starting...`);
1115
+ }
1116
+ if (!space) {
1117
+ throw new Error(`space required. (E: 5def0b1afab74b0c9286e3ac5060cb8f)`);
1118
+ }
1119
+ if (!text) {
1120
+ throw new Error(`${lc} text required`);
1121
+ }
1122
+ icon = icon || DEFAULT_TAG_ICON;
1123
+ description = description || DEFAULT_TAG_DESCRIPTION;
1124
+ const tagIb = tagTextToIb(text);
1125
+ const tagPrimitive = factory.primitive({ ib: "tag" });
1126
+ const resNewTag = await factory.firstGen({
1127
+ parentIbGib: tagPrimitive,
1128
+ ib: tagIb,
1129
+ data: { text, icon, description },
1130
+ linkedRel8ns: [Rel8n.past, Rel8n.ancestor],
1131
+ tjp: { uuid: true, timestamp: true },
1132
+ dna: true,
1133
+ nCounter: true,
1134
+ });
1135
+ const newTag = resNewTag.newIbGib;
1136
+ await persistTransformResult({ resTransform: resNewTag, isMeta: true, space });
1137
+ await registerNewIbGib({ ibGib: newTag, space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1138
+ const newTagsAddr = await rel8TagToTagsIbGib({
1139
+ tagIbGib: newTag, space, zeroSpace, fnUpdateBootstrap, fnBroadcast,
1140
+ });
1141
+ return { newTagIbGib: newTag, newTagsAddr };
1142
+ }
1143
+ catch (error) {
1144
+ console.error(`${lc} ${error.message}`);
1145
+ throw error;
1146
+ }
1147
+ finally {
1148
+ if (logalot) {
1149
+ console.log(`${lc} complete.`);
1150
+ }
1151
+ }
1152
+ }
1153
+ export async function createSpecial_Roots({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1154
+ const lc = `[${createSpecial_Roots.name}]`;
1155
+ try {
1156
+ if (!space) {
1157
+ throw new Error(`space required. (E: d12a8ea31163429fb6e53ff8e7579c57)`);
1158
+ }
1159
+ const configKey = getSpecialConfigKey({ type: "roots" });
1160
+ // const rootsIbGib = await createSpecialIbGib({type: "roots", space});
1161
+ const rootsIbGib = await createSpecialIbGib({
1162
+ type: "roots",
1163
+ space,
1164
+ zeroSpace,
1165
+ fnBroadcast,
1166
+ fnUpdateBootstrap,
1167
+ });
1168
+ let rootsAddr = getIbGibAddr({ ibGib: rootsIbGib });
1169
+ await setConfigAddr({ key: configKey, addr: rootsAddr, space, zeroSpace, fnUpdateBootstrap });
1170
+ // at this point, our ibGib has no associated ibGibs.
1171
+ // so we add initial roots
1172
+ const rootNames = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
1173
+ const initialDatas = rootNames.map(n => {
1174
+ return {
1175
+ text: `${n}root`,
1176
+ icon: DEFAULT_ROOT_ICON,
1177
+ description: DEFAULT_ROOT_DESCRIPTION
1178
+ };
1179
+ });
1180
+ let firstRoot = undefined;
1181
+ for (let i = 0; i < initialDatas.length; i++) {
1182
+ const data = initialDatas[i];
1183
+ const resCreate = await createRootIbGib({
1184
+ ...data,
1185
+ space,
1186
+ zeroSpace,
1187
+ fnUpdateBootstrap,
1188
+ fnBroadcast,
1189
+ });
1190
+ if (!firstRoot) {
1191
+ firstRoot = resCreate.newRootIbGib;
1192
+ }
1193
+ if (!resCreate.newRootIbGib) {
1194
+ throw new Error(`(UNEXPECTED) resCreate.newRootIbGib falsy? (E: c9fb2c94a9c1d762c1699b41a4d5ad23)`);
1195
+ }
1196
+ rootsAddr = resCreate.newRootsAddr;
1197
+ // update the config for the updated **roots** ibgib.
1198
+ // that roots ibgib is what points to the just created new root.
1199
+ await setConfigAddr({ key: configKey, addr: rootsAddr, space, zeroSpace, fnUpdateBootstrap });
1200
+ }
1201
+ if (!firstRoot) {
1202
+ throw new Error(`(UNEXPECTED) firstRoot still falsy? (E: b2e2c926d242966e7ed7159e4b129e23)`);
1203
+ }
1204
+ // initialize current root
1205
+ await setCurrentRoot({ root: firstRoot, space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
1206
+ // hack: the above line updates the roots in config. so get **that** addr.
1207
+ rootsAddr = await getConfigAddr({ key: configKey, space });
1208
+ if (!rootsAddr) {
1209
+ throw new Error('(UNEXPECTED) no roots address in config? (E: 76345340699a4738a195e48803ef0d31)');
1210
+ }
1211
+ return rootsAddr;
1212
+ }
1213
+ catch (error) {
1214
+ console.error(`${lc} ${error.message}`);
1215
+ return null;
1216
+ }
1217
+ }
1218
+ async function createRootIbGib({ text, icon, description, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1219
+ const lc = `[${createRootIbGib.name}]`;
1220
+ try {
1221
+ if (!space) {
1222
+ throw new Error(`space required. (E: cfa876e5c8c64a53a463ca7a645571c8)`);
1223
+ }
1224
+ text = text || DEFAULT_ROOT_TEXT;
1225
+ icon = icon || DEFAULT_ROOT_ICON;
1226
+ description = description || DEFAULT_ROOT_DESCRIPTION;
1227
+ const ib = getRootIb(text);
1228
+ const parentIbGib = factory.primitive({ ib: "root" });
1229
+ const resNewIbGib = await factory.firstGen({
1230
+ parentIbGib,
1231
+ ib,
1232
+ data: { text, icon, description },
1233
+ linkedRel8ns: [Rel8n.past, Rel8n.ancestor],
1234
+ tjp: { uuid: true, timestamp: true },
1235
+ dna: true,
1236
+ });
1237
+ const { newIbGib } = resNewIbGib;
1238
+ await persistTransformResult({
1239
+ resTransform: resNewIbGib,
1240
+ isMeta: true,
1241
+ space,
1242
+ });
1243
+ const newRootsAddr = await rel8ToSpecialIbGib({
1244
+ type: "roots",
1245
+ rel8nName: ROOT_REL8N_NAME,
1246
+ ibGibsToRel8: [newIbGib],
1247
+ // isMeta: true,
1248
+ space,
1249
+ zeroSpace,
1250
+ fnUpdateBootstrap,
1251
+ fnBroadcast,
1252
+ });
1253
+ return { newRootIbGib: newIbGib, newRootsAddr };
1254
+ }
1255
+ catch (error) {
1256
+ console.error(`${lc} ${error.message}`);
1257
+ throw error;
1258
+ }
1259
+ }
1260
+ async function createSpecial_Latest({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1261
+ const lc = `[${createSpecial_Latest.name}]`;
1262
+ try {
1263
+ if (!space) {
1264
+ throw new Error(`space required. (E: 173b08d7eb114238b32280c3efce9d1a)`);
1265
+ }
1266
+ const configKey = getSpecialConfigKey({ type: "latest" });
1267
+ // const special =
1268
+ // await createSpecialIbGib({type: "latest", skipRel8ToRoot: true, space});
1269
+ const special = await createSpecialIbGib({
1270
+ type: "latest",
1271
+ space,
1272
+ skipRel8ToRoot: true,
1273
+ zeroSpace,
1274
+ fnBroadcast,
1275
+ fnUpdateBootstrap,
1276
+ });
1277
+ let specialAddr = getIbGibAddr({ ibGib: special });
1278
+ await setConfigAddr({ key: configKey, addr: specialAddr, space, zeroSpace, fnUpdateBootstrap });
1279
+ // right now, the latest ibgib doesn't have any more initialization,
1280
+ // since it is supposed to be as ephemeral and non-tracked as possible.
1281
+ return specialAddr;
1282
+ }
1283
+ catch (error) {
1284
+ console.error(`${lc} ${error.message}`);
1285
+ return null;
1286
+ }
1287
+ }
1288
+ async function createSpecial_Secrets({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1289
+ const lc = `[${createSpecial_Secrets.name}]`;
1290
+ try {
1291
+ if (!space) {
1292
+ throw new Error(`space required. (E: 340960cd5ad24addb300b23d9722e30a)`);
1293
+ }
1294
+ let secretsAddr;
1295
+ const configKey = getSpecialConfigKey({ type: "secrets" });
1296
+ // special ibgib doesn't exist, so create it (empty)
1297
+ // const secretsIbgib = await createSpecialIbGib({type: "secrets", space});
1298
+ const secretsIbgib = await createSpecialIbGib({
1299
+ type: "secrets",
1300
+ space,
1301
+ zeroSpace,
1302
+ fnBroadcast,
1303
+ fnUpdateBootstrap,
1304
+ });
1305
+ secretsAddr = getIbGibAddr({ ibGib: secretsIbgib });
1306
+ await setConfigAddr({ key: configKey, addr: secretsAddr, space, zeroSpace, fnUpdateBootstrap });
1307
+ return secretsAddr;
1308
+ }
1309
+ catch (error) {
1310
+ console.error(`${lc} ${error.message}`);
1311
+ return null;
1312
+ }
1313
+ }
1314
+ async function createSpecial_Encryptions({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1315
+ const lc = `[${createSpecial_Encryptions.name}]`;
1316
+ try {
1317
+ if (!space) {
1318
+ throw new Error(`space required. (E: 5084e698b6924e7090697ca50075ca59)`);
1319
+ }
1320
+ let addr;
1321
+ const configKey = getSpecialConfigKey({ type: "encryptions" });
1322
+ // special ibgib doesn't exist, so create it (empty)
1323
+ // const encryptionsIbgib = await createSpecialIbGib({type: "encryptions", space});
1324
+ const encryptionsIbgib = await createSpecialIbGib({
1325
+ type: "encryptions",
1326
+ space,
1327
+ zeroSpace,
1328
+ fnBroadcast,
1329
+ fnUpdateBootstrap,
1330
+ });
1331
+ addr = getIbGibAddr({ ibGib: encryptionsIbgib });
1332
+ await setConfigAddr({ key: configKey, addr: addr, space, zeroSpace, fnUpdateBootstrap });
1333
+ return addr;
1334
+ }
1335
+ catch (error) {
1336
+ console.error(`${lc} ${error.message}`);
1337
+ return null;
1338
+ }
1339
+ }
1340
+ async function createSpecial_OuterSpaces({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1341
+ const lc = `[${createSpecial_OuterSpaces.name}]`;
1342
+ try {
1343
+ if (!space) {
1344
+ throw new Error(`space required. (E: 99dd9e92535c470482eb9f6625a33831)`);
1345
+ }
1346
+ let outerSpacesAddr;
1347
+ const configKey = getSpecialConfigKey({ type: "outerspaces" });
1348
+ // special outerspaces ibgib doesn't exist, so create it (empty)
1349
+ // const outerSpacesIbGib = await createSpecialIbGib({type: "outerspaces", space});
1350
+ const outerSpacesIbGib = await createSpecialIbGib({
1351
+ type: "outerspaces",
1352
+ space,
1353
+ zeroSpace,
1354
+ fnBroadcast,
1355
+ fnUpdateBootstrap,
1356
+ });
1357
+ outerSpacesAddr = getIbGibAddr({ ibGib: outerSpacesIbGib });
1358
+ await setConfigAddr({ key: configKey, addr: outerSpacesAddr, space, zeroSpace, fnUpdateBootstrap });
1359
+ return outerSpacesAddr;
1360
+ }
1361
+ catch (error) {
1362
+ console.error(`${lc} ${error.message}`);
1363
+ return null;
1364
+ }
1365
+ }
1366
+ async function createSpecial_Autosyncs({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1367
+ const lc = `[${createSpecial_Autosyncs.name}]`;
1368
+ try {
1369
+ if (!space) {
1370
+ throw new Error(`space required. (E: f01cf6a4a460486796e16d505d629522)`);
1371
+ }
1372
+ let autosyncsAddr;
1373
+ const configKey = getSpecialConfigKey({ type: "autosyncs" });
1374
+ const autosyncsIbGib = await createSpecialIbGib({
1375
+ type: "autosyncs",
1376
+ space,
1377
+ zeroSpace,
1378
+ fnBroadcast,
1379
+ fnUpdateBootstrap,
1380
+ });
1381
+ autosyncsAddr = getIbGibAddr({ ibGib: autosyncsIbGib });
1382
+ await setConfigAddr({ key: configKey, addr: autosyncsAddr, space, zeroSpace, fnUpdateBootstrap });
1383
+ return autosyncsAddr;
1384
+ }
1385
+ catch (error) {
1386
+ console.error(`${lc} ${error.message}`);
1387
+ return null;
1388
+ }
1389
+ }
1390
+ export async function createSpecial_Robbots({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1391
+ const lc = `[${createSpecial_Robbots.name}]`;
1392
+ try {
1393
+ if (!space) {
1394
+ throw new Error(`space required. (E: f01cf6a4a460486796e16d505d629522)`);
1395
+ }
1396
+ let robbotsAddr;
1397
+ const configKey = getSpecialConfigKey({ type: "robbots" });
1398
+ const robbotsIbGib = await createSpecialIbGib({
1399
+ type: "robbots",
1400
+ space,
1401
+ zeroSpace,
1402
+ fnBroadcast,
1403
+ fnUpdateBootstrap,
1404
+ });
1405
+ robbotsAddr = getIbGibAddr({ ibGib: robbotsIbGib });
1406
+ await setConfigAddr({ key: configKey, addr: robbotsAddr, space, zeroSpace, fnUpdateBootstrap });
1407
+ return robbotsAddr;
1408
+ }
1409
+ catch (error) {
1410
+ console.error(`${lc} ${error.message}`);
1411
+ return null;
1412
+ }
1413
+ }
1414
+ export async function createSpecial_Apps({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1415
+ const lc = `[${createSpecial_Apps.name}]`;
1416
+ try {
1417
+ if (!space) {
1418
+ throw new Error(`space required. (E: f01cf6a4a460486796e16d505d629522)`);
1419
+ }
1420
+ let appsAddr;
1421
+ const configKey = getSpecialConfigKey({ type: "apps" });
1422
+ const appsIbGib = await createSpecialIbGib({
1423
+ type: "apps",
1424
+ space,
1425
+ zeroSpace,
1426
+ fnBroadcast,
1427
+ fnUpdateBootstrap,
1428
+ });
1429
+ appsAddr = getIbGibAddr({ ibGib: appsIbGib });
1430
+ await setConfigAddr({ key: configKey, addr: appsAddr, space, zeroSpace, fnUpdateBootstrap });
1431
+ // at this point, our apps ibGib has no associated app ibGibs.
1432
+ // so create our initial apps.
1433
+ // appsAddr = await createApps_Chat({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
1434
+ appsAddr = await createApp({
1435
+ defaultAppData: DEFAULT_CHAT_APP_DATA_V1,
1436
+ defaultAppRel8ns: DEFAULT_CHAT_APP_REL8NS_V1,
1437
+ space, zeroSpace, fnUpdateBootstrap, fnBroadcast,
1438
+ });
1439
+ // appsAddr = await createApps_Raw({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
1440
+ appsAddr = await createApp({
1441
+ defaultAppData: DEFAULT_RAW_APP_DATA_V1,
1442
+ defaultAppRel8ns: DEFAULT_RAW_APP_REL8NS_V1,
1443
+ space, zeroSpace, fnUpdateBootstrap, fnBroadcast,
1444
+ });
1445
+ // appsAddr = await createApps_Todo({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
1446
+ appsAddr = await createApp({
1447
+ defaultAppData: DEFAULT_TODO_APP_DATA_V1,
1448
+ defaultAppRel8ns: DEFAULT_TODO_APP_REL8NS_V1,
1449
+ space, zeroSpace, fnUpdateBootstrap, fnBroadcast,
1450
+ });
1451
+ return appsAddr;
1452
+ }
1453
+ catch (error) {
1454
+ console.error(`${lc} ${error.message}`);
1455
+ return null;
1456
+ }
1457
+ }
1458
+ export async function createApp({ defaultAppData, defaultAppRel8ns, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1459
+ const lc = `[${createApp.name}]`;
1460
+ try {
1461
+ if (logalot) {
1462
+ console.log(`${lc} starting... (I: 677f68789abdc7316887e8f38c764e22)`);
1463
+ }
1464
+ // #region torn from chat-app-v1.ts because of circular dependency...eesh
1465
+ if (logalot) {
1466
+ console.log(`${lc} starting...`);
1467
+ }
1468
+ let data = clone(defaultAppData);
1469
+ let rel8ns = defaultAppRel8ns ? clone(defaultAppRel8ns) : undefined;
1470
+ data.uuid = data.uuid ?? await getUUID();
1471
+ let { classname } = data;
1472
+ const ib = getAppIb({ appData: data, classname });
1473
+ const resNewApp = await factory.firstGen({
1474
+ ib,
1475
+ parentIbGib: factory.primitive({ ib: `app ${classname}` }),
1476
+ data: data,
1477
+ rel8ns,
1478
+ dna: true,
1479
+ linkedRel8ns: [Rel8n.ancestor, Rel8n.past],
1480
+ nCounter: true,
1481
+ tjp: { timestamp: true },
1482
+ });
1483
+ // #endregion torn from chat-app-v1.ts because of circular dependency...eesh
1484
+ await persistTransformResult({ resTransform: resNewApp, space });
1485
+ await registerNewIbGib({
1486
+ ibGib: resNewApp.newIbGib,
1487
+ fnBroadcast, fnUpdateBootstrap,
1488
+ space, zeroSpace
1489
+ });
1490
+ let appsAddr = await rel8ToSpecialIbGib({
1491
+ type: "apps",
1492
+ rel8nName: APP_REL8N_NAME,
1493
+ ibGibsToRel8: [resNewApp.newIbGib],
1494
+ fnBroadcast, fnUpdateBootstrap,
1495
+ space, zeroSpace,
1496
+ });
1497
+ return appsAddr;
1498
+ }
1499
+ catch (error) {
1500
+ console.error(`${lc} ${error.message}`);
1501
+ throw error;
1502
+ }
1503
+ finally {
1504
+ if (logalot) {
1505
+ console.log(`${lc} complete.`);
1506
+ }
1507
+ }
1508
+ }
1509
+ async function createSpecial_Default({ type, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1510
+ const lc = `[${createSpecial_Autosyncs.name}]`;
1511
+ try {
1512
+ if (!space) {
1513
+ throw new Error(`space required. (E: c7bbafcbe901418db4c6048f17f53091)`);
1514
+ }
1515
+ if (logalot) {
1516
+ console.log(`${lc} creating special of type: ${type} (I: 283c8bb30ed6f9698b74b886c6078622)`);
1517
+ }
1518
+ let specialAddr;
1519
+ const configKey = getSpecialConfigKey({ type });
1520
+ const specialIbGib = await createSpecialIbGib({
1521
+ type,
1522
+ space,
1523
+ zeroSpace,
1524
+ fnBroadcast,
1525
+ fnUpdateBootstrap,
1526
+ });
1527
+ specialAddr = getIbGibAddr({ ibGib: specialIbGib });
1528
+ await setConfigAddr({ key: configKey, addr: specialAddr, space, zeroSpace, fnUpdateBootstrap });
1529
+ return specialAddr;
1530
+ }
1531
+ catch (error) {
1532
+ console.error(`${lc} ${error.message}`);
1533
+ return null;
1534
+ }
1535
+ }
1536
+ /**
1537
+ * 1. Creates a new robbot ibgib with the given properties.
1538
+ * 2. Persists graph in given {@link space}
1539
+ * 3. Registers the new robbot ibgib in that space, using the given
1540
+ * {@link fnUpdateBootstrap} and {@link fnBroadcast} functions.
1541
+ * 4. Relates the new robbot to the special robbots ibgib.
1542
+ *
1543
+ * @returns the new robbot ibgib and new robbots address.
1544
+ */
1545
+ // export async function createRobbotIbGib({
1546
+ // robbotData,
1547
+ // space,
1548
+ // zeroSpace,
1549
+ // fnUpdateBootstrap,
1550
+ // fnBroadcast,
1551
+ // }: {
1552
+ // robbotData: RobbotData_V1,
1553
+ // space: IbGibSpaceAny,
1554
+ // zeroSpace: IbGibSpaceAny,
1555
+ // fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
1556
+ // fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
1557
+ // }): Promise<{ newRobbotIbGib: RobbotIbGib_V1, newRobbotsAddr: string }> {
1558
+ // const lc = `[${createRobbotIbGib.name}]`;
1559
+ // try {
1560
+ // if (logalot) { console.log(`${lc} starting...`); }
1561
+ // if (!space) { throw new Error(`space required. (E: 5def0b1afab74b0c9286e3ac5060cb8f)`); }
1562
+ // if (!robbotData) { throw new Error(`robbotData required (E: cd0304401a2f5a63d86dd71f76f31222)`); }
1563
+ // const ib = getRobbotIb({ robbotData });
1564
+ // const resNewRobbot = await factory.firstGen({
1565
+ // parentIbGib: factory.primitive({ ib: "robbot" }),
1566
+ // ib,
1567
+ // data: robbotData,
1568
+ // linkedRel8ns: [Rel8n.past, Rel8n.ancestor],
1569
+ // tjp: { uuid: true, timestamp: true },
1570
+ // dna: true,
1571
+ // nCounter: true,
1572
+ // });
1573
+ // const newRobbot = (resNewRobbot.newIbGib as RobbotIbGib_V1);
1574
+ // await persistTransformResult({ resTransform: resNewRobbot, isMeta: true, space });
1575
+ // await registerNewIbGib({ ibGib: newRobbot, space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
1576
+ // const newRobbotsAddr = await rel8ToSpecialIbGib({
1577
+ // type: "robbots",
1578
+ // rel8nName: ROBBOT_REL8N_NAME,
1579
+ // ibGibsToRel8: [newRobbot],
1580
+ // space,
1581
+ // zeroSpace,
1582
+ // fnUpdateBootstrap,
1583
+ // fnBroadcast,
1584
+ // });
1585
+ // return { newRobbotIbGib: newRobbot, newRobbotsAddr };
1586
+ // } catch (error) {
1587
+ // console.error(`${lc} ${error.message}`);
1588
+ // throw error;
1589
+ // } finally {
1590
+ // if (logalot) { console.log(`${lc} complete.`); }
1591
+ // }
1592
+ // }
1593
+ /**
1594
+ * We are NOT searching through all of our data looking for a needle in a haystack.
1595
+ * What we ARE doing is we are looking through the past of the existing latest and
1596
+ * the prospective latest (the given ibGib param) and comparing between the two.
1597
+ *
1598
+ * Since `past` rel8n is usually a linked rel8n now, we may have to traverse it all
1599
+ * the way to its beginning for each possibility.
1600
+ *
1601
+ * @returns either {@param ibGibAddr} or {@param existingLatestAddr}
1602
+ */
1603
+ async function getLatestAddr_Brute({ ibGib, ibGibAddr, existingLatest, existingLatestAddr, tjpAddr, space, }) {
1604
+ const lc = `[${getLatestAddr_Brute.name}][${ibGibAddr}]`;
1605
+ try {
1606
+ if (logalot) {
1607
+ console.log(`${lc} starting...`);
1608
+ }
1609
+ if (!space) {
1610
+ throw new Error(`space required. (E: 64eb9a271f5d43deadec30b9638746c8)`);
1611
+ }
1612
+ // no nCounter, so we need to brute force.
1613
+ // The easiest way is to check each's past, as the most common
1614
+ // scenario would be registering a newer one, or less likely, a timing issue
1615
+ // with registering a previous ibGib frame.
1616
+ let ibGibPast = ibGib.rel8ns?.past || [];
1617
+ let existingLatestPast = existingLatest.rel8ns?.past || [];
1618
+ // going to check a bunch of specific, easy cases to narrow things down.
1619
+ if (ibGibPast.length === 1 && existingLatestPast.length === 0) {
1620
+ if (logalot) {
1621
+ console.log(`prospective has a past, so it "must" be newer. (won't quote "must" anymore)`);
1622
+ }
1623
+ return ibGibAddr;
1624
+ }
1625
+ else if (existingLatestPast.length === 1 && ibGibPast.length === 0) {
1626
+ if (logalot) {
1627
+ console.log(`existing has a past, so it must be newer.`);
1628
+ }
1629
+ return existingLatestAddr;
1630
+ }
1631
+ else if (existingLatestPast.length === 0 && ibGibPast.length === 0) {
1632
+ console.warn(`${lc} neither existing latest nor prospective new ibGib has a past, so keeping existing.`);
1633
+ return existingLatestAddr;
1634
+ }
1635
+ else if (existingLatestPast.includes(ibGibAddr)) {
1636
+ if (logalot) {
1637
+ console.log(`existing by definition is newer`);
1638
+ }
1639
+ return existingLatestAddr;
1640
+ }
1641
+ else if (ibGibPast.includes(existingLatestAddr)) {
1642
+ if (logalot) {
1643
+ console.log(`ibGib by definition is newer`);
1644
+ }
1645
+ return ibGibAddr;
1646
+ }
1647
+ else if (existingLatestAddr === ibGibAddr) {
1648
+ if (logalot) {
1649
+ console.log(`they're the same!`);
1650
+ }
1651
+ return existingLatestAddr;
1652
+ }
1653
+ else if (existingLatestAddr === tjpAddr && existingLatest.rel8ns?.tjp?.length === 1) {
1654
+ if (logalot) {
1655
+ console.log(`ibGib must be newer because the existingLatestAddr is the tjp, which is by definition first in unique past.`);
1656
+ }
1657
+ return ibGibAddr;
1658
+ }
1659
+ else if (ibGibAddr === tjpAddr && ibGib.rel8ns?.tjp?.length === 1) {
1660
+ if (logalot) {
1661
+ console.log(`existing must be newer because the ibGibAddr is the tjp, which is by definition first in unique past.`);
1662
+ }
1663
+ return existingLatestAddr;
1664
+ }
1665
+ // well, neither one really gives us any indicator alone
1666
+ // so load each one in the past
1667
+ if (logalot) {
1668
+ console.log(`${lc} brute forcing through iterating the pasts.`);
1669
+ }
1670
+ let newerAddr;
1671
+ let firstIterationCount = -1; // klugy hack, but is an ugly method anyway (brute after all!)
1672
+ let getPastCount = async (x, n, otherAddr) => {
1673
+ let xPast = x.rel8ns?.past || [];
1674
+ if (xPast.includes(otherAddr)) {
1675
+ // no need to proceed further, since the other is found in the past of x, so x is newer
1676
+ newerAddr = getIbGibAddr({ ibGib: x });
1677
+ return -1;
1678
+ }
1679
+ if (xPast.length === 0) {
1680
+ return n;
1681
+ } // no more past to increment
1682
+ let newCount = n + xPast.length;
1683
+ if (firstIterationCount !== -1 && newCount > firstIterationCount) {
1684
+ // we've determined that the second iteration has a longer past,
1685
+ // so we don't need to look further
1686
+ newerAddr = getIbGibAddr({ ibGib: x });
1687
+ return -1;
1688
+ }
1689
+ // load up the earliest one and call recursively
1690
+ let resNextX = await getFromSpace({ addr: xPast[0], space });
1691
+ if (!resNextX.success || resNextX.ibGibs?.length !== 1) {
1692
+ throw new Error(`Couldn't load past addr (xPast[0]): ${xPast[0]}`);
1693
+ }
1694
+ return getPastCount(resNextX.ibGibs[0], n + xPast.length, otherAddr);
1695
+ };
1696
+ if (logalot) {
1697
+ console.log(`${lc} doing ibGibPastCount`);
1698
+ }
1699
+ let ibGibPastCount = await getPastCount(ibGib, 0, existingLatestAddr);
1700
+ if (newerAddr) {
1701
+ return newerAddr;
1702
+ }
1703
+ // we didn't hit upon it, so set the firstIterationCount so we don't spend unnecessary cycles
1704
+ if (logalot) {
1705
+ console.log(`${lc} Doing existingPastCount`);
1706
+ }
1707
+ firstIterationCount = ibGibPastCount;
1708
+ let existingPastCount = await getPastCount(existingLatest, 0, ibGibAddr);
1709
+ if (newerAddr) {
1710
+ return newerAddr;
1711
+ }
1712
+ // we didn't yet determine it, so whichever has the longer past is newer
1713
+ if (ibGibPastCount > existingPastCount) {
1714
+ if (logalot) {
1715
+ console.log(`${lc} ibGibPastCount (${ibGibPastCount}) is longer than existingPastCount (${existingPastCount}), so ibGib is newer.`);
1716
+ }
1717
+ newerAddr = ibGibAddr;
1718
+ }
1719
+ else {
1720
+ if (logalot) {
1721
+ console.log(`${lc} existingPastCount (${existingPastCount}) is longer than ibGibPastCount (${ibGibPastCount}), so ibGib is newer.`);
1722
+ }
1723
+ newerAddr = existingLatestAddr;
1724
+ }
1725
+ return newerAddr;
1726
+ }
1727
+ catch (error) {
1728
+ console.error(`${lc} ${error.message}`);
1729
+ throw error;
1730
+ }
1731
+ finally {
1732
+ if (logalot) {
1733
+ console.log(`${lc} complete.`);
1734
+ }
1735
+ }
1736
+ }
1737
+ // #endregion
1738
+ /**
1739
+ * Relates the given tag to the TagsIbGib, saves the generated
1740
+ * TagsIbGib and updates the settings to point to the new TagsIbGib.
1741
+ *
1742
+ * @param tagIbGib to add to Tags
1743
+ */
1744
+ export function rel8TagToTagsIbGib({ tagIbGib, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
1745
+ return rel8ToSpecialIbGib({
1746
+ type: "tags",
1747
+ rel8nName: TAG_REL8N_NAME,
1748
+ ibGibsToRel8: [tagIbGib],
1749
+ space,
1750
+ zeroSpace,
1751
+ fnUpdateBootstrap,
1752
+ fnBroadcast,
1753
+ });
1754
+ }
1755
+ /**
1756
+ * Throws an error if any duplicates found in either array.
1757
+ *
1758
+ * ## notes
1759
+ *
1760
+ * Only pass in ibGib or ibGibAddrs, not both. Warns if both are passed in though.
1761
+ *
1762
+ * @throws if both params are falsy or if addrs || mapped addrs contains duplicates.
1763
+ */
1764
+ export function throwIfDuplicates({ ibGibs, ibGibAddrs, }) {
1765
+ const lc = `[${throwIfDuplicates.name}]`;
1766
+ try {
1767
+ if (!ibGibs && !ibGibAddrs) {
1768
+ throw new Error(`either ibGibs or ibGibAddrs required. (E: 37776788620f4966b0964945ce181fc6)`);
1769
+ }
1770
+ if (ibGibs && ibGibAddrs) {
1771
+ console.warn(`${lc} both ibGibs and ibGibAddrs provided. You should only provide one. Only ibGibAddrs will be checked. (W: dc13f9e197834e2daaba3bcfd08418db)`);
1772
+ }
1773
+ const addrs = ibGibAddrs ? ibGibAddrs.concat() : ibGibs.map(x => getIbGibAddr({ ibGib: x }));
1774
+ for (let i = 0; i < addrs.length; i++) {
1775
+ const addr = addrs[i];
1776
+ if (addrs.filter(x => x === addr).length > 1) {
1777
+ throw new Error(`duplicate addr found: ${addr} (E: 70fbef040dd449c38c667d53b8092053)`);
1778
+ }
1779
+ }
1780
+ }
1781
+ catch (error) {
1782
+ console.error(`${lc} ${error.message}`);
1783
+ throw error;
1784
+ }
1785
+ }
1786
+ export function getSpaceLockAddr({ space, scope, }) {
1787
+ const lc = `[${getSpaceLockAddr.name}]`;
1788
+ try {
1789
+ if (logalot) {
1790
+ console.log(`${lc} starting...`);
1791
+ }
1792
+ if (!space) {
1793
+ throw new Error(`space required. (E: 3ba16e6c3e5e47948b0e63448da11752)`);
1794
+ }
1795
+ if (!space.data?.uuid) {
1796
+ throw new Error(`invalid space (space.data.uuid falsy) (E: 273262b32f2ef27b2e690bc699f33822)`);
1797
+ }
1798
+ if (!scope) {
1799
+ throw new Error(`scope required. (E: f47801d6c45e2247b42a53d9b604b522)`);
1800
+ }
1801
+ while (scope.includes(IBGIB_DELIMITER)) {
1802
+ if (logalot) {
1803
+ console.log(`${lc} scope contains ibgib delimiter...replacing... (I: 0f456fd7cc6552a799673a0c5b4a7d22)`);
1804
+ }
1805
+ scope = scope.replace(IBGIB_DELIMITER, '_');
1806
+ }
1807
+ const spaceId = space.data.uuid;
1808
+ const ib = `${SPACE_LOCK_IB_TERM} ${spaceId} ${scope}`;
1809
+ const gib = GIB;
1810
+ return getIbGibAddr({ ib, gib });
1811
+ }
1812
+ catch (error) {
1813
+ console.error(`${lc} ${error.message}`);
1814
+ throw error;
1815
+ }
1816
+ finally {
1817
+ if (logalot) {
1818
+ console.log(`${lc} complete.`);
1819
+ }
1820
+ }
1821
+ }
1822
+ /**
1823
+ * Executes some function `fn` against/in a given `space` while
1824
+ * performing lock plumbing in that space.
1825
+ *
1826
+ * By this, I mean that this function takes care of acquiring the lock,
1827
+ * attempting retries according to the parameters, and then unlocking
1828
+ * the space regardless of result/error.
1829
+ *
1830
+ * @returns result of inner `fn` with `TResult`
1831
+ */
1832
+ export async function execInSpaceWithLocking({ space, scope, secondsValid, maxDelayMs, fn, callerInstanceId, maxLockAttempts, }) {
1833
+ const lc = `[${execInSpaceWithLocking.name}]`;
1834
+ try {
1835
+ if (logalot) {
1836
+ console.log(`${lc} starting...`);
1837
+ }
1838
+ // #region validation
1839
+ if (!space) {
1840
+ throw new Error(`space required. (E: 66fd8f21a5b2b572d18cdeb9472a7722)`);
1841
+ }
1842
+ if (!secondsValid) {
1843
+ throw new Error(`secondsValid required. (E: 92c5610e57ceede5ce83cff86d5c2a22)`);
1844
+ }
1845
+ if (secondsValid < 0) {
1846
+ throw new Error(`secondsValid must be positive. (E: 970a7510c517235d7a355a843d18d222)`);
1847
+ }
1848
+ // if (secondsValid > MAX_LOCK_SECONDS_VALID) { throw new Error(`secondsValid arg (${secondsValid}) exceeds max secondsValid (${MAX_LOCK_SECONDS_VALID}) (E: 4cffe49a23c8f1698bf7c78eaccbb722)`); }
1849
+ if (!fn) {
1850
+ throw new Error(`fnGet required (E: 7022e280252ec2faf756b6db05c56e22)`);
1851
+ }
1852
+ // #endregion validation
1853
+ let resultFn;
1854
+ if (logalot) {
1855
+ console.log(`${lc} attempting to acquire lock with scope ${scope} (I: fed36d42a975b1c52897a4df804ac722)`);
1856
+ }
1857
+ let lockIbGib;
1858
+ maxDelayMs =
1859
+ (maxDelayMs ?? 0) > 0 ? maxDelayMs : DEFAULT_MAX_DELAY_MS_RETRY_LOCK_ACQUIRE;
1860
+ let attempts = 0;
1861
+ maxLockAttempts =
1862
+ maxLockAttempts ?? -1 > 0 ?
1863
+ maxLockAttempts :
1864
+ DEFAULT_MAX_DELAY_RETRY_LOCK_ACQUIRE_ATTEMPTS;
1865
+ do {
1866
+ lockIbGib = await lockSpace({
1867
+ space,
1868
+ scope,
1869
+ secondsValid,
1870
+ instanceId: callerInstanceId,
1871
+ });
1872
+ if (lockIbGib?.data?.success) {
1873
+ break;
1874
+ }
1875
+ /** Delay a small random amount of time before trying again. */
1876
+ let delayMs = Math.ceil(Math.random() * maxDelayMs);
1877
+ await delay(delayMs);
1878
+ } while (attempts < maxLockAttempts);
1879
+ if (lockIbGib?.data?.success) {
1880
+ if (logalot) {
1881
+ console.log(`${lc} lock acquired. (I: d847fa953ee131a57e1a89c537342722)`);
1882
+ }
1883
+ }
1884
+ else {
1885
+ throw new Error(`could not acquire lock after ${attempts} attempts with intermittent delays of ${maxDelayMs} ms (E: 898c559dbd0c9bf20c14cf87a8f1e222)`);
1886
+ }
1887
+ // execute the actual get inside an additional try..catch..finally
1888
+ // to ensure (attempted) unlockSpace call.
1889
+ const lc2 = `${lc}[fn]`;
1890
+ try {
1891
+ if (logalot) {
1892
+ console.log(`${lc2} starting... (I: c2f7bedf95d3f1dd1f76de34a68d3f22)`);
1893
+ }
1894
+ resultFn = await fn();
1895
+ }
1896
+ catch (error) {
1897
+ console.error(`${lc2} ${error.message}`);
1898
+ throw error;
1899
+ }
1900
+ finally {
1901
+ if (logalot) {
1902
+ console.log(`${lc2} unlocking space with scope: ${scope} (I: 21034d9c3395499756e9000e40417d22)`);
1903
+ }
1904
+ await unlockSpace({ space: space, scope: scope, instanceId: callerInstanceId });
1905
+ if (logalot) {
1906
+ console.log(`${lc2} complete. (I: 79d8ac03714a4d429c7e6c2ac6e18d22)`);
1907
+ }
1908
+ }
1909
+ return resultFn;
1910
+ }
1911
+ catch (error) {
1912
+ console.error(`${lc} ${error.message}`);
1913
+ throw error;
1914
+ }
1915
+ finally {
1916
+ if (logalot) {
1917
+ console.log(`${lc} complete.`);
1918
+ }
1919
+ }
1920
+ }
1921
+ /**
1922
+ * Gets the bootstrap ibgib in the given `zeroSpace`.
1923
+ *
1924
+ * @example
1925
+ *
1926
+ * ```json
1927
+ * {
1928
+ * "ib":"bootstrap",
1929
+ * "gib":"gib",
1930
+ * "data":{
1931
+ * "defaultSpaceId":"d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33",
1932
+ * "spaceIds":["d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33"]
1933
+ * },
1934
+ * "rel8ns":{
1935
+ * "d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33":[
1936
+ * "witness space IonicSpace_V1 oij d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33^B336251655E8C56B38E9E86F20E0E42E6C153785F1A0A798ADE6916E71CF055B"
1937
+ * ]
1938
+ * }
1939
+ * }
1940
+ * ```
1941
+ *
1942
+ * @returns bootstrapIbGib if found
1943
+ */
1944
+ export async function getValidatedBootstrapIbGib({ zeroSpace, }) {
1945
+ const lc = `[${getValidatedBootstrapIbGib.name}]`;
1946
+ try {
1947
+ if (logalot) {
1948
+ console.log(`${lc} starting...`);
1949
+ }
1950
+ if (!zeroSpace) {
1951
+ throw new Error(`zeroSpace required. (E: 66fd8f21a5b2b572d18cdeb9472a7722)`);
1952
+ }
1953
+ const bootstrapAddr = BOOTSTRAP_IBGIB_ADDR;
1954
+ if (logalot) {
1955
+ console.log(`${lc} getting from zeroSpace...`);
1956
+ }
1957
+ const argGet = await zeroSpace.argy({
1958
+ ibMetadata: getSpaceArgMetadata({ space: zeroSpace }),
1959
+ argData: {
1960
+ cmd: 'get',
1961
+ ibGibAddrs: [bootstrapAddr],
1962
+ isMeta: true,
1963
+ },
1964
+ });
1965
+ const resGetBootstrapIbGib = await zeroSpace.witness(argGet);
1966
+ if (resGetBootstrapIbGib?.data?.success && resGetBootstrapIbGib.ibGibs?.length === 1) {
1967
+ // bootstrap found
1968
+ const bootstrapIbGib = resGetBootstrapIbGib.ibGibs[0];
1969
+ if (logalot) {
1970
+ console.log(`${lc} bootstrapibGib found: ${pretty(bootstrapIbGib)}`);
1971
+ }
1972
+ if (await validateBootstrapIbGib(bootstrapIbGib)) {
1973
+ return bootstrapIbGib;
1974
+ }
1975
+ else {
1976
+ if (logalot) {
1977
+ console.log(`${lc} bootstrapIbGib was invalid. (I: cce66b26805404fc85525d565e1f8b22)`);
1978
+ }
1979
+ return null;
1980
+ }
1981
+ }
1982
+ else {
1983
+ if (logalot) {
1984
+ console.log(`${lc} bootstrapIbGib NOT found. (I: 421562993bf3464eb507d2967d311e22)`);
1985
+ }
1986
+ return null;
1987
+ }
1988
+ }
1989
+ catch (error) {
1990
+ console.error(`${lc} ${error.message}`);
1991
+ throw error;
1992
+ }
1993
+ finally {
1994
+ if (logalot) {
1995
+ console.log(`${lc} complete.`);
1996
+ }
1997
+ }
1998
+ }
1999
+ /**
2000
+ * So when loading the local user space, even if the class changes or default
2001
+ * constructors change, the internal `data` is loaded from file.
2002
+ */
2003
+ export async function getLocalSpace({ zeroSpace, bootstrapIbGib, localSpaceId, lock, callerInstanceId, fnDtoToSpace, localSpaceCacheSvc, }) {
2004
+ const lc = `[${getLocalSpace.name}]`;
2005
+ try {
2006
+ if (!zeroSpace) {
2007
+ throw new Error(`zeroSpace required. (E: 0793781a98c456a666cfa9eb960bcd22)`);
2008
+ }
2009
+ if (!bootstrapIbGib) {
2010
+ if (logalot) {
2011
+ console.log(`${lc} bootstrap falsy, so loading it... (I: f2366e38283495a38b5501297aa34422)`);
2012
+ }
2013
+ if (lock) {
2014
+ const bootstrapAddr = BOOTSTRAP_IBGIB_ADDR;
2015
+ if (logalot) {
2016
+ console.log(`${lc} using locked version of loading bootstrap... (I: 52b9b11999674e586d051c2b23f59b22)`);
2017
+ }
2018
+ bootstrapIbGib = await execInSpaceWithLocking({
2019
+ space: zeroSpace,
2020
+ scope: bootstrapAddr,
2021
+ fn: async () => {
2022
+ let validatedBootstrapIbGib = await getValidatedBootstrapIbGib({ zeroSpace });
2023
+ if (validatedBootstrapIbGib) {
2024
+ return validatedBootstrapIbGib;
2025
+ }
2026
+ else {
2027
+ throw new Error(`(UNEXPECTED) unable to get bootstrap ibgib? (E: c111dc7627acbfb992134ddf4064ea23)`);
2028
+ }
2029
+ },
2030
+ callerInstanceId,
2031
+ secondsValid: DEFAULT_SECONDS_VALID_LOCAL,
2032
+ });
2033
+ }
2034
+ else {
2035
+ if (logalot) {
2036
+ console.log(`${lc} lock is false, so just getting the bootstrap ibgib (I: 49d55e5a824510bb3ee0ccd9f5ec3322)`);
2037
+ }
2038
+ bootstrapIbGib = await getValidatedBootstrapIbGib({ zeroSpace }) ?? undefined;
2039
+ }
2040
+ }
2041
+ if (!bootstrapIbGib) {
2042
+ throw new Error(`bootstrapIbGib falsy. not initialized? (E: 91f5c82b5e124178d958701ebcb09822)`);
2043
+ }
2044
+ if (!bootstrapIbGib.data) {
2045
+ throw new Error(`(UNEXPECTED) bootstrapIbGib.data required. invalid bootstrap? (E: 568c6b837c1a39f7a25d188a90167423)`);
2046
+ }
2047
+ localSpaceId = localSpaceId ?? bootstrapIbGib.data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY];
2048
+ const localSpaceAddr = bootstrapIbGib.rel8ns[localSpaceId][0]; // guaranteed b/c bootstrap was validated
2049
+ const fnGet = async () => {
2050
+ const argGet = await zeroSpace.argy({
2051
+ ibMetadata: getSpaceArgMetadata({ space: zeroSpace }),
2052
+ argData: {
2053
+ cmd: 'get',
2054
+ ibGibAddrs: [localSpaceAddr],
2055
+ isMeta: true,
2056
+ },
2057
+ });
2058
+ const resLocalSpace = await zeroSpace.witness(argGet);
2059
+ if (resLocalSpace?.data?.success && resLocalSpace.ibGibs?.length === 1) {
2060
+ const localSpaceDto = resLocalSpace.ibGibs[0];
2061
+ const localSpace = await fnDtoToSpace(localSpaceDto);
2062
+ if (localSpaceCacheSvc) {
2063
+ localSpace.cacheSvc = localSpaceCacheSvc;
2064
+ }
2065
+ return localSpace;
2066
+ }
2067
+ else {
2068
+ throw new Error(`Could not get local space addr (${localSpaceAddr}) specified in bootstrap space (${getIbGibAddr({ ibGib: bootstrapIbGib })}). (E: 6d6b45e7eae4472697ddc971438e4922)`);
2069
+ }
2070
+ };
2071
+ if (lock) {
2072
+ if (logalot) {
2073
+ console.log(`${lc} getting localSpaceId (${localSpaceId}) WITH locking (I: c48a0e4ac5971cdbc57273dd35f8a522)`);
2074
+ }
2075
+ return await execInSpaceWithLocking({
2076
+ space: zeroSpace,
2077
+ scope: localSpaceId,
2078
+ fn: () => { return fnGet(); },
2079
+ callerInstanceId,
2080
+ secondsValid: DEFAULT_SECONDS_VALID_LOCAL,
2081
+ });
2082
+ }
2083
+ else {
2084
+ if (logalot) {
2085
+ console.log(`${lc} getting localSpaceId (${localSpaceId}) WITHOUT locking (I: 48e504835dee4006839df8820d860b22)`);
2086
+ }
2087
+ return fnGet();
2088
+ }
2089
+ }
2090
+ catch (error) {
2091
+ console.error(`${lc} ${error.message}`);
2092
+ throw error;
2093
+ }
2094
+ }
2095
+ export async function lockSpace({ space, scope, secondsValid, instanceId, }) {
2096
+ const lc = `[${lockSpace.name}]`;
2097
+ try {
2098
+ if (logalot) {
2099
+ console.log(`${lc} starting...`);
2100
+ }
2101
+ if (!space) {
2102
+ throw new Error(`space required. (E: 5c0a7197a75f483a82d74e5eea60df37)`);
2103
+ }
2104
+ if (!scope) {
2105
+ throw new Error(`scope required. (E: c7f1dde9570f4df3b450faa2c2f85122)`);
2106
+ }
2107
+ if (!secondsValid) {
2108
+ throw new Error(`secondsValid required and positive (E: b42b6733638b46c06c9aff59a6c49822)`);
2109
+ }
2110
+ if (secondsValid < 0) {
2111
+ throw new Error(`secondsValid must be positive (E: bbe3b6d567583bfb35a1c0825eb29622)`);
2112
+ }
2113
+ /** what we will return */
2114
+ let resLockIbGib;
2115
+ /** space lock address is deterministic ibgib primitive (gib === 'gib') */
2116
+ const spaceLockAddr = getSpaceLockAddr({ space, scope });
2117
+ // check for existing lock...
2118
+ let existingLock;
2119
+ // ...in space's backing store (file, IndexedDB entry, DB, etc.)
2120
+ let getLock = await getFromSpace({
2121
+ addr: spaceLockAddr, isMeta: true, space, force: true
2122
+ });
2123
+ if (getLock.success && getLock.ibGibs?.length === 1) {
2124
+ existingLock = getLock.ibGibs[0];
2125
+ if (existingLock?.data?.expirationUTC) {
2126
+ if (isExpired({ expirationTimestampUTC: existingLock.data.expirationUTC })) {
2127
+ // lock expired, so log only. skipping delete atow because should be overwritten
2128
+ // when the new lock is in place.
2129
+ if (logalot) {
2130
+ console.log(`${lc} ignoring expired existing lock in space at ${spaceLockAddr}. Should be overwritten (I: 7421c5b051724b189f88cecbbd449b22)`);
2131
+ }
2132
+ existingLock = undefined;
2133
+ }
2134
+ }
2135
+ else {
2136
+ console.error(`${lc} exisingLock.data.expirationUTC falsy? (E: 218dc0e935534a149d0be153c532cf25)`);
2137
+ existingLock = undefined;
2138
+ }
2139
+ }
2140
+ else {
2141
+ if (logalot) {
2142
+ console.log(`${lc} existing lock not found for ${spaceLockAddr} (I: 191af56ec4e2db3d19084e46bf949222)`);
2143
+ }
2144
+ }
2145
+ // populate resLockIbGib if/else existingLock
2146
+ if (existingLock && existingLock.data) {
2147
+ if (!existingLock.data) {
2148
+ throw new Error(`(UNEXPECTED) existingLock.data falsy? (E: 00069b4662e5566d971760d15e293723)`);
2149
+ }
2150
+ // valid lock already exists, so return informing caller. this includes
2151
+ // the existing lock's info, i.e. its expiration
2152
+ resLockIbGib = clone(existingLock);
2153
+ resLockIbGib.data.alreadyLocked = true;
2154
+ resLockIbGib.data.success = false;
2155
+ }
2156
+ else {
2157
+ // not yet locked so immediately lock in memory for space, then via
2158
+ // `space.put(lock)`
2159
+ const { ib, gib } = getIbAndGib({ ibGibAddr: spaceLockAddr });
2160
+ resLockIbGib = {
2161
+ ib, gib,
2162
+ data: {
2163
+ scope,
2164
+ secondsValid,
2165
+ instanceId,
2166
+ expirationUTC: getExpirationUTCString({ seconds: secondsValid }),
2167
+ }
2168
+ };
2169
+ const resPut = await putInSpace({ ibGib: resLockIbGib, isMeta: true, force: true, space });
2170
+ if (resPut.success) {
2171
+ resLockIbGib.data.success = true;
2172
+ }
2173
+ else {
2174
+ const emsg = `${lc} there was an error putting the lock in the space: ${resPut.errorMsg}`;
2175
+ resLockIbGib.data.success = false;
2176
+ resLockIbGib.data.errorMsg = emsg;
2177
+ console.error(emsg);
2178
+ }
2179
+ }
2180
+ return resLockIbGib;
2181
+ }
2182
+ catch (error) {
2183
+ console.error(`${lc} ${error.message}`);
2184
+ throw error;
2185
+ }
2186
+ finally {
2187
+ if (logalot) {
2188
+ console.log(`${lc} complete.`);
2189
+ }
2190
+ }
2191
+ }
2192
+ export async function unlockSpace({ space, scope, instanceId, }) {
2193
+ const lc = `[${unlockSpace.name}]`;
2194
+ try {
2195
+ if (logalot) {
2196
+ console.log(`${lc} starting...`);
2197
+ }
2198
+ if (!space) {
2199
+ throw new Error(`space required. (E: 5c0a7197a75f483a82d74e5eea60df37)`);
2200
+ }
2201
+ if (!scope) {
2202
+ throw new Error(`scope required. (E: c7f1dde9570f4df3b450faa2c2f85122)`);
2203
+ }
2204
+ /** space lock address is deterministic ibgib primitive (gib === 'gib') */
2205
+ const spaceLockAddr = getSpaceLockAddr({ space, scope });
2206
+ // delete in file if it exists
2207
+ let resDelete = await deleteFromSpace({ addr: spaceLockAddr, isMeta: true, space, force: true });
2208
+ if (resDelete.success) {
2209
+ const { ib, gib } = getIbAndGib({ ibGibAddr: spaceLockAddr });
2210
+ return {
2211
+ ib, gib,
2212
+ data: {
2213
+ // action: 'unlock',
2214
+ success: true,
2215
+ instanceId,
2216
+ scope,
2217
+ }
2218
+ };
2219
+ }
2220
+ else {
2221
+ /** May NOT be an error, just setting this here is convenient to code. */
2222
+ const emsg = `Delete lock in space failed. delete errorMsg: ${resDelete.errorMsg}`;
2223
+ if (emsg.includes('not implemented')) {
2224
+ // rethrow error if space has not implemented a delete command handler
2225
+ throw new Error(emsg);
2226
+ }
2227
+ else if (emsg.toLowerCase().includes(`does not exist`) ||
2228
+ emsg.toLowerCase().includes(`doesn't exist`) ||
2229
+ emsg.toLowerCase().includes(`not found`)) {
2230
+ // don't want to warn if just file didn't exist
2231
+ if (logalot) {
2232
+ console.log(`${lc} ${emsg} (I: b647916fd0f3e5366e9387131be21c22)`);
2233
+ }
2234
+ const { ib, gib } = getIbAndGib({ ibGibAddr: spaceLockAddr });
2235
+ return {
2236
+ ib, gib,
2237
+ data: {
2238
+ action: 'unlock',
2239
+ success: true,
2240
+ instanceId,
2241
+ scope,
2242
+ }
2243
+ };
2244
+ }
2245
+ else {
2246
+ console.warn(`${lc} ${emsg} (W: 14c84fcac15944bd9a417099964d5d9d)`);
2247
+ }
2248
+ }
2249
+ }
2250
+ catch (error) {
2251
+ console.error(`${lc} ${error.message}`);
2252
+ throw error;
2253
+ }
2254
+ finally {
2255
+ if (logalot) {
2256
+ console.log(`${lc} complete.`);
2257
+ }
2258
+ }
2259
+ }
2260
+ /**
2261
+ * Updates the bootstrap^gib record in the default space data store
2262
+ * with the 'space' rel8n set to the `newSpaceAddr`.
2263
+ *
2264
+ * This way, if the app closes at this point, it will know to look at this
2265
+ * space when it loads.
2266
+ *
2267
+ * ## notes
2268
+ *
2269
+ * I'm probably typing this all over, but the bootstrap^gib is the
2270
+ * first record that the app looks at to know what space to load.
2271
+ * The space itself has configuration and has a proper gib hash
2272
+ * so it's verifiable. But the initial bootstrap^gib record is
2273
+ * NOT, since it only has 'gib' as its address (and thus its not hashed).
2274
+ *
2275
+ * In the future, this could be alleviated by asking other witnesses
2276
+ * "Hey what was my last bootstrap^gib hash", but there's no way to
2277
+ * do it beyond this without using some kind of authentication/secret(s)
2278
+ * that generate the record, i.e. encrypting bootstrap^gib cleverly.
2279
+ */
2280
+ export async function updateBootstrapIbGib({ space, zeroSpace, setSpaceAsDefault, createIfNotFound, }) {
2281
+ const lc = `[${updateBootstrapIbGib.name}]`;
2282
+ try {
2283
+ if (logalot) {
2284
+ console.log(`${lc} starting...`);
2285
+ }
2286
+ if (!space) {
2287
+ throw new Error(`space required. (E: 6fc19548fa7d1d5219e19871f280a322)`);
2288
+ }
2289
+ if (!space.data?.uuid) {
2290
+ throw new Error(`space.data.uuid required (E: 6483188ca6f2ed2085fd355595f3ab22)`);
2291
+ }
2292
+ if (!zeroSpace) {
2293
+ throw new Error(`zeroSpace required. (E: abbf156e18b1018d96273e22a260f122)`);
2294
+ }
2295
+ const spaceId = space.data.uuid;
2296
+ const newSpaceAddr = getIbGibAddr({ ibGib: space });
2297
+ /** validated bootstrap ibgib or null */
2298
+ let bootstrapIbGib = await getValidatedBootstrapIbGib({ zeroSpace });
2299
+ if (!bootstrapIbGib) {
2300
+ if (!createIfNotFound) {
2301
+ if (logalot) {
2302
+ console.log(`${lc} bootstrapIbGib not found but createIfNotFound falsy, so returning early. (I: 5c67d85a8599a5ba4a6780f26a66ea22)`);
2303
+ }
2304
+ return; /* <<<< returns early */
2305
+ }
2306
+ // create the bootstrap^gib space that points to user space
2307
+ if (logalot) {
2308
+ console.log(`${lc} creating new bootstrap ibgib for spaceId (${spaceId}) with address of (${newSpaceAddr}) (I: 651959c27bf2ebc5be1f7f44e2b9e422)`);
2309
+ }
2310
+ const { ib: bootstrapIb, gib } = getIbAndGib({ ibGibAddr: BOOTSTRAP_IBGIB_ADDR });
2311
+ bootstrapIbGib = factory.primitive({ ib: bootstrapIb });
2312
+ bootstrapIbGib.gib = gib;
2313
+ bootstrapIbGib.data = {
2314
+ /**
2315
+ * first space is automatically set as default, regardless of
2316
+ * `setSpaceAsDefault` value
2317
+ */
2318
+ [BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY]: spaceId,
2319
+ [BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY]: [spaceId],
2320
+ };
2321
+ bootstrapIbGib.rel8ns = {
2322
+ /**
2323
+ * individual spaces indexed by spaceId, should be length === 1
2324
+ * with the value being the most recent.
2325
+ */
2326
+ [spaceId]: [newSpaceAddr],
2327
+ };
2328
+ }
2329
+ else {
2330
+ // at this point, we have a validated bootstrap.
2331
+ // update existing bootstrap with newSpaceAddr for given spaceId
2332
+ if (logalot) {
2333
+ console.log(`${lc} updating existing bootstrap (I: 977d4aa7ed47bef73b35743c05ce0722)`);
2334
+ }
2335
+ if (bootstrapIbGib.data.spaceIds.includes(spaceId)) {
2336
+ if (logalot) {
2337
+ console.log(`${lc} space already rel8d to bootstrap, possibly updating its addr (I: b5e2c515ef732d4bbcf02625a9e7c722)`);
2338
+ }
2339
+ const existingSpaceAddr = bootstrapIbGib.rel8ns[spaceId][0];
2340
+ if (existingSpaceAddr === newSpaceAddr) {
2341
+ if (logalot) {
2342
+ console.log(`${lc} bootstrap already rel8d to space (I: c1be027b23e7350c64790a631cae2822)`);
2343
+ }
2344
+ }
2345
+ else {
2346
+ if (logalot) {
2347
+ console.log(`${lc} updating rel8ns[${spaceId}] with newSpaceAddr (${newSpaceAddr}). (Old address: ${existingSpaceAddr})(I: 297a9b0061fd471b8d28a06e04a6ad22)`);
2348
+ }
2349
+ bootstrapIbGib.rel8ns[spaceId] = [newSpaceAddr];
2350
+ }
2351
+ }
2352
+ else {
2353
+ // new space being rel8d to bootstrap
2354
+ if (logalot) {
2355
+ console.log(`${lc} new space being rel8d. adding spaceId to data.spaceIds and amending rel8ns (I: 40903d71719aa1d56e498299f5699a22)`);
2356
+ }
2357
+ bootstrapIbGib.data.spaceIds.push(spaceId);
2358
+ bootstrapIbGib.rel8ns[spaceId] = [newSpaceAddr];
2359
+ }
2360
+ if (setSpaceAsDefault) {
2361
+ if (logalot) {
2362
+ console.log(`${lc} setting spaceId (${spaceId}) as default space (I: f85eda6c6ad2b0bec9750ce3c7795b22)`);
2363
+ }
2364
+ bootstrapIbGib.data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY] = spaceId;
2365
+ }
2366
+ }
2367
+ if (!bootstrapIbGib) {
2368
+ throw new Error(`(UNEXPECTED) bootstrapIbGib still falsy? (E: cf21d7f1756710a66aa0e6a28d762723)`);
2369
+ }
2370
+ if (logalot) {
2371
+ console.log(`${lc} saving bootstrapIbGib: ${pretty(bootstrapIbGib)} (I: 3cceca0b98dde90e4a58a734be252322)`);
2372
+ }
2373
+ // save the bootstrap^gib in the zero space for future space loadings,
2374
+ // especially when the app first starts up
2375
+ const argPutBootstrap = await zeroSpace.argy({
2376
+ ibMetadata: bootstrapIbGib.ib,
2377
+ argData: {
2378
+ cmd: 'put', isMeta: true, force: true,
2379
+ ibGibAddrs: [getIbGibAddr({ ibGib: bootstrapIbGib })],
2380
+ },
2381
+ ibGibs: [bootstrapIbGib],
2382
+ });
2383
+ if (logalot) {
2384
+ console.log(`${lc} zeroSpace will witness/put... (I: 1be9aca22ffc4951b6690965a7aeae5b)`);
2385
+ }
2386
+ const resPutBootstrap = await zeroSpace.witness(argPutBootstrap);
2387
+ if (resPutBootstrap?.data?.success) {
2388
+ if (logalot) {
2389
+ console.log(`${lc} zero space put complete. (I: ac3056d655e841f1a3c442bcc64942f9)`);
2390
+ }
2391
+ }
2392
+ else {
2393
+ throw new Error(`${resPutBootstrap?.data?.errors?.join('|') || "There was a problem with zeroSpace witnessing the bootstrap^gib primitive pointing to the new user space"}`);
2394
+ }
2395
+ if (logalot) {
2396
+ console.log(`${lc} complete.`);
2397
+ }
2398
+ }
2399
+ catch (error) {
2400
+ console.error(`${lc} ${error.message}`);
2401
+ throw error;
2402
+ }
2403
+ }
2404
+ export function getSpaceArgMetadata({ space }) {
2405
+ return `${space.ib} ${getTimestampInTicks()}`;
2406
+ }
2407
+ export function getSpaceResultMetadata({ space }) {
2408
+ return `${space.ib} ${getTimestampInTicks()}`;
2409
+ }
2410
+ export function getSpaceIb({ space, classname, }) {
2411
+ const lc = `[${getSpaceIb.name}]`;
2412
+ try {
2413
+ if (!space) {
2414
+ throw new Error(`space required (E: 4dabec34ee77d67c9cc30ee3c3049622)`);
2415
+ }
2416
+ if (!space.data) {
2417
+ throw new Error(`space.data required (E: 058d298876ebbeada7bbddb9e3da2f23)`);
2418
+ }
2419
+ if (!classname) {
2420
+ throw new Error(`classname required (E: fa3af4613ad56742dab51d1b0d839322)`);
2421
+ }
2422
+ if (classname.includes(' ')) {
2423
+ throw new Error(`invalid classname. cannot contain spaces (E: 243adbf720dcce7904e2665933208b22)`);
2424
+ }
2425
+ const name = space.data?.name || IBGIB_SPACE_NAME_DEFAULT;
2426
+ if (name.includes(' ')) {
2427
+ throw new Error(`invalid space name. cannot contain spaces (E: a8450e1651081412c8ac018520182422)`);
2428
+ }
2429
+ const id = space.data?.uuid || undefined;
2430
+ if (!id) {
2431
+ throw new Error(`invalid space, space.data.uuid falsy (E: 50ae723a9ab24f4fc7132613e65faf23)`);
2432
+ }
2433
+ if (id.includes(' ')) {
2434
+ throw new Error(`invalid space id. cannot contain spaces (E: 8696830fe7f54bfa85e670a063f3e089)`);
2435
+ }
2436
+ let ib = `witness space ${classname} ${name} ${id}`;
2437
+ return ib;
2438
+ }
2439
+ catch (error) {
2440
+ console.error(`${lc} ${error.message}`);
2441
+ throw error;
2442
+ }
2443
+ }
2444
+ export function isSpaceIb({ ib }) {
2445
+ const lc = `[${isSpaceIb.name}]`;
2446
+ try {
2447
+ if (logalot) {
2448
+ console.log(`${lc} starting... (I: 53ad337f8148616a77caca5dff0f8722)`);
2449
+ }
2450
+ return ib.startsWith('witness space ') || ib.startsWith('outerspace sync ');
2451
+ }
2452
+ catch (error) {
2453
+ console.error(`${lc} ${error.message}`);
2454
+ throw error;
2455
+ }
2456
+ finally {
2457
+ if (logalot) {
2458
+ console.log(`${lc} complete.`);
2459
+ }
2460
+ }
2461
+ }
2462
+ /**
2463
+ * ## current schema FOR LOCAL (IONIC) SPACES:
2464
+ *
2465
+ * `witness space [classname] [spaceName] [spaceId]`
2466
+ *
2467
+ * ## current schema FOR SYNC (AWS) OUTERSPACES:
2468
+ *
2469
+ * `outerspace sync [spaceName]
2470
+ *
2471
+ * ## I need to fix this somehow...
2472
+ *
2473
+ * This is why I'm working on streamlining space management
2474
+ *
2475
+ * (To start with, I just had to get the ball rolling and tried my best.)
2476
+ *
2477
+ * ## NOTES
2478
+ *
2479
+ * * both schemas are space-delimited
2480
+ */
2481
+ export function getInfoFromSpaceIb({ spaceIb, }) {
2482
+ const lc = `[${getInfoFromSpaceIb.name}]`;
2483
+ try {
2484
+ if (!spaceIb) {
2485
+ throw new Error(`spaceIb required (E: fa5424cfb7e846e2851562f2f417944f)`);
2486
+ }
2487
+ if (spaceIb.startsWith('witness space ')) {
2488
+ const pieces = spaceIb.split(' ');
2489
+ return {
2490
+ spaceClassname: pieces[2],
2491
+ spaceName: pieces[3],
2492
+ spaceId: pieces[4],
2493
+ spaceType: 'local',
2494
+ };
2495
+ }
2496
+ else if (spaceIb.startsWith('outerspace sync ')) {
2497
+ const pieces = spaceIb.split(' ');
2498
+ return {
2499
+ spaceClassname: undefined,
2500
+ spaceName: pieces[2],
2501
+ spaceId: undefined,
2502
+ spaceType: 'outer',
2503
+ };
2504
+ }
2505
+ else {
2506
+ throw new Error(`unknown spaceIb schema (spaceIb: ${spaceIb}) (E: a6d361be85d5f25d6a464a5896186322)`);
2507
+ }
2508
+ }
2509
+ catch (error) {
2510
+ console.error(`${lc} ${error.message}`);
2511
+ throw error;
2512
+ }
2513
+ }
2514
+ /**
2515
+ * Helper function that generates a unique-ish id.
2516
+ *
2517
+ * atow this is just `return (await getUUID()).slice(0, DEFAULT_TX_ID_LENGTH);`
2518
+ *
2519
+ * ## notes
2520
+ *
2521
+ * The thinking is that it only has to be a couple characters in length
2522
+ * because this is supposed to only be a unique id within the scope of
2523
+ * a tx which has its own tjp (gib) used as the id for the entire communication
2524
+ * saga.
2525
+ *
2526
+ * @returns txId
2527
+ */
2528
+ export async function getNewTxId({ length, } = { length: DEFAULT_TX_ID_LENGTH }) {
2529
+ const lc = `[${getNewTxId.name}]`;
2530
+ try {
2531
+ length = length || DEFAULT_TX_ID_LENGTH;
2532
+ return (await getUUID()).slice(0, length);
2533
+ }
2534
+ catch (error) {
2535
+ console.error(`${lc} ${error.message}`);
2536
+ throw error;
2537
+ }
2538
+ }
2539
+ /**
2540
+ * wrapper for dealing with a space.
2541
+ *
2542
+ * convenience function for creating an arg ibgib to send to the given space
2543
+ * using Cmd/CmdModifiers for getting latest addrs.
2544
+ *
2545
+ * @returns space result ibgib from the given `space.witness` call.
2546
+ */
2547
+ export async function getLatestAddrs({ ibGibs, addrs, tjps, tjpAddrs, space, }) {
2548
+ let lc = `[${getLatestAddrs.name}]`;
2549
+ try {
2550
+ if (logalot) {
2551
+ console.log(`${lc} starting...`);
2552
+ }
2553
+ if (!space) {
2554
+ throw new Error(`space required. (E: 4d188d6c863246f28aa575753a052304)`);
2555
+ }
2556
+ // so we don't have to do a bunch of conditional checks all over
2557
+ ibGibs = ibGibs ?? [];
2558
+ addrs = addrs ?? [];
2559
+ tjps = tjps ?? [];
2560
+ tjpAddrs = tjpAddrs ?? [];
2561
+ if (addrs.length === 0 && ibGibs.length === 0 &&
2562
+ tjps.length === 0 && tjpAddrs.length === 0) {
2563
+ throw new Error(`Either addrs, ibGibs, tjps, or tjpAddrs required. (E: 7c6ebfbab98d4d21a431b144457fd991)`);
2564
+ }
2565
+ /**
2566
+ * Addrs that we'll ultimately send to the space. They start off as
2567
+ * tjpAddrs (and derived from `tjps` if any), and then add the incoming
2568
+ * ibgibs/addrs if we don't already have their corresponding tjpAddrs
2569
+ * being queried.
2570
+ * */
2571
+ const addrsToQuery = new Set(tjpAddrs.concat(tjps.map(ibGib => getIbGibAddr({ ibGib }))));
2572
+ // add ibgibs/addrs only if they do not already have their corresponding
2573
+ // tjpAddr in the query addrs. We can do this by checking if the tjpGib
2574
+ // is located in the ibGibAddr.gib, which has the form
2575
+ // [punctiliarHash].[tjpGib]
2576
+ const tjpGibs = Array.from(addrsToQuery).map(x => getIbAndGib({ ibGibAddr: x }).gib);
2577
+ ibGibs.map(ibGib => getIbGibAddr({ ibGib }))
2578
+ .concat(addrs)
2579
+ .forEach(ibGibAddr => {
2580
+ const { gib } = getIbAndGib({ ibGibAddr });
2581
+ const addrHasExistingTjpGib = tjpGibs.some(tjpGib => gib.includes(tjpGib));
2582
+ if (!addrHasExistingTjpGib) {
2583
+ addrsToQuery.add(ibGibAddr);
2584
+ }
2585
+ });
2586
+ if (logalot) {
2587
+ console.log(`${lc}[testing] ${space.data?.name || space.ib} (${space.data?.uuid || '[space.data.uuid falsy]'}) addrsToQuery: ${Array.from(addrsToQuery)} (I: 8a2202912c364238b6d6eb09577bc246)`);
2588
+ }
2589
+ // construct the arg and execute
2590
+ const argGet = await space.argy({
2591
+ ibMetadata: getSpaceArgMetadata({ space }),
2592
+ argData: {
2593
+ cmd: 'get',
2594
+ cmdModifiers: ['latest', 'addrs'],
2595
+ ibGibAddrs: Array.from(addrsToQuery),
2596
+ },
2597
+ });
2598
+ return await space.witness(argGet);
2599
+ }
2600
+ catch (error) {
2601
+ console.error(`${lc} ${error.message}`);
2602
+ throw error;
2603
+ }
2604
+ }
2605
+ /**
2606
+ * I'm making this because i want to archive on a special tags index ibgib.
2607
+ * But we can't allow archiving on any old special ibgib, like the 'latest' index.
2608
+ * so this checks to see if it's on the forbidden list (winging that atm), and if it
2609
+ * is then this throws.
2610
+ *
2611
+ * use this function inside of commands that act on ibgibs that are special.
2612
+ */
2613
+ export function throwIfContextIsSpecial({ ibGib_Context, }) {
2614
+ const lc = `[${throwIfContextIsSpecial.name}]`;
2615
+ try {
2616
+ if (logalot) {
2617
+ console.log(`${lc} starting... (I: 5f583fd94d27731a65d514e731b8aa22)`);
2618
+ }
2619
+ if (!isSpecial({ ibGib: ibGib_Context })) {
2620
+ return; /* <<<< returns early */
2621
+ ;
2622
+ }
2623
+ const FORBIDDEN_MANUAL_SPECIAL_TYPES = [
2624
+ 'latest', 'roots', 'autosyncs'
2625
+ ];
2626
+ if (FORBIDDEN_MANUAL_SPECIAL_TYPES.some(x => ibGib_Context.ib.includes(x))) {
2627
+ throw new Error(`cannot perform a modification of this type on this special ibgib (E: b8fb718a7323fc54454464b973412722)`);
2628
+ }
2629
+ }
2630
+ catch (error) {
2631
+ console.error(`${lc} ${error.message}`);
2632
+ throw error;
2633
+ }
2634
+ finally {
2635
+ if (logalot) {
2636
+ console.log(`${lc} complete.`);
2637
+ }
2638
+ }
2639
+ }
2640
+ export async function trash({ ibGib_Context, rel8nName_Context, addr, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
2641
+ const lc = `[${trash.name}]`;
2642
+ try {
2643
+ if (logalot) {
2644
+ console.log(`${lc} starting... (I: 2dc486bb2d516e4534f437aaf5ec7f22)`);
2645
+ }
2646
+ if (!ibGib_Context) {
2647
+ throw new Error(`ibGib_Context required (E: 75f7bfa93145d6dffe85d488443ca722)`);
2648
+ }
2649
+ if (!rel8nName_Context) {
2650
+ throw new Error(`rel8nName_Context required (E: 12aaa43de9e34b68b25dc9a2a68ad6b9)`);
2651
+ }
2652
+ if (!addr) {
2653
+ throw new Error(`addr required (E: e27df3bdc5a2554697cc9597afc4e422)`);
2654
+ }
2655
+ if (!space) {
2656
+ throw new Error(`space required (E: 2e3562486ed2956a770ed9e8d77a3f22)`);
2657
+ }
2658
+ const contextIsSpecialIbGib = isSpecial({ ibGib: ibGib_Context });
2659
+ if (contextIsSpecialIbGib) {
2660
+ throwIfContextIsSpecial({ ibGib_Context });
2661
+ }
2662
+ const resNewContext = await V1.rel8({
2663
+ src: ibGib_Context,
2664
+ rel8nsToAddByAddr: { [TRASH_REL8N_NAME]: [addr] },
2665
+ rel8nsToRemoveByAddr: { [rel8nName_Context]: [addr] },
2666
+ dna: true,
2667
+ nCounter: true,
2668
+ });
2669
+ await persistTransformResult({ resTransform: resNewContext, isMeta: contextIsSpecialIbGib, space });
2670
+ if (contextIsSpecialIbGib) {
2671
+ const newSpecialAddr = getIbGibAddr({ ibGib: resNewContext.newIbGib });
2672
+ const specialType = getSpecialTypeFromIb({ ib: ibGib_Context.ib });
2673
+ const configKey = getSpecialConfigKey({ type: specialType });
2674
+ await setConfigAddr({ key: configKey, addr: newSpecialAddr, space, zeroSpace, fnUpdateBootstrap });
2675
+ }
2676
+ // if (fnBroadcast && fnUpdateBootstrap) {
2677
+ await registerNewIbGib({
2678
+ ibGib: resNewContext.newIbGib,
2679
+ fnBroadcast,
2680
+ fnUpdateBootstrap,
2681
+ zeroSpace,
2682
+ space,
2683
+ });
2684
+ // };
2685
+ }
2686
+ catch (error) {
2687
+ console.error(`${lc} ${error.message}`);
2688
+ throw error;
2689
+ }
2690
+ finally {
2691
+ if (logalot) {
2692
+ console.log(`${lc} complete.`);
2693
+ }
2694
+ }
2695
+ }
2696
+ export async function archive({ ibGib_Context, rel8nName_Context, addr, space, zeroSpace, fnUpdateBootstrap, fnBroadcast, }) {
2697
+ const lc = `[${archive.name}]`;
2698
+ try {
2699
+ if (logalot) {
2700
+ console.log(`${lc} starting... (I: 38098552b830495187299bb24fcddff0)`);
2701
+ }
2702
+ if (!ibGib_Context) {
2703
+ throw new Error(`ibGib_Context required (E: d819e8c4db5b4c0bb721300ba434cd40)`);
2704
+ }
2705
+ if (!rel8nName_Context) {
2706
+ throw new Error(`rel8nName_Context required (E: de061adff8c04429a211aa09116a532d)`);
2707
+ }
2708
+ if (!addr) {
2709
+ throw new Error(`addr required (E: 7059ebb8ef6149ea94e22f961d6b5c81)`);
2710
+ }
2711
+ if (!space) {
2712
+ throw new Error(`space required (E: e19566f2d42347798621447edcae312e)`);
2713
+ }
2714
+ const contextIsSpecialIbGib = isSpecial({ ibGib: ibGib_Context });
2715
+ if (contextIsSpecialIbGib) {
2716
+ throwIfContextIsSpecial({ ibGib_Context });
2717
+ }
2718
+ const resNewContext = await V1.rel8({
2719
+ src: ibGib_Context,
2720
+ rel8nsToAddByAddr: { [ARCHIVE_REL8N_NAME]: [addr] },
2721
+ rel8nsToRemoveByAddr: { [rel8nName_Context]: [addr] },
2722
+ dna: true,
2723
+ nCounter: true,
2724
+ });
2725
+ await persistTransformResult({ resTransform: resNewContext, isMeta: contextIsSpecialIbGib, space });
2726
+ if (contextIsSpecialIbGib) {
2727
+ const newSpecialAddr = getIbGibAddr({ ibGib: resNewContext.newIbGib });
2728
+ const specialType = getSpecialTypeFromIb({ ib: ibGib_Context.ib });
2729
+ const configKey = getSpecialConfigKey({ type: specialType });
2730
+ await setConfigAddr({ key: configKey, addr: newSpecialAddr, space, zeroSpace, fnUpdateBootstrap });
2731
+ }
2732
+ // if (fnBroadcast && fnUpdateBootstrap) {
2733
+ await registerNewIbGib({
2734
+ ibGib: resNewContext.newIbGib,
2735
+ fnBroadcast,
2736
+ fnUpdateBootstrap,
2737
+ zeroSpace,
2738
+ space,
2739
+ });
2740
+ // } else {
2741
+ // console.warn(`${lc} fnBroadcast or fnUpdateBootstrap falsy, so we can't register `)
2742
+ // };
2743
+ }
2744
+ catch (error) {
2745
+ console.error(`${lc} ${error.message}`);
2746
+ throw error;
2747
+ }
2748
+ finally {
2749
+ if (logalot) {
2750
+ console.log(`${lc} complete.`);
2751
+ }
2752
+ }
2753
+ }
2754
+ export function spaceNameIsValid(name) {
2755
+ const lc = `[${spaceNameIsValid.name}]`;
2756
+ try {
2757
+ // non-falsy
2758
+ if (!name) {
2759
+ console.error(`${lc} name is falsy`);
2760
+ return false;
2761
+ }
2762
+ // valid characters are alphanumerics, numbers, underscores, hyphens
2763
+ const regexOnlyIncluded = /[\w-]+/;
2764
+ const matchOnlyIncluded = name.match(regexOnlyIncluded);
2765
+ if (matchOnlyIncluded?.length !== 1 || matchOnlyIncluded[0].length !== name.length) {
2766
+ console.error(`${lc} name can only contain letters, numbers, underscores, hyphens`);
2767
+ return false;
2768
+ }
2769
+ // start with alphanumeric
2770
+ const regexStart = /[a-zA-Z\d]/;
2771
+ const matchStart = name[0].match(regexStart);
2772
+ if (!matchStart) {
2773
+ console.error(`${lc} name must start with a letter or number`);
2774
+ return false;
2775
+ }
2776
+ return true;
2777
+ }
2778
+ catch (error) {
2779
+ console.error(`${lc} ${error.message}`);
2780
+ return false;
2781
+ }
2782
+ }
2783
+ export async function validateBootstrapIbGib(bootstrapSpace) {
2784
+ const lc = `[${validateBootstrapIbGib.name}]`;
2785
+ const errors = [];
2786
+ try {
2787
+ const addr = getIbGibAddr({ ibGib: bootstrapSpace });
2788
+ if (addr !== BOOTSTRAP_IBGIB_ADDR) {
2789
+ errors.push(`invalid bootstrapSpace addr. Should equal "${BOOTSTRAP_IBGIB_ADDR}" (E: ecfdbed719284db7a1aa3f867f706fe9)`);
2790
+ }
2791
+ let intrinsicErrors = await validateIbGibIntrinsically({ ibGib: bootstrapSpace });
2792
+ if (intrinsicErrors?.length ?? -1 > 0) {
2793
+ intrinsicErrors.forEach(e => errors.push(e));
2794
+ }
2795
+ const data = bootstrapSpace.data;
2796
+ const rel8ns = bootstrapSpace.rel8ns;
2797
+ if (Object.keys(data || {}).length === 0) {
2798
+ errors.push(`invalid bootstrapSpace data. data required (E: 5a9bd15dd0644f9b93cafbbba660cfdf)`);
2799
+ }
2800
+ if ((data.spaceIds ?? []).length === 0) {
2801
+ errors.push(`invalid bootstrapSpace, data.spaceIds required. (E: 6b91ddc12cfd41e59ded7d7502c1909f)`);
2802
+ }
2803
+ if (Object.keys(bootstrapSpace.rel8ns || {}).length === 0) {
2804
+ errors.push(`invalid bootstrapSpace rel8ns (empty). Should have at least one rel8n, with rel8nName corresponding to the spaceId (E: b188ce4ae25e49f794f35e141bc2ecde)`);
2805
+ }
2806
+ data.spaceIds.forEach((spaceId) => {
2807
+ if ((rel8ns[spaceId] ?? []).length === 0) {
2808
+ errors.push(`invalid bootstrap. Each spaceId listed in data should have a corresponding address in rel8ns. spaceId (${spaceId}) missing. (E: 62dd0d76e29a415a98b4b27deb8db17e)`);
2809
+ }
2810
+ });
2811
+ if (!data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY]) {
2812
+ errors.push(`invalid bootstrap. data.${BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY} required. (E: f763af2e275f445cbf1db5801bacafad)`);
2813
+ }
2814
+ else if ((rel8ns[data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY]] ?? []).length === 0) {
2815
+ errors.push(`invalid bootstrap. data.${BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY} (${data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY]}) not found in rel8ns. (E: 44d0799d232f4a51a0b0019ebebe019f)`);
2816
+ }
2817
+ if (errors.length === 0) {
2818
+ return true;
2819
+ }
2820
+ else {
2821
+ console.error(`${lc} errors: ${errors.join('|')}`);
2822
+ return false;
2823
+ }
2824
+ }
2825
+ catch (error) {
2826
+ console.error(`${lc} ${error.message}`);
2827
+ return false;
2828
+ }
2829
+ }
2830
+ //# sourceMappingURL=space-helper.mjs.map